2
0
Эх сурвалжийг харах

Material refactor WIP, it compiles

Marko Pintera 11 жил өмнө
parent
commit
3f94468a9f
34 өөрчлөгдсөн 1082 нэмэгдсэн , 1313 устгасан
  1. 0 2
      BansheeCore/BansheeCore.vcxproj
  2. 0 6
      BansheeCore/BansheeCore.vcxproj.filters
  3. 1 5
      BansheeCore/Include/BsCorePrerequisites.h
  4. 24 84
      BansheeCore/Include/BsGpuParam.h
  5. 5 0
      BansheeCore/Include/BsGpuParamBlockBuffer.h
  6. 6 30
      BansheeCore/Include/BsGpuParams.h
  7. 419 178
      BansheeCore/Include/BsMaterial.h
  8. 111 43
      BansheeCore/Include/BsMaterialParam.h
  9. 0 61
      BansheeCore/Include/BsMaterialProxy.h
  10. 1 1
      BansheeCore/Include/BsRenderer.h
  11. 8 19
      BansheeCore/Include/BsShader.h
  12. 5 17
      BansheeCore/Include/BsTechnique.h
  13. 10 5
      BansheeCore/Source/BsGpuParamBlockBuffer.cpp
  14. 284 571
      BansheeCore/Source/BsMaterial.cpp
  15. 0 81
      BansheeCore/Source/BsMaterialParam.cpp
  16. 0 6
      BansheeCore/Source/BsMaterialProxy.cpp
  17. 31 28
      BansheeCore/Source/BsRenderer.cpp
  18. 3 0
      BansheeCore/Source/BsTechnique.cpp
  19. 10 10
      BansheeEditor/Include/BsGizmoManager.h
  20. 4 4
      BansheeEditor/Include/BsHandleDrawManager.h
  21. 2 2
      BansheeEditor/Include/BsScenePicking.h
  22. 33 30
      BansheeEditor/Source/BsGizmoManager.cpp
  23. 13 13
      BansheeEditor/Source/BsHandleDrawManager.cpp
  24. 11 12
      BansheeEditor/Source/BsScenePicking.cpp
  25. 2 2
      BansheeEngine/Include/BsRenderQueue.h
  26. 18 2
      BansheeEngine/Include/BsRenderableProxy.h
  27. 7 7
      BansheeEngine/Source/BsRenderQueue.cpp
  28. 4 2
      BansheeEngine/Source/BsRenderableController.cpp
  29. 1 19
      BansheeEngine/Source/BsRenderableHandler.cpp
  30. 2 2
      BansheeRenderer/Include/BsBansheeLitTexRenderableController.h
  31. 0 1
      BansheeRenderer/Include/BsBansheeRenderer.h
  32. 47 39
      BansheeRenderer/Source/BsBansheeLitTexRenderableController.cpp
  33. 14 21
      BansheeRenderer/Source/BsBansheeRenderer.cpp
  34. 6 10
      TODO.txt

+ 0 - 2
BansheeCore/BansheeCore.vcxproj

@@ -281,7 +281,6 @@
     <ClInclude Include="Include\BsCoreObjectCore.h" />
     <ClInclude Include="Include\BsDrawList.h" />
     <ClInclude Include="Include\BsMaterialParam.h" />
-    <ClInclude Include="Include\BsMaterialProxy.h" />
     <ClInclude Include="Include\BsRenderStats.h" />
     <ClInclude Include="Include\BsCoreThread.h" />
     <ClInclude Include="Include\BsProfilerCPU.h" />
@@ -427,7 +426,6 @@
     <ClCompile Include="Source\BsCoreThread.cpp" />
     <ClCompile Include="Source\BsDrawList.cpp" />
     <ClCompile Include="Source\BsMaterialParam.cpp" />
-    <ClCompile Include="Source\BsMaterialProxy.cpp" />
     <ClCompile Include="Source\BsProfilerCPU.cpp" />
     <ClCompile Include="Source\BsDeferredCallManager.cpp" />
     <ClCompile Include="Source\BsDrawOps.cpp" />

+ 0 - 6
BansheeCore/BansheeCore.vcxproj.filters

@@ -495,9 +495,6 @@
     <ClInclude Include="Include\BsDrawList.h">
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
-    <ClInclude Include="Include\BsMaterialProxy.h">
-      <Filter>Header Files\Renderer</Filter>
-    </ClInclude>
     <ClInclude Include="Include\BsTextureImportOptions.h">
       <Filter>Header Files\Importer</Filter>
     </ClInclude>
@@ -809,9 +806,6 @@
     <ClCompile Include="Source\BsResourceMetaData.cpp">
       <Filter>Source Files\Resources</Filter>
     </ClCompile>
-    <ClCompile Include="Source\BsMaterialProxy.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
     <ClCompile Include="Source\BsMaterialParam.cpp">
       <Filter>Source Files\Material</Filter>
     </ClCompile>

+ 1 - 5
BansheeCore/Include/BsCorePrerequisites.h

@@ -101,7 +101,6 @@ namespace BansheeEngine
 	class RawInputHandler;
 	class Renderer;
 	class RendererFactory;
-	class PassParameters;
 	class AsyncOp;
 	class HardwareBufferManager;
 	class FontManager;
@@ -141,8 +140,6 @@ namespace BansheeEngine
 	class VideoModeInfo;
 	class RenderableElement;
 	class CameraHandlerCore;
-	struct MaterialProxy;
-	struct MaterialProxyPass;
 	class MeshCoreBase;
 	class MeshCore;
 	class DrawList;
@@ -158,6 +155,7 @@ namespace BansheeEngine
 	class ViewportCore;
 	class PassCore;
 	class TechniqueCore;
+	class MaterialCore;
 	// Asset import
 	class SpecificImporter;
 	class Importer;
@@ -220,7 +218,6 @@ namespace BansheeEngine
 	typedef std::shared_ptr<Material> MaterialPtr;
 	typedef std::shared_ptr<Renderer> RendererPtr;
 	typedef std::shared_ptr<RendererFactory> RendererFactoryPtr;
-	typedef std::shared_ptr<PassParameters> PassParametersPtr;
 	typedef std::shared_ptr<Component> ComponentPtr;
 	typedef std::shared_ptr<GameObject> GameObjectPtr;
 	typedef std::shared_ptr<SceneObject> SceneObjectPtr;
@@ -252,7 +249,6 @@ namespace BansheeEngine
 	typedef std::shared_ptr<VideoModeInfo> VideoModeInfoPtr;
 	typedef std::shared_ptr<DrawList> DrawListPtr;
 	typedef std::shared_ptr<RenderQueue> RenderQueuePtr;
-	typedef std::shared_ptr<MaterialProxy> MaterialProxyPtr;
 	typedef std::shared_ptr<GpuParamDesc> GpuParamDescPtr;
 	typedef std::shared_ptr<ResourceMetaData> ResourceMetaDataPtr;
 }

+ 24 - 84
BansheeCore/Include/BsGpuParam.h

@@ -218,53 +218,25 @@ namespace BansheeEngine
 		GpuParamObjectDesc* mParamDesc;
 	};
 
-	template<bool Core>
-	struct TGpuParamsPtrType
-	{ };
-
-	template<>
-	struct TGpuParamsPtrType<false>
-	{
-		typedef SPtr<GpuParams> Type;
-	};
+	template<bool Core> struct TGpuParamsPtrType { };
+	template<> struct TGpuParamsPtrType<false> { typedef SPtr<GpuParams> Type; };
+	template<> struct TGpuParamsPtrType<true> { typedef SPtr<GpuParamsCore> Type; };
 
-	template<>
-	struct TGpuParamsPtrType<true>
-	{
-		typedef SPtr<GpuParamsCore> Type;
-	};
+	template<bool Core> struct TGpuDataParamBaseType { };
+	template<> struct TGpuDataParamBaseType<false> { typedef GpuDataParamBase Type; };
+	template<> struct TGpuDataParamBaseType<true> { typedef GpuDataParamCoreBase Type;	};
 
-	template<bool Core>
-	struct TGpuDataParamBaseType
-	{ };
+	template<bool Core> struct TGpuObjectParamBaseType { };
+	template<> struct TGpuObjectParamBaseType<false> { typedef GpuObjectParamBase Type; };
+	template<> struct TGpuObjectParamBaseType<true> { typedef GpuObjectParamCoreBase Type; };
 
-	template<>
-	struct TGpuDataParamBaseType<false>
-	{ 
-		typedef GpuDataParamBase Type;
-	};
+	template<bool Core> struct TGpuParamTextureType { };
+	template<> struct TGpuParamTextureType < false > { typedef HTexture Type; };
+	template<> struct TGpuParamTextureType < true > { typedef SPtr<TextureCore> Type; };
 
-	template<>
-	struct TGpuDataParamBaseType<true>
-	{ 
-		typedef GpuDataParamCoreBase Type;
-	};
-
-	template<bool Core>
-	struct TGpuObjectParamBaseType
-	{ };
-
-	template<>
-	struct TGpuObjectParamBaseType<false>
-	{ 
-		typedef GpuObjectParamBase Type;
-	};
-
-	template<>
-	struct TGpuObjectParamBaseType<true>
-	{ 
-		typedef GpuObjectParamCoreBase Type;
-	};
+	template<bool Core> struct TGpuParamSamplerStateType { };
+	template<> struct TGpuParamSamplerStateType < false > { typedef HSamplerState Type; };
+	template<> struct TGpuParamSamplerStateType < true > { typedef SPtr<SamplerStateCore> Type; };
 
 	/**
 	 * @brief	A handle that allows you to set a GpuProgram parameter. Internally keeps a reference to the 
@@ -531,22 +503,6 @@ namespace BansheeEngine
 	template class TGpuParamStruct<false>;
 	template class TGpuParamStruct<true>;
 
-	template<bool Core>
-	struct GpuParamTextureType
-	{ };
-
-	template<>
-	struct GpuParamTextureType<false>
-	{ 
-		typedef HTexture Type;
-	};
-
-	template<>
-	struct GpuParamTextureType<true>
-	{
-		typedef SPtr<TextureCore> Type;
-	};
-
 	/**
 	 * @copydoc TGpuObjectParam
 	 */
@@ -568,7 +524,7 @@ namespace BansheeEngine
 		/**
 		 * @copydoc	TGpuDataParam::set
 		 */
-		void set(const typename GpuParamTextureType<Core>::Type& texture)
+		void set(const typename TGpuParamTextureType<Core>::Type& texture)
 		{
 			if (mParent == nullptr)
 				return;
@@ -582,10 +538,10 @@ namespace BansheeEngine
 		/**
 		 * @copydoc	TGpuDataParam::get
 		 */
-		typename GpuParamTextureType<Core>::Type get()
+		typename TGpuParamTextureType<Core>::Type get()
 		{
 			if (mParent == nullptr)
-				return GpuParamTextureType<Core>::Type();
+				return TGpuParamTextureType<Core>::Type();
 
 			return getTexture(mParamDesc->slot);
 		}
@@ -618,7 +574,7 @@ namespace BansheeEngine
 		/**
 		 * @copydoc	TGpuDataParam::set
 		 */
-		void set(const typename GpuParamTextureType<Core>::Type& texture, const TextureSurface& surface)
+		void set(const typename TGpuParamTextureType<Core>::Type& texture, const TextureSurface& surface)
 		{
 			if (mParent == nullptr)
 				return;
@@ -633,10 +589,10 @@ namespace BansheeEngine
 		/**
 		 * @copydoc	TGpuDataParam::get
 		 */
-		typename GpuParamTextureType<Core>::Type get()
+		typename TGpuParamTextureType<Core>::Type get()
 		{
 			if (mParent == nullptr)
-				return GpuParamTextureType<Core>::Type();
+				return TGpuParamTextureType<Core>::Type();
 
 			return getTexture(mParamDesc->slot);
 		}
@@ -648,22 +604,6 @@ namespace BansheeEngine
 	template class TGpuParamLoadStoreTexture<false>;
 	template class TGpuParamLoadStoreTexture<true>;
 
-	template<bool Core>
-	struct GpuParamSamplerStateType
-	{ };
-
-	template<>
-	struct GpuParamSamplerStateType<false>
-	{
-		typedef HSamplerState Type;
-	};
-
-	template<>
-	struct GpuParamSamplerStateType<true>
-	{
-		typedef SPtr<SamplerStateCore> Type;
-	};
-
 	/**
 	 * @copydoc TGpuObjectParam
 	 */
@@ -685,7 +625,7 @@ namespace BansheeEngine
 		/**
 		 * @copydoc	TGpuDataParam::set
 		 */
-		void set(const typename GpuParamSamplerStateType<Core>::Type& samplerState)
+		void set(const typename TGpuParamSamplerStateType<Core>::Type& samplerState)
 		{
 			if (mParent == nullptr)
 				return;
@@ -698,10 +638,10 @@ namespace BansheeEngine
 		/**
 		 * @copydoc	TGpuDataParam::get
 		 */
-		typename GpuParamSamplerStateType<Core>::Type get()
+		typename TGpuParamSamplerStateType<Core>::Type get()
 		{
 			if (mParent == nullptr)
-				return GpuParamSamplerStateType<Core>::Type();
+				return TGpuParamSamplerStateType<Core>::Type();
 
 			return getSamplerState(mParamDesc->slot);
 		}

+ 5 - 0
BansheeCore/Include/BsGpuParamBlockBuffer.h

@@ -69,6 +69,11 @@ namespace BansheeEngine
 		 */
 		UINT32 getSize() const { return mSize; }
 
+		/**
+		 * @copydoc	HardwareBufferCoreManager::createGpuParamBlockBuffer
+		 */
+		static SPtr<GpuParamBlockBufferCore> create(UINT32 size, GpuParamBlockUsage usage = GPBU_DYNAMIC);
+
 	protected:
 		/**
 		 * @copydoc	CoreObjectCore::syncToCore

+ 6 - 30
BansheeCore/Include/BsGpuParams.h

@@ -131,37 +131,13 @@ namespace BansheeEngine
 		bool mTransposeMatrices;
 	};
 
-	template<bool Core>
-	struct TGpuParamsBaseType
-	{ };
-
-	template<>
-	struct TGpuParamsBaseType<true>
-	{ 
-		typedef CoreObjectCore Type;
-	};
-
-	template<>
-	struct TGpuParamsBaseType<false>
-	{
-		typedef CoreObject Type;
-	};
-
-	template<bool Core>
-	struct TGpuParamsType
-	{ };
+	template<bool Core> struct TGpuParamsBaseType { };
+	template<> struct TGpuParamsBaseType<true> { typedef CoreObjectCore Type; };
+	template<> struct TGpuParamsBaseType<false> { typedef CoreObject Type; };
 
-	template<>
-	struct TGpuParamsType<false>
-	{
-		typedef GpuParams Type;
-	};
-
-	template<>
-	struct TGpuParamsType<true>
-	{
-		typedef GpuParamsCore Type;
-	};
+	template<bool Core> struct TGpuParamsType { };
+	template<> struct TGpuParamsType<false> { typedef GpuParams Type; };
+	template<> struct TGpuParamsType<true>{ typedef GpuParamsCore Type; };
 
 	/**
 	 * @brief	Templated version of GpuParams that contains functionality for both

+ 419 - 178
BansheeCore/Include/BsMaterial.h

@@ -3,46 +3,46 @@
 #include "BsCorePrerequisites.h"
 #include "BsResource.h"
 #include "BsMaterialParam.h"
-#include "BsMaterialProxy.h"
 #include "BsVector2.h"
 #include "BsVector3.h"
 #include "BsVector4.h"
 #include "BsMatrix3.h"
 #include "BsMatrix4.h"
 
+// TOOD REMOVE THIS
+#include "BsShader.h"
+#include "BsGpuParams.h"
+#include "BsTechnique.h"
+#include "BsPass.h"
+#include "BsHardwareBufferManager.h"
+
 namespace BansheeEngine
 {
-	/**
-	 * @brief	Type of material dirty flags
-	 */
-	enum class MaterialDirtyFlag
-	{
-		Material = 0x01, /**< Internal material data is dirty. */
-		Proxy = 0x02 /**< Active proxy needs to be updated. */
-	};
-
 	/**
 	 * @brief	Helper class containing parameters for all types
 	 * 			of GPU programs used in a pass.
 	 */
-	class BS_CORE_EXPORT PassParameters
+	template<bool Core>
+	class TPassParameters
 	{
 	public:
-		GpuParamsPtr mVertParams;
-		GpuParamsPtr mFragParams;
-		GpuParamsPtr mGeomParams;
-		GpuParamsPtr mHullParams;
-		GpuParamsPtr mDomainParams;
-		GpuParamsPtr mComputeParams;
+		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
+
+		GpuParamsType mVertParams;
+		GpuParamsType mFragParams;
+		GpuParamsType mGeomParams;
+		GpuParamsType mHullParams;
+		GpuParamsType mDomainParams;
+		GpuParamsType mComputeParams;
 
 		/**
 		 * @brief	Returns a set of GPU parameters based on an index.
 		 *
 		 * @note	Useful when needing to iterate over all sets of GPU parameters.
 		 */
-		GpuParamsPtr& getParamByIdx(UINT32 idx)
+		GpuParamsType& getParamByIdx(UINT32 idx)
 		{
-			GpuParamsPtr* paramArray[] = {&mVertParams, &mFragParams, &mGeomParams, &mHullParams, &mDomainParams, &mComputeParams};
+			GpuParamsType* paramArray[] = { &mVertParams, &mFragParams, &mGeomParams, &mHullParams, &mDomainParams, &mComputeParams };
 
 			return *paramArray[idx];
 		}
@@ -52,9 +52,9 @@ namespace BansheeEngine
 		 *
 		 * @note	Useful when needing to iterate over all sets of GPU parameters.
 		 */
-		void setParamByIdx(UINT32 idx, const GpuParamsPtr& params)
+		void setParamByIdx(UINT32 idx, const GpuParamsType& params)
 		{
-			GpuParamsPtr* paramArray[] = {&mVertParams, &mFragParams, &mGeomParams, &mHullParams, &mDomainParams, &mComputeParams};
+			GpuParamsType* paramArray[] = { &mVertParams, &mFragParams, &mGeomParams, &mHullParams, &mDomainParams, &mComputeParams };
 
 			(*paramArray[idx]) = params;
 		}
@@ -66,12 +66,23 @@ namespace BansheeEngine
 		UINT32 getNumParams() const { return 6; }
 	};
 
+	template<bool Core> struct TGpuParamBlockBufferPtrType { };
+	template<> struct TGpuParamBlockBufferPtrType<false> { typedef SPtr<GpuParamBlockBuffer> Type; };
+	template<> struct TGpuParamBlockBufferPtrType<true> { typedef SPtr<GpuParamBlockBufferCore> Type; };
+
+	template<bool Core> struct TGpuProgramType { };
+	template<> struct TGpuProgramType<false> { typedef HGpuProgram Type; };
+	template<> struct TGpuProgramType<true> { typedef SPtr<GpuProgramCore> Type; };
+
+	typedef TPassParameters<false> PassParameters;
+	typedef TPassParameters<true> PassParametersCore;
+
 	/**
 	 * @brief	Material represents a shader and parameters used to set up
 	 * 			that shader. It provides a simple interface for manipulating the
 	 * 			parameters.
 	 */
-	class BS_CORE_EXPORT Material : public Resource
+	class BS_CORE_EXPORT MaterialBase
 	{
 	public:
 		/**
@@ -102,7 +113,62 @@ namespace BansheeEngine
 			UINT32 size;
 		};
 
-		~Material();
+		virtual ~MaterialBase() { }
+
+	protected:
+		/**
+		 * @brief	Retrieves a list of all shader GPU parameters, and the GPU program variable names they map to.
+		 */
+		const Map<String, String>& getValidParamNames() const { return mValidParams; }
+
+		/**
+		 * @copydoc	CoreObject::markCoreDirty
+		 */
+		virtual void _markCoreDirty() { }
+
+		/**
+		 * @brief	Returns all GPU parameter descriptions in the specified technique.
+		 */
+		static Vector<GpuParamDescPtr> getAllParamDescs(const SPtr<Technique>& technique);
+
+		/**
+		 * @brief	Returns all GPU parameter descriptions in the specified technique.
+		 */
+		static Vector<GpuParamDescPtr> getAllParamDescs(const SPtr<TechniqueCore>& technique);
+
+		Set<String> mValidShareableParamBlocks;
+		Map<String, String> mValidParams; // Also maps Shader param name -> gpu variable name
+	};
+
+	template<bool Core>
+	class BS_CORE_EXPORT TMaterial : public MaterialBase
+	{
+	public:
+		template<bool Core> struct TPassType {};
+		template<> struct TPassType < false > { typedef SPtr<Pass> Type; };
+		template<> struct TPassType < true > { typedef SPtr<PassCore> Type; };
+
+		template<bool Core> struct TTechniqueType {};
+		template<> struct TTechniqueType < false > { typedef SPtr<Technique> Type; };
+		template<> struct TTechniqueType < true > { typedef SPtr<TechniqueCore> Type; };
+
+		template<bool Core> struct TShaderType {};
+		template<> struct TShaderType < false > { typedef SPtr<Shader> Type; };
+		template<> struct TShaderType < true > { typedef SPtr<ShaderCore> Type; };
+
+		template<bool Core> struct TGpuParamBlockBufferType {};
+		template<> struct TGpuParamBlockBufferType < false > { typedef GpuParamBlockBuffer Type; };
+		template<> struct TGpuParamBlockBufferType < true > { typedef GpuParamBlockBufferCore Type; };
+
+		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
+		typedef typename TGpuParamTextureType<Core>::Type TextureType;
+		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;
 
 		/**
 		 * @brief	Sets a shader that will be used by the material. Best technique within the
@@ -114,27 +180,40 @@ namespace BansheeEngine
 		 * 			dependent upon (render system, renderer, etc), you will need to call this 
 		 * 			method again on all your Materials to make sure technique used is updated.
 		 */
-		void setShader(ShaderPtr shader);
+		void setShader(ShaderType shader)
+		{
+			mShader = shader;
+
+			initBestTechnique();
+			_markCoreDirty();
+		}
 
 		/**
 		 * @brief	Returns the currently active shader.
 		 */
-		ShaderPtr getShader() const { return mShader; }
+		ShaderType getShader() const { return mShader; }
 
-		/** @brief	Assigns a texture to the shader parameter with the specified name. */
-		void setTexture(const String& name, const HTexture& value) { return getParamTexture(name).set(value); }
-
-		/** 
-		 * @brief	Assigns a texture to be used for random load/store operations to the
-		 *			shader parameter with the specified name.
+		/**
+		 * @brief	Returns the number of passes that are used
+		 * 			by the shader used in the material.
 		 */
-		void setLoadStoreTexture(const String& name, const HTexture& value, const TextureSurface& surface) 
-		{ 
-			return getParamLoadStoreTexture(name).set(value, surface); 
+		UINT32 getNumPasses() const
+		{
+			throwIfNotInitialized();
+
+			return mShader->getBestTechnique()->getNumPasses();
 		}
 
-		/** @brief	Assigns a sampler state to the shader parameter with the specified name. */
-		void setSamplerState(const String& name, const HSamplerState& value) { return getParamSamplerState(name).set(value); }
+		/**
+		 * @brief	Retrieves a specific shader pass.
+		 */
+		PassType getPass(UINT32 passIdx) const
+		{
+			if (passIdx < 0 || passIdx >= mShader->getBestTechnique()->getNumPasses())
+				BS_EXCEPT(InvalidParametersException, "Invalid pass index.");
+
+			return mShader->getBestTechnique()->getPass(passIdx);
+		}
 
 		/**   
 		 *  @brief	Assigns a float value to the shader parameter with the specified name. 
@@ -148,7 +227,10 @@ namespace BansheeEngine
 		 *
 		 *			Optionally if the parameter is an array you may provide an array index to assign the value to.
 		 */
-		void setColor(const String& name, const Color& value, UINT32 arrayIdx = 0);
+		void setColor(const String& name, const Color& value, UINT32 arrayIdx = 0)
+		{
+			return getParamVec4(name).set(Vector4(value.r, value.g, value.b, value.a), arrayIdx);
+		}
 
 		/**   
 		 *  @brief	Assigns a 2D vector to the shader parameter with the specified name. 
@@ -195,20 +277,20 @@ namespace BansheeEngine
 		 */
 		void setStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx = 0) { return getParamStruct(name).set(value, size, arrayIdx); }
 
-		/**
-		 * @brief	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 GpuParamBlockBufferPtr& paramBlock);
+		/** @brief	Assigns a texture to the shader parameter with the specified name. */
+		void setTexture(const String& name, const TextureType& value) { return getParamTexture(name).set(value); }
 
-		/** @brief	Returns a texture assigned with the parameter with the specified name. */
-		HTexture getTexture(const String& name) const { return getParamTexture(name).get(); }
+		/** 
+		 * @brief	Assigns a texture to be used for random load/store operations to the
+		 *			shader parameter with the specified name.
+		 */
+		void setLoadStoreTexture(const String& name, const TextureType& value, const TextureSurface& surface)
+		{ 
+			return getParamLoadStoreTexture(name).set(value, surface); 
+		}
 
-		/** @brief	Returns a sampler state assigned with the parameter with the specified name. */
-		HSamplerState getSamplerState(const String& name) const	{ return getParamSamplerState(name).get(); }
+		/** @brief	Assigns a sampler state to the shader parameter with the specified name. */
+		void setSamplerState(const String& name, const SamplerStateType& value) { return getParamSamplerState(name).set(value); }
 
 		/**
 		 * @brief	Returns a float value assigned with the parameter with the specified name.
@@ -259,12 +341,26 @@ namespace BansheeEngine
 		 */
 		Matrix4 getMat4(const String& name, UINT32 arrayIdx = 0) const { return getParamMat4(name).get(arrayIdx); }
 
+		/** @brief	Returns a texture assigned with the parameter with the specified name. */
+		TextureType getTexture(const String& name) const { return getParamTexture(name).get(); }
+
+		/** @brief	Returns a sampler state assigned with the parameter with the specified name. */
+		SamplerStateType getSamplerState(const String& name) const	{ return getParamSamplerState(name).get(); }
+
 		/**
 		 * @brief	Returns a buffer representing a structure assigned to the parameter with the specified name.
 		 *
 		 *			Optionally if the parameter is an array you may provide an array index you which to retrieve.
 		 */
-		StructData getStructData(const String& name, UINT32 arrayIdx = 0) const;
+		MaterialBase::StructData getStructData(const String& name, UINT32 arrayIdx = 0) const
+		{
+			TMaterialParamStruct<Core> structParam = getParamStruct(name);
+
+			MaterialBase::StructData data(structParam.getElementSize());
+			structParam.get(data.data.get(), structParam.getElementSize(), arrayIdx);
+
+			return data;
+		}
 
 		/**
 		 * @brief	Returns a float GPU parameter. This parameter may be used for
@@ -277,7 +373,13 @@ namespace BansheeEngine
 		 * 			
 		 *			If material shader changes this handle will be invalidated.
 		 */
-		MaterialParamFloat getParamFloat(const String& name) const;
+		TMaterialDataParam<float, Core> getParamFloat(const String& name) const
+		{
+			TMaterialDataParam<float, Core> gpuParam;
+			getParam(name, gpuParam);
+
+			return gpuParam;
+		}
 
 		/**
 		 * @brief	Returns a color GPU parameter. This parameter may be used for
@@ -290,7 +392,13 @@ namespace BansheeEngine
 		 * 			
 		 *			If material shader changes this handle will be invalidated.
 		 */
-		MaterialParamColor getParamColor(const String& name) const;
+		TMaterialDataParam<Color, Core> getParamColor(const String& name) const
+		{
+			TMaterialDataParam<Color, Core> gpuParam;
+			getParam(name, gpuParam);
+
+			return gpuParam;
+		}
 
 		/**
 		 * @brief	Returns a 2D vector GPU parameter. This parameter may be used for
@@ -303,7 +411,13 @@ namespace BansheeEngine
 		 * 			
 		 *			If material shader changes this handle will be invalidated.
 		 */
-		MaterialParamVec2 getParamVec2(const String& name) const;
+		TMaterialDataParam<Vector2, Core> getParamVec2(const String& name) const
+		{
+			TMaterialDataParam<Vector2, Core> gpuParam;
+			getParam(name, gpuParam);
+
+			return gpuParam;
+		}
 
 		/**
 		 * @brief	Returns a 3D vector GPU parameter. This parameter may be used for
@@ -316,7 +430,13 @@ namespace BansheeEngine
 		 * 			
 		 *			If material shader changes this handle will be invalidated.
 		 */
-		MaterialParamVec3 getParamVec3(const String& name) const;
+		TMaterialDataParam<Vector3, Core> getParamVec3(const String& name) const
+		{
+			TMaterialDataParam<Vector3, Core> gpuParam;
+			getParam(name, gpuParam);
+
+			return gpuParam;
+		}
 
 		/**
 		 * @brief	Returns a 4D vector GPU parameter. This parameter may be used for
@@ -329,7 +449,13 @@ namespace BansheeEngine
 		 * 			
 		 *			If material shader changes this handle will be invalidated.
 		 */
-		MaterialParamVec4 getParamVec4(const String& name) const;
+		TMaterialDataParam<Vector4, Core> getParamVec4(const String& name) const
+		{
+			TMaterialDataParam<Vector4, Core> gpuParam;
+			getParam(name, gpuParam);
+
+			return gpuParam;
+		}
 
 		/**
 		 * @brief	Returns a 3x3 matrix GPU parameter. This parameter may be used for
@@ -342,7 +468,13 @@ namespace BansheeEngine
 		 * 			
 		 *			If material shader changes this handle will be invalidated.
 		 */
-		MaterialParamMat3 getParamMat3(const String& name) const;
+		TMaterialDataParam<Matrix3, Core> getParamMat3(const String& name) const
+		{
+			TMaterialDataParam<Matrix3, Core> gpuParam;
+			getParam(name, gpuParam);
+
+			return gpuParam;
+		}
 
 		/**
 		 * @brief	Returns a 4x4 matrix GPU parameter. This parameter may be used for
@@ -355,7 +487,13 @@ namespace BansheeEngine
 		 * 			
 		 *			If material shader changes this handle will be invalidated.
 		 */
-		MaterialParamMat4 getParamMat4(const String& name) const;
+		TMaterialDataParam<Matrix4, Core> getParamMat4(const String& name) const
+		{
+			TMaterialDataParam<Matrix4, Core> gpuParam;
+			getParam(name, gpuParam);
+
+			return gpuParam;
+		}
 
 		/**
 		 * @brief	Returns a structure GPU parameter. This parameter may be used for
@@ -368,7 +506,40 @@ namespace BansheeEngine
 		 * 			
 		 *			If material shader changes this handle will be invalidated.
 		 */
-		MaterialParamStruct getParamStruct(const String& name) const;
+		TMaterialParamStruct<Core> getParamStruct(const String& name) const
+		{
+			throwIfNotInitialized();
+
+			auto iterFind = mValidParams.find(name);
+			if (iterFind == mValidParams.end())
+			{
+				LOGWRN("Material doesn't have a parameter named " + name);
+				return TMaterialParamStruct<Core>();
+			}
+
+			const String& gpuVarName = iterFind->second;
+			Vector<TGpuParamStruct<Core>> gpuParams;
+
+			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+			{
+				SPtr<TPassParameters<Core>> params = *iter;
+
+				for (UINT32 i = 0; i < params->getNumParams(); i++)
+				{
+					GpuParamsType& paramPtr = params->getParamByIdx(i);
+					if (paramPtr)
+					{
+						if (paramPtr->hasParam(gpuVarName))
+						{
+							gpuParams.push_back(TGpuParamStruct<Core>());
+							paramPtr->getStructParam(gpuVarName, gpuParams.back());
+						}
+					}
+				}
+			}
+
+			return TMaterialParamStruct<Core>(gpuParams);
+		}
 
 		/**
 		 * @brief	Returns a texture GPU parameter. This parameter may be used for
@@ -381,7 +552,40 @@ namespace BansheeEngine
 		 * 			
 		 *			If material shader changes this handle will be invalidated.
 		 */
-		MaterialParamTexture getParamTexture(const String& name) const;
+		TMaterialParamTexture<Core> getParamTexture(const String& name) const
+		{
+			throwIfNotInitialized();
+
+			auto iterFind = mValidParams.find(name);
+			if (iterFind == mValidParams.end())
+			{
+				LOGWRN("Material doesn't have a parameter named " + name);
+				return TMaterialParamTexture<Core>();
+			}
+
+			const String& gpuVarName = iterFind->second;
+			Vector<TGpuParamTexture<Core>> gpuParams;
+
+			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+			{
+				SPtr<TPassParameters<Core>> params = *iter;
+
+				for (UINT32 i = 0; i < params->getNumParams(); i++)
+				{
+					GpuParamsType& paramPtr = params->getParamByIdx(i);
+					if (paramPtr)
+					{
+						if (paramPtr->hasTexture(gpuVarName))
+						{
+							gpuParams.push_back(TGpuParamTexture<Core>());
+							paramPtr->getTextureParam(gpuVarName, gpuParams.back());
+						}
+					}
+				}
+			}
+
+			return TMaterialParamTexture<Core>(gpuParams);
+		}
 
 		/**
 		 * @brief	Returns a GPU parameter for binding a load/store texture. This parameter 
@@ -394,7 +598,40 @@ namespace BansheeEngine
 		 * 			
 		 *			If material shader changes this handle will be invalidated.
 		 */
-		MaterialParamLoadStoreTexture getParamLoadStoreTexture(const String& name) const;
+		TMaterialParamLoadStoreTexture<Core> getParamLoadStoreTexture(const String& name) const
+		{
+			throwIfNotInitialized();
+
+			auto iterFind = mValidParams.find(name);
+			if (iterFind == mValidParams.end())
+			{
+				LOGWRN("Material doesn't have a parameter named " + name);
+				return TMaterialParamLoadStoreTexture<Core>();
+			}
+
+			const String& gpuVarName = iterFind->second;
+			Vector<TGpuParamLoadStoreTexture<Core>> gpuParams;
+
+			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+			{
+				SPtr<TPassParameters<Core>> params = *iter;
+
+				for (UINT32 i = 0; i < params->getNumParams(); i++)
+				{
+					GpuParamsType& paramPtr = params->getParamByIdx(i);
+					if (paramPtr)
+					{
+						if (paramPtr->hasTexture(gpuVarName))
+						{
+							gpuParams.push_back(TGpuParamLoadStoreTexture<Core>());
+							paramPtr->getLoadStoreTextureParam(gpuVarName, gpuParams.back());
+						}
+					}
+				}
+			}
+
+			return TMaterialParamLoadStoreTexture<Core>(gpuParams);
+		}
 
 		/**
 		 * @brief	Returns a sampler state GPU parameter. This parameter may be used for
@@ -407,82 +644,79 @@ namespace BansheeEngine
 		 * 			
 		 *			If material shader changes this handle will be invalidated.
 		 */
-		MaterialParamSampState getParamSamplerState(const String& name) const;
-
-		/**
-		 * @brief	Returns the number of passes that are used
-		 * 			by the shader contained in the material.
-		 */
-		UINT32 getNumPasses() const;
-
-		/**
-		 * @brief	Retrieves a specific shader pass.
-		 */
-		PassPtr getPass(UINT32 passIdx) const;
+		TMaterialParamSampState<Core> getParamSamplerState(const String& name) const
+		{
+			throwIfNotInitialized();
 
-		/**
-		 * @brief	Returns a set of parameters for all GPU programs
-		 * 			in the specified shader pass.
-		 */
-		PassParametersPtr getPassParameters(UINT32 passIdx) const;
+			auto iterFind = mValidParams.find(name);
+			if (iterFind == mValidParams.end())
+			{
+				LOGWRN("Material doesn't have a parameter named " + name);
+				return TMaterialParamSampState<Core>();
+			}
 
-		/**
-		 * @brief	Creates a new empty material.
-		 * 			
-		 * @note	Make sure you call Material::setShader before using it.
-		 */
-		static HMaterial create();
+			const String& gpuVarName = iterFind->second;
+			Vector<TGpuParamSampState<Core>> gpuParams;
+			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+			{
+				SPtr<TPassParameters<Core>> params = *iter;
 
-		/**
-		 * @brief	Creates a new material with the specified shader.
-		 */
-		static HMaterial create(ShaderPtr shader);
+				for (UINT32 i = 0; i < params->getNumParams(); i++)
+				{
+					GpuParamsType& paramPtr = params->getParamByIdx(i);
+					if (paramPtr)
+					{
+						if (paramPtr->hasSamplerState(gpuVarName))
+						{
+							gpuParams.push_back(TGpuParamSampState<Core>());
+							paramPtr->getSamplerStateParam(gpuVarName, gpuParams.back());
+						}
+					}
+				}
+			}
 
-		/************************************************************************/
-		/* 								CORE PROXY                      		*/
-		/************************************************************************/
+			return TMaterialParamSampState<Core>(gpuParams);
+		}
 
 		/**
-		 * @brief	Checks is the core dirty flag set. This is used by external systems 
-		 *			to know when internal data has changed and core thread potentially needs to be notified.
-		 *
-		 * @note	Sim thread only.
+		 * @brief	Returns a set of parameters for all GPU programs
+		 * 			in the specified shader pass.
 		 */
-		bool _isCoreDirty(MaterialDirtyFlag flag) const;
+		SPtr<TPassParameters<Core>> getPassParameters(UINT32 passIdx) const { return mParametersPerPass[passIdx]; }
 
 		/**
-		 * @brief	Marks the core dirty flag as clean.
+		 * @brief	Assign a parameter block buffer with the specified name.
 		 *
-		 * @note	Sim thread only.
+		 * @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 _markCoreClean(MaterialDirtyFlag flag);
+		void setParamBlockBuffer(const String& name, const ParamBlockPtrType& paramBlock)
+		{
+			auto iterFind = mValidShareableParamBlocks.find(name);
+			if (iterFind == mValidShareableParamBlocks.end())
+			{
+				LOGWRN("Material doesn't have a parameter block named " + name);
+				return;
+			}
 
-		/**
-		 * @brief	Gets the currently active proxy of this material.
-		 */
-		MaterialProxyPtr _getActiveProxy() const { return mActiveProxy; }
+			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+			{
+				SPtr<TPassParameters<Core>> params = *iter;
 
-		/**
-		 * @brief	Sets an active proxy for this material.
-		 */
-		void _setActiveProxy(const MaterialProxyPtr& proxy) { mActiveProxy = proxy; }
+				for (UINT32 i = 0; i < params->getNumParams(); i++)
+				{
+					GpuParamsType& paramPtr = params->getParamByIdx(i);
+					if (paramPtr)
+					{
+						if (paramPtr->hasParamBlock(name))
+							paramPtr->setParamBlockBuffer(name, paramBlock);
+					}
+				}
+			}
+		}
 
-		/**
-		 * @brief	Creates a new core proxy from the currently set material data. Core proxies ensure
-		 *			that the core thread has all the necessary material data, while avoiding the need
-		 *			to manage Material itself on the core thread.
-		 *
-		 * @note	Sim thread only. 
-		 *			You generally need to update the core thread with a new proxy whenever core 
-		 *			dirty flag is set.
-		 */
-		MaterialProxyPtr _createProxy();
 	protected:
-		/**
-		 * @copydoc	Resource::destroy_internal
-		 */
-		void destroy_internal();
-
 		/**
 		 * @brief	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
@@ -492,7 +726,7 @@ namespace BansheeEngine
 		 * 			caller to keep track of that.
 		 */
 		template <typename T>
-		void getParam(const String& name, TMaterialDataParam<T, false>& output) const
+		void getParam(const String& name, TMaterialDataParam<T, Core>& output) const
 		{
 			throwIfNotInitialized();
 
@@ -504,104 +738,111 @@ namespace BansheeEngine
 			}
 
 			const String& gpuVarName = iterFind->second;
-			Vector<TGpuDataParam<T, false>> gpuParams;
+			Vector<TGpuDataParam<T, Core>> gpuParams;
 
 			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
 			{
-				PassParametersPtr params = *iter;
+				SPtr<TPassParameters<Core>> params = *iter;
 
 				for (UINT32 i = 0; i < params->getNumParams(); i++)
 				{
-					GpuParamsPtr& paramPtr = params->getParamByIdx(i);
+					GpuParamsType& paramPtr = params->getParamByIdx(i);
 					if (paramPtr)
 					{
 						if (paramPtr->hasParam(gpuVarName))
 						{
-							gpuParams.push_back(TGpuDataParam<T, false>());
+							gpuParams.push_back(TGpuDataParam<T, Core>());
 							paramPtr->getParam<T>(gpuVarName, gpuParams.back());
 						}
 					}
 				}
 			}
 
-			output = TMaterialDataParam<T, false>(gpuParams);
+			output = TMaterialDataParam<T, Core>(gpuParams);
 		}
 
-	private:
-		friend class MaterialManager;
-
-		ShaderPtr mShader;
-		TechniquePtr mBestTechnique;
-		INT32 mCoreDirtyFlags;
-
-		Set<String> mValidShareableParamBlocks;
-		Map<String, String> mValidParams; // Also maps Shader param name -> gpu variable name
-
-		Vector<PassParametersPtr> mParametersPerPass;
-		Vector<GpuParamBlockBufferPtr> mParamBuffers;
-
-		MaterialProxyPtr mActiveProxy;
-
-		Material();
+		/**
+		 * @brief	Initializes the material by using the best technique from the currently set shader. Shader
+		 * 			must contain the technique that matches the current renderer and render system.
+		 */
+		void initBestTechnique();
 
 		/**
 		 * @brief	Throw an exception if no shader is set, or no acceptable
 		 * 			technique was found.
 		 */
-		void throwIfNotInitialized() const;
+		void throwIfNotInitialized() const
+		{
+			if (mShader == nullptr)
+			{
+				BS_EXCEPT(InternalErrorException, "Material does not have shader set.");
+			}
 
-		/**
-		 * @brief	Marks the core data as dirty.
-		 */
-		void markCoreDirty() { mCoreDirtyFlags = 0xFFFFFFFF; }
+			if (mBestTechnique == nullptr)
+			{
+				BS_EXCEPT(InternalErrorException, "Shader does not contain a supported technique.");
+			}
+		}
 
-		/**
-		 * @brief	Retrieves a list of all shader GPU parameters, and the GPU program variable names they map to.
-		 */
-		const Map<String, String>& getValidParamNames() const { return mValidParams; }
+		Vector<SPtr<TPassParameters<Core>>> mParametersPerPass;
+		ShaderType mShader;
+		TechniqueType mBestTechnique;
+	};
 
-		/**
-		 * @brief	Initializes the material by using the best technique from the currently set shader. Shader
-		 * 			must contain the technique that matches the current renderer and render system.
-		 */
-		void initBestTechnique();
+	/**
+	 * @copydoc	MaterialBase
+	 */
+	class BS_CORE_EXPORT MaterialCore : public CoreObjectCore, public TMaterial<true>
+	{
+	public:
+		~MaterialCore() { }
 
-		/**
-		 * @brief	Constructs a map containing all data parameters (e.g. float, vector3, color).
-		 * 			Map contains parameter names and descriptions.
-		 */
-		Map<String, const GpuParamDataDesc*> determineValidDataParameters(const Vector<GpuParamDescPtr>& paramDescs) const;
+	private:
+		friend class Material;
+
+		MaterialCore() { }
+	};
+
+	/**
+	 * @copydoc	MaterialBase
+	 */
+	class BS_CORE_EXPORT Material : public Resource, public TMaterial<false>
+	{
+	public:
+		~Material();
 
 		/**
-		 * @brief	Constructs a list containing all object parameter (e.g. texture, sampler state) names.
+		 * @brief	Retrieves an implementation of a material usable only from the
+		 *			core thread.
 		 */
-		Vector<const GpuParamObjectDesc*> determineValidObjectParameters(const Vector<GpuParamDescPtr>& paramDescs) const;
+		SPtr<MaterialCore> getCore() const;
 
 		/**
-		 * @brief	Constructs a list containing all shareable parameter block names. Shareable blocks may be shared between
-		 * 			different GPU programs, passes or even materials. 
+		 * @brief	Creates a new empty material.
+		 * 			
+		 * @note	Make sure you call Material::setShader before using it.
 		 */
-		Set<String> determineValidShareableParamBlocks(const Vector<GpuParamDescPtr>& paramDescs) const;
+		static HMaterial create();
 
 		/**
-		 * @brief	Constructs a map that maps parameter names to a parameter block.
+		 * @brief	Creates a new material with the specified shader.
 		 */
-		Map<String, String> determineParameterToBlockMapping(const Vector<GpuParamDescPtr>& paramDescs);
+		static HMaterial create(ShaderPtr shader);
+
+	private:
+		friend class MaterialManager;
+
+		Material();
 
 		/**
-		 * @brief	Checks are the specified two parameters equal
-		 *
-		 * @param	paramA			   	The parameter a to compare.
-		 * @param	paramB			   	The parameter b to compare.
-		 * @param	ignoreBufferOffsets	(optional) If true, parameter offsets into the parameter buffer will be ignored
-		 * 								when comparing.
+		 * @copydoc	CoreObject::createCore
 		 */
-		bool areParamsEqual(const GpuParamDataDesc& paramA, const GpuParamDataDesc& paramB, bool ignoreBufferOffsets = false) const;
+		SPtr<CoreObjectCore> createCore() const;
 
 		/**
-		 * @brief	Frees all parameter block buffers.
+		 * @copydoc	CoreObject::markCoreDirty
 		 */
-		void freeParamBuffers();
+		void _markCoreDirty();
 
 		/************************************************************************/
 		/* 								RTTI		                     		*/

+ 111 - 43
BansheeCore/Include/BsMaterialParam.h

@@ -15,6 +15,10 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT TMaterialDataParam
 	{
 	public:
+		TMaterialDataParam(const Vector<TGpuDataParam<T, Core>>& params)
+			:mParams(params)
+		{ }
+
 		TMaterialDataParam() { }
 		
 		/**
@@ -37,12 +41,6 @@ namespace BansheeEngine
 			return mParams[0].get(arrayIdx); // They should all have the same value
 		}
 
-	private:
-		friend class Material;
-
-		TMaterialDataParam(const Vector<TGpuDataParam<T, Core>>& params)
-			:mParams(params)
-		{ }
 	protected:
 		Vector<TGpuDataParam<T, Core>> mParams;
 	};
@@ -66,110 +64,180 @@ namespace BansheeEngine
 	/**
 	 * @copydoc	TMaterialDataParam
 	 */
-	class BS_CORE_EXPORT MaterialParamStruct
+	template<bool Core>
+	class BS_CORE_EXPORT TMaterialParamStruct
 	{
 	public:
-		MaterialParamStruct() { }
+		TMaterialParamStruct(const Vector<TGpuParamStruct<Core>>& params)
+			:mParams(params)
+		{ }
+
+		TMaterialParamStruct() { }
 
 		/**
-		 * @copydoc	GpuParamStruct::set
+		 * @copydoc	TGpuParamStruct::set
 		 */
-		void set(const void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0);
+		void set(const void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0)
+		{
+			for (auto& param : mParams)
+				param.set(value, sizeBytes, arrayIdx);
+		}
 
 		/**
-		 * @copydoc	GpuParamStruct::get
+		 * @copydoc	TGpuParamStruct::get
 		 */
-		void get(void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0);
+		void get(void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0)
+		{
+			if (mParams.size() == 0)
+			{
+				value = nullptr;
+				return;
+			}
+
+			return mParams[0].get(value, sizeBytes, arrayIdx); // They should all have the same value
+		}
 
 		/**
-		 * @copydoc	GpuParamStruct::getElementSize
+		 * @copydoc	TGpuParamStruct::getElementSize
 		 */
-		UINT32 getElementSize() const;
+		UINT32 getElementSize() const
+		{
+			if (mParams.size() == 0)
+				return 0;
 
-	private:
-		friend class Material;
+			return mParams[0].getElementSize();
+		}
 
-		MaterialParamStruct(const Vector<GpuParamStruct>& params);
 	protected:
-		Vector<GpuParamStruct> mParams;
+		Vector<TGpuParamStruct<Core>> mParams;
 	};
 
+	typedef TMaterialParamStruct<false> MaterialParamStruct;
+	typedef TMaterialParamStruct<true> MaterialParamStructCore;
+
 	/**
 	 * @copydoc	TMaterialDataParam
 	 */
-	class BS_CORE_EXPORT MaterialParamTexture
+	template<bool Core>
+	class BS_CORE_EXPORT TMaterialParamTexture
 	{
 	public:
-		MaterialParamTexture() { }
+		typedef typename TGpuParamTextureType<Core>::Type TextureType;
+
+		TMaterialParamTexture(const Vector<TGpuParamTexture<Core>>& params)
+			:mParams(params)
+		{ }
+
+		TMaterialParamTexture() { }
 
 		/**
 		 * @copydoc	GpuParamTexture::set
 		 */
-		void set(const HTexture& texture);
+		void set(const TextureType& texture)
+		{
+			for (auto& param : mParams)
+				param.set(texture);
+		}
 
 		/**
 		 * @copydoc	GpuParamTexture::get
 		 */
-		HTexture get();
-
-	private:
-		friend class Material;
+		TextureType get()
+		{
+			if (mParams.size() == 0)
+				return TextureType();
 
-		MaterialParamTexture(const Vector<GpuParamTexture>& params);
+			return mParams[0].get(); // They should all have the same value
+		}
 
 	protected:
-		Vector<GpuParamTexture> mParams;
+		Vector<TGpuParamTexture<Core>> mParams;
 	};
 
+	typedef TMaterialParamTexture<false> MaterialParamTexture;
+	typedef TMaterialParamTexture<true> MaterialParamTextureCore;
+
 	/**
 	 * @copydoc	TMaterialDataParam
 	 */
-	class BS_CORE_EXPORT MaterialParamLoadStoreTexture
+	template<bool Core>
+	class BS_CORE_EXPORT TMaterialParamLoadStoreTexture
 	{
 	public:
-		MaterialParamLoadStoreTexture() { }
+		typedef typename TGpuParamTextureType<Core>::Type TextureType;
+
+		TMaterialParamLoadStoreTexture(const Vector<TGpuParamLoadStoreTexture<Core>>& params)
+			:mParams(params)
+		{ }
+
+		TMaterialParamLoadStoreTexture() { }
 
 		/**
 		 * @copydoc	GpuParamLoadStoreTexture::set
 		 */
-		void set(const HTexture& texture, const TextureSurface& surface);
+		void set(const TextureType& texture, const TextureSurface& surface)
+		{
+			for (auto& param : mParams)
+				param.set(texture, surface);
+		}
 
 		/**
 		 * @copydoc	GpuParamLoadStoreTexture::get
 		 */
-		HTexture get();
+		TextureType get()
+		{
+			if (mParams.size() == 0)
+				return TextureType();
 
-	private:
-		friend class Material;
+			return mParams[0].get(); // They should all have the same value
+		}
 
-		MaterialParamLoadStoreTexture(const Vector<GpuParamLoadStoreTexture>& params);
 	protected:
-		Vector<GpuParamLoadStoreTexture> mParams;
+		Vector<TGpuParamLoadStoreTexture<Core>> mParams;
 	};
 
+	typedef TMaterialParamLoadStoreTexture<false> MaterialParamLoadStoreTexture;
+	typedef TMaterialParamLoadStoreTexture<true> MaterialParamLoadStoreTextureCore;
+
 	/**
 	 * @copydoc	TMaterialDataParam
 	 */
-	class BS_CORE_EXPORT MaterialParamSampState
+	template<bool Core>
+	class BS_CORE_EXPORT TMaterialParamSampState
 	{
 	public:
-		MaterialParamSampState() { }
+		typedef typename TGpuParamSamplerStateType<Core>::Type SamplerType;
+
+		TMaterialParamSampState(const Vector<TGpuParamSampState<Core>>& params)
+			:mParams(params)
+		{ }
+
+		TMaterialParamSampState() { }
 
 		/**
 		 * @copydoc	GpuParamSampState::set
 		 */
-		void set(const HSamplerState& sampState);
+		void set(const SamplerType& sampState)
+		{
+			for (auto& param : mParams)
+				param.set(sampState);
+		}
 
 		/**
 		 * @copydoc	GpuParamSampState::get
 		 */
-		HSamplerState get();
+		SamplerType get()
+		{
+			if (mParams.size() == 0)
+				return SamplerType();
 
-	private:
-		friend class Material;
+			return mParams[0].get(); // They should all have the same value
+		}
 
-		MaterialParamSampState(const Vector<GpuParamSampState>& params);
 	protected:
-		Vector<GpuParamSampState> mParams;
+		Vector<TGpuParamSampState<Core>> mParams;
 	};
+
+	typedef TMaterialParamSampState<false> MaterialParamSampState;
+	typedef TMaterialParamSampState<true> MaterialParamSampStateCore;
 }

+ 0 - 61
BansheeCore/Include/BsMaterialProxy.h

@@ -1,61 +0,0 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Contains data about a single pass in a material used by the
-	 *			material proxy.
-	 */
-	struct BS_CORE_EXPORT MaterialProxyPass
-	{
-		HGpuProgram vertexProg;
-		HGpuProgram fragmentProg;
-		HGpuProgram geometryProg;
-		HGpuProgram hullProg;
-		HGpuProgram domainProg;
-		HGpuProgram computeProg;
-
-		UINT32 vertexProgParamsIdx;
-		UINT32 fragmentProgParamsIdx;
-		UINT32 geometryProgParamsIdx;
-		UINT32 hullProgParamsIdx;
-		UINT32 domainProgParamsIdx;
-		UINT32 computeProgParamsIdx;
-
-		HBlendState blendState;
-		HRasterizerState rasterizerState;
-		HDepthStencilState depthStencilState;
-		UINT32 stencilRefValue;
-	};
-
-	/**
-	 * @brief	Contains material information as seen by the core thread.
-	 *			(Used for rendering and such.)
-	 */
-	struct BS_CORE_EXPORT MaterialProxy
-	{
-		/**
-		 * @brief	Contains a hardware GPU parameter buffer and index of the parameters and the slot
-		 *			it binds to in a material proxy.
-		 */
-		struct BS_CORE_EXPORT BufferBindInfo
-		{
-			BufferBindInfo(UINT32 paramsIdx, UINT32 slotIdx, const SPtr<GpuParamBlockBufferCore>& buffer)
-				:paramsIdx(paramsIdx), slotIdx(slotIdx), buffer(buffer)
-			{ }
-
-			UINT32 paramsIdx;
-			UINT32 slotIdx;
-			SPtr<GpuParamBlockBufferCore> buffer;
-		};
-
-		Vector<MaterialProxyPass> passes;
-		Vector<SPtr<GpuParamsCore>> params;
-
-		SPtr<ShaderCore> shader;
-
-		Vector<BufferBindInfo> rendererBuffers;
-	};
-}

+ 1 - 1
BansheeCore/Include/BsRenderer.h

@@ -91,7 +91,7 @@ namespace BansheeEngine
 		 *
 		 * @note	Core thread only.
 		 */
-		static void setPass(const MaterialProxy& material, UINT32 passIdx);
+		static void setPass(const SPtr<MaterialCore>& material, UINT32 passIdx);
 
 		/**
 		 * @brief	Draws the specified mesh proxy with last set pass.

+ 8 - 19
BansheeCore/Include/BsShader.h

@@ -248,21 +248,6 @@ namespace BansheeEngine
 		String mName;
 	};
 
-	template<bool Core>
-	struct TTechniqueType {};
-
-	template<>
-	struct TTechniqueType<false>
-	{
-		typedef Technique Type;
-	};
-
-	template<>
-	struct TTechniqueType<true>
-	{
-		typedef TechniqueCore Type;
-	};
-
 	/**
 	 * @copydoc	ShaderBase
 	 *
@@ -273,7 +258,11 @@ namespace BansheeEngine
 	class TShader : public ShaderBase
 	{
 	public:
-		typedef typename TTechniqueType<Core>::Type TTechniqueType;
+		template<bool Core> struct TTechniqueType {};
+		template<> struct TTechniqueType < false > { typedef Technique Type; };
+		template<> struct TTechniqueType < true > { typedef TechniqueCore Type; };
+
+		typedef typename TTechniqueType<Core>::Type TechniqueType;
 
 		TShader(const String& name)
 			:ShaderBase(name)
@@ -303,7 +292,7 @@ namespace BansheeEngine
 		/**
 		 * @brief	Removes the specified technique.
 		 */
-		void removeTechnique(SPtr<TTechniqueType> technique)
+		void removeTechnique(SPtr<TechniqueType> technique)
 		{
 			auto iterFind = std::find(mTechniques.begin(), mTechniques.end(), technique);
 
@@ -323,7 +312,7 @@ namespace BansheeEngine
 		 * @brief	Gets the best supported technique based on current render and other systems.
 		 * 			Returns null if not a single technique is supported.
 		 */
-		SPtr<TTechniqueType> getBestTechnique() const
+		SPtr<TechniqueType> getBestTechnique() const
 		{
 			for (auto iter = mTechniques.begin(); iter != mTechniques.end(); ++iter)
 			{
@@ -339,7 +328,7 @@ namespace BansheeEngine
 		}
 
 	protected:
-		Vector<SPtr<TTechniqueType>> mTechniques;
+		Vector<SPtr<TechniqueType>> mTechniques;
 	};
 
 	/**

+ 5 - 17
BansheeCore/Include/BsTechnique.h

@@ -42,22 +42,6 @@ namespace BansheeEngine
 		String mRenderer;
 	};
 
-	template<bool Core>
-	struct TPassType
-	{ };
-
-	template<>
-	struct TPassType<false>
-	{
-		typedef Pass Type;
-	};
-
-	template<>
-	struct TPassType <true>
-	{
-		typedef PassCore Type;
-	};
-
 	/**
 	 * @copydoc	TechniqueBase
 	 *
@@ -65,9 +49,13 @@ namespace BansheeEngine
 	 *			both sim and core versions of Technique.
 	 */
 	template<bool Core>
-	class TTechnique : public TechniqueBase
+	class BS_CORE_EXPORT TTechnique : public TechniqueBase
 	{
 	public:
+		template<bool Core> struct TPassType { };
+		template<> struct TPassType < false > { typedef Pass Type; };
+		template<> struct TPassType < true > { typedef PassCore Type; };
+
 		typedef typename TPassType<Core>::Type PassType;
 		
 		TTechnique(const String& renderSystem, const String& renderer)

+ 10 - 5
BansheeCore/Source/BsGpuParamBlockBuffer.cpp

@@ -79,6 +79,11 @@ namespace BansheeEngine
 		write(0, data.getBuffer(), data.getBufferSize());
 	}
 
+	SPtr<GpuParamBlockBufferCore> GpuParamBlockBufferCore::create(UINT32 size, GpuParamBlockUsage usage)
+	{
+		return HardwareBufferCoreManager::instance().createGpuParamBlockBuffer(size, usage);
+	}
+
 	GpuParamBlockBuffer::GpuParamBlockBuffer(UINT32 size, GpuParamBlockUsage usage)
 		:mSize(size), mUsage(usage), mCachedData(nullptr)
 	{
@@ -156,6 +161,11 @@ namespace BansheeEngine
 		return CoreSyncData(buffer, mSize);
 	}
 
+	GpuParamBlockBufferPtr GpuParamBlockBuffer::create(UINT32 size, GpuParamBlockUsage usage)
+	{
+		return HardwareBufferManager::instance().createGpuParamBlockBuffer(size, usage);
+	}
+
 	GenericGpuParamBlockBufferCore::GenericGpuParamBlockBufferCore(UINT32 size, GpuParamBlockUsage usage)
 		:GpuParamBlockBufferCore(size, usage), mData(nullptr)
 	{ }
@@ -187,9 +197,4 @@ namespace BansheeEngine
 
 		GpuParamBlockBufferCore::initialize();
 	}
-
-	static GpuParamBlockBufferPtr create(UINT32 size, GpuParamBlockUsage usage)
-	{
-		return HardwareBufferManager::instance().createGpuParamBlockBuffer(size, usage);
-	}
 }

+ 284 - 571
BansheeCore/Source/BsMaterial.cpp

@@ -16,289 +16,54 @@
 
 namespace BansheeEngine
 {
-	Material::Material()
-		:Resource(false), mCoreDirtyFlags(0xFFFFFFFF)
-	{
-
-	}
-
-	Material::~Material()
-	{
-
-	}
-
-	void Material::setShader(ShaderPtr shader)
+	struct ShaderBlockDesc
 	{
-		mShader = shader;
+		String name;
+		GpuParamBlockUsage usage;
+		int size;
+		bool create;
+	};
 
-		initBestTechnique();
-	}
-
-	void Material::initBestTechnique()
+	bool areParamsEqual(const GpuParamDataDesc& paramA, const GpuParamDataDesc& paramB, bool ignoreBufferOffsets)
 	{
-		mBestTechnique = nullptr;
-		mParametersPerPass.clear();
-		freeParamBuffers();
-
-		if(mShader)
-		{
-			mBestTechnique = mShader->getBestTechnique();
-
-			if(mBestTechnique == nullptr)
-				return;
-
-			mValidShareableParamBlocks.clear();
-			mValidParams.clear();
-
-			Vector<GpuParamDescPtr> allParamDescs;
-
-			// Make sure all gpu programs are fully loaded
-			for(UINT32 i = 0; i < mBestTechnique->getNumPasses(); i++)
-			{
-				PassPtr curPass = mBestTechnique->getPass(i);
-
-				HGpuProgram vertProgram = curPass->getVertexProgram();
-				if(vertProgram)
-				{
-					vertProgram.synchronize();
-					allParamDescs.push_back(vertProgram->getParamDesc());
-				}
-
-				HGpuProgram fragProgram = curPass->getFragmentProgram();
-				if(fragProgram)
-				{
-					fragProgram.synchronize();
-					allParamDescs.push_back(fragProgram->getParamDesc());
-				}
-
-				HGpuProgram geomProgram = curPass->getGeometryProgram();
-				if(geomProgram)
-				{
-					geomProgram.synchronize();
-					allParamDescs.push_back(geomProgram->getParamDesc());
-				}
-
-				HGpuProgram hullProgram = curPass->getHullProgram();
-				if(hullProgram)
-				{
-					hullProgram.synchronize();
-					allParamDescs.push_back(hullProgram->getParamDesc());
-				}
-
-				HGpuProgram domainProgram = curPass->getDomainProgram();
-				if(domainProgram)
-				{
-					domainProgram.synchronize();
-					allParamDescs.push_back(domainProgram->getParamDesc());
-				}
-
-				HGpuProgram computeProgram = curPass->getComputeProgram();
-				if(computeProgram)
-				{
-					computeProgram.synchronize();
-					allParamDescs.push_back(computeProgram->getParamDesc());
-				}
-			}
-
-			// Fill out various helper structures
-			Map<String, const GpuParamDataDesc*> validDataParameters = determineValidDataParameters(allParamDescs);
-			Vector<const GpuParamObjectDesc*> validObjectParameters = determineValidObjectParameters(allParamDescs);
-
-			Set<String> validShareableParamBlocks = determineValidShareableParamBlocks(allParamDescs);
-			Map<String, String> paramToParamBlockMap = determineParameterToBlockMapping(allParamDescs);
-			Map<String, GpuParamBlockBufferPtr> paramBlockBuffers;
-
-			// Create param blocks
-			const Map<String, SHADER_PARAM_BLOCK_DESC>& shaderDesc = mShader->getParamBlocks();
-			for(auto iter = validShareableParamBlocks.begin(); iter != validShareableParamBlocks.end(); ++iter)
-			{
-				bool createBlockBuffer = true;
-				GpuParamBlockUsage usage = GPBU_STATIC;
-
-				auto iterFind = shaderDesc.find(*iter);
-				if(iterFind != shaderDesc.end())
-				{
-					createBlockBuffer = !iterFind->second.shared && iterFind->second.rendererSemantic == 0;
-					usage = iterFind->second.usage;
-				}
-
-				GpuParamBlockDesc blockDesc;
-				for(auto iter2 = allParamDescs.begin(); iter2 != allParamDescs.end(); ++iter2)
-				{
-					auto findParamBlockDesc = (*iter2)->paramBlocks.find(*iter);
-
-					if(findParamBlockDesc != (*iter2)->paramBlocks.end())
-					{
-						blockDesc = findParamBlockDesc->second;
-						break;
-					}
-				}
-
-				GpuParamBlockBufferPtr newParamBlockBuffer;
-				if(createBlockBuffer)
-				{
-					newParamBlockBuffer = HardwareBufferManager::instance().createGpuParamBlockBuffer(blockDesc.blockSize * sizeof(UINT32), usage);
-					mParamBuffers.push_back(newParamBlockBuffer);
-				}
-
-				paramBlockBuffers[*iter] = newParamBlockBuffer;
-				mValidShareableParamBlocks.insert(*iter);
-			}
-
-			// Create data param mappings
-			const Map<String, SHADER_DATA_PARAM_DESC>& dataParamDesc = mShader->getDataParams();
-			for(auto iter = dataParamDesc.begin(); iter != dataParamDesc.end(); ++iter)
-			{
-				auto findIter = validDataParameters.find(iter->second.gpuVariableName);
-
-				// Not valid so we skip it
-				if(findIter == validDataParameters.end())
-					continue;
-
-				if(findIter->second->type != iter->second.type)
-				{
-					LOGWRN("Ignoring shader parameter \"" + iter->first  +"\". Type doesn't match the one defined in the gpu program. "
-						+ "Shader defined type: " + toString(iter->second.type) + " - Gpu program defined type: " + toString(findIter->second->type));
-					continue;
-				}
-
-				if(findIter->second->arraySize != iter->second.arraySize)
-				{
-					LOGWRN("Ignoring shader parameter \"" + iter->first  +"\". Array size doesn't match the one defined in the gpu program."
-						+ "Shader defined array size: " + toString(iter->second.arraySize) + " - Gpu program defined array size: " + toString(findIter->second->arraySize));
-					continue;
-				}
-
-				auto findBlockIter = paramToParamBlockMap.find(iter->second.gpuVariableName);
-
-				if(findBlockIter == paramToParamBlockMap.end())
-					BS_EXCEPT(InternalErrorException, "Parameter doesn't exist in param to param block map but exists in valid param map.");
-
-				String& paramBlockName = findBlockIter->second;
-				mValidParams[iter->first] = iter->second.gpuVariableName;
-			}
-
-			// Create object param mappings
-			const Map<String, SHADER_OBJECT_PARAM_DESC>& objectParamDesc = mShader->getObjectParams();
-			for(auto iter = objectParamDesc.begin(); iter != objectParamDesc.end(); ++iter)
-			{
-				const Vector<String>& gpuVariableNames = iter->second.gpuVariableNames;
-				for (auto iter2 = gpuVariableNames.begin(); iter2 != gpuVariableNames.end(); ++iter2)
-				{
-					for (auto iter3 = validObjectParameters.begin(); iter3 != validObjectParameters.end(); ++iter3)
-					{
-						if ((*iter3)->name == (*iter2) && (*iter3)->type == iter->second.type)
-						{
-							mValidParams[iter->first] = *iter2;
-							break;
-						}
-					}
-				}
-			}
-
-			for(UINT32 i = 0; i < mBestTechnique->getNumPasses(); i++)
-			{
-				PassPtr curPass = mBestTechnique->getPass(i);
-				PassParametersPtr params = PassParametersPtr(new PassParameters());
-
-				HGpuProgram vertProgram = curPass->getVertexProgram();
-				if(vertProgram)
-					params->mVertParams = vertProgram->createParameters();
-
-				HGpuProgram fragProgram = curPass->getFragmentProgram();
-				if(fragProgram)
-					params->mFragParams = fragProgram->createParameters();
-
-				HGpuProgram geomProgram = curPass->getGeometryProgram();
-				if(geomProgram)
-					params->mGeomParams = geomProgram->createParameters();	
-
-				HGpuProgram hullProgram = curPass->getHullProgram();
-				if(hullProgram)
-					params->mHullParams = hullProgram->createParameters();
-
-				HGpuProgram domainProgram = curPass->getDomainProgram();
-				if(domainProgram)
-					params->mDomainParams = domainProgram->createParameters();
-
-				HGpuProgram 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)
-			{
-				PassParametersPtr params = *iter;
-
-				for(UINT32 i = 0; i < params->getNumParams(); i++)
-				{
-					GpuParamsPtr& paramPtr = params->getParamByIdx(i);
-					if(paramPtr)
-					{
-						// Assign shareable buffers
-						for(auto iterBlock = mValidShareableParamBlocks.begin(); iterBlock != mValidShareableParamBlocks.end(); ++iterBlock)
-						{
-							const String& paramBlockName = *iterBlock;
-							if(paramPtr->hasParamBlock(paramBlockName))
-							{
-								GpuParamBlockBufferPtr 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)
-							{
-								GpuParamBlockBufferPtr newParamBlockBuffer = HardwareBufferManager::instance().createGpuParamBlockBuffer(iterBlockDesc->second.blockSize * sizeof(UINT32));
-								mParamBuffers.push_back(newParamBlockBuffer);
+		bool equal = paramA.arraySize == paramB.arraySize && paramA.elementSize == paramB.elementSize
+			&& paramA.type == paramB.type && paramA.arrayElementStride == paramB.arrayElementStride;
 
-								paramPtr->setParamBlockBuffer(iterBlockDesc->first, newParamBlockBuffer);
-							}
-						}
-					}
-				}
-			}
-		}
+		if (!ignoreBufferOffsets)
+			equal &= paramA.cpuMemOffset == paramB.cpuMemOffset && paramA.gpuMemOffset == paramB.gpuMemOffset;
 
-		mCoreDirtyFlags = 0xFFFFFFFF;
+		return equal;
 	}
 
-	Map<String, const GpuParamDataDesc*> Material::determineValidDataParameters(const Vector<GpuParamDescPtr>& paramDescs) const
+	Map<String, const GpuParamDataDesc*> determineValidDataParameters(const Vector<GpuParamDescPtr>& paramDescs)
 	{
 		Map<String, const GpuParamDataDesc*> foundDataParams;
 		Map<String, bool> validParams;
 
-		for(auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
+		for (auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
 		{
 			const GpuParamDesc& curDesc = **iter;
 
 			// Check regular data params
-			for(auto iter2 = curDesc.params.begin(); iter2 != curDesc.params.end(); ++iter2)
+			for (auto iter2 = curDesc.params.begin(); iter2 != curDesc.params.end(); ++iter2)
 			{
 				bool isParameterValid = true;
 				const GpuParamDataDesc& curParam = iter2->second;
 
 				auto dataFindIter = validParams.find(iter2->first);
-				if(dataFindIter == validParams.end())
+				if (dataFindIter == validParams.end())
 				{
 					validParams[iter2->first] = true;
 					foundDataParams[iter2->first] = &curParam;
 				}
 				else
 				{
-					if(validParams[iter2->first])
+					if (validParams[iter2->first])
 					{
 						auto dataFindIter2 = foundDataParams.find(iter2->first);
 
 						const GpuParamDataDesc* otherParam = dataFindIter2->second;
-						if(!areParamsEqual(curParam, *otherParam, true))
+						if (!areParamsEqual(curParam, *otherParam, true))
 						{
 							validParams[iter2->first] = false;
 							foundDataParams.erase(dataFindIter2);
@@ -311,28 +76,28 @@ namespace BansheeEngine
 		return foundDataParams;
 	}
 
-	Vector<const GpuParamObjectDesc*> Material::determineValidObjectParameters(const Vector<GpuParamDescPtr>& paramDescs) const
+	Vector<const GpuParamObjectDesc*> determineValidObjectParameters(const Vector<GpuParamDescPtr>& paramDescs)
 	{
 		Vector<const GpuParamObjectDesc*> validParams;
 
-		for(auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
+		for (auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
 		{
 			const GpuParamDesc& curDesc = **iter;
 
 			// Check sampler params
-			for(auto iter2 = curDesc.samplers.begin(); iter2 != curDesc.samplers.end(); ++iter2)
+			for (auto iter2 = curDesc.samplers.begin(); iter2 != curDesc.samplers.end(); ++iter2)
 			{
 				validParams.push_back(&iter2->second);
 			}
 
 			// Check texture params
-			for(auto iter2 = curDesc.textures.begin(); iter2 != curDesc.textures.end(); ++iter2)
+			for (auto iter2 = curDesc.textures.begin(); iter2 != curDesc.textures.end(); ++iter2)
 			{
 				validParams.push_back(&iter2->second);
 			}
 
 			// Check buffer params
-			for(auto iter2 = curDesc.buffers.begin(); iter2 != curDesc.buffers.end(); ++iter2)
+			for (auto iter2 = curDesc.buffers.begin(); iter2 != curDesc.buffers.end(); ++iter2)
 			{
 				validParams.push_back(&iter2->second);
 			}
@@ -341,25 +106,25 @@ namespace BansheeEngine
 		return validParams;
 	}
 
-	Set<String> Material::determineValidShareableParamBlocks(const Vector<GpuParamDescPtr>& paramDescs) const
+	Set<String> determineValidShareableParamBlocks(const Vector<GpuParamDescPtr>& paramDescs)
 	{
 		// Make sure param blocks with the same name actually are the same
 		Map<String, std::pair<String, GpuParamDescPtr>> uniqueParamBlocks;
 		Map<String, bool> validParamBlocks;
 
-		for(auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
+		for (auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
 		{
 			const GpuParamDesc& curDesc = **iter;
-			for(auto blockIter = curDesc.paramBlocks.begin(); blockIter != curDesc.paramBlocks.end(); ++blockIter)
+			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
+				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())
+				if (iterFind == uniqueParamBlocks.end())
 				{
 					uniqueParamBlocks[blockIter->first] = std::make_pair(blockIter->first, *iter);
 					validParamBlocks[blockIter->first] = true;
@@ -369,17 +134,17 @@ namespace BansheeEngine
 				String otherBlockName = iterFind->second.first;
 				GpuParamDescPtr otherDesc = iterFind->second.second;
 
-				for(auto myParamIter = curDesc.params.begin(); myParamIter != curDesc.params.end(); ++myParamIter)
+				for (auto myParamIter = curDesc.params.begin(); myParamIter != curDesc.params.end(); ++myParamIter)
 				{
 					const GpuParamDataDesc& myParam = myParamIter->second;
 
-					if(myParam.paramBlockSlot != curBlock.slot)
+					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())
+					if (otherParamFind == otherDesc->params.end())
 					{
 						isBlockValid = false;
 						break;
@@ -387,16 +152,16 @@ namespace BansheeEngine
 
 					const GpuParamDataDesc& otherParam = otherParamFind->second;
 
-					if(!areParamsEqual(myParam, otherParam) || curBlock.name != otherBlockName)
+					if (!areParamsEqual(myParam, otherParam, false) || curBlock.name != otherBlockName)
 					{
 						isBlockValid = false;
 						break;
 					}
 				}
 
-				if(!isBlockValid)
+				if (!isBlockValid)
 				{
-					if(validParamBlocks[blockIter->first])
+					if (validParamBlocks[blockIter->first])
 					{
 						LOGWRN("Found two param blocks with the same name but different contents: " + blockIter->first);
 						validParamBlocks[blockIter->first] = false;
@@ -406,33 +171,33 @@ namespace BansheeEngine
 		}
 
 		Set<String> validParamBlocksReturn;
-		for(auto iter = validParamBlocks.begin(); iter != validParamBlocks.end(); ++iter)
+		for (auto iter = validParamBlocks.begin(); iter != validParamBlocks.end(); ++iter)
 		{
-			if(iter->second)
+			if (iter->second)
 				validParamBlocksReturn.insert(iter->first);
 		}
 
 		return validParamBlocksReturn;
 	}
 
-	Map<String, String> Material::determineParameterToBlockMapping(const Vector<GpuParamDescPtr>& paramDescs)
+	Map<String, String> determineParameterToBlockMapping(const Vector<GpuParamDescPtr>& paramDescs)
 	{
 		Map<String, String> paramToParamBlock;
 
-		for(auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
+		for (auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
 		{
 			const GpuParamDesc& curDesc = **iter;
-			for(auto iter2 = curDesc.params.begin(); iter2 != curDesc.params.end(); ++iter2)
+			for (auto iter2 = curDesc.params.begin(); iter2 != curDesc.params.end(); ++iter2)
 			{
 				const GpuParamDataDesc& curParam = iter2->second;
-				
+
 				auto iterFind = paramToParamBlock.find(curParam.name);
-				if(iterFind != paramToParamBlock.end())
+				if (iterFind != paramToParamBlock.end())
 					continue;
 
-				for(auto iterBlock = curDesc.paramBlocks.begin(); iterBlock != curDesc.paramBlocks.end(); ++iterBlock)
+				for (auto iterBlock = curDesc.paramBlocks.begin(); iterBlock != curDesc.paramBlocks.end(); ++iterBlock)
 				{
-					if(iterBlock->second.slot == curParam.paramBlockSlot)
+					if (iterBlock->second.slot == curParam.paramBlockSlot)
 					{
 						paramToParamBlock[curParam.name] = iterBlock->second.name;
 						break;
@@ -444,390 +209,338 @@ namespace BansheeEngine
 		return paramToParamBlock;
 	}
 
-	bool Material::areParamsEqual(const GpuParamDataDesc& paramA, const GpuParamDataDesc& paramB, bool ignoreBufferOffsets) const
+	Map<String, String> determineParamMappings(const Vector<GpuParamDescPtr>& paramDescs, const Map<String, SHADER_DATA_PARAM_DESC>& dataParams,
+		const Map<String, SHADER_OBJECT_PARAM_DESC>& objectParam)
 	{
-		bool equal = paramA.arraySize == paramB.arraySize && paramA.elementSize == paramB.elementSize 
-			&& paramA.type == paramB.type && paramA.arrayElementStride == paramB.arrayElementStride;
+		Map<String, String> validParams;
 
-		if(!ignoreBufferOffsets)
-			equal &= paramA.cpuMemOffset == paramB.cpuMemOffset && paramA.gpuMemOffset == paramB.gpuMemOffset;
+		Map<String, const GpuParamDataDesc*> validDataParameters = determineValidDataParameters(paramDescs);
+		Vector<const GpuParamObjectDesc*> validObjectParameters = determineValidObjectParameters(paramDescs);
+		Map<String, String> paramToParamBlockMap = determineParameterToBlockMapping(paramDescs);
 
-		return equal;
-	}
-
-	void Material::throwIfNotInitialized() const
-	{
-		if(mShader == nullptr)
+		// Create data param mappings
+		for (auto iter = dataParams.begin(); iter != dataParams.end(); ++iter)
 		{
-			BS_EXCEPT(InternalErrorException, "Material does not have shader set.");
-		}
+			auto findIter = validDataParameters.find(iter->second.gpuVariableName);
 
-		if(mBestTechnique == nullptr)
-		{
-			BS_EXCEPT(InternalErrorException, "Shader does not contain a supported technique.");
-		}
-	}
+			// Not valid so we skip it
+			if (findIter == validDataParameters.end())
+				continue;
 
-	void Material::setColor(const String& name, const Color& value, UINT32 arrayIdx)				
-	{ 
-		return getParamVec4(name).set(Vector4(value.r, value.g, value.b, value.a), arrayIdx); 
-	}
+			if (findIter->second->type != iter->second.type)
+			{
+				LOGWRN("Ignoring shader parameter \"" + iter->first + "\". Type doesn't match the one defined in the gpu program. "
+					+ "Shader defined type: " + toString(iter->second.type) + " - Gpu program defined type: " + toString(findIter->second->type));
+				continue;
+			}
 
-	void Material::setParamBlockBuffer(const String& name, const GpuParamBlockBufferPtr& paramBlockBuffer)
-	{
-		auto iterFind = mValidShareableParamBlocks.find(name);
-		if(iterFind == mValidShareableParamBlocks.end())
-		{
-			LOGWRN("Material doesn't have a parameter block named " + name);
-			return;
+			if (findIter->second->arraySize != iter->second.arraySize)
+			{
+				LOGWRN("Ignoring shader parameter \"" + iter->first + "\". Array size doesn't match the one defined in the gpu program."
+					+ "Shader defined array size: " + toString(iter->second.arraySize) + " - Gpu program defined array size: " + toString(findIter->second->arraySize));
+				continue;
+			}
+
+			auto findBlockIter = paramToParamBlockMap.find(iter->second.gpuVariableName);
+
+			if (findBlockIter == paramToParamBlockMap.end())
+				BS_EXCEPT(InternalErrorException, "Parameter doesn't exist in param to param block map but exists in valid param map.");
+
+			String& paramBlockName = findBlockIter->second;
+			validParams[iter->first] = iter->second.gpuVariableName;
 		}
 
-		for(auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+		// Create object param mappings
+		for (auto iter = objectParam.begin(); iter != objectParam.end(); ++iter)
 		{
-			PassParametersPtr params = *iter;
-
-			for(UINT32 i = 0; i < params->getNumParams(); i++)
+			const Vector<String>& gpuVariableNames = iter->second.gpuVariableNames;
+			for (auto iter2 = gpuVariableNames.begin(); iter2 != gpuVariableNames.end(); ++iter2)
 			{
-				GpuParamsPtr& paramPtr = params->getParamByIdx(i);
-				if(paramPtr)
+				for (auto iter3 = validObjectParameters.begin(); iter3 != validObjectParameters.end(); ++iter3)
 				{
-					if(paramPtr->hasParamBlock(name))
-						paramPtr->setParamBlockBuffer(name, paramBlockBuffer);
+					if ((*iter3)->name == (*iter2) && (*iter3)->type == iter->second.type)
+					{
+						validParams[iter->first] = *iter2;
+						break;
+					}
 				}
 			}
 		}
-	}
 
-	UINT32 Material::getNumPasses() const
-	{
-		throwIfNotInitialized();
-
-		return mShader->getBestTechnique()->getNumPasses();
+		return validParams;
 	}
 
-	PassPtr Material::getPass(UINT32 passIdx) const
+	Vector<ShaderBlockDesc> determineShaderBlockData(const Set<String>& paramBlocks, const Vector<GpuParamDescPtr>& paramDescs,
+		const Map<String, SHADER_PARAM_BLOCK_DESC>& shaderDesc)
 	{
-		if(passIdx < 0 || passIdx >= mShader->getBestTechnique()->getNumPasses())
-			BS_EXCEPT(InvalidParametersException, "Invalid pass index.");
+		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 == 0;
+				shaderBlockDesc.usage = iterFind->second.usage;
+			}
 
-		return mShader->getBestTechnique()->getPass(passIdx);
-	}
+			for (auto iter2 = paramDescs.begin(); iter2 != paramDescs.end(); ++iter2)
+			{
+				auto findParamBlockDesc = (*iter2)->paramBlocks.find(*iter);
 
-	PassParametersPtr Material::getPassParameters(UINT32 passIdx) const
-	{
-		if(passIdx < 0 || passIdx >= mParametersPerPass.size())
-			BS_EXCEPT(InvalidParametersException, "Invalid pass index.");
+				if (findParamBlockDesc != (*iter2)->paramBlocks.end())
+				{
+					shaderBlockDesc.size = findParamBlockDesc->second.blockSize * sizeof(UINT32);
+					break;
+				}
+			}
 
-		PassParametersPtr params = mParametersPerPass[passIdx];
+			output.push_back(shaderBlockDesc);
+		}
 
-		return params;
+		return output;
 	}
 
-	Material::StructData Material::getStructData(const String& name, UINT32 arrayIdx) const
+	Vector<GpuParamDescPtr> MaterialBase::getAllParamDescs(const SPtr<Technique>& technique)
 	{
-		MaterialParamStruct structParam = getParamStruct(name);
+		Vector<GpuParamDescPtr> allParamDescs;
 
-		StructData data(structParam.getElementSize());
-		structParam.get(data.data.get(), structParam.getElementSize(), arrayIdx);
+		// Make sure all gpu programs are fully loaded
+		for (UINT32 i = 0; i < technique->getNumPasses(); i++)
+		{
+			PassPtr curPass = technique->getPass(i);
 
-		return data;
-	}
+			HGpuProgram vertProgram = curPass->getVertexProgram();
+			if (vertProgram)
+			{
+				vertProgram.synchronize();
+				allParamDescs.push_back(vertProgram->getParamDesc());
+			}
 
-	MaterialParamFloat Material::getParamFloat(const String& name) const
-	{
-		TMaterialDataParam<float, false> gpuParam;
-		getParam(name, gpuParam);
+			HGpuProgram fragProgram = curPass->getFragmentProgram();
+			if (fragProgram)
+			{
+				fragProgram.synchronize();
+				allParamDescs.push_back(fragProgram->getParamDesc());
+			}
 
-		return gpuParam;
-	}
+			HGpuProgram geomProgram = curPass->getGeometryProgram();
+			if (geomProgram)
+			{
+				geomProgram.synchronize();
+				allParamDescs.push_back(geomProgram->getParamDesc());
+			}
 
-	MaterialParamColor Material::getParamColor(const String& name) const
-	{
-		TMaterialDataParam<Color, false> gpuParam;
-		getParam(name, gpuParam);
+			HGpuProgram hullProgram = curPass->getHullProgram();
+			if (hullProgram)
+			{
+				hullProgram.synchronize();
+				allParamDescs.push_back(hullProgram->getParamDesc());
+			}
 
-		return gpuParam;
-	}
+			HGpuProgram domainProgram = curPass->getDomainProgram();
+			if (domainProgram)
+			{
+				domainProgram.synchronize();
+				allParamDescs.push_back(domainProgram->getParamDesc());
+			}
 
-	MaterialParamVec2 Material::getParamVec2(const String& name) const
-	{
-		TMaterialDataParam<Vector2, false> gpuParam;
-		getParam(name, gpuParam);
+			HGpuProgram computeProgram = curPass->getComputeProgram();
+			if (computeProgram)
+			{
+				computeProgram.synchronize();
+				allParamDescs.push_back(computeProgram->getParamDesc());
+			}
+		}
 
-		return gpuParam;
+		return allParamDescs;
 	}
 
-	MaterialParamVec3 Material::getParamVec3(const String& name) const
+	Vector<GpuParamDescPtr> MaterialBase::getAllParamDescs(const SPtr<TechniqueCore>& technique)
 	{
-		TMaterialDataParam<Vector3, false> gpuParam;
-		getParam(name, gpuParam);
+		Vector<GpuParamDescPtr> allParamDescs;
 
-		return gpuParam;
-	}
+		// Make sure all gpu programs are fully loaded
+		for (UINT32 i = 0; i < technique->getNumPasses(); i++)
+		{
+			SPtr<PassCore> curPass = technique->getPass(i);
 
-	MaterialParamVec4 Material::getParamVec4(const String& name) const
-	{
-		TMaterialDataParam<Vector4, false> gpuParam;
-		getParam(name, gpuParam);
+			SPtr<GpuProgramCore> vertProgram = curPass->getVertexProgram();
+			if (vertProgram)
+				allParamDescs.push_back(vertProgram->getParamDesc());
 
-		return gpuParam;
-	}
+			SPtr<GpuProgramCore> fragProgram = curPass->getFragmentProgram();
+			if (fragProgram)
+				allParamDescs.push_back(fragProgram->getParamDesc());
 
-	MaterialParamMat3 Material::getParamMat3(const String& name) const
-	{
-		TMaterialDataParam<Matrix3, false> gpuParam;
-		getParam(name, gpuParam);
+			SPtr<GpuProgramCore> geomProgram = curPass->getGeometryProgram();
+			if (geomProgram)
+				allParamDescs.push_back(geomProgram->getParamDesc());
 
-		return gpuParam;
-	}
+			SPtr<GpuProgramCore> hullProgram = curPass->getHullProgram();
+			if (hullProgram)
+				allParamDescs.push_back(hullProgram->getParamDesc());
 
-	MaterialParamMat4 Material::getParamMat4(const String& name) const
-	{
-		TMaterialDataParam<Matrix4, false> gpuParam;
-		getParam(name, gpuParam);
+			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 gpuParam;
+		return allParamDescs;
 	}
 
-	MaterialParamStruct Material::getParamStruct(const String& name) const
+	template<bool Core>
+	void TMaterial<Core>::initBestTechnique()
 	{
-		throwIfNotInitialized();
-
-		auto iterFind = mValidParams.find(name);
-		if(iterFind == mValidParams.end())
-		{
-			LOGWRN("Material doesn't have a parameter named " + name);
-			return MaterialParamStruct();
-		}
-
-		const String& gpuVarName = iterFind->second;
-		Vector<GpuParamStruct> gpuParams;
+		mBestTechnique = nullptr;
+		mParametersPerPass.clear();
 
-		for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+		if (mShader)
 		{
-			PassParametersPtr params = *iter;
-
-			for (UINT32 i = 0; i < params->getNumParams(); i++)
-			{
-				GpuParamsPtr& paramPtr = params->getParamByIdx(i);
-				if (paramPtr)
-				{
-					if (paramPtr->hasParam(gpuVarName))
-					{
-						gpuParams.push_back(GpuParamStruct());
-						paramPtr->getStructParam(gpuVarName, gpuParams.back());
-					}
-				}
-			}
-		}
+			mBestTechnique = mShader->getBestTechnique();
 
-		return MaterialParamStruct(gpuParams);
-	}
+			if (mBestTechnique == nullptr)
+				return;
 
-	MaterialParamTexture Material::getParamTexture(const String& name) const
-	{
-		throwIfNotInitialized();
+			mValidShareableParamBlocks.clear();
+			Vector<GpuParamDescPtr> allParamDescs = getAllParamDescs(mBestTechnique);
 
-		auto iterFind = mValidParams.find(name);
-		if(iterFind == mValidParams.end())
-		{
-			LOGWRN("Material doesn't have a parameter named " + name);
-			return MaterialParamTexture();
-		}
+			mValidParams = determineParamMappings(allParamDescs, mShader->getDataParams(), mShader->getObjectParams());
 
-		const String& gpuVarName = iterFind->second;
-		Vector<GpuParamTexture> gpuParams;
+			// Fill out various helper structures
+			Set<String> validShareableParamBlocks = determineValidShareableParamBlocks(allParamDescs);
+			Vector<ShaderBlockDesc> paramBlockData = determineShaderBlockData(validShareableParamBlocks, allParamDescs, mShader->getParamBlocks());
 
-		for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-		{
-			PassParametersPtr params = *iter;
+			Map<String, ParamBlockPtrType> paramBlockBuffers;
 
-			for (UINT32 i = 0; i < params->getNumParams(); i++)
+			// Create param blocks
+			for (auto& paramBlock : paramBlockData)
 			{
-				GpuParamsPtr& paramPtr = params->getParamByIdx(i);
-				if (paramPtr)
+				ParamBlockPtrType newParamBlockBuffer;
+				if (paramBlock.create)
 				{
-					if (paramPtr->hasTexture(gpuVarName))
-					{
-						gpuParams.push_back(GpuParamTexture());
-						paramPtr->getTextureParam(gpuVarName, gpuParams.back());
-					}
+					newParamBlockBuffer = ParamBlockType::create(paramBlock.size, paramBlock.usage);
 				}
-			}
-		}
-
-		return MaterialParamTexture(gpuParams);
-	}
 
-	MaterialParamLoadStoreTexture Material::getParamLoadStoreTexture(const String& name) const
-	{
-		throwIfNotInitialized();
+				paramBlockBuffers[paramBlock.name] = newParamBlockBuffer;
+				mValidShareableParamBlocks.insert(paramBlock.name);
+			}
 
-		auto iterFind = mValidParams.find(name);
-		if (iterFind == mValidParams.end())
-		{
-			LOGWRN("Material doesn't have a parameter named " + name);
-			return MaterialParamLoadStoreTexture();
-		}
+			for (UINT32 i = 0; i < mBestTechnique->getNumPasses(); i++)
+			{
+				PassType curPass = mBestTechnique->getPass(i);
+				SPtr<TPassParameters<Core>> params = SPtr<TPassParameters<Core>>(new TPassParameters<Core>());
 
-		const String& gpuVarName = iterFind->second;
-		Vector<GpuParamLoadStoreTexture> gpuParams;
+				GpuProgramType vertProgram = curPass->getVertexProgram();
+				if (vertProgram)
+					params->mVertParams = vertProgram->createParameters();
 
-		for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-		{
-			PassParametersPtr params = *iter;
+				GpuProgramType fragProgram = curPass->getFragmentProgram();
+				if (fragProgram)
+					params->mFragParams = fragProgram->createParameters();
 
-			for (UINT32 i = 0; i < params->getNumParams(); i++)
-			{
-				GpuParamsPtr& paramPtr = params->getParamByIdx(i);
-				if (paramPtr)
-				{
-					if (paramPtr->hasTexture(gpuVarName))
-					{
-						gpuParams.push_back(GpuParamLoadStoreTexture());
-						paramPtr->getLoadStoreTextureParam(gpuVarName, gpuParams.back());
-					}
-				}
-			}
-		}
+				GpuProgramType geomProgram = curPass->getGeometryProgram();
+				if (geomProgram)
+					params->mGeomParams = geomProgram->createParameters();
 
-		return MaterialParamLoadStoreTexture(gpuParams);
-	}
+				GpuProgramType hullProgram = curPass->getHullProgram();
+				if (hullProgram)
+					params->mHullParams = hullProgram->createParameters();
 
-	MaterialParamSampState Material::getParamSamplerState(const String& name) const
-	{
-		throwIfNotInitialized();
+				GpuProgramType domainProgram = curPass->getDomainProgram();
+				if (domainProgram)
+					params->mDomainParams = domainProgram->createParameters();
 
-		auto iterFind = mValidParams.find(name);
-		if(iterFind == mValidParams.end())
-		{
-			LOGWRN("Material doesn't have a parameter named " + name);
-			return MaterialParamSampState();
-		}
+				GpuProgramType computeProgram = curPass->getComputeProgram();
+				if (computeProgram)
+					params->mComputeParams = computeProgram->createParameters();
 
-		const String& gpuVarName = iterFind->second;
-		Vector<GpuParamSampState> gpuParams;
-		for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-		{
-			PassParametersPtr params = *iter;
+				mParametersPerPass.push_back(params);
+			}
 
-			for (UINT32 i = 0; i < params->getNumParams(); i++)
+			// Assign param block buffers
+			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
 			{
-				GpuParamsPtr& paramPtr = params->getParamByIdx(i);
-				if (paramPtr)
+				SPtr<TPassParameters<Core>> params = *iter;
+
+				for (UINT32 i = 0; i < params->getNumParams(); i++)
 				{
-					if (paramPtr->hasSamplerState(gpuVarName))
+					GpuParamsType& paramPtr = params->getParamByIdx(i);
+					if (paramPtr)
 					{
-						gpuParams.push_back(GpuParamSampState());
-						paramPtr->getSamplerStateParam(gpuVarName, gpuParams.back());
+						// Assign shareable buffers
+						for (auto iterBlock = mValidShareableParamBlocks.begin(); iterBlock != mValidShareableParamBlocks.end(); ++iterBlock)
+						{
+							const String& paramBlockName = *iterBlock;
+							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);
+							}
+						}
 					}
 				}
 			}
 		}
-
-		return MaterialParamSampState(gpuParams);
 	}
 
-	bool Material::_isCoreDirty(MaterialDirtyFlag flag) const
-	{ 
-		return (mCoreDirtyFlags & (UINT32)flag) != 0;
-	}
+	template class TMaterial < false > ;
+	template class TMaterial < true > ;
 
-	void Material::_markCoreClean(MaterialDirtyFlag flag)
-	{ 
-		mCoreDirtyFlags &= ~(UINT32)flag;
-	}
-
-	MaterialProxyPtr Material::_createProxy()
+	Material::Material()
 	{
-		throwIfNotInitialized();
-
-		MaterialProxyPtr proxy = bs_shared_ptr<MaterialProxy>();
-
-		UINT32 numPasses = mShader->getBestTechnique()->getNumPasses();
-		for (UINT32 i = 0; i < numPasses; i++)
-		{
-			PassParametersPtr params = mParametersPerPass[i];
-			PassPtr pass = mShader->getBestTechnique()->getPass(i);
-
-			proxy->passes.push_back(MaterialProxyPass());
-			MaterialProxyPass& passData = proxy->passes.back();
-
-			if (pass->hasVertexProgram())
-			{
-				passData.vertexProg = pass->getVertexProgram();
-				passData.vertexProgParamsIdx = (UINT32)proxy->params.size();
-				proxy->params.push_back(params->mVertParams->getCore());
-			}
-			else
-				passData.vertexProgParamsIdx = 0;
-
-			if (pass->hasFragmentProgram())
-			{
-				passData.fragmentProg = pass->getFragmentProgram();
-				passData.fragmentProgParamsIdx = (UINT32)proxy->params.size();
-				proxy->params.push_back(params->mFragParams->getCore());
-			}
-			else
-				passData.fragmentProgParamsIdx = 0;
-
-			if (pass->hasGeometryProgram())
-			{
-				passData.geometryProg = pass->getGeometryProgram();
-				passData.geometryProgParamsIdx = (UINT32)proxy->params.size();
-				proxy->params.push_back(params->mGeomParams->getCore());
-			}
-			else
-				passData.geometryProgParamsIdx = 0;
-
-			if (pass->hasHullProgram())
-			{
-				passData.hullProg = pass->getHullProgram();
-				passData.hullProgParamsIdx = (UINT32)proxy->params.size();
-				proxy->params.push_back(params->mHullParams->getCore());
-			}
-			else
-				passData.hullProgParamsIdx = 0;
 
-			if (pass->hasDomainProgram())
-			{
-				passData.domainProg = pass->getDomainProgram();
-				passData.domainProgParamsIdx = (UINT32)proxy->params.size();
-				proxy->params.push_back(params->mDomainParams->getCore());
-			}
-			else
-				passData.domainProgParamsIdx = 0;
+	}
 
-			if (pass->hasComputeProgram())
-			{
-				passData.computeProg = pass->getComputeProgram();
-				passData.computeProgParamsIdx = (UINT32)proxy->params.size();
-				proxy->params.push_back(params->mComputeParams->getCore());
-			}
-			else
-				passData.computeProgParamsIdx = 0;
+	Material::~Material()
+	{
 
-			passData.blendState = pass->getBlendState();
-			passData.rasterizerState = pass->getRasterizerState();
-			passData.depthStencilState = pass->getDepthStencilState();
-			passData.stencilRefValue = pass->getStencilRefValue();
-		}
+	}
 
-		proxy->shader = mShader->getCore();
+	void Material::_markCoreDirty()
+	{
+		markCoreDirty();
+	}
 
-		return proxy;
+	SPtr<MaterialCore> Material::getCore() const
+	{
+		return std::static_pointer_cast<MaterialCore>(mCoreSpecific);
 	}
 
-	void Material::destroy_internal()
+	SPtr<CoreObjectCore> Material::createCore() const
 	{
-		freeParamBuffers();
+		MaterialCore* material = new (bs_alloc<MaterialCore>()) MaterialCore();
+		SPtr<MaterialCore> materialPtr = bs_shared_ptr<MaterialCore, GenAlloc>(material);
+		materialPtr->_setThisPtr(materialPtr);
 
-		Resource::destroy_internal();
+		return materialPtr;
 	}
 
-	void Material::freeParamBuffers()
+	void Material::_markCoreDirty()
 	{
-		mParamBuffers.clear();
+		markCoreDirty();
 	}
 
 	HMaterial Material::create()

+ 0 - 81
BansheeCore/Source/BsMaterialParam.cpp

@@ -2,86 +2,5 @@
 
 namespace BansheeEngine
 {
-	void MaterialParamStruct::set(const void* value, UINT32 sizeBytes, UINT32 arrayIdx)
-	{
-		for (auto& param : mParams)
-			param.set(value, sizeBytes, arrayIdx);
-	}
 
-	void MaterialParamStruct::get(void* value, UINT32 sizeBytes, UINT32 arrayIdx)
-	{
-		if (mParams.size() == 0)
-		{
-			value = nullptr;
-			return;
-		}
-
-		return mParams[0].get(value, sizeBytes, arrayIdx); // They should all have the same value
-	}
-
-	UINT32 MaterialParamStruct::getElementSize() const
-	{
-		if (mParams.size() == 0)
-			return 0;
-
-		return mParams[0].getElementSize();
-	}
-
-	MaterialParamStruct::MaterialParamStruct(const Vector<GpuParamStruct>& params)
-		:mParams(params)
-	{ }
-
-	void MaterialParamTexture::set(const HTexture& texture)
-	{
-		for (auto& param : mParams)
-			param.set(texture);
-	}
-
-	HTexture MaterialParamTexture::get()
-	{
-		if (mParams.size() == 0)
-			return HTexture();
-
-		return mParams[0].get(); // They should all have the same value
-	}
-
-	MaterialParamTexture::MaterialParamTexture(const Vector<GpuParamTexture>& params)
-		:mParams(params)
-	{ }
-
-	void MaterialParamLoadStoreTexture::set(const HTexture& texture, const TextureSurface& surface)
-	{
-		for (auto& param : mParams)
-			param.set(texture, surface);
-	}
-
-	HTexture MaterialParamLoadStoreTexture::get()
-	{
-		if (mParams.size() == 0)
-			return HTexture();
-
-		return mParams[0].get(); // They should all have the same value
-	}
-
-	MaterialParamLoadStoreTexture::MaterialParamLoadStoreTexture(const Vector<GpuParamLoadStoreTexture>& params)
-		:mParams(params)
-	{ }
-
-	void MaterialParamSampState::set(const HSamplerState& sampState)
-	{
-		for (auto& param : mParams)
-			param.set(sampState);
-	}
-
-	HSamplerState MaterialParamSampState::get()
-	{
-		if (mParams.size() == 0)
-			return HSamplerState();
-
-		return mParams[0].get(); // They should all have the same value
-	}
-
-	MaterialParamSampState::MaterialParamSampState(const Vector<GpuParamSampState>& params)
-		:mParams(params)
-	{ }
 }

+ 0 - 6
BansheeCore/Source/BsMaterialProxy.cpp

@@ -1,6 +0,0 @@
-#include "BsMaterialProxy.h"
-
-namespace BansheeEngine
-{
-
-}

+ 31 - 28
BansheeCore/Source/BsRenderer.cpp

@@ -1,65 +1,68 @@
 #include "BsRenderer.h"
 #include "BsCoreThread.h"
 #include "BsRenderSystem.h"
-#include "BsMaterialProxy.h"
 #include "BsMesh.h"
+#include "BsMaterial.h"
+#include "BsPass.h"
 #include "BsBlendState.h"
 #include "BsDepthStencilState.h"
 #include "BsRasterizerState.h"
 
 namespace BansheeEngine
 {
-	void Renderer::setPass(const MaterialProxy& material, UINT32 passIdx)
+	void Renderer::setPass(const SPtr<MaterialCore>& material, UINT32 passIdx)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
 		RenderSystem& rs = RenderSystem::instance();
 
-		const MaterialProxyPass& pass = material.passes[passIdx];
-		if (pass.vertexProg && pass.vertexProg.isLoaded())
+		SPtr<PassCore> pass = material->getPass(passIdx);
+		SPtr<PassParametersCore> passParams = material->getPassParameters(passIdx);
+
+		if (pass->hasVertexProgram())
 		{
-			rs.bindGpuProgram(pass.vertexProg->getCore());
-			rs.bindGpuParams(GPT_VERTEX_PROGRAM, material.params[pass.vertexProgParamsIdx]);
+			rs.bindGpuProgram(pass->getVertexProgram());
+			rs.bindGpuParams(GPT_VERTEX_PROGRAM, passParams->mVertParams);
 		}
 		else
 			rs.unbindGpuProgram(GPT_VERTEX_PROGRAM);
 
-		if (pass.fragmentProg && pass.fragmentProg.isLoaded())
+		if (pass->hasFragmentProgram())
 		{
-			rs.bindGpuProgram(pass.fragmentProg->getCore());
-			rs.bindGpuParams(GPT_FRAGMENT_PROGRAM, material.params[pass.fragmentProgParamsIdx]);
+			rs.bindGpuProgram(pass->getFragmentProgram());
+			rs.bindGpuParams(GPT_FRAGMENT_PROGRAM, passParams->mFragParams);
 		}
 		else
 			rs.unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
 
-		if (pass.geometryProg && pass.geometryProg.isLoaded())
+		if (pass->hasGeometryProgram())
 		{
-			rs.bindGpuProgram(pass.geometryProg->getCore());
-			rs.bindGpuParams(GPT_GEOMETRY_PROGRAM, material.params[pass.geometryProgParamsIdx]);
+			rs.bindGpuProgram(pass->getGeometryProgram());
+			rs.bindGpuParams(GPT_GEOMETRY_PROGRAM, passParams->mGeomParams);
 		}
 		else
 			rs.unbindGpuProgram(GPT_GEOMETRY_PROGRAM);
 
-		if (pass.hullProg && pass.hullProg.isLoaded())
+		if (pass->hasHullProgram())
 		{
-			rs.bindGpuProgram(pass.hullProg->getCore());
-			rs.bindGpuParams(GPT_HULL_PROGRAM, material.params[pass.hullProgParamsIdx]);
+			rs.bindGpuProgram(pass->getHullProgram());
+			rs.bindGpuParams(GPT_HULL_PROGRAM, passParams->mHullParams);
 		}
 		else
 			rs.unbindGpuProgram(GPT_HULL_PROGRAM);
 
-		if (pass.domainProg && pass.domainProg.isLoaded())
+		if (pass->hasDomainProgram())
 		{
-			rs.bindGpuProgram(pass.domainProg->getCore());
-			rs.bindGpuParams(GPT_DOMAIN_PROGRAM, material.params[pass.domainProgParamsIdx]);
+			rs.bindGpuProgram(pass->getDomainProgram());
+			rs.bindGpuParams(GPT_DOMAIN_PROGRAM, passParams->mDomainParams);
 		}
 		else
 			rs.unbindGpuProgram(GPT_DOMAIN_PROGRAM);
 
-		if (pass.computeProg && pass.computeProg.isLoaded())
+		if (pass->hasComputeProgram())
 		{
-			rs.bindGpuProgram(pass.computeProg->getCore());
-			rs.bindGpuParams(GPT_COMPUTE_PROGRAM, material.params[pass.computeProgParamsIdx]);
+			rs.bindGpuProgram(pass->getComputeProgram());
+			rs.bindGpuParams(GPT_COMPUTE_PROGRAM, passParams->mComputeParams);
 		}
 		else
 			rs.unbindGpuProgram(GPT_COMPUTE_PROGRAM);
@@ -67,18 +70,18 @@ namespace BansheeEngine
 		// TODO - Try to limit amount of state changes, if previous state is already the same
 
 		// Set up non-texture related pass settings
-		if (pass.blendState != nullptr)
-			rs.setBlendState(pass.blendState->getCore());
+		if (pass->getBlendState() != nullptr)
+			rs.setBlendState(pass->getBlendState());
 		else
 			rs.setBlendState(BlendState::getDefault()->getCore());
 
-		if (pass.depthStencilState != nullptr)
-			rs.setDepthStencilState(pass.depthStencilState->getCore(), pass.stencilRefValue);
+		if (pass->getDepthStencilState() != nullptr)
+			rs.setDepthStencilState(pass->getDepthStencilState(), pass->getStencilRefValue());
 		else
-			rs.setDepthStencilState(DepthStencilState::getDefault()->getCore(), pass.stencilRefValue);
+			rs.setDepthStencilState(DepthStencilState::getDefault()->getCore(), pass->getStencilRefValue());
 
-		if (pass.rasterizerState != nullptr)
-			rs.setRasterizerState(pass.rasterizerState->getCore());
+		if (pass->getRasterizerState() != nullptr)
+			rs.setRasterizerState(pass->getRasterizerState());
 		else
 			rs.setRasterizerState(RasterizerState::getDefault()->getCore());
 	}

+ 3 - 0
BansheeCore/Source/BsTechnique.cpp

@@ -33,6 +33,9 @@ namespace BansheeEngine
 			BS_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx));
 	}
 
+	template class TTechnique < false > ;
+	template class TTechnique < true >;
+
 	TechniqueCore::TechniqueCore(const String& renderSystem, const String& renderer)
 		:TTechnique(renderSystem, renderer)
 	{ }

+ 10 - 10
BansheeEditor/Include/BsGizmoManager.h

@@ -97,11 +97,11 @@ namespace BansheeEngine
 
 		struct CoreInitData
 		{
-			MaterialProxyPtr solidMatProxy;
-			MaterialProxyPtr wireMatProxy;
-			MaterialProxyPtr iconMatProxy;
-			MaterialProxyPtr pickingMatProxy;
-			MaterialProxyPtr alphaPickingMatProxy;
+			SPtr<MaterialCore> solidMat;
+			SPtr<MaterialCore> wireMat;
+			SPtr<MaterialCore> iconMat;
+			SPtr<MaterialCore> pickingMat;
+			SPtr<MaterialCore> alphaPickingMat;
 		};
 
 		typedef Vector<IconRenderData> IconRenderDataVec;
@@ -170,19 +170,19 @@ namespace BansheeEngine
 
 		struct SolidMaterialData
 		{
-			MaterialProxyPtr proxy;
+			SPtr<MaterialCore> mat;
 			GpuParamMat4Core mViewProj;
 		};
 
 		struct WireMaterialData
 		{
-			MaterialProxyPtr proxy;
+			SPtr<MaterialCore> mat;
 			GpuParamMat4Core mViewProj;
 		};
 
 		struct IconMaterialData
 		{
-			MaterialProxyPtr proxy;
+			SPtr<MaterialCore> mat;
 			SPtr<GpuParamsCore> mFragParams[2];
 			GpuParamMat4Core mViewProj[2];
 			GpuParamTextureCore mTexture[2];
@@ -190,13 +190,13 @@ namespace BansheeEngine
 
 		struct PickingMaterialData
 		{
-			MaterialProxyPtr proxy;
+			SPtr<MaterialCore> mat;
 			GpuParamMat4Core mViewProj;
 		};
 
 		struct AlphaPickingMaterialData
 		{
-			MaterialProxyPtr proxy;
+			SPtr<MaterialCore> mat;
 			SPtr<GpuParamsCore> mFragParams;
 			GpuParamMat4Core mViewProj;
 			GpuParamTextureCore mTexture;

+ 4 - 4
BansheeEditor/Include/BsHandleDrawManager.h

@@ -33,7 +33,7 @@ namespace BansheeEngine
 	private:
 		friend class HandleDrawManagerCore;
 
-		void initializeCore(const MaterialProxyPtr& wireMatProxy, const MaterialProxyPtr& solidMatProxy);
+		void initializeCore(const SPtr<MaterialCore>& wireMat, const SPtr<MaterialCore>& solidMat);
 		void destroyCore(HandleDrawManagerCore* core);
 
 		static const UINT32 SPHERE_QUALITY;
@@ -49,13 +49,13 @@ namespace BansheeEngine
 	{
 		struct SolidMaterialData
 		{
-			MaterialProxyPtr proxy;
+			SPtr<MaterialCore> mat;
 			GpuParamMat4Core mViewProj;
 		};
 
 		struct WireMaterialData
 		{
-			MaterialProxyPtr proxy;
+			SPtr<MaterialCore> mat;
 			GpuParamMat4Core mViewProj;
 		};
 
@@ -82,7 +82,7 @@ namespace BansheeEngine
 	private:
 		friend class HandleDrawManager;
 
-		void initialize(const MaterialProxyPtr& wireMatProxy, const MaterialProxyPtr& solidMatProxy);
+		void initialize(const SPtr<MaterialCore>& wireMat, const SPtr<MaterialCore>& solidMat);
 
 		void updateData(const RenderTargetPtr& rt, const Vector<MeshData>& meshes);
 		void render(const CameraHandlerCore& camera);

+ 2 - 2
BansheeEditor/Include/BsScenePicking.h

@@ -26,8 +26,8 @@ namespace BansheeEngine
 			HMaterial mMatPickingAlpha;
 
 			// Core thread
-			MaterialProxyPtr mMatPickingProxy;
-			MaterialProxyPtr mMatPickingAlphaProxy;
+			SPtr<MaterialCore> mMatPickingCore;
+			SPtr<MaterialCore> mMatPickingAlphaCore;
 
 			SPtr<GpuParamsCore> mParamPickingVertParams;
 			SPtr<GpuParamsCore> mParamPickingFragParams;

+ 33 - 30
BansheeEditor/Source/BsGizmoManager.cpp

@@ -53,11 +53,11 @@ namespace BansheeEngine
 
 		CoreInitData initData;
 
-		initData.solidMatProxy = solidMaterial->_createProxy();
-		initData.wireMatProxy = wireMaterial->_createProxy();
-		initData.iconMatProxy = iconMaterial->_createProxy();
-		initData.pickingMatProxy = pickingMaterial->_createProxy();
-		initData.alphaPickingMatProxy = alphaPickingMaterial->_createProxy();
+		initData.solidMat = solidMaterial->getCore();
+		initData.wireMat = wireMaterial->getCore();
+		initData.iconMat = iconMaterial->getCore();
+		initData.pickingMat = pickingMaterial->getCore();
+		initData.alphaPickingMat = alphaPickingMaterial->getCore();
 
 		mCore = bs_new<GizmoManagerCore>(GizmoManagerCore::PrivatelyConstuct());
 
@@ -640,56 +640,59 @@ namespace BansheeEngine
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		mSolidMaterial.proxy = initData.solidMatProxy;
-		mWireMaterial.proxy = initData.wireMatProxy;
-		mIconMaterial.proxy = initData.iconMatProxy;
-		mPickingMaterial.proxy = initData.pickingMatProxy;
-		mAlphaPickingMaterial.proxy = initData.alphaPickingMatProxy;
+		mSolidMaterial.mat = initData.solidMat;
+		mWireMaterial.mat = initData.wireMat;
+		mIconMaterial.mat = initData.iconMat;
+		mPickingMaterial.mat = initData.pickingMat;
+		mAlphaPickingMaterial.mat = initData.alphaPickingMat;
 
-		// TODO - Make a better interface when dealing with parameters through proxies?
 		{
-			MaterialProxyPtr proxy = mWireMaterial.proxy;
-			SPtr<GpuParamsCore> vertParams = proxy->params[proxy->passes[0].vertexProgParamsIdx];
+			SPtr<MaterialCore> mat = mWireMaterial.mat;
+			SPtr<GpuParamsCore> vertParams = mat->getPassParameters(0)->mVertParams;
 
 			vertParams->getParam("matViewProj", mWireMaterial.mViewProj);
 		}
 
 		{
-			MaterialProxyPtr proxy = mSolidMaterial.proxy;
-			SPtr<GpuParamsCore> vertParams = proxy->params[proxy->passes[0].vertexProgParamsIdx];
+			SPtr<MaterialCore> mat = mSolidMaterial.mat;
+			SPtr<GpuParamsCore> vertParams = mat->getPassParameters(0)->mVertParams;
 
 			vertParams->getParam("matViewProj", mSolidMaterial.mViewProj);
 		}
 
 		{
-			MaterialProxyPtr proxy = mIconMaterial.proxy;
-			SPtr<GpuParamsCore> vertParams0 = proxy->params[proxy->passes[0].vertexProgParamsIdx];
-			SPtr<GpuParamsCore> vertParams1 = proxy->params[proxy->passes[1].vertexProgParamsIdx];
+			SPtr<MaterialCore> mat = mIconMaterial.mat;
+			SPtr<PassParametersCore> pass0Params = mat->getPassParameters(0);
+			SPtr<PassParametersCore> pass1Params = mat->getPassParameters(1);
+
+			SPtr<GpuParamsCore> vertParams0 = pass0Params->mVertParams;
+			SPtr<GpuParamsCore> vertParams1 = pass1Params->mVertParams;
 
 			vertParams0->getParam("matViewProj", mIconMaterial.mViewProj[0]);
 			vertParams1->getParam("matViewProj", mIconMaterial.mViewProj[1]);
 
-			mIconMaterial.mFragParams[0] = proxy->params[proxy->passes[0].fragmentProgParamsIdx];
-			mIconMaterial.mFragParams[1] = proxy->params[proxy->passes[1].fragmentProgParamsIdx];
+			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]);
 		}
 
 		{
-			MaterialProxyPtr proxy = mPickingMaterial.proxy;
-			SPtr<GpuParamsCore> vertParams = proxy->params[proxy->passes[0].vertexProgParamsIdx];
+			SPtr<MaterialCore> mat = mPickingMaterial.mat;
+			SPtr<GpuParamsCore> vertParams = mat->getPassParameters(0)->mVertParams;
 
 			vertParams->getParam("matViewProj", mPickingMaterial.mViewProj);
 		}
 
 		{
-			MaterialProxyPtr proxy = mAlphaPickingMaterial.proxy;
-			SPtr<GpuParamsCore> vertParams = proxy->params[proxy->passes[0].vertexProgParamsIdx];
+			SPtr<MaterialCore> mat = mAlphaPickingMaterial.mat;
+			SPtr<PassParametersCore> passParams = mat->getPassParameters(0);
+			SPtr<GpuParamsCore> vertParams = passParams->mVertParams;
 
 			vertParams->getParam("matViewProj", mAlphaPickingMaterial.mViewProj);
 
-			mAlphaPickingMaterial.mFragParams = proxy->params[proxy->passes[0].fragmentProgParamsIdx];
+			mAlphaPickingMaterial.mFragParams = passParams->mFragParams;
 			mAlphaPickingMaterial.mFragParams->getTextureParam("mainTexture", mAlphaPickingMaterial.mTexture);
 
 			GpuParamFloatCore alphaCutoffParam;
@@ -749,15 +752,15 @@ namespace BansheeEngine
 		{
 		case GizmoManager::GizmoMaterial::Solid:
 			mSolidMaterial.mViewProj.set(viewProjMat);
-			Renderer::setPass(*mSolidMaterial.proxy, 0);
+			Renderer::setPass(mSolidMaterial.mat, 0);
 			break;
 		case GizmoManager::GizmoMaterial::Wire:
 			mWireMaterial.mViewProj.set(viewProjMat);
-			Renderer::setPass(*mWireMaterial.proxy, 0);
+			Renderer::setPass(mWireMaterial.mat, 0);
 			break;
 		case GizmoManager::GizmoMaterial::Picking:
 			mPickingMaterial.mViewProj.set(viewProjMat);
-			Renderer::setPass(*mPickingMaterial.proxy, 0);
+			Renderer::setPass(mPickingMaterial.mat, 0);
 			break;
 		}
 		
@@ -805,7 +808,7 @@ namespace BansheeEngine
 
 			for (UINT32 passIdx = 0; passIdx < 2; passIdx++)
 			{
-				Renderer::setPass(*mIconMaterial.proxy, passIdx);
+				Renderer::setPass(mIconMaterial.mat, passIdx);
 
 				UINT32 curIndexOffset = mesh->getIndexOffset();
 				for (auto curRenderData : *renderData)
@@ -822,7 +825,7 @@ namespace BansheeEngine
 		{
 			mAlphaPickingMaterial.mViewProj.set(projMat);
 
-			Renderer::setPass(*mAlphaPickingMaterial.proxy, 0);
+			Renderer::setPass(mAlphaPickingMaterial.mat, 0);
 
 			UINT32 curIndexOffset = 0;
 			for (auto curRenderData : *renderData)

+ 13 - 13
BansheeEditor/Source/BsHandleDrawManager.cpp

@@ -26,8 +26,8 @@ namespace BansheeEngine
 		HMaterial solidMaterial = BuiltinEditorResources::instance().createSolidHandleMat();
 		HMaterial wireMaterial = BuiltinEditorResources::instance().createWireHandleMat();
 
-		MaterialProxyPtr solidMaterialProxy = solidMaterial->_createProxy();
-		MaterialProxyPtr wireMaterialProxy = wireMaterial->_createProxy();
+		SPtr<MaterialCore> solidMaterialProxy = solidMaterial->getCore();
+		SPtr<MaterialCore> wireMaterialProxy = wireMaterial->getCore();
 
 		mCore = bs_new<HandleDrawManagerCore>(HandleDrawManagerCore::PrivatelyConstruct());
 
@@ -41,11 +41,11 @@ namespace BansheeEngine
 		gCoreAccessor().queueCommand(std::bind(&HandleDrawManager::destroyCore, this, mCore));
 	}
 
-	void HandleDrawManager::initializeCore(const MaterialProxyPtr& wireMatProxy, const MaterialProxyPtr& solidMatProxy)
+	void HandleDrawManager::initializeCore(const SPtr<MaterialCore>& wireMat, const SPtr<MaterialCore>& solidMat)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		mCore->initialize(wireMatProxy, solidMatProxy);
+		mCore->initialize(wireMat, solidMat);
 	}
 
 	void HandleDrawManager::destroyCore(HandleDrawManagerCore* core)
@@ -183,19 +183,19 @@ namespace BansheeEngine
 		mDrawHelper->clear();
 	}
 
-	void HandleDrawManagerCore::initialize(const MaterialProxyPtr& wireMatProxy, const MaterialProxyPtr& solidMatProxy)
+	void HandleDrawManagerCore::initialize(const SPtr<MaterialCore>& wireMat, const SPtr<MaterialCore>& solidMat)
 	{
 		// TODO - Make a better interface when dealing with parameters through proxies?
 		{
-			mWireMaterial.proxy = wireMatProxy;
-			SPtr<GpuParamsCore> vertParams = wireMatProxy->params[wireMatProxy->passes[0].vertexProgParamsIdx];
+			mWireMaterial.mat = wireMat;
+			SPtr<GpuParamsCore> vertParams = wireMat->getPassParameters(0)->mVertParams;
 
 			vertParams->getParam("matViewProj", mWireMaterial.mViewProj);
 		}
 
 		{
-			mSolidMaterial.proxy = solidMatProxy;
-			SPtr<GpuParamsCore> vertParams = solidMatProxy->params[solidMatProxy->passes[0].vertexProgParamsIdx];
+			mSolidMaterial.mat = solidMat;
+			SPtr<GpuParamsCore> vertParams = solidMat->getPassParameters(0)->mVertParams;
 
 			vertParams->getParam("matViewProj", mSolidMaterial.mViewProj);
 		}
@@ -239,9 +239,9 @@ namespace BansheeEngine
 			currentType = mMeshes[0].type;
 
 			if (currentType == MeshType::Solid)
-				Renderer::setPass(*mSolidMaterial.proxy, 0);
+				Renderer::setPass(mSolidMaterial.mat, 0);
 			else
-				Renderer::setPass(*mWireMaterial.proxy, 0);
+				Renderer::setPass(mWireMaterial.mat, 0);
 		}
 
 		for (auto& meshData : mMeshes)
@@ -249,9 +249,9 @@ namespace BansheeEngine
 			if (currentType != meshData.type)
 			{
 				if (meshData.type == MeshType::Solid)
-					Renderer::setPass(*mSolidMaterial.proxy, 0);
+					Renderer::setPass(mSolidMaterial.mat, 0);
 				else
-					Renderer::setPass(*mWireMaterial.proxy, 0);
+					Renderer::setPass(mWireMaterial.mat, 0);
 
 				currentType = meshData.type;
 			}

+ 11 - 12
BansheeEditor/Source/BsScenePicking.cpp

@@ -37,8 +37,8 @@ namespace BansheeEngine
 			mMaterialData[i].mMatPicking = BuiltinEditorResources::instance().createPicking((CullingMode)i);
 			mMaterialData[i].mMatPickingAlpha = BuiltinEditorResources::instance().createPickingAlpha((CullingMode)i);
 
-			mMaterialData[i].mMatPickingProxy = mMaterialData[i].mMatPicking->_createProxy();
-			mMaterialData[i].mMatPickingAlphaProxy = mMaterialData[i].mMatPickingAlpha->_createProxy();
+			mMaterialData[i].mMatPickingCore = mMaterialData[i].mMatPicking->getCore();
+			mMaterialData[i].mMatPickingAlphaCore = mMaterialData[i].mMatPickingAlpha->getCore();
 		}
 
 		gCoreAccessor().queueCommand(std::bind(&ScenePicking::initializeCore, this));
@@ -51,23 +51,22 @@ namespace BansheeEngine
 			MaterialData& md = mMaterialData[i];
 
 			{
-				// TODO - Make a better interface when dealing with parameters through proxies?
-				MaterialProxyPtr proxy = md.mMatPickingProxy;
+				SPtr<PassParametersCore> passParams = md.mMatPickingCore->getPassParameters(0);
 
-				md.mParamPickingVertParams = proxy->params[proxy->passes[0].vertexProgParamsIdx];
+				md.mParamPickingVertParams = passParams->mVertParams;
 				md.mParamPickingVertParams->getParam("matWorldViewProj", md.mParamPickingWVP);
 
-				md.mParamPickingFragParams = proxy->params[proxy->passes[0].fragmentProgParamsIdx];
+				md.mParamPickingFragParams = passParams->mFragParams;
 				md.mParamPickingFragParams->getParam("colorIndex", md.mParamPickingColor);
 			}
 
 			{
-				MaterialProxyPtr proxy = md.mMatPickingAlphaProxy;
+				SPtr<PassParametersCore> passParams = md.mMatPickingAlphaCore->getPassParameters(0);
 
-				md.mParamPickingAlphaVertParams = proxy->params[proxy->passes[0].vertexProgParamsIdx];
+				md.mParamPickingAlphaVertParams = passParams->mVertParams;
 				md.mParamPickingAlphaVertParams->getParam("matWorldViewProj", md.mParamPickingAlphaWVP);
 
-				md.mParamPickingAlphaFragParams = proxy->params[proxy->passes[0].fragmentProgParamsIdx];
+				md.mParamPickingAlphaFragParams = passParams->mFragParams;
 
 				md.mParamPickingAlphaFragParams->getParam("colorIndex", md.mParamPickingAlphaColor);
 				md.mParamPickingAlphaFragParams->getTextureParam("mainTexture", md.mParamPickingAlphaTexture);
@@ -230,7 +229,7 @@ namespace BansheeEngine
 		rs.clearRenderTarget(FBT_COLOR | FBT_DEPTH | FBT_STENCIL, Color::White);
 		rs.setScissorRect(position.x, position.y, position.x + area.x, position.y + area.y);
 
-		Renderer::setPass(*mMaterialData[0].mMatPickingProxy, 0);
+		Renderer::setPass(mMaterialData[0].mMatPickingCore, 0);
 		bool activeMaterialIsAlpha = false;
 		CullingMode activeMaterialCull = (CullingMode)0;
 
@@ -242,9 +241,9 @@ namespace BansheeEngine
 				activeMaterialCull = renderable.cullMode;
 
 				if (activeMaterialIsAlpha)
-					Renderer::setPass(*mMaterialData[(UINT32)activeMaterialCull].mMatPickingAlphaProxy, 0);
+					Renderer::setPass(mMaterialData[(UINT32)activeMaterialCull].mMatPickingAlphaCore, 0);
 				else
-					Renderer::setPass(*mMaterialData[(UINT32)activeMaterialCull].mMatPickingProxy, 0);
+					Renderer::setPass(mMaterialData[(UINT32)activeMaterialCull].mMatPickingCore, 0);
 			}
 
 			Color color = encodeIndex(renderable.index);

+ 2 - 2
BansheeEngine/Include/BsRenderQueue.h

@@ -16,7 +16,7 @@ namespace BansheeEngine
 		{ }
 
 		RenderableElement* renderElem;
-		MaterialProxyPtr material;
+		SPtr<MaterialCore> material;
 		SPtr<MeshCoreBase> mesh;
 		SubMesh subMesh;
 		UINT32 passIdx;
@@ -60,7 +60,7 @@ namespace BansheeEngine
 		 * @param	subMesh			Portion of the mesh to draw.
 		 * @param	distFromCamera	Distance of this object from the camera. Used for distance sorting.
 		 */
-		void add(const MaterialProxyPtr& material, const SPtr<MeshCoreBase>& mesh, const SubMesh& subMesh, float distFromCamera);
+		void add(const SPtr<MaterialCore>& material, const SPtr<MeshCoreBase>& mesh, const SubMesh& subMesh, float distFromCamera);
 
 		/**
 		 * @brief	Adds new entries from the provided render queue to this queue.

+ 18 - 2
BansheeEngine/Include/BsRenderableProxy.h

@@ -1,7 +1,6 @@
 #pragma once
 
 #include "BsPrerequisites.h"
-#include "BsMaterialProxy.h"
 #include "BsBounds.h"
 #include "BsMatrix4.h"
 #include "BsSubMesh.h"
@@ -15,6 +14,22 @@ namespace BansheeEngine
 	class BS_EXPORT RenderableElement
 	{
 	public:
+		/**
+		 * @brief	Contains a hardware GPU parameter buffer and index of the parameters and the slot
+		 *			it binds to in a material proxy.
+		 */
+		struct BS_CORE_EXPORT BufferBindInfo
+		{
+			BufferBindInfo(UINT32 passIdx, UINT32 paramsIdx, UINT32 slotIdx, const SPtr<GpuParamBlockBufferCore>& buffer)
+				:passIdx(passIdx), paramsIdx(paramsIdx), slotIdx(slotIdx), buffer(buffer)
+			{ }
+
+			UINT32 passIdx;
+			UINT32 paramsIdx;
+			UINT32 slotIdx;
+			SPtr<GpuParamBlockBufferCore> buffer;
+		};
+
 		RenderableElement();
 
 		/**
@@ -46,7 +61,7 @@ namespace BansheeEngine
 		/**
 		 * @brief	Proxy of the material to render the mesh with.
 		 */
-		MaterialProxyPtr material;
+		SPtr<MaterialCore> material;
 
 		/**
 		 * @brief	Optional layer that may be used for the camera for culling
@@ -69,6 +84,7 @@ namespace BansheeEngine
 		 */
 		RenderableType renderableType;
 
+		Vector<BufferBindInfo> rendererBuffers;
 	private:
 		bool mBoundsDirty;
 	};

+ 7 - 7
BansheeEngine/Source/BsRenderQueue.cpp

@@ -1,9 +1,9 @@
 #include "BsRenderQueue.h"
-#include "BsMaterialProxy.h"
 #include "BsRenderableProxy.h"
 #include "BsSubMesh.h"
 #include "BsShader.h"
 #include "BsMesh.h"
+#include "BsMaterial.h"
 
 namespace BansheeEngine
 {
@@ -30,15 +30,15 @@ namespace BansheeEngine
 		renderOp.subMesh = element->subMesh;
 
 		sortData.distFromCamera = distFromCamera;
-		sortData.priority = element->material->shader->getQueuePriority();
-		sortData.sortType = element->material->shader->getQueueSortType();
+		sortData.priority = element->material->getShader()->getQueuePriority();
+		sortData.sortType = element->material->getShader()->getQueueSortType();
 		sortData.seqIdx = (UINT32)mRenderElements.size();
 
 		// TODO - Make sure elements are cached so we dont allocate memory for them every frame
 		mRenderElements.insert(sortData);
 	}
 
-	void RenderQueue::add(const MaterialProxyPtr& material, const SPtr<MeshCoreBase>& mesh, const SubMesh& subMesh, float distFromCamera)
+	void RenderQueue::add(const SPtr<MaterialCore>& material, const SPtr<MeshCoreBase>& mesh, const SubMesh& subMesh, float distFromCamera)
 	{
 		SortData sortData;
 
@@ -49,8 +49,8 @@ namespace BansheeEngine
 		renderOp.subMesh = subMesh;
 
 		sortData.distFromCamera = distFromCamera;
-		sortData.priority = material->shader->getQueuePriority();
-		sortData.sortType = material->shader->getQueueSortType();
+		sortData.priority = material->getShader()->getQueuePriority();
+		sortData.sortType = material->getShader()->getQueueSortType();
 		sortData.seqIdx = (UINT32)mRenderElements.size();
 
 		// TODO - Make sure elements are cached so we dont allocate memory for them every frame
@@ -74,7 +74,7 @@ namespace BansheeEngine
 		for (auto& sortData : mRenderElements)
 		{
 			const RenderQueueElement& renderElem = sortData.element;
-			UINT32 numPasses = (UINT32)renderElem.material->passes.size();
+			UINT32 numPasses = (UINT32)renderElem.material->getNumPasses();
 			for (UINT32 i = 0; i < numPasses; i++)
 			{
 				mSortedRenderElements.push_back(RenderQueueElement());

+ 4 - 2
BansheeEngine/Source/BsRenderableController.cpp

@@ -1,14 +1,16 @@
 #include "BsRenderableController.h"
 #include "BsRenderableProxy.h"
 #include "BsGpuParams.h"
+#include "BsMaterial.h"
 
 namespace BansheeEngine
 {
 	void RenderableController::bindGlobalBuffers(const RenderableElement* element)
 	{
-		for (auto& rendererBuffer : element->material->rendererBuffers)
+		for (auto& rendererBuffer : element->rendererBuffers)
 		{
-			element->material->params[rendererBuffer.paramsIdx]->setParamBlockBuffer(rendererBuffer.slotIdx, rendererBuffer.buffer);
+			SPtr<PassParametersCore> passParams = element->material->getPassParameters(rendererBuffer.passIdx);
+			passParams->getParamByIdx(rendererBuffer.paramsIdx)->setParamBlockBuffer(rendererBuffer.slotIdx, rendererBuffer.buffer);
 		}
 	}
 }

+ 1 - 19
BansheeEngine/Source/BsRenderableHandler.cpp

@@ -70,23 +70,11 @@ namespace BansheeEngine
 	{
 		updateResourceLoadStates();
 
-		for (auto& materialData : mMaterialData)
-		{
-			if (materialData.material != nullptr && materialData.material.isLoaded() && materialData.material->_isCoreDirty(MaterialDirtyFlag::Material))
-				return true;
-		}
-
 		return mCoreDirtyFlags != 0;
 	}
 
 	void RenderableHandler::_markCoreClean()
 	{
-		for (auto& materialData : mMaterialData)
-		{
-			if (materialData.material != nullptr && materialData.material.isLoaded())
-				materialData.material->_markCoreClean(MaterialDirtyFlag::Material);
-		}
-
 		mCoreDirtyFlags = 0;
 	}
 
@@ -134,13 +122,7 @@ namespace BansheeEngine
 			if (material == nullptr || !material.isLoaded())
 				material = BuiltinResources::instance().createDummyMaterial();
 
-			if (material->_isCoreDirty(MaterialDirtyFlag::Proxy))
-			{
-				material->_setActiveProxy(material->_createProxy());
-				material->_markCoreClean(MaterialDirtyFlag::Proxy);
-			}
-
-			renElement->material = material->_getActiveProxy();
+			renElement->material = material->getCore();
 
 			proxy->renderableElements.push_back(renElement);
 		}

+ 2 - 2
BansheeRenderer/Include/BsBansheeLitTexRenderableController.h

@@ -2,9 +2,9 @@
 
 #include "BsBansheeRendererPrerequisites.h"
 #include "BsRenderableController.h"
-#include "BsMaterialProxy.h"
 #include "BsGpuParamDesc.h"
 #include "BsGpuParam.h"
+#include "BsRenderableProxy.h"
 
 namespace BansheeEngine
 {
@@ -28,7 +28,7 @@ namespace BansheeEngine
 			bool hasWVPParam = false;
 			GpuParamMat4Core wvpParam;
 
-			Vector<MaterialProxy::BufferBindInfo> perObjectBuffers;
+			Vector<RenderableElement::BufferBindInfo> perObjectBuffers;
 		};
 
 		LitTexRenderableController();

+ 0 - 1
BansheeRenderer/Include/BsBansheeRenderer.h

@@ -2,7 +2,6 @@
 
 #include "BsBansheeRendererPrerequisites.h"
 #include "BsRenderer.h"
-#include "BsMaterialProxy.h"
 #include "BsBounds.h"
 
 namespace BansheeEngine

+ 47 - 39
BansheeRenderer/Source/BsBansheeLitTexRenderableController.cpp

@@ -7,6 +7,7 @@
 #include "BsGpuParamBlockBuffer.h"
 #include "BsTechnique.h"
 #include "BsPass.h"
+#include "BsMaterial.h"
 #include "BsRenderSystem.h"
 
 namespace BansheeEngine
@@ -132,7 +133,7 @@ namespace BansheeEngine
 		element->rendererData = PerObjectData();
 		PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element->rendererData);
 
-		SPtr<ShaderCore> shader = element->material->shader;
+		SPtr<ShaderCore> shader = element->material->getShader();
 
 		const Map<String, SHADER_PARAM_BLOCK_DESC>& paramBlockDescs = shader->getParamBlocks();
 		const Map<String, SHADER_DATA_PARAM_DESC>& dataParamDescs = shader->getDataParams();
@@ -164,68 +165,75 @@ namespace BansheeEngine
 				wvpParamName = paramDesc.second.gpuVariableName;
 		}
 
-		UINT32 idx = 0;
-		for (auto& gpuParams : element->material->params)
+		UINT32 numPasses = element->material->getNumPasses();
+		for (UINT32 i = 0; i < numPasses; i++)
 		{
-			const GpuParamDesc& paramsDesc = gpuParams->getParamDesc();
+			SPtr<PassParametersCore> passParams = element->material->getPassParameters(i);
 
-			if (staticBlockName != "")
+			for (UINT32 j = 0; j < passParams->getNumParams(); j++)
 			{
-				auto findIter = paramsDesc.paramBlocks.find(staticBlockName);
-				if (findIter != paramsDesc.paramBlocks.end())
+				SPtr<GpuParamsCore> gpuParams = passParams->getParamByIdx(j);
+				if (gpuParams == nullptr)
+					continue;
+
+				const GpuParamDesc& paramsDesc = gpuParams->getParamDesc();
+
+				if (staticBlockName != "")
 				{
-					// TODO - We only compare block sizes but not actual contents. Should I check them too?
-					//        Probably shouldn't concern myself with that here, instead check that on a higher level.
-					if (findIter->second.blockSize == staticParamBlockDesc.blockSize)
+					auto findIter = paramsDesc.paramBlocks.find(staticBlockName);
+					if (findIter != paramsDesc.paramBlocks.end())
 					{
-						UINT32 slotIdx = findIter->second.slot;
-						element->material->rendererBuffers.push_back(MaterialProxy::BufferBindInfo(idx, slotIdx, staticParamBuffer));
+						// TODO - We only compare block sizes but not actual contents. Should I check them too?
+						//        Probably shouldn't concern myself with that here, instead check that on a higher level.
+						if (findIter->second.blockSize == staticParamBlockDesc.blockSize)
+						{
+							UINT32 slotIdx = findIter->second.slot;
+							element->rendererBuffers.push_back(RenderableElement::BufferBindInfo(i, j, slotIdx, staticParamBuffer));
+						}
 					}
 				}
-			}
 
-			if (perFrameBlockName != "")
-			{
-				auto findIter = paramsDesc.paramBlocks.find(perFrameBlockName);
-				if (findIter != paramsDesc.paramBlocks.end())
+				if (perFrameBlockName != "")
 				{
-					if (findIter->second.blockSize == perFrameParamBlockDesc.blockSize)
+					auto findIter = paramsDesc.paramBlocks.find(perFrameBlockName);
+					if (findIter != paramsDesc.paramBlocks.end())
 					{
-						UINT32 slotIdx = findIter->second.slot;
-						element->material->rendererBuffers.push_back(MaterialProxy::BufferBindInfo(idx, slotIdx, perFrameParamBuffer));
+						if (findIter->second.blockSize == perFrameParamBlockDesc.blockSize)
+						{
+							UINT32 slotIdx = findIter->second.slot;
+							element->rendererBuffers.push_back(RenderableElement::BufferBindInfo(i, j, slotIdx, perFrameParamBuffer));
+						}
 					}
 				}
-			}
 
-			if (perObjectBlockName != "")
-			{
-				auto findIter = paramsDesc.paramBlocks.find(perObjectBlockName);
-				if (findIter != paramsDesc.paramBlocks.end())
+				if (perObjectBlockName != "")
 				{
-					if (findIter->second.blockSize == perObjectParamBlockDesc.blockSize)
+					auto findIter = paramsDesc.paramBlocks.find(perObjectBlockName);
+					if (findIter != paramsDesc.paramBlocks.end())
 					{
-						if (rendererData->perObjectParamBuffer == nullptr)
-							rendererData->perObjectParamBuffer = HardwareBufferCoreManager::instance().createGpuParamBlockBuffer(perObjectParamBlockDesc.blockSize * sizeof(UINT32));
+						if (findIter->second.blockSize == perObjectParamBlockDesc.blockSize)
+						{
+							if (rendererData->perObjectParamBuffer == nullptr)
+								rendererData->perObjectParamBuffer = HardwareBufferCoreManager::instance().createGpuParamBlockBuffer(perObjectParamBlockDesc.blockSize * sizeof(UINT32));
 
-						rendererData->perObjectBuffers.push_back(MaterialProxy::BufferBindInfo(idx, findIter->second.slot, rendererData->perObjectParamBuffer));
+							rendererData->perObjectBuffers.push_back(RenderableElement::BufferBindInfo(i, j, findIter->second.slot, rendererData->perObjectParamBuffer));
 
-						if (!rendererData->hasWVPParam && wvpParamName != "")
-						{
-							auto findIter2 = paramsDesc.params.find(wvpParamName);
-							if (findIter2 != paramsDesc.params.end())
+							if (!rendererData->hasWVPParam && wvpParamName != "")
 							{
-								if (paramsMatch(findIter2->second, wvpParamDesc))
+								auto findIter2 = paramsDesc.params.find(wvpParamName);
+								if (findIter2 != paramsDesc.params.end())
 								{
-									gpuParams->getParam(wvpParamName, rendererData->wvpParam);
-									rendererData->hasWVPParam = true;
+									if (paramsMatch(findIter2->second, wvpParamDesc))
+									{
+										gpuParams->getParam(wvpParamName, rendererData->wvpParam);
+										rendererData->hasWVPParam = true;
+									}
 								}
 							}
 						}
 					}
 				}
 			}
-
-			idx++;
 		}
 
 		bindGlobalBuffers(element);
@@ -236,7 +244,7 @@ namespace BansheeEngine
 		const PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element->rendererData);
 		for (auto& perObjectBuffer : rendererData->perObjectBuffers)
 		{
-			SPtr<GpuParamsCore> params = element->material->params[perObjectBuffer.paramsIdx];
+			SPtr<GpuParamsCore> params = element->material->getPassParameters(perObjectBuffer.passIdx)->getParamByIdx(perObjectBuffer.paramsIdx);
 
 			params->setParamBlockBuffer(perObjectBuffer.slotIdx, rendererData->perObjectParamBuffer);
 		}

+ 14 - 21
BansheeRenderer/Source/BsBansheeRenderer.cpp

@@ -243,29 +243,14 @@ namespace BansheeEngine
 			RenderQueuePtr renderQueue = bs_shared_ptr<RenderQueue>();
 			const Vector<DrawOperation>& drawOps = drawList->getDrawOperations();
 
-			// Note: It is important that draw ops update happens after renderables are updated, so that
-			// renderable proxies properly update in case they both share the same material/mesh
 			for (auto& drawOp : drawOps)
 			{
-				// Note: It is assumed render operations queued in the draw list is going
-				// to change every frame so we create new proxies using frame allocator
-				// every frame. It /might/ be more efficient not to use frame allocator
-				// and only update when they actually change. That might also cause
-				// issue if material/mesh is used both in draw list and a Renderable
-
-				if (drawOp.material->_isCoreDirty(MaterialDirtyFlag::Proxy))
-				{
-					drawOp.material->_setActiveProxy(drawOp.material->_createProxy());
-					drawOp.material->_markCoreClean(MaterialDirtyFlag::Proxy);
-					drawOp.material->_markCoreClean(MaterialDirtyFlag::Material);
-				}
-
-				MaterialProxyPtr materialProxy = drawOp.material->_getActiveProxy();
+				SPtr<MaterialCore> materialCore = drawOp.material->getCore();
 				SPtr<MeshCoreBase> meshCore = drawOp.mesh->getCore();
 				SubMesh subMesh = meshCore->getProperties().getSubMesh(drawOp.submeshIdx);
 
 				float distanceToCamera = (cameraSO->getPosition() - drawOp.worldPosition).length();
-				renderQueue->add(materialProxy, meshCore, subMesh, distanceToCamera);
+				renderQueue->add(materialCore, meshCore, subMesh, distanceToCamera);
 			}
 
 			gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::addToRenderQueue, this, camera->getCore(), renderQueue));
@@ -387,9 +372,17 @@ namespace BansheeEngine
 					mLitTexHandler->updatePerObjectBuffers(renderElem, worldViewProjMatrix);
 				}
 
-				for (auto& param : renderElem->material->params)
+				UINT32 numPasses = renderElem->material->getNumPasses();
+				for (UINT32 i = 0; i < numPasses; i++)
 				{
-					param->updateHardwareBuffers();
+					SPtr<PassParametersCore> passParams = renderElem->material->getPassParameters(i);
+
+					for (UINT32 j = 0; j < passParams->getNumParams(); j++)
+					{
+						SPtr<GpuParamsCore> params = passParams->getParamByIdx(j);
+						if (params != nullptr)
+							params->updateHardwareBuffers();
+					}
 				}
 
 				// Do frustum culling
@@ -416,9 +409,9 @@ namespace BansheeEngine
 
 		for(auto iter = sortedRenderElements.begin(); iter != sortedRenderElements.end(); ++iter)
 		{
-			MaterialProxyPtr materialProxy = iter->material;
+			SPtr<MaterialCore> material = iter->material;
 
-			setPass(*materialProxy, iter->passIdx);
+			setPass(material, iter->passIdx);
 			draw(iter->mesh, iter->subMesh);
 		}
 

+ 6 - 10
TODO.txt

@@ -1,13 +1,14 @@
 --------- ALL LONG TERM TASKS / FIXES BELONG TO GOOGLE DOCS: ImplementationTODO OR PossibleImprovements ----------
 
-TODO - CoreObject refactor:
-Resource
- - Material -> Remove MaterialProxy
- - BansheeRenderer::mDeletedRenderableProxies is holding references to core objects
-Also:
  - Make RenderableHandler a CoreObject and remove RenderableProxy
+   - BansheeRenderer::mDeletedRenderableProxies is holding references to core objects
  - Rename CoreObject initialize_internal and destroy_internal to initializeCore/destroyCore and make them private
 
+Add getCore/createCore and MaterialCore for Material
+Try compiling and see if that works. Then begin on template refactor:
+ - Refactor Material/GpuParams/MaterialParam/GpuParam/Technique/Shader so they use explicit tempalate instantiation and move their implementations to the source file
+Dont forget material sync methods
+
 GpuParams refactor:
 
 I need to ensure renderer buffers get set properly after GpuParams are synced
@@ -32,11 +33,6 @@ Disallow CoreObject creation from core thread
 
 -----------------
 
-
-Refactor GizmoManager and HandleManager so they accept a CameraHandler
- - I need to ensure scene CameraHandler has proper position/rotation before being passed to handle and gizmo manager
- - Delete SceneViewLocator, I don't think it's used anywhere
-
 Port SceneCameraController to C#
 Port RenderTexture to C# and likely extend Texture2D so it accepts renderable flags. While at it add TextureCube and Texture3D as well.
  - Actually Texture2D doesn't seem to be implemented at all. Will also need to add PixelData wrapper.