Explorar o código

WIP Renderer refactor - Checkin before I start modifying GpuParams

Marko Pintera %!s(int64=11) %!d(string=hai) anos
pai
achega
6084fe01cc
Modificáronse 41 ficheiros con 861 adicións e 312 borrados
  1. 4 4
      BansheeCore/BansheeCore.vcxproj
  2. 12 12
      BansheeCore/BansheeCore.vcxproj.filters
  3. 0 34
      BansheeCore/Include/BsBindableGpuParamBlock.h
  4. 2 0
      BansheeCore/Include/BsCameraProxy.h
  5. 4 3
      BansheeCore/Include/BsCorePrerequisites.h
  6. 8 1
      BansheeCore/Include/BsGpuParamBlock.h
  7. 6 0
      BansheeCore/Include/BsGpuParamBlockBuffer.h
  8. 16 0
      BansheeCore/Include/BsGpuParamBlockBufferProxy.h
  9. 30 6
      BansheeCore/Include/BsGpuParams.h
  10. 7 18
      BansheeCore/Include/BsGpuParamsProxy.h
  11. 1 1
      BansheeCore/Include/BsHardwareBufferManager.h
  12. 53 19
      BansheeCore/Include/BsMaterial.h
  13. 23 2
      BansheeCore/Include/BsMeshBase.h
  14. 1 1
      BansheeCore/Include/BsMeshBaseRTTI.h
  15. 1 1
      BansheeCore/Include/BsRenderSystem.h
  16. 1 0
      BansheeCore/Include/BsRenderableProxy.h
  17. 0 11
      BansheeCore/Include/BsRenderer.h
  18. 1 1
      BansheeCore/Include/BsRendererParams.h
  19. 0 15
      BansheeCore/Source/BsBindableGpuParamBlock.cpp
  20. 1 1
      BansheeCore/Source/BsCoreThreadAccessor.cpp
  21. 6 0
      BansheeCore/Source/BsGpuParamBlock.cpp
  22. 9 0
      BansheeCore/Source/BsGpuParamBlockBuffer.cpp
  23. 14 0
      BansheeCore/Source/BsGpuParamBlockBufferProxy.cpp
  24. 112 29
      BansheeCore/Source/BsGpuParams.cpp
  25. 57 33
      BansheeCore/Source/BsGpuParamsProxy.cpp
  26. 38 7
      BansheeCore/Source/BsMaterial.cpp
  27. 2 0
      BansheeCore/Source/BsMeshBase.cpp
  28. 12 4
      BansheeD3D11RenderSystem/Include/BsD3D11RenderSystem.h
  29. 7 7
      BansheeD3D11RenderSystem/Source/BsD3D11RenderSystem.cpp
  30. 1 1
      BansheeD3D9RenderSystem/Include/BsD3D9RenderSystem.h
  31. 6 6
      BansheeD3D9RenderSystem/Source/BsD3D9RenderSystem.cpp
  32. 12 0
      BansheeEngine/Include/BsEnums.h
  33. 4 12
      BansheeEngine/Include/BsRenderable.h
  34. 1 1
      BansheeEngine/Include/BsRenderableRTTI.h
  35. 37 17
      BansheeEngine/Source/BsRenderable.cpp
  36. 1 1
      BansheeGLRenderSystem/Include/BsGLRenderSystem.h
  37. 6 6
      BansheeGLRenderSystem/Source/BsGLRenderSystem.cpp
  38. 32 7
      BansheeRenderer/Include/BsBansheeRenderer.h
  39. 198 44
      BansheeRenderer/Source/BsBansheeRenderer.cpp
  40. 123 0
      BansheeUtility/Include/BsFrameAlloc.h
  41. 12 7
      Renderer.txt

+ 4 - 4
BansheeCore/BansheeCore.vcxproj

@@ -272,6 +272,8 @@
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClInclude Include="Include\BsGpuParamBlockBufferProxy.h" />
+    <ClInclude Include="Include\BsGpuParamsProxy.h" />
     <ClInclude Include="Include\BsCameraProxy.h" />
     <ClInclude Include="Include\BsDrawList.h" />
     <ClInclude Include="Include\BsMaterialProxy.h" />
@@ -279,8 +281,6 @@
     <ClInclude Include="Include\BsRenderableProxy.h" />
     <ClInclude Include="Include\BsRendererParams.h" />
     <ClInclude Include="Include\BsRenderStats.h" />
-    <ClInclude Include="Include\BsBindableGpuParamBlock.h" />
-    <ClInclude Include="Include\BsBindableGpuParams.h" />
     <ClInclude Include="Include\BsCoreThread.h" />
     <ClInclude Include="Include\BsProfilerCPU.h" />
     <ClInclude Include="Include\BsDeferredCallManager.h" />
@@ -420,8 +420,8 @@
     <ClInclude Include="Source\BsMeshRTTI.h" />
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="Source\BsBindableGpuParamBlock.cpp" />
-    <ClCompile Include="Source\BsBindableGpuParams.cpp" />
+    <ClCompile Include="Source\BsGpuParamBlockBufferProxy.cpp" />
+    <ClCompile Include="Source\BsGpuParamsProxy.cpp" />
     <ClCompile Include="Source\BsCameraProxy.cpp" />
     <ClCompile Include="Source\BsCoreThread.cpp" />
     <ClCompile Include="Source\BsDrawList.cpp" />

+ 12 - 12
BansheeCore/BansheeCore.vcxproj.filters

@@ -405,12 +405,6 @@
     <ClInclude Include="Include\BsBlendState.h">
       <Filter>Header Files\RenderSystem</Filter>
     </ClInclude>
-    <ClInclude Include="Include\BsBindableGpuParams.h">
-      <Filter>Header Files\RenderSystem</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsBindableGpuParamBlock.h">
-      <Filter>Header Files\RenderSystem</Filter>
-    </ClInclude>
     <ClInclude Include="Include\BsRenderQueue.h">
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
@@ -528,6 +522,12 @@
     <ClInclude Include="Include\BsMaterialProxy.h">
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsGpuParamsProxy.h">
+      <Filter>Header Files\Renderer</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGpuParamBlockBufferProxy.h">
+      <Filter>Header Files\Renderer</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsCoreApplication.cpp">
@@ -638,12 +638,6 @@
     <ClCompile Include="Source\BsVertexDataDesc.cpp">
       <Filter>Source Files\Resources</Filter>
     </ClCompile>
-    <ClCompile Include="Source\BsBindableGpuParamBlock.cpp">
-      <Filter>Source Files\RenderSystem</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsBindableGpuParams.cpp">
-      <Filter>Source Files\RenderSystem</Filter>
-    </ClCompile>
     <ClCompile Include="Source\BsBlendState.cpp">
       <Filter>Source Files\RenderSystem</Filter>
     </ClCompile>
@@ -836,5 +830,11 @@
     <ClCompile Include="Source\BsRendererParams.cpp">
       <Filter>Source Files\Renderer</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsGpuParamsProxy.cpp">
+      <Filter>Source Files\Renderer</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsGpuParamBlockBufferProxy.cpp">
+      <Filter>Source Files\Renderer</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 0 - 34
BansheeCore/Include/BsBindableGpuParamBlock.h

@@ -5,39 +5,5 @@
 
 namespace BansheeEngine
 {
-	/**
-	 * @brief	Specialized class for binding GPU parameters to the render system. Represents a single
-	 * 			parameter block buffer and is used for temporary storage of GPU parameters.
-	 * 
-	 * @note	Due to the way allocation is handled, this class is not allowed to have a destructor.
-	 * 			
-	 * @see		BindableGpuParams
- 	 */
-	class BS_CORE_EXPORT BindableGpuParamBlock
-	{
-	public:
-		BindableGpuParamBlock();
 
-		/**
-		 * @brief	Uploads the current data to the specified buffer, and marks the block a non-dirty.
-		 * 			
-		 * @note	Core thread only.			
-		 */
-		void uploadToBuffer(GpuParamBlockBufferPtr buffer);
-
-		/**
-		 * @brief	Query if this object is dirty. If dirty the data of this block
-		 * 			will need to be uploaded to a GPU buffer.
-		 *
-		 * @note	Core thread only.
-		 */
-		bool isDirty() const { return mDirty; }
-	protected:
-		friend class GpuParams;
-		friend class BindableGpuParams;
-
-		UINT8* mData;
-		UINT32 mSize;
-		bool mDirty;
-	};
 }

+ 2 - 0
BansheeCore/Include/BsCameraProxy.h

@@ -16,5 +16,7 @@ namespace BansheeEngine
 		INT32 priority;
 		UINT64 layer;
 		bool ignoreSceneRenderables;
+
+		RenderQueuePtr renderQueue;
 	};
 }

+ 4 - 3
BansheeCore/Include/BsCorePrerequisites.h

@@ -116,8 +116,6 @@ namespace BansheeEngine
 	class GameObject;
 	class GpuResource;
 	class GpuResourceData;
-	class BindableGpuParams;
-	class BindableGpuParamBlock;
 	struct RenderOperation;
 	class RenderQueue;
 	struct ProfilerReport;
@@ -136,6 +134,8 @@ namespace BansheeEngine
 	class MaterialProxy;
 	class MaterialProxyPass;
 	class MeshProxy;
+	class GpuParamBlockBufferProxy;
+	class GpuParamsProxy;
 	class DrawList;
 	// Asset import
 	class SpecificImporter;
@@ -196,7 +196,6 @@ namespace BansheeEngine
 	typedef std::shared_ptr<Pass> PassPtr;
 	typedef std::shared_ptr<Shader> ShaderPtr;
 	typedef std::shared_ptr<Material> MaterialPtr;
-	typedef std::shared_ptr<BindableGpuParams> BindableGpuParamsPtr;
 	typedef std::shared_ptr<Renderer> RendererPtr;
 	typedef std::shared_ptr<RendererFactory> RendererFactoryPtr;
 	typedef std::shared_ptr<PassParameters> PassParametersPtr;
@@ -235,6 +234,8 @@ namespace BansheeEngine
 	typedef std::shared_ptr<CameraProxy> CameraProxyPtr;
 	typedef std::shared_ptr<MaterialProxy> MaterialProxyPtr;
 	typedef std::shared_ptr<MeshProxy> MeshProxyPtr;
+	typedef std::shared_ptr<GpuParams> GpuParamsPtr;
+	typedef std::shared_ptr<GpuParamBlockBufferProxy> GpuParamBlockBufferProxyPtr;
 }
 
 /************************************************************************/

+ 8 - 1
BansheeCore/Include/BsGpuParamBlock.h

@@ -47,6 +47,13 @@ namespace BansheeEngine
 		 */
 		UINT8* getData() const { return mData; }
 
+		/**
+		 * @brief	Uploads the current data to the specified buffer, and marks the block a non-dirty.
+		 * 			
+		 * @note	Core thread only.			
+		 */
+		void uploadToBuffer(const GpuParamBlockBufferPtr& buffer);
+
 		/**
 		 * @brief	Checks if something has been written to the buffer
 		 *			since the last time object was clean.
@@ -57,7 +64,7 @@ namespace BansheeEngine
 		 * @brief	Marks the object as dirty or clean. Signifies
 		 *			whether or not some new data has been written in the buffer.
 		 */
-		void setDirty() { mDirty = true; }
+		void setDirty(bool dirty) { mDirty = dirty; }
 	protected:
 		UINT8* mData;
 		UINT32 mSize;

+ 6 - 0
BansheeCore/Include/BsGpuParamBlockBuffer.h

@@ -61,11 +61,17 @@ namespace BansheeEngine
 		 */
 		GpuParamBlock* getParamBlock() const { return mParamBlock; }
 
+		// TODO UNDOCUMENTED
+		GpuParamBlockBufferProxyPtr _createProxy() const;
+		void _setActiveProxy(const GpuParamBlockBufferProxyPtr& activeProxy) { mActiveProxy = activeProxy; }
+		GpuParamBlockBufferProxyPtr _getActiveProxy() const { return mActiveProxy; }
+
 	protected:
 		GpuParamBlockUsage mUsage;
 		UINT32 mSize;
 
 		GpuParamBlock* mParamBlock;
+		GpuParamBlockBufferProxyPtr mActiveProxy;
 	};
 
 	/**

+ 16 - 0
BansheeCore/Include/BsGpuParamBlockBufferProxy.h

@@ -0,0 +1,16 @@
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsGpuParamBlock.h"
+
+namespace BansheeEngine
+{
+	// TODO UNDOCUMENTED
+	struct BS_CORE_EXPORT GpuParamBlockBufferProxy
+	{
+		GpuParamBlockBufferProxy(UINT32 size);
+		~GpuParamBlockBufferProxy();
+
+		GpuParamBlock* block;
+	};
+}

+ 30 - 6
BansheeCore/Include/BsGpuParams.h

@@ -2,7 +2,6 @@
 
 #include "BsCorePrerequisites.h"
 #include "BsGpuParam.h"
-#include "BsBindableGpuParams.h"
 
 namespace BansheeEngine
 {
@@ -208,10 +207,35 @@ namespace BansheeEngine
 		 */
 		void getSamplerStateParam(const String& name, GpuParamSampState& output) const;
 
+		/**
+		 * @brief	Uploads all CPU stored parameter buffer data to the GPU buffers.
+		 *
+		 * @note	Core thread only.
+		 */
+		void updateHardwareBuffers();
+
+		/**
+		 * @brief	Gets a parameter block buffer from the specified slot.
+		 */
+		GpuParamBlockBufferPtr getParamBlockBuffer(UINT32 slot) const;
+
+		/**
+		 * @brief	Gets a texture bound to the specified slot.
+		 */
+		HTexture getTexture(UINT32 slot);
+
+		/**
+		 * @brief	Gets a sampler state bound to the specified slot.
+		 */
+		HSamplerState getSamplerState(UINT32 slot);
+
 		/**
 		 * @brief	Returns an exact copy of this object.
+		 *
+		 * @note	Optional frame allocator to allocate the returned data with. If not specified
+		 *			allocation will be done using normal means.
 		 */
-		GpuParamsPtr clone() const;
+		GpuParamsPtr clone(FrameAlloc* frameAlloc = nullptr) const;
 
 		/**
 		 * @brief	Checks is the core dirty flag set. This is used by external systems 
@@ -229,9 +253,8 @@ namespace BansheeEngine
 		void _markCoreClean();
 
 	private:
-		friend class BindableGpuParams;
+		friend class GpuParamsProxy;
 
-	private:
 		GpuParamDesc& mParamDesc;
 		std::shared_ptr<GpuParamsInternalData> mInternalData;
 
@@ -244,7 +267,7 @@ namespace BansheeEngine
 		 * @brief	Calculates size and offsets used when splitting a large memory chunk into separate buffers.
 		 *			Parameter counts must have been previously assigned.
 		 */
-		void getInternalBufferData(UINT32& bufferSize, UINT32& paramBlockOffset, UINT32& paramBlockBufferOffset,
+		void getInternalBufferData(UINT32& bufferSize, UINT32& paramBlockBufferOffset,
 			UINT32& textureOffset, UINT32& samplerStateOffset) const;
 
 		/**
@@ -266,7 +289,6 @@ namespace BansheeEngine
 		UINT32 mNumTextures;
 		UINT32 mNumSamplerStates;
 
-		GpuParamBlock** mParamBlocks;
 		GpuParamBlockBufferPtr* mParamBlockBuffers;
 		HTexture* mTextures;
 		HSamplerState* mSamplerStates;
@@ -274,5 +296,7 @@ namespace BansheeEngine
 		bool mTransposeMatrices;
 		bool mIsDestroyed;
 		UINT32 mCoreDirtyFlags;
+
+		FrameAlloc* mFrameAlloc;
 	};
 }

+ 7 - 18
BansheeCore/Include/BsBindableGpuParams.h → BansheeCore/Include/BsGpuParamsProxy.h

@@ -5,25 +5,15 @@
 namespace BansheeEngine
 {
 	/**
-	 * @brief	Specialized class for binding GPU parameters to the render system. This is a temporary class that
-	 * 			is used for temporarily saving parameter data while parameters are scheduled to be bound to the GPU.
-	 * 			This allows us to freely modify base GpuParams without worrying about changing scheduled by still 
-	 * 			not executed parameter binds.
-	 * 			
-	 * @note	Upon assignment this class transfers ownership of its internal data. Internal data
-	 * 			is destroyed when last assigned instance goes out of scope.
-	 * 			(In short, you should never have more than one active copy of an instance of this class)
-	 * 			
-	 *			Created on the sim thread and used exclusively on the core thread.
-	 *			
-	 * @see		CoreThreadAccessorBase::bindGpuParams
+	 * @brief	Contains a snapshot of GpuParams data. It can be used for
+	 *			creating a temporary or permanent copy of GpuParams data for use
+	 *			on another thread.
 	**/
-	class BS_CORE_EXPORT BindableGpuParams
+	class BS_CORE_EXPORT GpuParamsProxy
 	{
 	public:
-		BindableGpuParams(const GpuParamsPtr& sourceParams, FrameAlloc* allocator);
-		BindableGpuParams(const BindableGpuParams& source);
-		~BindableGpuParams();
+		GpuParamsProxy(const GpuParamsPtr& sourceParams, FrameAlloc* allocator);
+		~GpuParamsProxy();
 
 		/**
 		 * @brief	Uploads all CPU stored parameter buffer data to the GPU buffers.
@@ -56,7 +46,6 @@ namespace BansheeEngine
 		const GpuParamDesc& getParamDesc() const { return mParamDesc; }
 
 	private:
-		mutable bool mOwnsData;
 		const GpuParamDesc& mParamDesc;
 		UINT8* mData;
 
@@ -65,7 +54,7 @@ namespace BansheeEngine
 		UINT32 mNumSamplerStates;
 
 		FrameAlloc* mAllocator;
-		BindableGpuParamBlock** mParamBlocks;
+		GpuParamsBlockProxy** mParamBlocks;
 		GpuParamBlockBufferPtr* mParamBlockBuffers;
 		HTexture* mTextures;
 		HSamplerState* mSamplerStates;

+ 1 - 1
BansheeCore/Include/BsHardwareBufferManager.h

@@ -54,7 +54,7 @@ namespace BansheeEngine
 		virtual GpuParamBlockBufferPtr createGpuParamBlockBuffer(UINT32 size, GpuParamBlockUsage usage = GPBU_DYNAMIC);
 
 		/**
-		 * @brief	Creates a generic buffer that can be passed as a parameter to a shader. This type of buffer can hold
+		 * @brief	Creates a generic buffer that can be passed as a parameter to a GPU program. This type of buffer can hold
 		 *			various type of data and can be used for various purposes. See "GpuBufferType" for explanation of
 		 *			different buffer types.
 		 *

+ 53 - 19
BansheeCore/Include/BsMaterial.h

@@ -12,6 +12,16 @@
 
 namespace BansheeEngine
 {
+	/**
+	 * @brief	Type of material dirty flags
+	 */
+	enum MaterialDirtyFlag
+	{
+		Material = 0x01, /**< Internal material data is dirty. */
+		Proxy = 0x02, /**< Active proxy needs to be updated. */
+		Params = 0x04 /**< Parameters are dirty. */
+	};
+
 	/**
 	 * @brief	Helper class containing parameters for all types
 	 * 			of GPU programs used in a pass.
@@ -38,6 +48,18 @@ namespace BansheeEngine
 			return *paramArray[idx];
 		}
 
+		/**
+		 * @brief	Sets GPU parameters based on an index.
+		 *
+		 * @note	Useful when needing to iterate over all sets of GPU parameters.
+		 */
+		void setParamByIdx(UINT32 idx, const GpuParamsPtr& params)
+		{
+			GpuParamsPtr* paramArray[] = {&mVertParams, &mFragParams, &mGeomParams, &mHullParams, &mDomainParams, &mComputeParams};
+
+			(*paramArray[idx]) = params;
+		}
+
 		/**
 		 * @brief	Returns the total number of stored sets of 
 		 * 			GPU parameters in this object.
@@ -101,17 +123,17 @@ namespace BansheeEngine
 		ShaderPtr 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); }
+		void setTexture(const String& name, const HTexture& value) { return getParamTexture(name).set(value); }
 
 		/** @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); }
+		void setSamplerState(const String& name, const HSamplerState& value) { return getParamSamplerState(name).set(value); }
 
 		/**   
 		 *  @brief	Assigns a float value to the shader parameter with the specified name. 
 		 *
 		 *			Optionally if the parameter is an array you may provide an array index to assign the value to.
 		 */
-		void setFloat(const String& name, float value, UINT32 arrayIdx = 0)						{ return getParamFloat(name).set(value, arrayIdx); }
+		void setFloat(const String& name, float value, UINT32 arrayIdx = 0)	{ return getParamFloat(name).set(value, arrayIdx); }
 
 		/**   
 		 *  @brief	Assigns a color to the shader parameter with the specified name. 
@@ -125,35 +147,35 @@ namespace BansheeEngine
 		 *
 		 *			Optionally if the parameter is an array you may provide an array index to assign the value to.
 		 */
-		void setVec2(const String& name, const Vector2& value, UINT32 arrayIdx = 0)				{ return getParamVec2(name).set(value, arrayIdx); }
+		void setVec2(const String& name, const Vector2& value, UINT32 arrayIdx = 0)	{ return getParamVec2(name).set(value, arrayIdx); }
 
 		/**   
 		 *  @brief	Assigns a 3D vector to the shader parameter with the specified name. 
 		 *
 		 *			Optionally if the parameter is an array you may provide an array index to assign the value to.
 		 */
-		void setVec3(const String& name, const Vector3& value, UINT32 arrayIdx = 0)				{ return getParamVec3(name).set(value, arrayIdx); }
+		void setVec3(const String& name, const Vector3& value, UINT32 arrayIdx = 0)	{ return getParamVec3(name).set(value, arrayIdx); }
 
 		/**   
 		 *  @brief	Assigns a 4D vector to the shader parameter with the specified name. 
 		 *
 		 *			Optionally if the parameter is an array you may provide an array index to assign the value to.
 		 */
-		void setVec4(const String& name, const Vector4& value, UINT32 arrayIdx = 0)				{ return getParamVec4(name).set(value, arrayIdx); }
+		void setVec4(const String& name, const Vector4& value, UINT32 arrayIdx = 0)	{ return getParamVec4(name).set(value, arrayIdx); }
 
 		/**   
 		 *  @brief	Assigns a 3x3 matrix to the shader parameter with the specified name. 
 		 *
 		 *			Optionally if the parameter is an array you may provide an array index to assign the value to.
 		 */
-		void setMat3(const String& name, const Matrix3& value, UINT32 arrayIdx = 0)				{ return getParamMat3(name).set(value, arrayIdx); }
+		void setMat3(const String& name, const Matrix3& value, UINT32 arrayIdx = 0)	{ return getParamMat3(name).set(value, arrayIdx); }
 
 		/**   
 		 *  @brief	Assigns a 4x4 matrix to the shader parameter with the specified name. 
 		 *
 		 *			Optionally if the parameter is an array you may provide an array index to assign the value to.
 		 */
-		void setMat4(const String& name, const Matrix4& value, UINT32 arrayIdx = 0)				{ return getParamMat4(name).set(value, arrayIdx); }
+		void setMat4(const String& name, const Matrix4& value, UINT32 arrayIdx = 0)	{ return getParamMat4(name).set(value, arrayIdx); }
 
 		/**   
 		 *  @brief	Assigns a structure to the shader parameter with the specified name.
@@ -163,7 +185,7 @@ namespace BansheeEngine
 		 *
 		 *			Optionally if the parameter is an array you may provide an array index to assign the value to.
 		 */
-		void setStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx = 0)	{ return getParamStruct(name).set(value, size, arrayIdx); }
+		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.
@@ -175,52 +197,52 @@ namespace BansheeEngine
 		void setParamBlockBuffer(const String& name, const GpuParamBlockBufferPtr& paramBlock);
 
 		/** @brief	Returns a texture assigned with the parameter with the specified name. */
-		HTexture getTexture(const String& name) const										{ return getParamTexture(name).get(); }
+		HTexture getTexture(const String& name) const { return getParamTexture(name).get(); }
 
 		/** @brief	Returns a sampler state assigned with the parameter with the specified name. */
-		HSamplerState getSamplerState(const String& name) const								{ return getParamSamplerState(name).get(); }
+		HSamplerState getSamplerState(const String& name) const	{ return getParamSamplerState(name).get(); }
 
 		/**
 		 * @brief	Returns a float value assigned with the parameter with the specified name.
 		 *
 		 *			Optionally if the parameter is an array you may provide an array index you which to retrieve.
 		 */
-		float getFloat(const String& name, UINT32 arrayIdx = 0) const						{ return getParamFloat(name).get(arrayIdx); }
+		float getFloat(const String& name, UINT32 arrayIdx = 0) const { return getParamFloat(name).get(arrayIdx); }
 
 		/**
 		 * @brief	Returns a 2D vector assigned with the parameter with the specified name.
 		 *
 		 *			Optionally if the parameter is an array you may provide an array index you which to retrieve.
 		 */
-		Vector2 getVec2(const String& name, UINT32 arrayIdx = 0) const						{ return getParamVec2(name).get(arrayIdx); }
+		Vector2 getVec2(const String& name, UINT32 arrayIdx = 0) const { return getParamVec2(name).get(arrayIdx); }
 
 		/**
 		 * @brief	Returns a 3D vector assigned with the parameter with the specified name.
 		 *
 		 *			Optionally if the parameter is an array you may provide an array index you which to retrieve.
 		 */
-		Vector3 getVec3(const String& name, UINT32 arrayIdx = 0) const						{ return getParamVec3(name).get(arrayIdx); }
+		Vector3 getVec3(const String& name, UINT32 arrayIdx = 0) const { return getParamVec3(name).get(arrayIdx); }
 
 		/**
 		 * @brief	Returns a 4D vector assigned with the parameter with the specified name.
 		 *
 		 *			Optionally if the parameter is an array you may provide an array index you which to retrieve.
 		 */
-		Vector4 getVec4(const String& name, UINT32 arrayIdx = 0) const						{ return getParamVec4(name).get(arrayIdx); }
+		Vector4 getVec4(const String& name, UINT32 arrayIdx = 0) const { return getParamVec4(name).get(arrayIdx); }
 
 		/**
 		 * @brief	Returns a 3x3 matrix assigned with the parameter with the specified name.
 		 *
 		 *			Optionally if the parameter is an array you may provide an array index you which to retrieve.
 		 */
-		Matrix3 getMat3(const String& name, UINT32 arrayIdx = 0) const						{ return getParamMat3(name).get(arrayIdx); }
+		Matrix3 getMat3(const String& name, UINT32 arrayIdx = 0) const { return getParamMat3(name).get(arrayIdx); }
 
 		/**
 		 * @brief	Returns a 4x4 matrix assigned with the parameter with the specified name.
 		 *
 		 *			Optionally if the parameter is an array you may provide an array index you which to retrieve.
 		 */
-		Matrix4 getMat4(const String& name, UINT32 arrayIdx = 0) const						{ return getParamMat4(name).get(arrayIdx); }
+		Matrix4 getMat4(const String& name, UINT32 arrayIdx = 0) const { return getParamMat4(name).get(arrayIdx); }
 
 		/**
 		 * @brief	Returns a buffer representing a structure assigned to the parameter with the specified name.
@@ -385,14 +407,24 @@ namespace BansheeEngine
 		 *
 		 * @note	Sim thread only.
 		 */
-		bool _isCoreDirty() const;
+		bool _isCoreDirty(MaterialDirtyFlag flag) const;
 
 		/**
 		 * @brief	Marks the core dirty flag as clean.
 		 *
 		 * @note	Sim thread only.
 		 */
-		void _markCoreClean();
+		void _markCoreClean(MaterialDirtyFlag flag);
+
+		/**
+		 * @brief	Gets the currently active proxy of this material.
+		 */
+		MaterialProxyPtr _getActiveProxy() const { return mActiveProxy; }
+
+		/**
+		 * @brief	Sets an active proxy for this material.
+		 */
+		void _setActiveProxy(const MaterialProxyPtr& proxy) { mActiveProxy = proxy; }
 
 		/**
 		 * @brief	Creates a new core proxy from the currently set material data. Core proxies ensure
@@ -449,6 +481,8 @@ namespace BansheeEngine
 		Vector<PassParametersPtr> mParametersPerPass;
 		Vector<GpuParamBlockBufferPtr> mParamBuffers;
 
+		MaterialProxyPtr mActiveProxy;
+
 		Material();
 
 		/**

+ 23 - 2
BansheeCore/Include/BsMeshBase.h

@@ -9,6 +9,16 @@
 
 namespace BansheeEngine
 {
+	/**
+	 * @brief	Type of mesh dirty flags
+	 */
+	enum MeshDirtyFlag
+	{
+		Mesh = 0x01, /**< Internal mesh data is dirty. */
+		Proxy = 0x02 /**< Active proxy needs to be updated. */
+	};
+
+
 	/**
 	 * @brief	Type of buffers used by a mesh. These options usually affect performance and 
 	 *			you should specify static if you don't plan on modifying the mesh often,
@@ -138,14 +148,24 @@ namespace BansheeEngine
 		 *
 		 * @note	Sim thread only.
 		 */
-		bool _isCoreDirty() const { mCoreDirtyFlags != 0; }
+		bool _isCoreDirty(MeshDirtyFlag flag) const { (mCoreDirtyFlags & flag) != 0; }
 
 		/**
 		 * @brief	Marks the core dirty flag as clean.
 		 *
 		 * @note	Sim thread only.
 		 */
-		void _markCoreClean() { mCoreDirtyFlags = 0; }
+		void _markCoreClean(MeshDirtyFlag flag) { mCoreDirtyFlags &= ~flag; }
+
+		/**
+		 * @brief	Gets the currently active proxy of this material.
+		 */
+		MeshProxyPtr _getActiveProxy(UINT32 i) const { return mActiveProxies[i]; }
+
+		/**
+		 * @brief	Sets an active proxy for this material.
+		 */
+		void _setActiveProxy(UINT32 i, const MeshProxyPtr& proxy) { mActiveProxies[i] = proxy; }
 
 		/**
 		 * @brief	Creates a new core proxy from the current mesh data. Core proxy contains a snapshot of 
@@ -167,6 +187,7 @@ namespace BansheeEngine
 		Vector<SubMesh> mSubMeshes; // Immutable
 		UINT32 mNumVertices; // Immutable
 		UINT32 mNumIndices; // Immutable
+		Vector<MeshProxyPtr> mActiveProxies;
 
 		UINT32 mCoreDirtyFlags;
 

+ 1 - 1
BansheeCore/Include/BsMeshBaseRTTI.h

@@ -15,7 +15,7 @@ namespace BansheeEngine
 		SubMesh& getSubMesh(MeshBase* obj, UINT32 arrayIdx) { return obj->mSubMeshes[arrayIdx]; }
 		void setSubMesh(MeshBase* obj, UINT32 arrayIdx, SubMesh& value) { obj->mSubMeshes[arrayIdx] = value; }
 		UINT32 getNumSubmeshes(MeshBase* obj) { return (UINT32)obj->mSubMeshes.size(); }
-		void setNumSubmeshes(MeshBase* obj, UINT32 numElements) { obj->mSubMeshes.resize(numElements); }
+		void setNumSubmeshes(MeshBase* obj, UINT32 numElements) { obj->mSubMeshes.resize(numElements); obj->mActiveProxies.resize(numElements); }
 
 		UINT32& getNumVertices(MeshBase* obj) { return obj->mNumVertices; }
 		void setNumVertices(MeshBase* obj, UINT32& value) { obj->mNumVertices = value; }

+ 1 - 1
BansheeCore/Include/BsRenderSystem.h

@@ -187,7 +187,7 @@ namespace BansheeEngine
 		 * @brief	Binds GPU program parameters. Caller must ensure these match the previously
 		 *			bound GPU program.
 		 */
-		virtual void bindGpuParams(GpuProgramType gptype, BindableGpuParams& params) = 0;
+		virtual void bindGpuParams(GpuProgramType gptype, GpuParamsPtr params) = 0;
 
 		/**
 		 * @brief	Unbinds a program of a given type. 

+ 1 - 0
BansheeCore/Include/BsRenderableProxy.h

@@ -34,6 +34,7 @@ namespace BansheeEngine
 		~RenderableProxy();
 
 		Vector<RenderableElement*> renderableElements;
+		RenderableType renderableType;
 	};
 
 	typedef std::shared_ptr<RenderableProxy> RenderableProxyPtr;

+ 0 - 11
BansheeCore/Include/BsRenderer.h

@@ -7,17 +7,6 @@
 
 namespace BansheeEngine
 {
-	/**
-	 * @brief	Contains a basic sent of renderable types that may be supported by a renderer.
-	 *			These can be used as a guide and renderer plugins can use their own types as needed.
-	 */
-	enum RenderableType
-	{
-		RenType_UnlitUntextured,
-		RenType_UnlitTextured
-		// TODO - Add more types as I improve the Renderer with advanced techniques
-	};
-
 	/**
 	 * @brief	Primarily rendering class that allows you to specify how to render objects that exist
 	 *			in the scene graph. You need to provide your own implementation of your class.

+ 1 - 1
BansheeCore/Include/BsRendererParams.h

@@ -10,7 +10,7 @@ namespace BansheeEngine
 	// TODO UNDOCUMENTED
 	enum RendererBlockSemantic
 	{
-		RBS_Once,
+		RBS_Occassional,
 		RBS_PerFrame,
 		RBS_PerObject
 	};

+ 0 - 15
BansheeCore/Source/BsBindableGpuParamBlock.cpp

@@ -1,15 +0,0 @@
-#include "BsBindableGpuParamBlock.h"
-#include "BsGpuParamBlockBuffer.h"
-
-namespace BansheeEngine
-{
-	BindableGpuParamBlock::BindableGpuParamBlock()
-		:mDirty(true), mData(nullptr), mSize(0)
-	{ }
-
-	void BindableGpuParamBlock::uploadToBuffer(GpuParamBlockBufferPtr buffer)
-	{
-		buffer->writeData(mData);
-		mDirty = false;
-	}
-}

+ 1 - 1
BansheeCore/Source/BsCoreThreadAccessor.cpp

@@ -101,7 +101,7 @@ namespace BansheeEngine
 
 	void CoreThreadAccessorBase::bindGpuParams(GpuProgramType gptype, const GpuParamsPtr& params)
 	{
-		mCommandQueue->queue(std::bind(&RenderSystem::bindGpuParams, RenderSystem::instancePtr(), gptype, BindableGpuParams(params, gCoreThread().getFrameAlloc())));
+		mCommandQueue->queue(std::bind(&RenderSystem::bindGpuParams, RenderSystem::instancePtr(), gptype, params->clone(gCoreThread().getFrameAlloc())));
 	}
 
 	void CoreThreadAccessorBase::beginRender()

+ 6 - 0
BansheeCore/Source/BsGpuParamBlock.cpp

@@ -72,4 +72,10 @@ namespace BansheeEngine
 
 		mDirty = true;
 	}
+
+	void GpuParamBlock::uploadToBuffer(const GpuParamBlockBufferPtr& buffer)
+	{
+		buffer->writeData(mData);
+		mDirty = false;
+	}
 }

+ 9 - 0
BansheeCore/Source/BsGpuParamBlockBuffer.cpp

@@ -1,5 +1,6 @@
 #include "BsGpuParamBlockBuffer.h"
 #include "BsGpuParamBlock.h"
+#include "BsGpuParamBlockBufferProxy.h"
 
 namespace BansheeEngine
 {
@@ -25,6 +26,14 @@ namespace BansheeEngine
 		CoreObject::initialize();
 	}
 
+	GpuParamBlockBufferProxyPtr GpuParamBlockBuffer::_createProxy() const
+	{
+		GpuParamBlockBufferProxyPtr proxy = bs_shared_ptr<GpuParamBlockBufferProxy>(mSize);
+		memcpy(proxy->block->getData(), mParamBlock->getData(), mSize);
+		
+		return proxy;
+	}
+
 	void GenericGpuParamBlockBuffer::writeData(const UINT8* data)
 	{
 		memcpy(mData, data, mSize);

+ 14 - 0
BansheeCore/Source/BsGpuParamBlockBufferProxy.cpp

@@ -0,0 +1,14 @@
+#include "BsGpuParamBlockBufferProxy.h"
+
+namespace BansheeEngine
+{
+	GpuParamBlockBufferProxy::GpuParamBlockBufferProxy(UINT32 size)
+	{
+		block = bs_new<GpuParamBlock>(size);
+	}
+
+	GpuParamBlockBufferProxy::~GpuParamBlockBufferProxy()
+	{
+		bs_delete(block);
+	}
+}

+ 112 - 29
BansheeCore/Source/BsGpuParams.cpp

@@ -2,16 +2,16 @@
 #include "BsGpuParamDesc.h"
 #include "BsGpuParamBlock.h"
 #include "BsGpuParamBlockBuffer.h"
-#include "BsBindableGpuParamBlock.h"
 #include "BsVector2.h"
+#include "BsFrameAlloc.h"
 #include "BsDebug.h"
 #include "BsException.h"
 
 namespace BansheeEngine
 {
 	GpuParamsInternalData::GpuParamsInternalData()
-		:mTransposeMatrices(false), mData(nullptr), mNumParamBlocks(0), mNumTextures(0), mNumSamplerStates(0),
-		mParamBlocks(nullptr), mParamBlockBuffers(nullptr), mTextures(nullptr), mSamplerStates(nullptr), mCoreDirtyFlags(0xFFFFFFFF)
+		:mTransposeMatrices(false), mData(nullptr), mNumParamBlocks(0), mNumTextures(0), mNumSamplerStates(0), mFrameAlloc(nullptr),
+		mParamBlockBuffers(nullptr), mTextures(nullptr), mSamplerStates(nullptr), mCoreDirtyFlags(0xFFFFFFFF)
 	{ }
 
 	GpuParams::GpuParams(GpuParamDesc& paramDesc, bool transposeMatrices)
@@ -40,15 +40,13 @@ namespace BansheeEngine
 
 		// Allocate everything in a single block of memory to get rid of extra memory allocations
 		UINT32 bufferSize = 0;
-		UINT32 paramBlockOffset = 0;
 		UINT32 paramBlockBufferOffset = 0;
 		UINT32 textureOffset = 0;
 		UINT32 samplerStateOffset = 0;
 
-		getInternalBufferData(bufferSize, paramBlockOffset, paramBlockBufferOffset, textureOffset, samplerStateOffset);
+		getInternalBufferData(bufferSize, paramBlockBufferOffset, textureOffset, samplerStateOffset);
 
 		mInternalData->mData = (UINT8*)bs_alloc(bufferSize);
-		mInternalData->mParamBlocks = (GpuParamBlock**)(mInternalData->mData + paramBlockOffset);
 		mInternalData->mParamBlockBuffers = (GpuParamBlockBufferPtr*)(mInternalData->mData + paramBlockBufferOffset);
 		mInternalData->mTextures = (HTexture*)(mInternalData->mData + textureOffset);
 		mInternalData->mSamplerStates = (HSamplerState*)(mInternalData->mData + samplerStateOffset);
@@ -56,8 +54,6 @@ namespace BansheeEngine
 		// Ensure everything is constructed
 		for (UINT32 i = 0; i < mInternalData->mNumParamBlocks; i++)
 		{
-			mInternalData->mParamBlocks[i] = nullptr;
-
 			GpuParamBlockBufferPtr* ptrToIdx = (&mInternalData->mParamBlockBuffers[i]);
 			ptrToIdx = new (&mInternalData->mParamBlockBuffers[i]) GpuParamBlockBufferPtr(nullptr);
 		}
@@ -78,7 +74,7 @@ namespace BansheeEngine
 	GpuParams::GpuParams(GpuParamDesc& paramDesc, PrivatelyConstruct& dummy)
 		:mParamDesc(paramDesc)
 	{
-		mInternalData = bs_shared_ptr<GpuParamsInternalData>();
+		
 	}
 
 	GpuParams::~GpuParams()
@@ -97,7 +93,10 @@ namespace BansheeEngine
 		for (UINT32 i = 0; i < mInternalData->mNumSamplerStates; i++)
 			mInternalData->mSamplerStates[i].~ResourceHandle();
 
-		bs_free(mInternalData->mData);
+		if (mInternalData->mFrameAlloc != nullptr)
+			mInternalData->mFrameAlloc->dealloc(mInternalData->mData);
+		else
+			bs_free(mInternalData->mData);
 	}
 
 	void GpuParams::setParamBlockBuffer(UINT32 slot, const GpuParamBlockBufferPtr& paramBlockBuffer)
@@ -109,7 +108,6 @@ namespace BansheeEngine
 		}
 
 		mInternalData->mParamBlockBuffers[slot] = paramBlockBuffer;
-		mInternalData->mParamBlocks[slot] = paramBlockBuffer->getParamBlock();
 
 		markCoreDirty();
 	}
@@ -125,7 +123,6 @@ namespace BansheeEngine
 		}
 
 		mInternalData->mParamBlockBuffers[iterFind->second.slot] = paramBlockBuffer;
-		mInternalData->mParamBlocks[iterFind->second.slot] = paramBlockBuffer->getParamBlock();
 
 		markCoreDirty();
 	}
@@ -210,49 +207,135 @@ namespace BansheeEngine
 		return nullptr;
 	}
 
-	GpuParamsPtr GpuParams::clone() const
+	GpuParamBlockBufferPtr GpuParams::getParamBlockBuffer(UINT32 slot) const
 	{
-		GpuParamsPtr myClone = bs_shared_ptr<GpuParams>(mParamDesc, PrivatelyConstruct());
-		myClone->mInternalData->mIsDestroyed = mInternalData->mIsDestroyed;
-		myClone->mInternalData->mTransposeMatrices = mInternalData->mTransposeMatrices;
-		myClone->mInternalData->mNumParamBlocks = mInternalData->mNumParamBlocks;
-		myClone->mInternalData->mNumTextures = mInternalData->mNumTextures;
-		myClone->mInternalData->mNumSamplerStates = mInternalData->mNumSamplerStates;
+		if (slot < 0 || slot >= mInternalData->mNumParamBlocks)
+		{
+			BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
+				toString(mInternalData->mNumParamBlocks - 1) + ". Requested: " + toString(slot));
+		}
+
+		return mInternalData->mParamBlockBuffers[slot];
+	}
+
+	HTexture GpuParams::getTexture(UINT32 slot)
+	{
+		if (slot < 0 || slot >= mInternalData->mNumTextures)
+		{
+			BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
+				toString(mInternalData->mNumTextures - 1) + ". Requested: " + toString(slot));
+		}
+
+		return mInternalData->mTextures[slot];
+	}
+
+	HSamplerState GpuParams::getSamplerState(UINT32 slot)
+	{
+		if (slot < 0 || slot >= mInternalData->mNumSamplerStates)
+		{
+			BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
+				toString(mInternalData->mNumSamplerStates - 1) + ". Requested: " + toString(slot));
+		}
+
+		return mInternalData->mSamplerStates[slot];
+	}
+
+	void GpuParams::updateHardwareBuffers()
+	{
+		for (UINT32 i = 0; i < mInternalData->mNumParamBlocks; i++)
+		{
+			if (mInternalData->mParamBlockBuffers[i] != nullptr)
+			{
+				GpuParamBlock* block = mInternalData->mParamBlockBuffers[i]->getParamBlock();
+				if (block->isDirty())
+					block->uploadToBuffer(mInternalData->mParamBlockBuffers[i]);
+			}
+		}
+	}
 
+	GpuParamsPtr GpuParams::clone(FrameAlloc* frameAlloc) const
+	{
 		UINT32 bufferSize = 0;
-		UINT32 paramBlockOffset = 0;
 		UINT32 paramBlockBufferOffset = 0;
 		UINT32 textureOffset = 0;
 		UINT32 samplerStateOffset = 0;
 
-		getInternalBufferData(bufferSize, paramBlockOffset, paramBlockBufferOffset, textureOffset, samplerStateOffset);
+		getInternalBufferData(bufferSize, paramBlockBufferOffset, textureOffset, samplerStateOffset);
 
-		myClone->mInternalData->mData = (UINT8*)bs_alloc(bufferSize);
-		memcpy(myClone->mInternalData->mData, mInternalData->mData, bufferSize);
+		GpuParamsPtr myClone = nullptr;
+		
+		if (frameAlloc != nullptr)
+		{
+			StdFrameAlloc<GpuParams> myAlloc(frameAlloc);
+			myClone = std::allocate_shared<GpuParams>(myAlloc, mParamDesc, PrivatelyConstruct());
+			myClone->mInternalData = std::allocate_shared<GpuParamsInternalData>(myAlloc);
+			myClone->mInternalData->mData = frameAlloc->alloc(bufferSize);
+			myClone->mInternalData->mFrameAlloc = frameAlloc;
+		}
+		else
+		{
+			myClone = bs_shared_ptr<GpuParams>(mParamDesc, PrivatelyConstruct());;
+			myClone->mInternalData = bs_shared_ptr<GpuParamsInternalData>();
+			myClone->mInternalData->mData = (UINT8*)bs_alloc(bufferSize);
+		}
+		
+		myClone->mInternalData->mIsDestroyed = mInternalData->mIsDestroyed;
+		myClone->mInternalData->mTransposeMatrices = mInternalData->mTransposeMatrices;
+		myClone->mInternalData->mNumParamBlocks = mInternalData->mNumParamBlocks;
+		myClone->mInternalData->mNumTextures = mInternalData->mNumTextures;
+		myClone->mInternalData->mNumSamplerStates = mInternalData->mNumSamplerStates;
 
-		myClone->mInternalData->mParamBlocks = (GpuParamBlock**)(myClone->mInternalData->mData + paramBlockOffset);
 		myClone->mInternalData->mParamBlockBuffers = (GpuParamBlockBufferPtr*)(myClone->mInternalData->mData + paramBlockBufferOffset);
 		myClone->mInternalData->mTextures = (HTexture*)(myClone->mInternalData->mData + textureOffset);
 		myClone->mInternalData->mSamplerStates = (HSamplerState*)(myClone->mInternalData->mData + samplerStateOffset);
 
+		for (UINT32 i = 0; i < mInternalData->mNumParamBlocks; i++)
+		{
+			myClone->mInternalData->mParamBlockBuffers[i] = mInternalData->mParamBlockBuffers[i];
+		}
+
+		for (UINT32 i = 0; i < mInternalData->mNumTextures; i++)
+		{
+			myClone->mInternalData->mTextures[i] = mInternalData->mTextures[i];
+		}
+
+		for (UINT32 i = 0; i < mInternalData->mNumSamplerStates; i++)
+		{
+			myClone->mInternalData->mSamplerStates[i] = mInternalData->mSamplerStates[i];
+		}
+
 		return myClone;
 	}
 
-	void GpuParams::getInternalBufferData(UINT32& bufferSize, UINT32& paramBlockOffset, UINT32& paramBlockBufferOffset,
+	void GpuParams::getInternalBufferData(UINT32& bufferSize, UINT32& paramBlockBufferOffset,
 		UINT32& textureOffset, UINT32& samplerStateOffset) const
 	{
-		UINT32 paramBlockBufferSize = mInternalData->mNumParamBlocks * sizeof(GpuParamBlock*);
 		UINT32 paramBlockBuffersBufferSize = mInternalData->mNumParamBlocks * sizeof(GpuParamBlockBufferPtr);
 		UINT32 textureBufferSize = mInternalData->mNumTextures * sizeof(HTexture);
 		UINT32 samplerStateBufferSize = mInternalData->mNumSamplerStates * sizeof(HSamplerState);
 
-		bufferSize = paramBlockBufferSize + paramBlockBuffersBufferSize + textureBufferSize + samplerStateBufferSize;
-		paramBlockOffset = 0;
-		paramBlockBufferOffset = paramBlockOffset + paramBlockBufferSize;
+		bufferSize = paramBlockBuffersBufferSize + textureBufferSize + samplerStateBufferSize;
+		paramBlockBufferOffset = 0;
 		textureOffset = paramBlockBufferOffset + paramBlockBuffersBufferSize;
 		samplerStateOffset = textureOffset + textureBufferSize;
 	}
 
+	bool GpuParams::_isCoreDirty() const 
+	{ 
+		return mInternalData->mCoreDirtyFlags != 0; 
+	}
+
+	void GpuParams::_markCoreClean()
+	{
+		mInternalData->mCoreDirtyFlags = 0;
+
+		for (UINT32 i = 0; i < mInternalData->mNumParamBlocks; i++)
+		{
+			if (mInternalData->mParamBlockBuffers[i] != nullptr)
+				mInternalData->mParamBlockBuffers[i]->getParamBlock()->setDirty(false);
+		}
+	}
+
 	void GpuParams::markCoreDirty() 
 	{ 
 		mInternalData->mCoreDirtyFlags = 0xFFFFFFFF; 

+ 57 - 33
BansheeCore/Source/BsBindableGpuParams.cpp → BansheeCore/Source/BsGpuParamsProxy.cpp

@@ -1,4 +1,4 @@
-#include "BsBindableGpuParams.h"
+#include "BsGpuParamsProxy.h"
 #include "BsGpuParams.h"
 #include "BsGpuParamDesc.h"
 #include "BsBindableGpuParamBlock.h"
@@ -8,12 +8,54 @@
 
 namespace BansheeEngine
 {
-	BindableGpuParams::BindableGpuParams(const GpuParamsPtr& params, FrameAlloc* allocator)
-		:mOwnsData(true), mParamDesc(params->getParamDesc()), mData(nullptr), mNumParamBlocks(0), mAllocator(allocator),
+	/**
+	* @brief	Specialized class for send GPU parameters to the core thread. Represents a single
+	* 			parameter block buffer and is used for temporary storage of GPU parameters.
+	*
+	* @note		Due to the way allocation is handled, this class is not allowed to have a destructor.
+	*
+	* @see		BindableGpuParams
+	*/
+	class BS_CORE_EXPORT GpuParamsBlockProxy
+	{
+	public:
+		GpuParamsBlockProxy()
+			:mDirty(true), mData(nullptr), mSize(0)
+		{ }
+
+		/**
+		* @brief	Uploads the current data to the specified buffer, and marks the block a non-dirty.
+		*
+		* @note	Core thread only.
+		*/
+		void uploadToBuffer(GpuParamBlockBufferPtr buffer)
+		{
+			buffer->writeData(mData);
+			mDirty = false;
+		}
+
+		/**
+		* @brief	Query if this object is dirty. If dirty the data of this block
+		* 			will need to be uploaded to a GPU buffer.
+		*
+		* @note	Core thread only.
+		*/
+		bool isDirty() const { return mDirty; }
+	protected:
+		friend class GpuParams;
+		friend class GpuParamsProxy;
+
+		UINT8* mData;
+		UINT32 mSize;
+		bool mDirty;
+	};
+
+	GpuParamsProxy::GpuParamsProxy(const GpuParamsPtr& params, FrameAlloc* allocator)
+		:mParamDesc(params->getParamDesc()), mData(nullptr), mNumParamBlocks(0), mAllocator(allocator),
 		mNumTextures(0), mNumSamplerStates(0),mParamBlocks(nullptr), mParamBlockBuffers(nullptr), mTextures(nullptr), mSamplerStates(nullptr)
 	{
 		// Allocate everything in a single block of memory to get rid of extra memory allocations
-		UINT32 paramBlockBufferSize = params->mInternalData->mNumParamBlocks * sizeof(BindableGpuParamBlock*);
+		UINT32 paramBlockBufferSize = params->mInternalData->mNumParamBlocks * sizeof(GpuParamsBlockProxy*);
 		UINT32 paramBlockBuffersBufferSize = params->mInternalData->mNumParamBlocks * sizeof(GpuParamBlockBufferPtr);
 		UINT32 textureBufferSize = params->mInternalData->mNumTextures * sizeof(HTexture);
 		UINT32 samplerStateBufferSize = params->mInternalData->mNumSamplerStates * sizeof(HSamplerState);
@@ -22,7 +64,7 @@ namespace BansheeEngine
 		for (UINT32 i = 0; i < params->mInternalData->mNumParamBlocks; i++)
 		{
 			if (params->mInternalData->mParamBlockBuffers[i] != nullptr)
-				bufferSize += sizeof(BindableGpuParamBlock)+params->mInternalData->mParamBlockBuffers[i]->getSize();
+				bufferSize += sizeof(GpuParamsBlockProxy)+params->mInternalData->mParamBlockBuffers[i]->getSize();
 		}
 
 		mData = (UINT8*)allocator->alloc(bufferSize);
@@ -31,7 +73,7 @@ namespace BansheeEngine
 		mNumSamplerStates = params->mInternalData->mNumSamplerStates;
 
 		UINT8* dataIter = mData;
-		mParamBlocks = (BindableGpuParamBlock**)dataIter;
+		mParamBlocks = (GpuParamsBlockProxy**)dataIter;
 		dataIter += paramBlockBufferSize;
 
 		mParamBlockBuffers = (GpuParamBlockBufferPtr*)dataIter;
@@ -55,9 +97,9 @@ namespace BansheeEngine
 				GpuParamBlock* paramBlock = params->mInternalData->mParamBlockBuffers[i]->getParamBlock();
 
 				UINT32 bufferSize = paramBlock->getSize();
-				mParamBlocks[i] = (BindableGpuParamBlock*)dataIter;
+				mParamBlocks[i] = (GpuParamsBlockProxy*)dataIter;
 
-				dataIter += sizeof(BindableGpuParamBlock);
+				dataIter += sizeof(GpuParamsBlockProxy);
 				mParamBlocks[i]->mData = dataIter;
 
 				dataIter += bufferSize;
@@ -69,33 +111,15 @@ namespace BansheeEngine
 		}
 	}
 
-	BindableGpuParams::BindableGpuParams(const BindableGpuParams& source)
-		:mParamDesc(source.mParamDesc)
-	{
-		mOwnsData = true;
-		source.mOwnsData = false;
-
-		mAllocator = source.mAllocator;
-		mData = source.mData;
-		mNumParamBlocks = source.mNumParamBlocks;
-		mNumTextures = source.mNumTextures;
-		mNumSamplerStates = source.mNumSamplerStates;
-
-		mParamBlocks = source.mParamBlocks;
-		mParamBlockBuffers = source.mParamBlockBuffers;
-		mTextures = source.mTextures;
-		mSamplerStates = source.mSamplerStates;
-	}
-
-	BindableGpuParams::~BindableGpuParams()
+	GpuParamsProxy::~GpuParamsProxy()
 	{
-		if(mOwnsData && mData != nullptr)
+		if(mData != nullptr)
 		{
 			mAllocator->dealloc(mData);
 		}
 	}
 
-	GpuParamBlockBufferPtr BindableGpuParams::getParamBlockBuffer(UINT32 slot) const
+	GpuParamBlockBufferPtr GpuParamsProxy::getParamBlockBuffer(UINT32 slot) const
 	{
 		if(slot < 0 || slot >= mNumParamBlocks)
 		{
@@ -106,7 +130,7 @@ namespace BansheeEngine
 		return mParamBlockBuffers[slot];
 	}
 
-	GpuParamBlockBufferPtr BindableGpuParams::getParamBlockBuffer(const String& name) const
+	GpuParamBlockBufferPtr GpuParamsProxy::getParamBlockBuffer(const String& name) const
 	{
 		auto iterFind = mParamDesc.paramBlocks.find(name);
 
@@ -119,7 +143,7 @@ namespace BansheeEngine
 		return mParamBlockBuffers[iterFind->second.slot];
 	}
 
-	HTexture BindableGpuParams::getTexture(UINT32 slot)
+	HTexture GpuParamsProxy::getTexture(UINT32 slot)
 	{
 		if(slot < 0 || slot >= mNumTextures)
 		{
@@ -130,7 +154,7 @@ namespace BansheeEngine
 		return mTextures[slot];
 	}
 
-	HSamplerState BindableGpuParams::getSamplerState(UINT32 slot)
+	HSamplerState GpuParamsProxy::getSamplerState(UINT32 slot)
 	{
 		if(slot < 0 || slot >= mNumSamplerStates)
 		{
@@ -141,7 +165,7 @@ namespace BansheeEngine
 		return mSamplerStates[slot];
 	}
 
-	void BindableGpuParams::updateHardwareBuffers()
+	void GpuParamsProxy::updateHardwareBuffers()
 	{
 		for(size_t i = 0; i < mNumParamBlocks; i++)
 		{

+ 38 - 7
BansheeCore/Source/BsMaterial.cpp

@@ -10,7 +10,6 @@
 #include "BsGpuParamDesc.h"
 #include "BsMaterialRTTI.h"
 #include "BsMaterialManager.h"
-#include "BsBindableGpuParams.h"
 #include "BsDebug.h"
 #include "BsResources.h"
 
@@ -700,17 +699,49 @@ namespace BansheeEngine
 		BS_EXCEPT(InternalErrorException, "Shader has no parameter with the name: " + name);
 	}
 
-	bool Material::_isCoreDirty() const 
+	bool Material::_isCoreDirty(MaterialDirtyFlag flag) const
 	{ 
-		return mCoreDirtyFlags != 0 || (mShader != nullptr && mShader->_isCoreDirty()); 
+		if (flag == MaterialDirtyFlag::Params)
+		{
+			for (auto& paramsPerPass : mParametersPerPass)
+			{
+				for (UINT32 i = 0; i < paramsPerPass->getNumParams(); i++)
+				{
+					GpuParamsPtr params = paramsPerPass->getParamByIdx(i);
+					if (params != nullptr && params->_isCoreDirty())
+						return true;
+				}
+			}
+
+			return false;
+		}
+		else
+			return (mCoreDirtyFlags & flag) != 0 || (mShader != nullptr && mShader->_isCoreDirty());
 	}
 
-	void Material::_markCoreClean() 
+	void Material::_markCoreClean(MaterialDirtyFlag flag)
 	{ 
-		mCoreDirtyFlags = 0; 
+		mCoreDirtyFlags &= ~flag;
 
-		if (mShader != nullptr)
-			mShader->_markCoreClean();
+		if (flag == MaterialDirtyFlag::Material)
+		{
+			if (mShader != nullptr)
+				mShader->_markCoreClean();
+		}
+		
+		if (flag == MaterialDirtyFlag::Material || flag == MaterialDirtyFlag::Params)
+		{
+			for (auto& paramsPerPass : mParametersPerPass)
+			{
+				for (UINT32 i = 0; i < paramsPerPass->getNumParams(); i++)
+				{
+					GpuParamsPtr params = paramsPerPass->getParamByIdx(i);
+
+					if (params != nullptr)
+						params->_markCoreClean();
+				}
+			}
+		}
 	}
 
 	MaterialProxyPtr Material::_createProxy()

+ 2 - 0
BansheeCore/Source/BsMeshBase.cpp

@@ -9,12 +9,14 @@ namespace BansheeEngine
 		:mNumIndices(numIndices), mNumVertices(numVertices), mCoreDirtyFlags(0xFFFFFF)
 	{
 		mSubMeshes.push_back(SubMesh(0, numIndices, drawOp));
+		mActiveProxies.resize(mSubMeshes.size());
 	}
 
 	MeshBase::MeshBase(UINT32 numVertices, UINT32 numIndices, const Vector<SubMesh>& subMeshes)
 		: mNumIndices(numIndices), mNumVertices(numVertices), mCoreDirtyFlags(0xFFFFFF)
 	{
 		mSubMeshes = subMeshes;
+		mActiveProxies.resize(mSubMeshes.size());
 	}
 
 	MeshBase::MeshBase()

+ 12 - 4
BansheeD3D11RenderSystem/Include/BsD3D11RenderSystem.h

@@ -57,12 +57,20 @@ namespace BansheeEngine
 		/** @copydoc RenderSystem::drawIndexed() */
 		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount);
 
-		/** @copydoc RenderSystem::bindGpuProgram() */
+		/** 
+		 * @copydoc RenderSystem::bindGpuProgram
+		 */
 		void bindGpuProgram(HGpuProgram prg);
-		/** @copydoc RenderSystem::unbindGpuProgram() */
+
+		/** 
+		 * @copydoc RenderSystem::unbindGpuProgram
+		 */
 		void unbindGpuProgram(GpuProgramType gptype);
-		/** @copydoc RenderSystem::bindGpuParams() */
-		void bindGpuParams(GpuProgramType gptype, BindableGpuParams& params);
+
+		/** 
+		 * @copydoc RenderSystem::bindGpuParams
+		 */
+		void bindGpuParams(GpuProgramType gptype, GpuParamsPtr params);
 		
 		void setClipPlanesImpl(const PlaneList& clipPlanes);
 

+ 7 - 7
BansheeD3D11RenderSystem/Source/BsD3D11RenderSystem.cpp

@@ -19,7 +19,7 @@
 #include "BsD3D11GpuParamBlockBuffer.h"
 #include "BsD3D11InputLayoutManager.h"
 #include "BsD3D11RenderUtility.h"
-#include "BsBindableGpuParams.h"
+#include "BsGpuParams.h"
 #include "BsCoreThread.h"
 #include "BsD3D11QueryManager.h"
 #include "BsDebug.h"
@@ -484,17 +484,17 @@ namespace BansheeEngine
 		mRenderStats.numGpuProgramBinds++;
 	}
 
-	void D3D11RenderSystem::bindGpuParams(GpuProgramType gptype, BindableGpuParams& bindableParams)
+	void D3D11RenderSystem::bindGpuParams(GpuProgramType gptype, GpuParamsPtr bindableParams)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		bindableParams.updateHardwareBuffers();
+		bindableParams->updateHardwareBuffers();
 
-		const GpuParamDesc& paramDesc = bindableParams.getParamDesc();
+		const GpuParamDesc& paramDesc = bindableParams->getParamDesc();
 		
 		for(auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
 		{
-			HSamplerState& samplerState = bindableParams.getSamplerState(iter->second.slot);
+			HSamplerState& samplerState = bindableParams->getSamplerState(iter->second.slot);
 
 			if(samplerState == nullptr)
 				setSamplerState(gptype, iter->second.slot, SamplerState::getDefault());
@@ -504,7 +504,7 @@ namespace BansheeEngine
 
 		for(auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
 		{
-			HTexture texture = bindableParams.getTexture(iter->second.slot);
+			HTexture texture = bindableParams->getTexture(iter->second.slot);
 
 			if(!texture.isLoaded())
 				setTexture(gptype, iter->second.slot, false, nullptr);
@@ -518,7 +518,7 @@ namespace BansheeEngine
 
 		for(auto iter = paramDesc.paramBlocks.begin(); iter != paramDesc.paramBlocks.end(); ++iter)
 		{
-			GpuParamBlockBufferPtr currentBlockBuffer = bindableParams.getParamBlockBuffer(iter->second.slot);
+			GpuParamBlockBufferPtr currentBlockBuffer = bindableParams->getParamBlockBuffer(iter->second.slot);
 
 			if(currentBlockBuffer != nullptr)
 			{

+ 1 - 1
BansheeD3D9RenderSystem/Include/BsD3D9RenderSystem.h

@@ -47,7 +47,7 @@ namespace BansheeEngine
 		/**
 		 * @copydoc RenderSystem::bindGpuParams()
 		 */
-		void bindGpuParams(GpuProgramType gptype, BindableGpuParams& params);
+		void bindGpuParams(GpuProgramType gptype, GpuParamsPtr params);
 
 		/**
 		 * @copydoc RenderSystem::setVertexBuffers()

+ 6 - 6
BansheeD3D9RenderSystem/Source/BsD3D9RenderSystem.cpp

@@ -291,16 +291,16 @@ namespace BansheeEngine
 		RenderSystem::unbindGpuProgram(gptype);
 	}
 
-	void D3D9RenderSystem::bindGpuParams(GpuProgramType gptype, BindableGpuParams& bindableParams)
+	void D3D9RenderSystem::bindGpuParams(GpuProgramType gptype, GpuParamsPtr bindableParams)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		bindableParams.updateHardwareBuffers();
-		const GpuParamDesc& paramDesc = bindableParams.getParamDesc();
+		bindableParams->updateHardwareBuffers();
+		const GpuParamDesc& paramDesc = bindableParams->getParamDesc();
 
 		for(auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
 		{
-			HSamplerState& samplerState = bindableParams.getSamplerState(iter->second.slot);
+			HSamplerState& samplerState = bindableParams->getSamplerState(iter->second.slot);
 
 			if(samplerState == nullptr)
 				setSamplerState(gptype, iter->second.slot, SamplerState::getDefault());
@@ -310,7 +310,7 @@ namespace BansheeEngine
 
 		for(auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
 		{
-			HTexture texture = bindableParams.getTexture(iter->second.slot);
+			HTexture texture = bindableParams->getTexture(iter->second.slot);
 
 			if(!texture.isLoaded())
 				setTexture(gptype, iter->second.slot, false, nullptr);
@@ -329,7 +329,7 @@ namespace BansheeEngine
 
 			if(iterFind == bufferData.end())
 			{
-				GpuParamBlockBufferPtr paramBlock = bindableParams.getParamBlockBuffer(paramBlockSlot);
+				GpuParamBlockBufferPtr paramBlock = bindableParams->getParamBlockBuffer(paramBlockSlot);
 
 				UINT8* data = (UINT8*)bs_alloc<ScratchAlloc>(paramBlock->getSize());
 				paramBlock->readData(data);

+ 12 - 0
BansheeEngine/Include/BsEnums.h

@@ -18,4 +18,16 @@ namespace BansheeEngine
 		// Keep at the end
 		Count
 	};
+
+	/**
+	 * @brief	Contains a basic sent of renderable types that may be supported by a renderer.
+	 *			These can be used as a guide and renderer plugins can use their own types as needed.
+	 */
+	enum RenderableType
+	{
+		RenType_UnlitUntextured,
+		RenType_UnlitTextured,
+		RenType_LitTextured
+		// TODO - Add more types as I improve the Renderer with advanced techniques
+	};
 }

+ 4 - 12
BansheeEngine/Include/BsRenderable.h

@@ -34,13 +34,11 @@ namespace BansheeEngine
 		};
 
 	public:
-		void setMesh(HMesh mesh);
-
 		/**
-		 * @brief	Sets the number of materials used by the renderable. Each material
-		 *			will be used for rendering a sub-mesh in the provided Mesh.
+		 * @brief	Sets the mesh to render. All sub-meshes of the mesh will be rendered,
+		 *			and you may set individual materials for each sub-mesh.
 		 */
-		void setNumMaterials(UINT32 numMaterials);
+		void setMesh(HMesh mesh);
 
 		/**
 		 * @brief	Sets a material that will be used for rendering a sub-mesh with
@@ -69,17 +67,11 @@ namespace BansheeEngine
 		 */
 		UINT64 getLayer() const { return mLayer; }
 
-		/**
-		 * @brief	Return the number of materials used by the renderable. Each material
-		 *			will be used for rendering a sub-mesh in the provided Mesh.
-		 */
-		UINT32 getNumMaterials() const { return (UINT32)mMaterialData.size(); }
-
 		/**
 		 * @brief	Returns the material used for rendering a sub-mesh with
 		 *			the specified index.
 		 */
-		HMaterial& getMaterial(UINT32 idx) { return mMaterialData[idx].material; }
+		HMaterial getMaterial(UINT32 idx) const;
 
 		/************************************************************************/
 		/* 								CORE PROXY                      		*/

+ 1 - 1
BansheeEngine/Include/BsRenderableRTTI.h

@@ -19,7 +19,7 @@ namespace BansheeEngine
 		HMaterial& getMaterial(Renderable* obj, UINT32 idx) { return obj->mMaterialData[idx].material; }
 		void setMaterial(Renderable* obj, UINT32 idx, HMaterial& val) { obj->setMaterial(idx, val); }
 		UINT32 getNumMaterials(Renderable* obj) { return (UINT32)obj->mMaterialData.size(); }
-		void setNumMaterials(Renderable* obj, UINT32 num) { obj->setNumMaterials(num); }
+		void setNumMaterials(Renderable* obj, UINT32 num) { obj->mMaterialData.resize(num); }
 
 	public:
 		RenderableRTTI()

+ 37 - 17
BansheeEngine/Source/BsRenderable.cpp

@@ -2,7 +2,6 @@
 #include "BsRenderableRTTI.h"
 #include "BsSceneObject.h"
 #include "BsBuiltinMaterialManager.h"
-#include "BsMeshRenderData.h"
 #include "BsMesh.h"
 #include "BsMaterial.h"
 #include "BsRenderQueue.h"
@@ -32,15 +31,7 @@ namespace BansheeEngine
 	void Renderable::setMesh(HMesh mesh)
 	{
 		mMeshData = mesh;
-
-		markCoreDirty();
-	}
-
-	void Renderable::setNumMaterials(UINT32 numMaterials)
-	{
-		numMaterials = std::max(1U, numMaterials);
-
-		mMaterialData.resize(numMaterials);
+		mMaterialData.resize(mesh->getNumSubMeshes());
 
 		markCoreDirty();
 	}
@@ -57,6 +48,14 @@ namespace BansheeEngine
 		setMaterial(0, material);
 	}
 
+	HMaterial Renderable::getMaterial(UINT32 idx) const
+	{ 
+		if (mMaterialData[idx].material != nullptr)
+			return mMaterialData[idx].material;
+		else
+			return mMaterialData[0].material;
+	}
+
 	void Renderable::setLayer(UINT64 layer)
 	{
 		bool isPow2 = layer && !((layer - 1) & layer);
@@ -74,11 +73,11 @@ namespace BansheeEngine
 
 		for (auto& materialData : mMaterialData)
 		{
-			if (materialData.material != nullptr && materialData.material.isLoaded() && materialData.material->_isCoreDirty())
+			if (materialData.material != nullptr && materialData.material.isLoaded() && materialData.material->_isCoreDirty(MaterialDirtyFlag::Material))
 				return true;
 		}
 
-		if (mMeshData.mesh != nullptr && mMeshData.mesh.isLoaded() && mMeshData.mesh->_isCoreDirty())
+		if (mMeshData.mesh != nullptr && mMeshData.mesh.isLoaded() && mMeshData.mesh->_isCoreDirty(MeshDirtyFlag::Mesh))
 			return true;
 
 		return mCoreDirtyFlags; 
@@ -89,11 +88,11 @@ namespace BansheeEngine
 		for (auto& materialData : mMaterialData)
 		{
 			if (materialData.material != nullptr && materialData.material.isLoaded())
-				materialData.material->_markCoreClean();
+				materialData.material->_markCoreClean(MaterialDirtyFlag::Material);
 		}
 
 		if (mMeshData.mesh != nullptr && mMeshData.mesh.isLoaded())
-			mMeshData.mesh->_markCoreClean();
+			mMeshData.mesh->_markCoreClean(MeshDirtyFlag::Mesh);
 
 		mCoreDirtyFlags = 0;
 	}
@@ -125,15 +124,23 @@ namespace BansheeEngine
 
 		RenderableProxyPtr proxy = bs_shared_ptr<RenderableProxy>();
 
+		bool markMeshProxyClean = false;
 		for (UINT32 i = 0; i < mMeshData.mesh->getNumSubMeshes(); i++)
 		{
 			RenderableElement* renElement = bs_new<RenderableElement>();
 			renElement->layer = mLayer;
 			renElement->worldTransform = SO()->getWorldTfrm();
-			renElement->mesh = mMeshData.mesh->_createProxy(i);
+
+			if (mMeshData.mesh->_isCoreDirty(MeshDirtyFlag::Proxy))
+			{
+				mMeshData.mesh->_setActiveProxy(i, mMeshData.mesh->_createProxy(i));
+				markMeshProxyClean = true;
+			}
+
+			renElement->mesh = mMeshData.mesh->_getActiveProxy(i);
 
 			HMaterial material;
-			if (i < mMaterialData.size())
+			if (mMaterialData[i].material != nullptr)
 				material = mMaterialData[i].material;
 			else
 				material = mMaterialData[0].material;
@@ -141,11 +148,24 @@ namespace BansheeEngine
 			if (material == nullptr || !material.isLoaded())
 				material = BuiltinMaterialManager::instance().createDummyMaterial();
 
-			renElement->material = material->_createProxy();
+			if (material->_isCoreDirty(MaterialDirtyFlag::Proxy))
+			{
+				material->_setActiveProxy(material->_createProxy());
+				material->_markCoreClean(MaterialDirtyFlag::Proxy);
+			}
+
+			renElement->material = material->_getActiveProxy();
 
 			proxy->renderableElements.push_back(renElement);
 		}
 
+		if (markMeshProxyClean)
+		{
+			mMeshData.mesh->_markCoreClean(MeshDirtyFlag::Proxy);
+		}
+
+		proxy->renderableType = RenType_LitTextured;
+
 		return proxy;
 	}
 

+ 1 - 1
BansheeGLRenderSystem/Include/BsGLRenderSystem.h

@@ -100,7 +100,7 @@ namespace BansheeEngine
 		/**
 		 * @copydoc RenderSystem::bindGpuParams()
 		 */
-		void bindGpuParams(GpuProgramType gptype, BindableGpuParams& params);
+		void bindGpuParams(GpuProgramType gptype, GpuParamsPtr params);
 
 		/**
 		 * @copydoc RenderSystem::beginFrame()

+ 6 - 6
BansheeGLRenderSystem/Source/BsGLRenderSystem.cpp

@@ -237,18 +237,18 @@ namespace BansheeEngine
 		RenderSystem::unbindGpuProgram(gptype);
 	}
 
-	void GLRenderSystem::bindGpuParams(GpuProgramType gptype, BindableGpuParams& bindableParams)
+	void GLRenderSystem::bindGpuParams(GpuProgramType gptype, GpuParamsPtr bindableParams)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		bindableParams.updateHardwareBuffers();
-		const GpuParamDesc& paramDesc = bindableParams.getParamDesc();
+		bindableParams->updateHardwareBuffers();
+		const GpuParamDesc& paramDesc = bindableParams->getParamDesc();
 		GLSLGpuProgramPtr activeProgram = getActiveProgram(gptype);
 		GLuint glProgram = activeProgram->getGLHandle();
 
 		for(auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
 		{
-			HTexture texture = bindableParams.getTexture(iter->second.slot);
+			HTexture texture = bindableParams->getTexture(iter->second.slot);
 
 			if(!texture.isLoaded())
 				setTexture(gptype, iter->second.slot, false, nullptr);
@@ -259,7 +259,7 @@ namespace BansheeEngine
 		UINT32 texUnit = 0;
 		for(auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
 		{
-			HSamplerState& samplerState = bindableParams.getSamplerState(iter->second.slot);
+			HSamplerState& samplerState = bindableParams->getSamplerState(iter->second.slot);
 
 			if(samplerState == nullptr)
 				setSamplerState(gptype, iter->second.slot, SamplerState::getDefault());
@@ -276,7 +276,7 @@ namespace BansheeEngine
 		UINT32 blockBinding = 0;
 		for(auto iter = paramDesc.paramBlocks.begin(); iter != paramDesc.paramBlocks.end(); ++iter)
 		{
-			GpuParamBlockBufferPtr paramBlockBuffer = bindableParams.getParamBlockBuffer(iter->second.slot);
+			GpuParamBlockBufferPtr paramBlockBuffer = bindableParams->getParamBlockBuffer(iter->second.slot);
 			if(paramBlockBuffer == nullptr)
 				continue;
 

+ 32 - 7
BansheeRenderer/Include/BsBansheeRenderer.h

@@ -2,11 +2,35 @@
 
 #include "BsBansheeRendererPrerequisites.h"
 #include "BsRenderer.h"
+#include "BsMaterial.h"
+#include "BsGpuParamDesc.h"
 #include "BsBounds.h"
 #include "BsCameraProxy.h"
 
 namespace BansheeEngine
 {
+	enum BansheeRendererParamSemantic
+	{
+		BRPS_Time = 1000,
+		BRPS_LightDir = 1001
+	};
+
+	struct RenderableLitTexturedData
+	{
+		ShaderPtr defaultShader;
+
+		GpuParamBlockDesc staticParamBlockDesc;
+		GpuParamBlockDesc perFrameParamBlockDesc;
+		GpuParamBlockDesc perObjectParamBlockDesc;
+
+		GpuParamDataDesc timeParamDesc;
+		GpuParamDataDesc lightDirParamDesc;
+		GpuParamDataDesc wvpParamDesc;
+
+		GpuParamBlockBufferPtr staticParamBuffer;
+		GpuParamBlockBufferPtr perFrameParamBuffer;
+	};
+
 	/**
 	 * @brief	Default renderer for Banshee. Performs frustum culling, sorting and renders
 	 *			objects plainly according to their shaders with no fancy effects.
@@ -15,16 +39,10 @@ namespace BansheeEngine
 	// TODO UNDOCUMENTED
 	class BS_BSRND_EXPORT BansheeRenderer : public Renderer
 	{
-		struct CameraData
-		{
-			CameraProxyPtr cameraProxy;
-			RenderQueuePtr renderQueue;
-		};
-
 		struct RenderTargetData
 		{
 			RenderTargetPtr target;
-			Vector<CameraData> cameras;
+			Vector<CameraProxyPtr> cameras;
 		};
 
 	public:
@@ -50,6 +68,9 @@ namespace BansheeEngine
 		void removeCameraProxy(CameraProxyPtr proxy);
 		void updateCameraProxy(CameraProxyPtr proxy, Matrix4 viewMatrix);
 
+		void setDrawList(CameraProxyPtr proxy, DrawListPtr drawList);
+		void updateMaterialProxy(MaterialProxyPtr proxy, Vector<PassParameters> dirtyPassParams);
+
 		void renderAllCore();
 
 		/**
@@ -63,6 +84,8 @@ namespace BansheeEngine
 		void renderableRemoved(const HRenderable& renderable);
 		void cameraRemoved(const HCamera& camera);
 
+		ShaderPtr getDefaultShader(RenderableType type) const;
+
 		Vector<RenderableProxyPtr> mDeletedRenderableProxies;
 		Vector<CameraProxyPtr> mDeletedCameraProxies;
 
@@ -75,6 +98,8 @@ namespace BansheeEngine
 		Vector<Matrix4> mWorldTransforms;
 		Vector<Bounds> mWorldBounds;
 
+		RenderableLitTexturedData mLitTexturedData;
+
 		HEvent mRenderableRemovedConn;
 		HEvent mCameraRemovedConn;
 	};

+ 198 - 44
BansheeRenderer/Source/BsBansheeRenderer.cpp

@@ -18,7 +18,10 @@
 #include "BsDrawHelper3D.h"
 #include "BsGUIManager.h"
 #include "BsCoreThread.h"
+#include "BsGpuParams.h"
 #include "BsProfilerCPU.h"
+#include "BsShader.h"
+#include "BsTechnique.h"
 #include "BsDrawList.h"
 
 using namespace std::placeholders;
@@ -30,7 +33,7 @@ namespace BansheeEngine
 		mRenderableRemovedConn = gBsSceneManager().onRenderableRemoved.connect(std::bind(&BansheeRenderer::renderableRemoved, this, _1));
 		mCameraRemovedConn = gBsSceneManager().onCameraRemoved.connect(std::bind(&BansheeRenderer::cameraRemoved, this, _1));
 
-		// Init compatibile material params
+		// Init compatible material params
 		RendererMaterialParams dx9params("BansheeD3D9RenderSystem", RenType_UnlitUntextured);
 
 		// TODO - In a perfect world I would get element size and offsets by creating a dummy version of the param block
@@ -38,6 +41,72 @@ namespace BansheeEngine
 		dx9params.addDataParam(RPS_WorldViewProjTfrm, GPT_VERTEX_PROGRAM, GPDT_MATRIX_4X4, sizeof(Matrix4), 0, 0, RP_AnyPass, RBS_PerObject);
 
 		mRenderableMaterialParams.insert(dx9params);
+
+		// Init default shaders
+		mLitTexturedData.defaultShader = getDefaultShader(RenType_LitTextured);
+		TechniquePtr defaultTechnique = mLitTexturedData.defaultShader->getBestTechnique();
+		PassPtr defaultPass = defaultTechnique->getPass(0);
+
+		const GpuParamDesc& vertParamDesc = defaultPass->getVertexProgram()->getParamDesc();
+		const GpuParamDesc& fragParamDesc = defaultPass->getFragmentProgram()->getParamDesc();
+
+		const Map<String, SHADER_DATA_PARAM_DESC>& dataParams = mLitTexturedData.defaultShader->_getDataParams();
+		for (auto& param : dataParams)
+		{
+			if (param.second.rendererSemantic == BRPS_LightDir)
+			{
+				auto iterFind = fragParamDesc.params.find(param.second.gpuVariableName);
+				if (iterFind == fragParamDesc.params.end())
+					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
+
+				mLitTexturedData.lightDirParamDesc = iterFind->second;
+			}
+			else if (param.second.rendererSemantic == BRPS_Time)
+			{
+				auto iterFind = vertParamDesc.params.find(param.second.gpuVariableName);
+				if (iterFind == vertParamDesc.params.end())
+					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
+
+				mLitTexturedData.timeParamDesc = iterFind->second;
+			}
+			else if (param.second.rendererSemantic == RPS_WorldViewProjTfrm)
+			{
+				auto iterFind = vertParamDesc.params.find(param.second.gpuVariableName);
+				if (iterFind == vertParamDesc.params.end())
+					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
+
+				mLitTexturedData.wvpParamDesc = iterFind->second;
+			}
+		}
+
+		const Map<String, SHADER_PARAM_BLOCK_DESC>& paramBlocks = mLitTexturedData.defaultShader->_getParamBlocks();
+		for (auto& block : paramBlocks)
+		{
+			if (block.second.rendererSemantic == RBS_Occassional)
+			{
+				auto iterFind = vertParamDesc.paramBlocks.find(block.second.name);
+				if (iterFind == vertParamDesc.paramBlocks.end())
+					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
+
+				mLitTexturedData.staticParamBlockDesc = iterFind->second;
+			}
+			else if (block.second.rendererSemantic == RBS_PerFrame)
+			{
+				auto iterFind = fragParamDesc.paramBlocks.find(block.second.name);
+				if (iterFind == fragParamDesc.paramBlocks.end())
+					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
+
+				mLitTexturedData.perFrameParamBlockDesc = iterFind->second;
+			}
+			else if (block.second.rendererSemantic == RBS_PerObject)
+			{
+				auto iterFind = vertParamDesc.paramBlocks.find(block.second.name);
+				if (iterFind == vertParamDesc.paramBlocks.end())
+					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
+
+				mLitTexturedData.perObjectParamBlockDesc = iterFind->second;
+			}
+		}
 	}
 
 	BansheeRenderer::~BansheeRenderer()
@@ -52,6 +121,11 @@ namespace BansheeEngine
 		return name;
 	}
 
+	ShaderPtr BansheeRenderer::getDefaultShader(RenderableType type) const
+	{
+		return nullptr;
+	}
+
 	void BansheeRenderer::addRenderableProxy(RenderableProxyPtr proxy)
 	{
 		for (auto& element : proxy->renderableElements)
@@ -100,32 +174,27 @@ namespace BansheeEngine
 
 		if (findIter != mRenderTargets.end())
 		{
-			findIter->cameras.push_back(CameraData());
-			CameraData& camData = findIter->cameras.back();
+			proxy->renderQueue = bs_shared_ptr<RenderQueue>();
 
-			camData.cameraProxy = proxy;
-			camData.renderQueue = bs_shared_ptr<RenderQueue>();
+			findIter->cameras.push_back(proxy);
 		}
 		else
 		{
 			mRenderTargets.push_back(RenderTargetData());
 			RenderTargetData& renderTargetData = mRenderTargets.back();
 
-			renderTargetData.cameras.push_back(CameraData());
-			CameraData& camData = renderTargetData.cameras.back();
-
-			camData.cameraProxy = proxy;
-			camData.renderQueue = bs_shared_ptr<RenderQueue>();
+			proxy->renderQueue = bs_shared_ptr<RenderQueue>();
+			renderTargetData.cameras.push_back(proxy);
 		}
 
 		// Sort everything based on priority
-		auto cameraComparer = [&](const CameraData& a, const CameraData& b) { return a.cameraProxy->priority > b.cameraProxy->priority; };
+		auto cameraComparer = [&](const CameraProxyPtr& a, const CameraProxyPtr& b) { return a->priority > b->priority; };
 		auto renderTargetInfoComparer = [&](const RenderTargetData& a, const RenderTargetData& b) { return a.target->getPriority() > b.target->getPriority(); };
 		std::sort(begin(mRenderTargets), end(mRenderTargets), renderTargetInfoComparer);
 
 		for (auto& camerasPerTarget : mRenderTargets)
 		{
-			Vector<CameraData>& cameras = camerasPerTarget.cameras;
+			Vector<CameraProxyPtr>& cameras = camerasPerTarget.cameras;
 
 			std::sort(begin(cameras), end(cameras), cameraComparer);
 		}
@@ -187,11 +256,16 @@ namespace BansheeEngine
 		// Add or update Renderable proxies
 		const Vector<HRenderable>& allRenderables = gBsSceneManager().getAllRenderables();
 		Vector<HSceneObject> dirtySceneObjects;
+		Vector<HRenderable> dirtyRenderables;
+
 		for (auto& renderable : allRenderables)
 		{
+			bool addedNewProxy = false;
+			RenderableProxyPtr proxy;
+
 			if (!renderable->_isCoreDirty())
 			{
-				RenderableProxyPtr proxy = renderable->_getActiveProxy();
+				proxy = renderable->_getActiveProxy();
 
 				if (proxy != nullptr)
 					gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::removeRenderableProxy, this, proxy));
@@ -201,19 +275,59 @@ namespace BansheeEngine
 
 				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::addRenderableProxy, this, proxy));
 
-				renderable->_markCoreClean();
-
+				dirtyRenderables.push_back(renderable);
 				dirtySceneObjects.push_back(renderable->SO());
+				addedNewProxy = true;
 			}
 			else if (!renderable->SO()->_isCoreDirty())
 			{
-				RenderableProxyPtr proxy = renderable->_getActiveProxy();
+				proxy = renderable->_getActiveProxy();
 				assert(proxy != nullptr);
 
 				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::updateRenderableProxy, this, proxy, renderable->SO()->getWorldTfrm()));
 
 				dirtySceneObjects.push_back(renderable->SO());
 			}
+
+			if (!addedNewProxy)
+			{
+				for (UINT32 i = 0; i < (UINT32)proxy->renderableElements.size(); i++)
+				{
+					HMaterial mat = renderable->getMaterial(i);
+					if (mat != nullptr && mat.isLoaded() && mat->_isCoreDirty(MaterialDirtyFlag::Params))
+					{
+						Vector<PassParameters> dirtyPassParams;
+						for (UINT32 j = 0; j < mat->getNumPasses(); j++)
+						{
+							PassParametersPtr passParams = mat->getPassParameters(j);
+
+							PassParameters dirtyParams;
+							for (UINT32 k = 0; k < passParams->getNumParams(); k++)
+							{
+								GpuParamsPtr params = passParams->getParamByIdx(k);
+								if (params != nullptr && params->_isCoreDirty())
+								{
+									dirtyParams.setParamByIdx(k, params->clone());
+
+									params->_markCoreClean();
+								}
+							}
+
+							dirtyPassParams.push_back(dirtyParams);
+						}
+						
+						gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::updateMaterialProxy, this, proxy->renderableElements[i]->material, dirtyPassParams));
+					}
+				}
+			}
+		}
+
+		// Mark all renderables as clean (needs to be done after all proxies are updated as
+		// this will also clean materials & meshes which may be shared, so we don't want to clean them
+		// too early.
+		for (auto& renderable : dirtyRenderables)
+		{
+			renderable->_markCoreClean();
 		}
 
 		// Remove proxies from deleted Cameras
@@ -253,67 +367,107 @@ namespace BansheeEngine
 			}
 		}
 
-		// Mark everything clean
+		// Mark scene objects clean
 		for (auto& dirtySO : dirtySceneObjects)
 		{
 			dirtySO->_markCoreClean();
 		}
 
 		// Populate direct draw lists
-		UINT32 idx = 0;
 		for (auto& camera : allCameras)
 		{
-			DrawList drawList;
+			DrawListPtr drawList = bs_shared_ptr<DrawList>();
 
 			// Get GUI render operations
-			GUIManager::instance().render(camera->getViewport(), drawList);
+			GUIManager::instance().render(camera->getViewport(), *drawList);
 
 			// Get overlay render operations
-			OverlayManager::instance().render(camera->getViewport(), drawList);
+			OverlayManager::instance().render(camera->getViewport(), *drawList);
 
 			// Get debug render operations
-			DrawHelper3D::instance().render(camera, drawList);
-			DrawHelper2D::instance().render(camera, drawList);
+			DrawHelper3D::instance().render(camera, *drawList);
+			DrawHelper2D::instance().render(camera, *drawList);
 
 			// Get any operations from hooked up callbacks
 			const Viewport* viewportRawPtr = camera->getViewport().get();
 			auto callbacksForViewport = mRenderCallbacks[viewportRawPtr];
 
 			for (auto& callback : callbacksForViewport)
-				callback(viewportRawPtr, drawList);
+				callback(viewportRawPtr, *drawList);
 
-			RenderQueuePtr renderQueue = renderQueues[idx];
+			gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::setDrawList, camera->_getActiveProxy(), drawList));
+		}
 
-			const Vector<DrawOperation>& drawOps = drawList.getDrawOperations();
-			for (auto& drawOp : drawOps)
-			{
-				// TODO - Will I need to check if materials match renderer?
+		gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::renderAllCore, this));
+	}
 
-				renderQueue->add(drawOp.material->_createProxy(),
-					drawOp.mesh->_createProxy(drawOp.submeshIdx), drawOp.worldPosition);
-			}
+	void BansheeRenderer::setDrawList(CameraProxyPtr proxy, DrawListPtr drawList)
+	{
+		RenderQueuePtr renderQueue = proxy->renderQueue;
 
-			idx++;
+		const Vector<DrawOperation>& drawOps = drawList->getDrawOperations();
+		for (auto& drawOp : drawOps)
+		{
+			// TODO - Will I need to check if materials match renderer?
+
+			renderQueue->add(drawOp.material->_createProxy(),
+				drawOp.mesh->_createProxy(drawOp.submeshIdx), drawOp.worldPosition);
 		}
+	}
 
-		gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::renderAllCore, this));
+	void BansheeRenderer::updateMaterialProxy(MaterialProxyPtr proxy, Vector<PassParameters> dirtyPassParams)
+	{
+		assert(proxy->passes.size() == dirtyPassParams.size());
+
+		for (UINT32 i = 0; i < (UINT32)proxy->passes.size(); i++)
+		{
+			PassParameters& dirtyParams = dirtyPassParams[i];
+
+			if (dirtyParams.mVertParams != nullptr)
+				proxy->passes[i].vertexProgParams = dirtyParams.mVertParams;
+
+			if (dirtyParams.mFragParams != nullptr)
+				proxy->passes[i].fragmentProgParams = dirtyParams.mFragParams;
+
+			if (dirtyParams.mGeomParams != nullptr)
+				proxy->passes[i].geometryProgParams = dirtyParams.mGeomParams;
+
+			if (dirtyParams.mHullParams != nullptr)
+				proxy->passes[i].hullProgParams = dirtyParams.mHullParams;
+
+			if (dirtyParams.mDomainParams != nullptr)
+				proxy->passes[i].domainProgParams = dirtyParams.mDomainParams;
+
+			if (dirtyParams.mComputeParams != nullptr)
+				proxy->passes[i].computeProgParams = dirtyParams.mComputeParams;
+		}
 	}
 
 	void BansheeRenderer::renderAllCore()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
+		// TODO: Perform hardware buffer updates
+		// For each render type
+		//   - Update static and per-frame gpu buffers update it with new data
+		//     e.g. write lightDir parameter to static buffer and write time parameter to per-frame buffer
+		//     (I will also likely need per-camera buffers later)
+		//   - Go through all RenderableProxies and get their per-object buffers, update them with per-object data
+		//   - Call updateHardwareBuffers() on all params
+		//   - Ensure that when MaterialProxy is added/updated I properly create per-object buffers and hook up
+		//     buffers
+
 		// Render everything, target by target
 		for (auto& renderTargetData : mRenderTargets)
 		{
 			RenderTargetPtr target = renderTargetData.target;
-			Vector<CameraData>& cameraData = renderTargetData.cameras;
+			Vector<CameraProxyPtr>& cameras = renderTargetData.cameras;
 
 			RenderSystem::instance().beginFrame();
 
-			for(auto& data : cameraData)
+			for(auto& camera : cameras)
 			{
-				Viewport& viewport = data.cameraProxy->viewport;
+				Viewport& viewport = camera->viewport;
 				RenderSystem::instance().setViewport(viewport);
 
 				UINT32 clearBuffers = 0;
@@ -329,7 +483,7 @@ namespace BansheeEngine
 				if(clearBuffers != 0)
 					RenderSystem::instance().clearViewport(clearBuffers, viewport.getClearColor(), viewport.getClearDepthValue(), viewport.getClearStencilValue());
 
-				render(*data.cameraProxy, data.renderQueue);
+				render(*camera, camera->renderQueue);
 			}
 
 			RenderSystem::instance().endFrame();
@@ -381,7 +535,7 @@ namespace BansheeEngine
 		if (pass.vertexProg)
 		{
 			rs.bindGpuProgram(pass.vertexProg);
-			rs.bindGpuParams(GPT_VERTEX_PROGRAM, *pass.vertexProgParams);
+			rs.bindGpuParams(GPT_VERTEX_PROGRAM, pass.vertexProgParams);
 		}
 		else
 			rs.unbindGpuProgram(GPT_VERTEX_PROGRAM);
@@ -389,7 +543,7 @@ namespace BansheeEngine
 		if (pass.fragmentProg)
 		{
 			rs.bindGpuProgram(pass.fragmentProg);
-			rs.bindGpuParams(GPT_FRAGMENT_PROGRAM, *pass.geometryProgParams);
+			rs.bindGpuParams(GPT_FRAGMENT_PROGRAM, pass.geometryProgParams);
 		}
 		else
 			rs.unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
@@ -397,7 +551,7 @@ namespace BansheeEngine
 		if (pass.geometryProg)
 		{
 			rs.bindGpuProgram(pass.geometryProg);
-			rs.bindGpuParams(GPT_GEOMETRY_PROGRAM, *pass.geometryProgParams);
+			rs.bindGpuParams(GPT_GEOMETRY_PROGRAM, pass.geometryProgParams);
 		}
 		else
 			rs.unbindGpuProgram(GPT_GEOMETRY_PROGRAM);
@@ -405,7 +559,7 @@ namespace BansheeEngine
 		if (pass.hullProg)
 		{
 			rs.bindGpuProgram(pass.hullProg);
-			rs.bindGpuParams(GPT_HULL_PROGRAM, *pass.hullProgParams);
+			rs.bindGpuParams(GPT_HULL_PROGRAM, pass.hullProgParams);
 		}
 		else
 			rs.unbindGpuProgram(GPT_HULL_PROGRAM);
@@ -413,7 +567,7 @@ namespace BansheeEngine
 		if (pass.domainProg)
 		{
 			rs.bindGpuProgram(pass.domainProg);
-			rs.bindGpuParams(GPT_DOMAIN_PROGRAM, *pass.domainProgParams);
+			rs.bindGpuParams(GPT_DOMAIN_PROGRAM, pass.domainProgParams);
 		}
 		else
 			rs.unbindGpuProgram(GPT_DOMAIN_PROGRAM);
@@ -421,7 +575,7 @@ namespace BansheeEngine
 		if (pass.computeProg)
 		{
 			rs.bindGpuProgram(pass.computeProg);
-			rs.bindGpuParams(GPT_COMPUTE_PROGRAM, *pass.computeProgParams);
+			rs.bindGpuParams(GPT_COMPUTE_PROGRAM, pass.computeProgParams);
 		}
 		else
 			rs.unbindGpuProgram(GPT_COMPUTE_PROGRAM);

+ 123 - 0
BansheeUtility/Include/BsFrameAlloc.h

@@ -67,4 +67,127 @@ namespace BansheeEngine
 		MemBlock* allocBlock(UINT32 wantedSize);
 		void deallocBlock(MemBlock* block);
 	};
+
+	/**
+	 * @brief	Allocator for the standard library that internally uses a
+	 * 			frame allocator.
+	 */
+	template <class Tc>
+	class StdFrameAlloc
+	{
+	public:
+		// Type definitions
+		typedef T        value_type;
+		typedef T*       pointer;
+		typedef const T* const_pointer;
+		typedef T&       reference;
+		typedef const T& const_reference;
+		typedef std::size_t    size_type;
+		typedef std::ptrdiff_t difference_type;
+
+		/**
+		 * @brief	Rebind allocator to type U
+		 */
+		template <class U>
+		struct rebind
+		{
+			typedef StdFrameAlloc<U> other;
+		};
+
+		StdFrameAlloc() throw()
+			:mFrameAlloc(nullptr)
+		{ }
+
+		StdFrameAlloc(FrameAlloc* frameAlloc) throw()
+			:mFrameAlloc(frameAlloc)
+		{ }
+
+		StdFrameAlloc(const StdFrameAlloc&) throw()
+		{ }
+
+		template <class U>
+		StdFrameAlloc(const StdFrameAlloc<U>&) throw()
+		{ }
+
+		~StdFrameAlloc() throw()
+		{ }
+
+		/**
+		 * @brief	Return address of value.
+		 */
+		pointer address(reference value) const
+		{
+			return &value;
+		}
+
+		/**
+		 * @brief	Return address of value.
+		 */
+		const_pointer address(const_reference value) const
+		{
+			return &value;
+		}
+
+		/**
+		 * @brief	Return maximum number of elements that can be allocated.
+		 */
+		size_type max_size() const throw()
+		{
+			return std::numeric_limits<std::size_t>::max() / sizeof(T);
+		}
+
+		/**
+		 * @brief	Allocate but don't initialize number elements of type T.
+		 */
+		pointer allocate(size_type num, const void* = 0)
+		{
+			pointer ret = (pointer)(mFrameAlloc->alloc((size_t)num*sizeof(T)));
+			return ret;
+		}
+
+		/**
+		 * @brief	Initialize elements of allocated storage p with value "value".
+		 */
+		void construct(pointer p, const T& value)
+		{
+			new((void*)p)T(value);
+		}
+
+		/**
+		 * @brief	Destroy elements of initialized storage p.
+		 */
+		void destroy(pointer p)
+		{
+			p->~T();
+		}
+
+		/**
+		 * @brief	Deallocate storage p of deleted elements.
+		 */
+		void deallocate(pointer p, size_type num)
+		{
+			mFrameAlloc->dealloc((UINT8*)p);
+		}
+
+	private:
+		FrameAlloc* mFrameAlloc;
+	};
+
+	/**
+	 * @brief	Return that all specializations of this allocator are interchangeable.
+	 */
+	template <class T1, class T2>
+	bool operator== (const StdFrameAlloc<T1>&,
+		const StdFrameAlloc<T2>&) throw() {
+		return true;
+	}
+
+	/**
+	 * @brief	Return that all specializations of this allocator are interchangeable.
+	 */
+	template <class T1, class T2>
+	bool operator!= (const StdFrameAlloc<T1>&,
+		const StdFrameAlloc<T2>&) throw() {
+		return false;
+	}
 }

+ 12 - 7
Renderer.txt

@@ -1,11 +1,8 @@
-1. Refactor proxies
-
-Finish refactoring draw lists
-
 2. Gpu params update 
-   - Way to update sim -> core gpu params (send BindableGpuParams and update core buffers using it)
-   - Add a way to bind gpu params by using GpuParams directly
-   - And a way to update hardware buffers without using BindableGpuParams
+
+ISSUE - GpuParamBlock is tied to the hardware buffer. But I need separate param blocks for CPU and GPU. I need to break that tie
+ and also ensure these blocks are marked as dirty/clean when needed.
+  - I guess I could write these directly to the GPU buffer
 
 3. Renderer parameters and buffers
    - Will likely need to finalize material <-> renderer interface matching first
@@ -14,6 +11,14 @@ Finish refactoring draw lists
    - Update renderable parameters each frame
       - Apply world view proj matrix in renderer
 
+IMPORTANT - Renderer now requires GpuparamBuffers to exist. Separate for each renderer semantic. Add
+GpuParamBlockBuffer emulation to DX9 (they can be user-specified via import settings or something).
+
+Make sure to update param buffers in bulk before doing any rendering:
+ - They're updated when material proxies are first created
+ - When material proxies are updated
+ - And when renderer updates its own parameters
+
 -----------------------------------------------------------
 NON TRIVIAL BUT SIMPLE