Просмотр исходного кода

Finished with the renderer most, checkin before prettying it up

Marko Pintera 11 лет назад
Родитель
Сommit
e33c0e5624

+ 1 - 4
BansheeCore/BansheeCore.vcxproj

@@ -276,7 +276,6 @@
     <ClInclude Include="Include\BsDrawList.h" />
     <ClInclude Include="Include\BsMaterialProxy.h" />
     <ClInclude Include="Include\BsMeshProxy.h" />
-    <ClInclude Include="Include\BsRendererParams.h" />
     <ClInclude Include="Include\BsRenderStats.h" />
     <ClInclude Include="Include\BsCoreThread.h" />
     <ClInclude Include="Include\BsProfilerCPU.h" />
@@ -308,7 +307,6 @@
     <ClInclude Include="Include\BsPlatform.h" />
     <ClInclude Include="Include\BsProfilingManager.h" />
     <ClInclude Include="Include\BsQueryManager.h" />
-    <ClInclude Include="Include\BsRenderQueue.h" />
     <ClInclude Include="Include\BsResourceManifest.h" />
     <ClInclude Include="Include\BsResourceManifestRTTI.h" />
     <ClInclude Include="Include\BsSceneObjectRTTI.h" />
@@ -349,6 +347,7 @@
     <ClInclude Include="Include\BsOcclusionQuery.h" />
     <ClInclude Include="Include\BsPixelBuffer.h" />
     <ClInclude Include="Include\BsGpuProgIncludeImporter.h" />
+    <ClInclude Include="Include\BsShaderProxy.h" />
     <ClInclude Include="Include\BsSubMesh.h" />
     <ClInclude Include="Include\BsTextureView.h" />
     <ClInclude Include="Include\BsTextData.h" />
@@ -468,8 +467,6 @@
     <ClCompile Include="Source\BsProfilingManager.cpp" />
     <ClCompile Include="Source\BsQueryManager.cpp" />
     <ClCompile Include="Source\BsRenderer.cpp" />
-    <ClCompile Include="Source\BsRendererParams.cpp" />
-    <ClCompile Include="Source\BsRenderQueue.cpp" />
     <ClCompile Include="Source\BsResourceManifest.cpp" />
     <ClCompile Include="Source\BsTextureView.cpp" />
     <ClCompile Include="Source\BsTextData.cpp" />

+ 3 - 12
BansheeCore/BansheeCore.vcxproj.filters

@@ -405,9 +405,6 @@
     <ClInclude Include="Include\BsBlendState.h">
       <Filter>Header Files\RenderSystem</Filter>
     </ClInclude>
-    <ClInclude Include="Include\BsRenderQueue.h">
-      <Filter>Header Files\Renderer</Filter>
-    </ClInclude>
     <ClInclude Include="Include\BsRendererManager.h">
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
@@ -510,15 +507,15 @@
     <ClInclude Include="Include\BsDrawList.h">
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
-    <ClInclude Include="Include\BsRendererParams.h">
-      <Filter>Header Files\Renderer</Filter>
-    </ClInclude>
     <ClInclude Include="Include\BsMeshProxy.h">
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
     <ClInclude Include="Include\BsMaterialProxy.h">
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsShaderProxy.h">
+      <Filter>Header Files\Renderer</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsCoreApplication.cpp">
@@ -737,9 +734,6 @@
     <ClCompile Include="Source\BsRendererManager.cpp">
       <Filter>Source Files\Renderer</Filter>
     </ClCompile>
-    <ClCompile Include="Source\BsRenderQueue.cpp">
-      <Filter>Source Files\Renderer</Filter>
-    </ClCompile>
     <ClCompile Include="Source\Win32\BsWin32FolderMonitor.cpp">
       <Filter>Source Files\Platform</Filter>
     </ClCompile>
@@ -815,8 +809,5 @@
     <ClCompile Include="Source\BsCameraProxy.cpp">
       <Filter>Source Files\Renderer</Filter>
     </ClCompile>
-    <ClCompile Include="Source\BsRendererParams.cpp">
-      <Filter>Source Files\Renderer</Filter>
-    </ClCompile>
   </ItemGroup>
 </Project>

+ 2 - 0
BansheeCore/Include/BsCorePrerequisites.h

@@ -135,6 +135,7 @@ namespace BansheeEngine
 	struct MeshProxy;
 	class GpuParamBlockBufferProxy;
 	class GpuParamsProxy;
+	class ShaderProxy;
 	class DrawList;
 	// Asset import
 	class SpecificImporter;
@@ -235,6 +236,7 @@ namespace BansheeEngine
 	typedef std::shared_ptr<MeshProxy> MeshProxyPtr;
 	typedef std::shared_ptr<GpuParamsProxy> GpuParamsProxyPtr;
 	typedef std::shared_ptr<GpuParamBlockBufferProxy> GpuParamBlockBufferProxyPtr;
+	typedef std::shared_ptr<ShaderProxy> ShaderProxyPtr;
 }
 
 /************************************************************************/

+ 3 - 3
BansheeCore/Include/BsGpuParam.h

@@ -27,7 +27,7 @@ namespace BansheeEngine
 		/**
 		 * @brief	Checks if the gpu param is still valid or were the parent GpuParams destroyed.
 		 */
-		bool getIsDestroyed() const;
+		bool isDestroyed() const;
 
 		/**
 		 * @brief	Gets a parameter block at the specified slot index.
@@ -119,7 +119,7 @@ namespace BansheeEngine
 		 */
 		void set(const T& value, UINT32 arrayIdx = 0)
 		{
-			if (getIsDestroyed())
+			if (isDestroyed())
 				BS_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
 
 #if BS_DEBUG_MODE
@@ -160,7 +160,7 @@ namespace BansheeEngine
 		 */
 		T get(UINT32 arrayIdx = 0)
 		{
-			if (getIsDestroyed())
+			if (isDestroyed())
 				BS_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
 
 #if BS_DEBUG_MODE

+ 6 - 5
BansheeCore/Include/BsGpuParams.h

@@ -230,26 +230,27 @@ namespace BansheeEngine
 		HSamplerState getSamplerState(UINT32 slot);
 
 		/**
-		 * @brief	Returns an exact copy of this object. Cloned object will have a core copy of the GPU
-		 *			param blocks, so it should only be used on the core thread.
+		 * @brief	Returns an exact copy of this object. Internal parameter buffers will also be cloned,
+		 *			but should only be used on the core thread.
 		 *
 		 * @note	Optional frame allocator to allocate the returned data with. If not specified
 		 *			allocation will be done using normal means.
+		 *			Internal method.
 		 */
-		GpuParamsPtr cloneForCore(FrameAlloc* frameAlloc = nullptr) const;
+		GpuParamsPtr _cloneForCore(FrameAlloc* frameAlloc = nullptr) const;
 
 		/**
 		 * @brief	Checks is the core dirty flag set. This is used by external systems 
 		 *			to know  when internal data has changed and core proxy potentially needs to be updated.
 		 *
-		 * @note	Sim thread only.
+		 * @note	Internal method. Sim thread only.
 		 */
 		bool _isCoreDirty() const;
 
 		/**
 		 * @brief	Marks the core dirty flag as clean.
 		 *
-		 * @note	Sim thread only.
+		 * @note	Internal method. Sim thread only.
 		 */
 		void _markCoreClean();
 

+ 6 - 0
BansheeCore/Include/BsGpuProgram.h

@@ -122,6 +122,12 @@ namespace BansheeEngine
 		 */
 		virtual bool isAdjacencyInfoRequired() const { return mNeedsAdjacencyInfo; }
 
+		/**
+		 * @brief	Returns true if matrices need to be transposed before sent to the GPU
+		 *			program as GPU program parameters.
+		 */
+		virtual bool requiresMatrixTranspose() const { return false; }
+
 		/**
 		 * @brief	Creates a new parameters object compatible with this program definition. You
 		 *			may populate the returned object with actual parameter values and bind it

+ 5 - 0
BansheeCore/Include/BsMaterial.h

@@ -426,6 +426,11 @@ namespace BansheeEngine
 		 */
 		void _setActiveProxy(const MaterialProxyPtr& proxy) { mActiveProxy = proxy; }
 
+		/**
+		 * @brief	Returns updated GPU parameters since the last time the parameters were marked clean.
+		 */
+		Vector<MaterialProxy::ParamsBindInfo> _getDirtyProxyParams();
+
 		/**
 		 * @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

+ 39 - 9
BansheeCore/Include/BsMaterialProxy.h

@@ -17,12 +17,12 @@ namespace BansheeEngine
 		HGpuProgram domainProg;
 		HGpuProgram computeProg;
 
-		GpuParamsPtr vertexProgParams;
-		GpuParamsPtr fragmentProgParams;
-		GpuParamsPtr geometryProgParams;
-		GpuParamsPtr hullProgParams;
-		GpuParamsPtr domainProgParams;
-		GpuParamsPtr computeProgParams;
+		UINT32 vertexProgParamsIdx;
+		UINT32 fragmentProgParamsIdx;
+		UINT32 geometryProgParamsIdx;
+		UINT32 hullProgParamsIdx;
+		UINT32 domainProgParamsIdx;
+		UINT32 computeProgParamsIdx;
 
 		HBlendState blendState;
 		HRasterizerState rasterizerState;
@@ -36,9 +36,39 @@ namespace BansheeEngine
 	 */
 	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 GpuParamBlockBufferPtr& buffer)
+				:paramsIdx(paramsIdx), slotIdx(slotIdx), buffer(buffer)
+			{ }
+
+			UINT32 paramsIdx;
+			UINT32 slotIdx;
+			GpuParamBlockBufferPtr buffer;
+		};
+
+		/**
+		 * @brief	Contains GPU parameters and index of the parameters it binds to in the material proxy.
+		 */
+		struct BS_CORE_EXPORT ParamsBindInfo
+		{
+			ParamsBindInfo(UINT32 paramsIdx, const GpuParamsPtr& params)
+				:paramsIdx(paramsIdx), params(params)
+			{ }
+
+			UINT32 paramsIdx;
+			GpuParamsPtr params;
+		};
+
 		Vector<MaterialProxyPass> passes;
-		bool separablePasses;
-		UINT32 queuePriority;
-		QueueSortType queueSortType;
+		Vector<GpuParamsPtr> params;
+
+		ShaderProxyPtr shader;
+
+		Vector<BufferBindInfo> rendererBuffers;
 	};
 }

+ 23 - 2
BansheeCore/Include/BsRenderer.h

@@ -1,12 +1,34 @@
 #pragma once
 
 #include "BsCorePrerequisites.h"
-#include "BsRendererParams.h"
 #include "BsGameObject.h"
 #include "BsEvent.h"
 
 namespace BansheeEngine
 {
+	/**
+	 * @brief	Available parameter block semantics that allow the renderer to identify
+	 *			the use of a GPU program parameter block specified in a shader.
+	 */
+	enum RendererBlockSemantic
+	{
+		RBS_Static,
+		RBS_PerCamera,
+		RBS_PerFrame,
+		RBS_PerObject
+	};
+
+	/**
+	 * @brief	Available parameter semantics that allow the renderer to identify
+	 *			the use of a GPU parameter specified in a shader.
+	 */
+	enum RendererParamSemantic
+	{
+		RPS_WorldViewProjTfrm,
+		RPS_ViewProjTfrm,
+		RPS_WorldTfrm
+	};
+
 	/**
 	 * @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.
@@ -37,6 +59,5 @@ namespace BansheeEngine
 
 	protected:
 		UnorderedMap<const Viewport*, Vector<std::function<void(const Viewport*, DrawList&)>>> mRenderCallbacks;
-		UnorderedSet<RendererMaterialParams> mRenderableMaterialParams;
 	};
 }

+ 0 - 108
BansheeCore/Include/BsRendererParams.h

@@ -1,108 +0,0 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsGpuProgram.h"
-#include "BsUtil.h"
-#include "BsGpuParamDesc.h"
-
-namespace BansheeEngine
-{
-	// TODO UNDOCUMENTED
-	enum RendererBlockSemantic
-	{
-		RBS_Occassional,
-		RBS_PerFrame,
-		RBS_PerObject
-	};
-
-	enum RendererParamSemantic
-	{
-		RPS_WorldViewProjTfrm,
-		RPS_ViewProjTfrm,
-		RPS_WorldTfrm
-	};
-
-	enum RendererPass
-	{
-		RP_AnyPass = 0xFFFFFFFF
-	};
-
-	enum RendererBlock
-	{
-		RB_NoBlock = 0xFFFFFFFF
-	};
-
-	struct BS_CORE_EXPORT RendererMaterialParam
-	{
-		RendererMaterialParam(UINT32 semantic, GpuProgramType program, bool isObject, UINT32 passIdx = RP_AnyPass, UINT32 blockSemantic = RB_NoBlock);
-		virtual ~RendererMaterialParam() {}
-
-		UINT32 semantic;
-		GpuProgramType program;
-		UINT32 passIdx; /**< 0xFFFFFFFF any pass. */
-		UINT32 blockSemantic; /**< 0xFFFFFFFF no block. */
-		bool isObject;
-	};
-
-	struct BS_CORE_EXPORT RendererMaterialDataParam : public RendererMaterialParam
-	{
-		RendererMaterialDataParam(UINT32 semantic, GpuProgramType program, GpuParamDataType type, UINT32 elementSize,
-			UINT32 arraySize, UINT32 arrayElementStride, UINT32 cpuOffset, UINT32 gpuOffset,
-			UINT32 passIdx = RP_AnyPass, UINT32 blockSemantic = RB_NoBlock);
-
-		GpuParamDataType type;
-		UINT32 elementSize;
-		UINT32 arraySize;
-		UINT32 arrayElementStride;
-		UINT32 cpuOffset; 
-		UINT32 gpuOffset;
-	};
-
-	struct BS_CORE_EXPORT RendererMaterialObjectParam : public RendererMaterialParam
-	{
-		RendererMaterialObjectParam(UINT32 semantic, GpuProgramType program, GpuParamObjectType type,
-			UINT32 slot, UINT32 passIdx = RP_AnyPass, UINT32 blockSemantic = RB_NoBlock);
-
-		GpuParamObjectType type;
-		UINT32 slot;
-	};
-
-	class BS_CORE_EXPORT RendererMaterialParams
-	{
-	public:
-		RendererMaterialParams(const String& renderSystem, UINT32 renderableType);
-		~RendererMaterialParams();
-
-		bool operator== (const RendererMaterialParams& params) const;
-
-		void addDataParam(UINT32 semantic, GpuProgramType program, GpuParamDataType type, UINT32 elementSize,
-			UINT32 cpuOffset, UINT32 gpuOffset,	UINT32 passIdx = RP_AnyPass, UINT32 blockSemantic = RB_NoBlock);
-
-		void addArrayDataParam(UINT32 semantic, GpuProgramType program, GpuParamDataType type, UINT32 elementSize,
-			UINT32 arraySize, UINT32 arrayElementStride, UINT32 cpuOffset, UINT32 gpuOffset, UINT32 passIdx = RP_AnyPass, 
-			UINT32 blockSemantic = RB_NoBlock);
-
-		void addObjectParam(UINT32 semantic, GpuProgramType program, GpuParamObjectType type,
-			UINT32 slot, UINT32 passIdx = RP_AnyPass, UINT32 blockSemantic = RB_NoBlock);
-
-	private:
-		friend struct std::hash<RendererMaterialParams>;
-
-		Vector<RendererMaterialParam*> mParams;
-		String mRenderSystem;
-		UINT32 mRenderableType;
-	};
-}
-
-template<>
-struct std::hash<BansheeEngine::RendererMaterialParams>
-{
-	size_t operator()(const BansheeEngine::RendererMaterialParams& params) const
-	{
-		size_t hash = 0;
-		BansheeEngine::hash_combine(hash, params.mRenderSystem);
-		BansheeEngine::hash_combine(hash, params.mRenderableType);
-
-		return hash;
-	}
-};

+ 45 - 9
BansheeCore/Include/BsShader.h

@@ -5,6 +5,15 @@
 
 namespace BansheeEngine
 {
+	/**
+	 * @brief	Type of shader dirty flags
+	 */
+	enum class ShaderDirtyFlag
+	{
+		Shader = 0x01, /**< Internal shader data is dirty. */
+		Proxy = 0x02 /**< Active proxy needs to be updated. */
+	};
+
 	/**
 	 * @brief Describes a single data (int, Vector2, etc.) shader parameter.
 	 *
@@ -241,26 +250,51 @@ namespace BansheeEngine
 		 */
 		const Map<String, SHADER_PARAM_BLOCK_DESC>& _getParamBlocks() const { return mParamBlocks; }
 
+		static bool isSampler(GpuParamObjectType type);
+		static bool isTexture(GpuParamObjectType type);
+		static bool isBuffer(GpuParamObjectType type);
+
+		/** 
+		 * @brief	Returns an empty shader object with the specified name. Caller must register
+		 *			techniques with the shader before using it in a Material.
+		 */
+		static ShaderPtr create(const String& name);
+
+		/************************************************************************/
+		/* 								CORE PROXY                      		*/
+		/************************************************************************/
+
 		/**
 		 * @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.
 		 */
-		bool _isCoreDirty() const { return mCoreDirtyFlags != 0; }
+		bool _isCoreDirty(ShaderDirtyFlag flag) const { return (mCoreDirtyFlags & (UINT32)flag) != 0; }
 
 		/**
 		 * @brief	Marks the core dirty flag as clean.
 		 */
-		void _markCoreClean() { mCoreDirtyFlags = 0; }
+		void _markCoreClean(ShaderDirtyFlag flag) { mCoreDirtyFlags &= ~(UINT32)flag; }
 
-		static bool isSampler(GpuParamObjectType type);
-		static bool isTexture(GpuParamObjectType type);
-		static bool isBuffer(GpuParamObjectType type);
+		/**
+		 * @brief	Gets the currently active proxy of this material.
+		 */
+		ShaderProxyPtr _getActiveProxy() const { return mActiveProxy; }
 
-		/** 
-		 * @brief	Returns an empty shader object with the specified name. Caller must register
-		 *			techniques with the shader before using it in a Material.
+		/**
+		 * @brief	Sets an active proxy for this material.
 		 */
-		static ShaderPtr create(const String& name);
+		void _setActiveProxy(const ShaderProxyPtr& proxy) { mActiveProxy = proxy; }
+
+		/**
+		 * @brief	Creates a new core proxy from the currently set shader data. Core proxies ensure
+		 *			that the core thread has all the necessary data, while avoiding the need
+		 *			to manage Shader 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.
+		 */
+		ShaderProxyPtr _createProxy();
 
 	private:
 		Shader(const String& name);
@@ -282,6 +316,8 @@ namespace BansheeEngine
 		Map<String, SHADER_OBJECT_PARAM_DESC> mObjectParams;
 		Map<String, SHADER_PARAM_BLOCK_DESC> mParamBlocks;
 
+		ShaderProxyPtr mActiveProxy;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/

+ 18 - 0
BansheeCore/Include/BsShaderProxy.h

@@ -0,0 +1,18 @@
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsShader.h"
+
+namespace BansheeEngine
+{
+	struct BS_CORE_EXPORT ShaderProxy
+	{
+		QueueSortType queueSortType;
+		UINT32 queuePriority;
+		bool separablePasses;
+
+		Map<String, SHADER_DATA_PARAM_DESC> dataParams;
+		Map<String, SHADER_OBJECT_PARAM_DESC> objectParams;
+		Map<String, SHADER_PARAM_BLOCK_DESC> paramBlocks;
+	};
+}

+ 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, params->cloneForCore(gCoreThread().getFrameAlloc())));
+		mCommandQueue->queue(std::bind(&RenderSystem::bindGpuParams, RenderSystem::instancePtr(), gptype, params->_cloneForCore(gCoreThread().getFrameAlloc())));
 	}
 
 	void CoreThreadAccessorBase::beginRender()

+ 1 - 1
BansheeCore/Source/BsGpuParam.cpp

@@ -11,7 +11,7 @@ namespace BansheeEngine
 		:mParamDesc(paramDesc), mInternalData(internalData)
 	{ }
 
-	bool GpuDataParamBase::getIsDestroyed() const
+	bool GpuDataParamBase::isDestroyed() const
 	{
 		return mInternalData->mIsDestroyed;
 	}

+ 1 - 1
BansheeCore/Source/BsGpuParams.cpp

@@ -264,7 +264,7 @@ namespace BansheeEngine
 		}
 	}
 
-	GpuParamsPtr GpuParams::cloneForCore(FrameAlloc* frameAlloc) const
+	GpuParamsPtr GpuParams::_cloneForCore(FrameAlloc* frameAlloc) const
 	{
 		UINT32 bufferSize = 0;
 		UINT32 paramBlockOffset = 0;

+ 96 - 11
BansheeCore/Source/BsMaterial.cpp

@@ -716,7 +716,7 @@ namespace BansheeEngine
 			return false;
 		}
 		else
-			return (mCoreDirtyFlags & (UINT32)flag) != 0 || (mShader != nullptr && mShader->_isCoreDirty());
+			return (mCoreDirtyFlags & (UINT32)flag) != 0 || (mShader != nullptr && mShader->_isCoreDirty(ShaderDirtyFlag::Shader));
 	}
 
 	void Material::_markCoreClean(MaterialDirtyFlag flag)
@@ -726,7 +726,7 @@ namespace BansheeEngine
 		if (flag == MaterialDirtyFlag::Material)
 		{
 			if (mShader != nullptr)
-				mShader->_markCoreClean();
+				mShader->_markCoreClean(ShaderDirtyFlag::Shader);
 		}
 		
 		if (flag == MaterialDirtyFlag::Material || flag == MaterialDirtyFlag::Params)
@@ -744,6 +744,69 @@ namespace BansheeEngine
 		}
 	}
 
+	Vector<MaterialProxy::ParamsBindInfo> Material::_getDirtyProxyParams()
+	{
+		Vector<MaterialProxy::ParamsBindInfo> dirtyParams;
+		UINT32 idx = 0;
+
+		UINT32 numPasses = mShader->getBestTechnique()->getNumPasses();
+		for (UINT32 i = 0; i < numPasses; i++)
+		{
+			PassParametersPtr params = mParametersPerPass[i];
+			PassPtr pass = mShader->getBestTechnique()->getPass(i);
+
+			if (pass->hasVertexProgram())
+			{
+				if (params->mVertParams->_isCoreDirty())
+					dirtyParams.push_back(MaterialProxy::ParamsBindInfo(idx, params->mVertParams));
+
+				idx++;
+			}
+
+			if (pass->hasFragmentProgram())
+			{
+				if (params->mFragParams->_isCoreDirty())
+					dirtyParams.push_back(MaterialProxy::ParamsBindInfo(idx, params->mFragParams));
+
+				idx++;
+			}
+
+			if (pass->hasGeometryProgram())
+			{
+				if (params->mGeomParams->_isCoreDirty())
+					dirtyParams.push_back(MaterialProxy::ParamsBindInfo(idx, params->mGeomParams));
+
+				idx++;
+			}
+
+			if (pass->hasHullProgram())
+			{
+				if (params->mHullParams->_isCoreDirty())
+					dirtyParams.push_back(MaterialProxy::ParamsBindInfo(idx, params->mHullParams));
+
+				idx++;
+			}
+
+			if (pass->hasDomainProgram())
+			{
+				if (params->mDomainParams->_isCoreDirty())
+					dirtyParams.push_back(MaterialProxy::ParamsBindInfo(idx, params->mDomainParams));
+
+				idx++;
+			}
+
+			if (pass->hasComputeProgram())
+			{
+				if (params->mComputeParams->_isCoreDirty())
+					dirtyParams.push_back(MaterialProxy::ParamsBindInfo(idx, params->mComputeParams));
+
+				idx++;
+			}
+
+			return dirtyParams;
+		}
+	}
+
 	MaterialProxyPtr Material::_createProxy()
 	{
 		throwIfNotInitialized();
@@ -762,38 +825,56 @@ namespace BansheeEngine
 			if (pass->hasVertexProgram())
 			{
 				passData.vertexProg = pass->getVertexProgram();
-				passData.vertexProgParams = params->mVertParams->cloneForCore();
+				passData.vertexProgParamsIdx = proxy->params.size();
+				proxy->params.push_back(params->mVertParams->_cloneForCore());
 			}
+			else
+				passData.vertexProgParamsIdx = 0;
 
 			if (pass->hasFragmentProgram())
 			{
 				passData.fragmentProg = pass->getFragmentProgram();
-				passData.fragmentProgParams = params->mFragParams->cloneForCore();
+				passData.fragmentProgParamsIdx = proxy->params.size();
+				proxy->params.push_back(params->mFragParams->_cloneForCore());
 			}
+			else
+				passData.fragmentProgParamsIdx = 0;
 
 			if (pass->hasGeometryProgram())
 			{
 				passData.geometryProg = pass->getGeometryProgram();
-				passData.geometryProgParams = params->mGeomParams->cloneForCore();
+				passData.geometryProgParamsIdx = proxy->params.size();
+				proxy->params.push_back(params->mGeomParams->_cloneForCore());
 			}
+			else
+				passData.geometryProgParamsIdx = 0;
 
 			if (pass->hasHullProgram())
 			{
 				passData.hullProg = pass->getHullProgram();
-				passData.hullProgParams = params->mHullParams->cloneForCore();
+				passData.hullProgParamsIdx = proxy->params.size();
+				proxy->params.push_back(params->mHullParams->_cloneForCore());
 			}
+			else
+				passData.hullProgParamsIdx = 0;
 
 			if (pass->hasDomainProgram())
 			{
 				passData.domainProg = pass->getDomainProgram();
-				passData.domainProgParams = params->mDomainParams->cloneForCore();
+				passData.domainProgParamsIdx = proxy->params.size();
+				proxy->params.push_back(params->mDomainParams->_cloneForCore());
 			}
+			else
+				passData.domainProgParamsIdx = 0;
 
 			if (pass->hasComputeProgram())
 			{
 				passData.computeProg = pass->getComputeProgram();
-				passData.computeProgParams = params->mComputeParams->cloneForCore();
+				passData.computeProgParamsIdx = proxy->params.size();
+				proxy->params.push_back(params->mComputeParams->_cloneForCore());
 			}
+			else
+				passData.computeProgParamsIdx = 0;
 
 			passData.blendState = pass->getBlendState();
 			passData.rasterizerState = pass->getRasterizerState();
@@ -801,9 +882,13 @@ namespace BansheeEngine
 			passData.stencilRefValue = pass->getStencilRefValue();
 		}
 
-		proxy->queuePriority = mShader->getQueuePriority();
-		proxy->queueSortType = mShader->getQueueSortType();
-		proxy->separablePasses = mShader->getAllowSeparablePasses();
+		if (mShader->_isCoreDirty(ShaderDirtyFlag::Proxy))
+		{
+			mShader->_setActiveProxy(mShader->_createProxy());
+			mShader->_markCoreClean(ShaderDirtyFlag::Proxy);
+		}
+
+		proxy->shader = mShader->_getActiveProxy();
 
 		return proxy;
 	}

+ 0 - 61
BansheeCore/Source/BsRendererParams.cpp

@@ -1,61 +0,0 @@
-#include "BsRendererParams.h"
-
-namespace BansheeEngine
-{
-	RendererMaterialParam::RendererMaterialParam(UINT32 semantic, GpuProgramType program, bool isObject, UINT32 passIdx, UINT32 blockSemantic)
-		:semantic(semantic), program(program), isObject(isObject), passIdx(passIdx), blockSemantic(blockSemantic)
-	{
-
-	}
-
-	RendererMaterialDataParam::RendererMaterialDataParam(UINT32 semantic, GpuProgramType program, GpuParamDataType type, UINT32 elementSize,
-		UINT32 arraySize, UINT32 arrayElementStride, UINT32 cpuOffset, UINT32 gpuOffset, UINT32 passIdx, UINT32 blockSemantic)
-		: RendererMaterialParam(semantic, program, false, passIdx, blockSemantic), type(type), elementSize(elementSize), arraySize(arraySize),
-		arrayElementStride(arrayElementStride), cpuOffset(cpuOffset), gpuOffset(gpuOffset)
-	{
-
-	}
-
-	RendererMaterialObjectParam::RendererMaterialObjectParam(UINT32 semantic, GpuProgramType program, GpuParamObjectType type,
-		UINT32 slot, UINT32 passIdx, UINT32 blockSemantic)
-		: RendererMaterialParam(semantic, program, true, passIdx, blockSemantic), type(type), slot(slot)
-	{
-
-	}
-
-	RendererMaterialParams::RendererMaterialParams(const String& renderSystem, UINT32 renderableType)
-		:mRenderSystem(renderSystem), mRenderableType(renderableType)
-	{ }
-
-	RendererMaterialParams::~RendererMaterialParams()
-	{
-		for (auto& param : mParams)
-		{
-			bs_delete(param);
-		}
-	}
-
-	bool RendererMaterialParams::operator== (const RendererMaterialParams& params) const
-	{
-		return mRenderSystem == params.mRenderSystem && mRenderableType == params.mRenderableType;
-	}
-
-	void RendererMaterialParams::addDataParam(UINT32 semantic, GpuProgramType program, GpuParamDataType type, UINT32 elementSize, 
-		UINT32 cpuOffset, UINT32 gpuOffset, UINT32 passIdx, UINT32 blockSemantic)
-	{
-		mParams.push_back(bs_new<RendererMaterialDataParam>(semantic, program, type, elementSize, 1, elementSize, cpuOffset, gpuOffset, passIdx, blockSemantic));
-	}
-
-	void RendererMaterialParams::addArrayDataParam(UINT32 semantic, GpuProgramType program, GpuParamDataType type, UINT32 elementSize,
-		UINT32 arraySize, UINT32 arrayElementStride, UINT32 cpuOffset, UINT32 gpuOffset, UINT32 passIdx, UINT32 blockSemantic)
-	{
-		mParams.push_back(bs_new<RendererMaterialDataParam>(semantic, program, type, elementSize, arraySize, arrayElementStride, 
-			cpuOffset, gpuOffset, passIdx, blockSemantic));
-	}
-
-	void RendererMaterialParams::addObjectParam(UINT32 semantic, GpuProgramType program, GpuParamObjectType type,
-		UINT32 slot, UINT32 passIdx, UINT32 blockSemantic)
-	{
-		mParams.push_back(bs_new<RendererMaterialObjectParam>(semantic, program, type, slot, passIdx, blockSemantic));
-	}
-}

+ 14 - 0
BansheeCore/Source/BsShader.cpp

@@ -2,6 +2,7 @@
 #include "BsTechnique.h"
 #include "BsException.h"
 #include "BsDebug.h"
+#include "BsShaderProxy.h"
 #include "BsShaderRTTI.h"
 
 namespace BansheeEngine
@@ -242,6 +243,19 @@ namespace BansheeEngine
 		return newShader;
 	}
 
+	ShaderProxyPtr Shader::_createProxy()
+	{
+		ShaderProxyPtr proxy = bs_shared_ptr<ShaderProxy>();
+		proxy->dataParams = mDataParams;
+		proxy->objectParams = mObjectParams;
+		proxy->paramBlocks = mParamBlocks;
+		proxy->queuePriority = mQueuePriority;
+		proxy->queueSortType = mQueueSortType;
+		proxy->separablePasses = mSeparablePasses;
+
+		return proxy;
+	}
+
 	RTTITypeBase* Shader::getRTTIStatic()
 	{
 		return ShaderRTTI::instance();

+ 5 - 0
BansheeD3D11RenderSystem/Include/BsD3D11GpuProgram.h

@@ -16,6 +16,11 @@ namespace BansheeEngine
 
 		GpuParamsPtr createParameters();
 
+		/**
+		 * @copydoc	GpuProgram::requiresMatrixTranspose
+		 */
+		virtual bool requiresMatrixTranspose() const { return mColumnMajorMatrices; }
+
 		/** Sets whether matrix packing in column-major order. */
 		void setColumnMajorMatrices(bool columnMajor) { mColumnMajorMatrices = columnMajor; }
 		/** Gets whether matrix packed in column-major order. */

+ 3 - 10
BansheeD3D11RenderSystem/Source/BsD3D11HardwareBuffer.cpp

@@ -10,16 +10,9 @@ namespace BansheeEngine
 {
 	D3D11HardwareBuffer::D3D11HardwareBuffer(BufferType btype, GpuBufferUsage usage, UINT32 elementCount, UINT32 elementSize, 
 		D3D11Device& device, bool useSystemMem, bool streamOut, bool randomGpuWrite, bool useCounter)
-		: HardwareBuffer(usage, useSystemMem),
-		mD3DBuffer(0),
-		mpTempStagingBuffer(0),
-		mUseTempStagingBuffer(false),
-		mBufferType(btype),
-		mDevice(device),
-		mElementCount(elementCount),
-		mElementSize(elementSize),
-		mRandomGpuWrite(randomGpuWrite),
-		mUseCounter(useCounter)
+		: HardwareBuffer(usage, useSystemMem), mD3DBuffer(nullptr), mpTempStagingBuffer(nullptr), mUseTempStagingBuffer(false),
+		 mBufferType(btype), mDevice(device), mElementCount(elementCount), mElementSize(elementSize), mRandomGpuWrite(randomGpuWrite),
+		 mUseCounter(useCounter)
 	{
 		assert((!streamOut || btype == BT_VERTEX) && "Stream out flag is only supported on vertex buffers");
 		assert(!randomGpuWrite || (btype & BT_GROUP_GENERIC) != 0 && "randomGpuWrite flag can only be enabled with append/consume, indirect argument, structured or raw buffers");

+ 5 - 0
BansheeD3D9RenderSystem/Include/BsD3D9GpuProgram.h

@@ -23,6 +23,11 @@ namespace BansheeEngine
     public:
         ~D3D9GpuProgram();
 
+		/**
+		 * @copydoc	GpuProgram::requiresMatrixTranspose
+		 */
+		virtual bool requiresMatrixTranspose() const { return mColumnMajorMatrices; }
+
 		/** Sets the preprocessor defines use to compile the program. */
 		void setPreprocessorDefines(const String& defines) { mPreprocessorDefines = defines; }
 		/** Sets the preprocessor defines use to compile the program. */

+ 2 - 0
BansheeEngine/BansheeEngine.vcxproj

@@ -229,6 +229,7 @@
     <ClCompile Include="Source\BsCursor.cpp" />
     <ClCompile Include="Source\BsInputConfiguration.cpp" />
     <ClCompile Include="Source\BsRenderableProxy.cpp" />
+    <ClCompile Include="Source\BsRenderQueue.cpp" />
     <ClCompile Include="Source\BsVirtualInput.cpp" />
     <ClInclude Include="Include\BsApplication.h" />
     <ClInclude Include="Include\BsCursor.h" />
@@ -289,6 +290,7 @@
     <ClInclude Include="Include\BsProfilerOverlay.h" />
     <ClInclude Include="Include\BsRectOffset.h" />
     <ClInclude Include="Include\BsRenderableProxy.h" />
+    <ClInclude Include="Include\BsRenderQueue.h" />
     <ClInclude Include="Include\BsSceneManager.h" />
     <ClInclude Include="Include\BsGUIScrollArea.h" />
     <ClInclude Include="Include\BsScriptManager.h" />

+ 6 - 0
BansheeEngine/BansheeEngine.vcxproj.filters

@@ -276,6 +276,9 @@
     <ClInclude Include="Include\BsRenderableProxy.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsRenderQueue.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsGUIElement.cpp">
@@ -476,5 +479,8 @@
     <ClCompile Include="Source\BsRenderableProxy.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsRenderQueue.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 4 - 2
BansheeCore/Include/BsRenderQueue.h → BansheeEngine/Include/BsRenderQueue.h

@@ -1,8 +1,6 @@
 #pragma once
 
 #include "BsCorePrerequisites.h"
-#include "BsMaterialProxy.h"
-#include "BsMeshProxy.h"
 
 namespace BansheeEngine 
 {
@@ -15,6 +13,8 @@ namespace BansheeEngine
 			:passIdx(0)
 		{ }
 
+		RenderableProxyPtr renderable;
+		RenderableElement* renderElem;
 		MaterialProxyPtr material;
 		MeshProxyPtr mesh;
 		Vector3 worldPosition;
@@ -35,6 +35,8 @@ namespace BansheeEngine
 	public:
 		RenderQueue();
 
+		void add(const RenderableProxyPtr& renderable, RenderableElement* element, const Vector3& worldPosForSort);
+
 		void add(const MaterialProxyPtr& material, const MeshProxyPtr& mesh, const Vector3& worldPosForSort);
 
 		/**

+ 2 - 0
BansheeEngine/Include/BsRenderableProxy.h

@@ -24,6 +24,8 @@ namespace BansheeEngine
 
 		UINT64 layer;
 
+		Any rendererData;
+
 	private:
 		bool mBoundsDirty;
 	};

+ 21 - 1
BansheeCore/Source/BsRenderQueue.cpp → BansheeEngine/Source/BsRenderQueue.cpp

@@ -1,4 +1,7 @@
 #include "BsRenderQueue.h"
+#include "BsMaterialProxy.h"
+#include "BsMeshProxy.h"
+#include "BsRenderableProxy.h"
 
 namespace BansheeEngine
 {
@@ -13,12 +16,27 @@ namespace BansheeEngine
 		mSortedRenderElements.clear();
 	}
 
+	void RenderQueue::add(const RenderableProxyPtr& renderable, RenderableElement* element, const Vector3& worldPosForSort)
+	{
+		// TODO - Make sure RenderQueueElements are cached so we dont allocate memory for them every frame
+		mRenderElements.push_back(RenderQueueElement());
+
+		RenderQueueElement& renderOp = mRenderElements.back();
+		renderOp.renderable = renderable;
+		renderOp.renderElem = element;
+		renderOp.material = element->material;
+		renderOp.mesh = element->mesh;
+		renderOp.worldPosition = worldPosForSort;
+	}
+
 	void RenderQueue::add(const MaterialProxyPtr& material, const MeshProxyPtr& mesh, const Vector3& worldPosForSort)
 	{
 		// TODO - Make sure RenderQueueElements are cached so we dont allocate memory for them every frame
 		mRenderElements.push_back(RenderQueueElement());
 
 		RenderQueueElement& renderOp = mRenderElements.back();
+		renderOp.renderable = nullptr;
+		renderOp.renderElem = nullptr;
 		renderOp.material = material;
 		renderOp.mesh = mesh;
 		renderOp.worldPosition = worldPosForSort;
@@ -29,12 +47,14 @@ namespace BansheeEngine
 		// Just pass-through for now
 		for (auto& renderElem : mRenderElements)
 		{
-			UINT32 numPasses = (UINT32)renderElem.material->passes.size();
+			UINT32 numPasses = (UINT32)renderElem.renderElem->material->passes.size();
 			for (UINT32 i = 0; i < numPasses; i++)
 			{
 				mSortedRenderElements.push_back(RenderQueueElement());
 
 				RenderQueueElement& sortedElem = mSortedRenderElements.back();
+				sortedElem.renderable = renderElem.renderable;
+				sortedElem.renderElem = renderElem.renderElem;
 				sortedElem.material = renderElem.material;
 				sortedElem.mesh = renderElem.mesh;
 				sortedElem.worldPosition = renderElem.worldPosition;

+ 29 - 8
BansheeRenderer/Include/BsBansheeRenderer.h

@@ -11,11 +11,11 @@ namespace BansheeEngine
 {
 	enum BansheeRendererParamSemantic
 	{
-		BRPS_Time = 1000,
-		BRPS_LightDir = 1001
+		RPS_Time = 1000,
+		RPS_LightDir = 1001
 	};
 
-	struct RenderableLitTexturedData
+	struct RenderLitTexturedGlobalData
 	{
 		ShaderPtr defaultShader;
 
@@ -29,6 +29,22 @@ namespace BansheeEngine
 
 		GpuParamBlockBufferPtr staticParamBuffer;
 		GpuParamBlockBufferPtr perFrameParamBuffer;
+
+		GpuParamsPtr staticParams;
+		GpuParamsPtr perFrameParams;
+
+		GpuParamVec4 lightDirParam;
+		GpuParamFloat timeParam;
+	};
+
+	struct RenderLitTexturedPerObjectData
+	{
+		GpuParamBlockBufferPtr perObjectParamBuffer;
+
+		bool hasWVPParam;
+		GpuParamMat4 wvpParam;
+
+		Vector<MaterialProxy::BufferBindInfo> perObjectBuffers;
 	};
 
 	/**
@@ -60,6 +76,8 @@ namespace BansheeEngine
 		virtual void renderAll();
 
 	private:
+		void initRenderableLitTexturedData();
+
 		void addRenderableProxy(RenderableProxyPtr proxy);
 		void removeRenderableProxy(RenderableProxyPtr proxy);
 		void updateRenderableProxy(RenderableProxyPtr proxy, Matrix4 localToWorld);
@@ -68,22 +86,25 @@ 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 addToRenderQueue(CameraProxyPtr proxy, RenderQueuePtr renderQueue);
+		void updateMaterialProxy(MaterialProxyPtr proxy, Vector<MaterialProxy::ParamsBindInfo> dirtyParams);
 
-		void renderAllCore();
+		void renderAllCore(float time);
 
 		/**
 		 * @brief	Renders all objects visible by the provided camera.
 		 */
 		virtual void render(const CameraProxy& cameraProxy, const RenderQueuePtr& renderQueue);
 
-		void setPass(const MaterialProxyPass& pass);
+		void setPass(const MaterialProxyPtr& material, UINT32 passIdx);
 		void draw(const MeshProxy& mesh);
 
 		void renderableRemoved(const HRenderable& renderable);
 		void cameraRemoved(const HCamera& camera);
 
+		void bindGlobalBuffers(const RenderableElement* element);
+		void bindPerObjectBuffers(const RenderableProxyPtr& renderable, const RenderableElement* element);
+
 		ShaderPtr getDefaultShader(RenderableType type) const;
 
 		Vector<RenderableProxyPtr> mDeletedRenderableProxies;
@@ -98,7 +119,7 @@ namespace BansheeEngine
 		Vector<Matrix4> mWorldTransforms;
 		Vector<Bounds> mWorldBounds;
 
-		RenderableLitTexturedData mLitTexturedData;
+		RenderLitTexturedGlobalData mLitTexturedData;
 
 		HEvent mRenderableRemovedConn;
 		HEvent mCameraRemovedConn;

+ 267 - 107
BansheeRenderer/Source/BsBansheeRenderer.cpp

@@ -23,6 +23,11 @@
 #include "BsShader.h"
 #include "BsTechnique.h"
 #include "BsDrawList.h"
+#include "BsHardwareBufferManager.h"
+#include "BsGpuParamBlockBuffer.h"
+#include "BsShader.h"
+#include "BsShaderProxy.h"
+#include "BsTime.h"
 
 using namespace std::placeholders;
 
@@ -33,41 +38,56 @@ namespace BansheeEngine
 		mRenderableRemovedConn = gBsSceneManager().onRenderableRemoved.connect(std::bind(&BansheeRenderer::renderableRemoved, this, _1));
 		mCameraRemovedConn = gBsSceneManager().onCameraRemoved.connect(std::bind(&BansheeRenderer::cameraRemoved, this, _1));
 
-		// Init compatible material params
-		RendererMaterialParams dx9params("BansheeD3D9RenderSystem", RenType_UnlitUntextured);
+		// Init default shaders
+		initRenderableLitTexturedData();
+	}
 
-		// TODO - In a perfect world I would get element size and offsets by creating a dummy version of the param block
-		// and reading the values.
-		dx9params.addDataParam(RPS_WorldViewProjTfrm, GPT_VERTEX_PROGRAM, GPDT_MATRIX_4X4, sizeof(Matrix4), 0, 0, RP_AnyPass, RBS_PerObject);
+	BansheeRenderer::~BansheeRenderer()
+	{
+		mRenderableRemovedConn.disconnect();
+		mCameraRemovedConn.disconnect();
+	}
 
-		mRenderableMaterialParams.insert(dx9params);
+	const String& BansheeRenderer::getName() const
+	{
+		static String name = "BansheeRenderer";
+		return name;
+	}
 
-		// Init default shaders
+	void BansheeRenderer::initRenderableLitTexturedData()
+	{
 		mLitTexturedData.defaultShader = getDefaultShader(RenType_LitTextured);
 		TechniquePtr defaultTechnique = mLitTexturedData.defaultShader->getBestTechnique();
 		PassPtr defaultPass = defaultTechnique->getPass(0);
 
+		bool matrixTranspose = defaultPass->getVertexProgram()->requiresMatrixTranspose(); // This is a static setting across all GPU programs
 		const GpuParamDesc& vertParamDesc = defaultPass->getVertexProgram()->getParamDesc();
 		const GpuParamDesc& fragParamDesc = defaultPass->getFragmentProgram()->getParamDesc();
 
+		GpuParamDesc staticParamsDesc;
+		GpuParamDesc perFrameParamsDesc;
+		GpuParamDesc perObjectParamsDesc;
+
 		const Map<String, SHADER_DATA_PARAM_DESC>& dataParams = mLitTexturedData.defaultShader->_getDataParams();
 		for (auto& param : dataParams)
 		{
-			if (param.second.rendererSemantic == BRPS_LightDir)
+			if (param.second.rendererSemantic == RPS_LightDir)
 			{
 				auto iterFind = fragParamDesc.params.find(param.second.gpuVariableName);
 				if (iterFind == fragParamDesc.params.end())
 					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
 
 				mLitTexturedData.lightDirParamDesc = iterFind->second;
+				staticParamsDesc.params[iterFind->first] = iterFind->second;
 			}
-			else if (param.second.rendererSemantic == BRPS_Time)
+			else if (param.second.rendererSemantic == RPS_Time)
 			{
 				auto iterFind = vertParamDesc.params.find(param.second.gpuVariableName);
 				if (iterFind == vertParamDesc.params.end())
 					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
 
 				mLitTexturedData.timeParamDesc = iterFind->second;
+				perFrameParamsDesc.params[iterFind->first] = iterFind->second;
 			}
 			else if (param.second.rendererSemantic == RPS_WorldViewProjTfrm)
 			{
@@ -76,19 +96,21 @@ namespace BansheeEngine
 					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
 
 				mLitTexturedData.wvpParamDesc = iterFind->second;
+				perObjectParamsDesc.params[iterFind->first] = iterFind->second;
 			}
 		}
 
 		const Map<String, SHADER_PARAM_BLOCK_DESC>& paramBlocks = mLitTexturedData.defaultShader->_getParamBlocks();
 		for (auto& block : paramBlocks)
 		{
-			if (block.second.rendererSemantic == RBS_Occassional)
+			if (block.second.rendererSemantic == RBS_Static)
 			{
 				auto iterFind = vertParamDesc.paramBlocks.find(block.second.name);
 				if (iterFind == vertParamDesc.paramBlocks.end())
 					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
 
 				mLitTexturedData.staticParamBlockDesc = iterFind->second;
+				staticParamsDesc.paramBlocks[iterFind->first] = iterFind->second;
 			}
 			else if (block.second.rendererSemantic == RBS_PerFrame)
 			{
@@ -97,6 +119,7 @@ namespace BansheeEngine
 					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
 
 				mLitTexturedData.perFrameParamBlockDesc = iterFind->second;
+				perFrameParamsDesc.paramBlocks[iterFind->first] = iterFind->second;
 			}
 			else if (block.second.rendererSemantic == RBS_PerObject)
 			{
@@ -105,20 +128,24 @@ namespace BansheeEngine
 					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
 
 				mLitTexturedData.perObjectParamBlockDesc = iterFind->second;
+				perObjectParamsDesc.paramBlocks[iterFind->first] = iterFind->second;
 			}
 		}
-	}
 
-	BansheeRenderer::~BansheeRenderer()
-	{
-		mRenderableRemovedConn.disconnect();
-		mCameraRemovedConn.disconnect();
-	}
+		// Create global GPU param buffers and get parameter handles
+		mLitTexturedData.staticParams = bs_shared_ptr<GpuParams>(staticParamsDesc, matrixTranspose);
+		mLitTexturedData.perFrameParams = bs_shared_ptr<GpuParams>(perFrameParamsDesc, matrixTranspose);
 
-	const String& BansheeRenderer::getName() const
-	{
-		static String name = "BansheeRenderer";
-		return name;
+		mLitTexturedData.staticParamBuffer = HardwareBufferManager::instance().createGpuParamBlockBuffer(mLitTexturedData.staticParamBlockDesc.blockSize);
+		mLitTexturedData.perFrameParamBuffer = HardwareBufferManager::instance().createGpuParamBlockBuffer(mLitTexturedData.perFrameParamBlockDesc.blockSize);
+
+		mLitTexturedData.staticParams->setParamBlockBuffer(mLitTexturedData.staticParamBlockDesc.slot, mLitTexturedData.staticParamBuffer);
+		mLitTexturedData.perFrameParams->setParamBlockBuffer(mLitTexturedData.perFrameParamBlockDesc.slot, mLitTexturedData.perFrameParamBuffer);
+
+		mLitTexturedData.staticParams->getParam(mLitTexturedData.lightDirParamDesc.name, mLitTexturedData.lightDirParam);
+		mLitTexturedData.staticParams->getParam(mLitTexturedData.timeParamDesc.name, mLitTexturedData.timeParam);
+
+		mLitTexturedData.lightDirParam.set(Vector4(0.707f, 0.707f, 0.707f, 0.0f));
 	}
 
 	ShaderPtr BansheeRenderer::getDefaultShader(RenderableType type) const
@@ -136,6 +163,120 @@ namespace BansheeEngine
 
 			element->id = (UINT32)(mRenderableElements.size() - 1);
 		}
+
+		// Find and set up renderer buffers and parameters
+		static auto paramsMatch = [](const GpuParamDataDesc& a, const GpuParamDataDesc& b)
+		{
+			return a.gpuMemOffset == b.gpuMemOffset && a.elementSize == b.elementSize &&
+				a.arraySize == b.arraySize && a.arrayElementStride == b.arrayElementStride;
+		};
+
+		if (proxy->renderableType == RenType_LitTextured)
+		{
+			for (auto& element : proxy->renderableElements)
+			{
+				element->rendererData = RenderLitTexturedPerObjectData();
+				RenderLitTexturedPerObjectData* rendererData = any_cast_unsafe<RenderLitTexturedPerObjectData>(&element->rendererData);
+
+				ShaderProxyPtr shader = element->material->shader;
+
+				const Map<String, SHADER_PARAM_BLOCK_DESC>& paramBlockDescs = shader->paramBlocks;
+				const Map<String, SHADER_DATA_PARAM_DESC>& dataParamDescs = shader->dataParams;
+				String staticBlockName;
+				String perFrameBlockName;
+				String perObjectBlockName;
+
+				String wvpParamName;
+
+				for (auto& paramBlockDesc : paramBlockDescs)
+				{
+					switch (paramBlockDesc.second.rendererSemantic)
+					{
+					case RBS_Static:
+						staticBlockName = paramBlockDesc.second.name;
+						break;
+					case RBS_PerFrame:
+						perFrameBlockName = paramBlockDesc.second.name;
+						break;
+					case RBS_PerObject:
+						perObjectBlockName = paramBlockDesc.second.name;
+						break;
+					}
+				}
+
+				for (auto& paramDesc : dataParamDescs)
+				{
+					if (paramDesc.second.rendererSemantic == RPS_WorldViewProjTfrm)
+						wvpParamName = paramDesc.second.gpuVariableName;
+				}
+
+				UINT32 idx = 0;
+				for (auto& gpuParams : element->material->params)
+				{
+					const GpuParamDesc& paramsDesc = gpuParams->getParamDesc();
+
+					if (staticBlockName != "")
+					{
+						auto findIter = paramsDesc.paramBlocks.find(staticBlockName);
+						if (findIter != paramsDesc.paramBlocks.end())
+						{
+							// 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 == mLitTexturedData.staticParamBlockDesc.blockSize)
+							{
+								UINT32 slotIdx = findIter->second.slot;
+								element->material->rendererBuffers.push_back(MaterialProxy::BufferBindInfo(idx, slotIdx, mLitTexturedData.staticParamBuffer));
+							}
+						}
+					}
+					
+					if (perFrameBlockName != "")
+					{
+						auto findIter = paramsDesc.paramBlocks.find(perFrameBlockName);
+						if (findIter != paramsDesc.paramBlocks.end())
+						{
+							if (findIter->second.blockSize == mLitTexturedData.perFrameParamBlockDesc.blockSize)
+							{
+								UINT32 slotIdx = findIter->second.slot;
+								element->material->rendererBuffers.push_back(MaterialProxy::BufferBindInfo(idx, slotIdx, mLitTexturedData.perFrameParamBuffer));
+							}
+						}
+					}
+
+					if (perObjectBlockName != "")
+					{
+						auto findIter = paramsDesc.paramBlocks.find(perObjectBlockName);
+						if (findIter != paramsDesc.paramBlocks.end())
+						{
+							if (findIter->second.blockSize == mLitTexturedData.perObjectParamBlockDesc.blockSize)
+							{
+								if (rendererData->perObjectParamBuffer == nullptr)
+									rendererData->perObjectParamBuffer = HardwareBufferManager::instance().createGpuParamBlockBuffer(mLitTexturedData.perObjectParamBlockDesc.blockSize);
+
+								rendererData->perObjectBuffers.push_back(MaterialProxy::BufferBindInfo(idx, findIter->second.slot, rendererData->perObjectParamBuffer));
+
+								if (!rendererData->hasWVPParam && wvpParamName != "")
+								{
+									auto findIter2 = paramsDesc.params.find(wvpParamName);
+									if (findIter2 != paramsDesc.params.end())
+									{
+										if (paramsMatch(findIter2->second, mLitTexturedData.wvpParamDesc))
+										{
+											gpuParams->getParam(wvpParamName, rendererData->wvpParam);
+											rendererData->hasWVPParam = true;
+										}
+									}
+								}
+							}
+						}
+					}
+
+					idx++;
+				}
+
+				bindGlobalBuffers(element);
+			}
+		}
 	}
 
 	void BansheeRenderer::removeRenderableProxy(RenderableProxyPtr proxy)
@@ -242,8 +383,6 @@ namespace BansheeEngine
 
 	void BansheeRenderer::renderAll() 
 	{
-		gProfilerCPU().beginSample("renderA");
-
 		gBsSceneManager().updateRenderableTransforms();
 
 		// Remove proxies from deleted Renderables
@@ -296,27 +435,8 @@ namespace BansheeEngine
 					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->cloneForCore());
-
-									params->_markCoreClean();
-								}
-							}
-
-							dirtyPassParams.push_back(dirtyParams);
-						}
-						
-						gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::updateMaterialProxy, this, proxy->renderableElements[i]->material, dirtyPassParams));
+						gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::updateMaterialProxy, this, proxy->renderableElements[i]->material, mat->_getDirtyProxyParams()));
+						mat->_markCoreClean(MaterialDirtyFlag::Params);
 					}
 				}
 			}
@@ -395,67 +515,57 @@ namespace BansheeEngine
 			for (auto& callback : callbacksForViewport)
 				callback(viewportRawPtr, *drawList);
 
-			gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::setDrawList, this, camera->_getActiveProxy(), drawList));
-		}
+			RenderQueuePtr renderQueue = bs_shared_ptr<RenderQueue>();
+			const Vector<DrawOperation>& drawOps = drawList->getDrawOperations();
+			for (auto& drawOp : drawOps)
+			{
+				if (drawOp.material->_isCoreDirty(MaterialDirtyFlag::Proxy))
+					drawOp.material->_setActiveProxy(drawOp.material->_createProxy());
 
-		gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::renderAllCore, this));
-	}
+				if (drawOp.mesh->_isCoreDirty(MeshDirtyFlag::Proxy))
+					drawOp.mesh->_setActiveProxy(drawOp.submeshIdx, drawOp.mesh->_createProxy(drawOp.submeshIdx));
 
-	void BansheeRenderer::setDrawList(CameraProxyPtr proxy, DrawListPtr drawList)
-	{
-		RenderQueuePtr renderQueue = proxy->renderQueue;
+				MaterialProxyPtr materialProxy = drawOp.material->_getActiveProxy();
+				MeshProxyPtr meshProxy = drawOp.mesh->_getActiveProxy(drawOp.submeshIdx);
 
-		const Vector<DrawOperation>& drawOps = drawList->getDrawOperations();
-		for (auto& drawOp : drawOps)
-		{
-			// TODO - Will I need to check if materials match renderer?
+				renderQueue->add(materialProxy, meshProxy, drawOp.worldPosition);
+			}
 
-			renderQueue->add(drawOp.material->_createProxy(),
-				drawOp.mesh->_createProxy(drawOp.submeshIdx), drawOp.worldPosition);
+			gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::addToRenderQueue, this, camera->_getActiveProxy(), drawList));
 		}
+
+		gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::renderAllCore, this, gTime().getTime()));
 	}
 
-	void BansheeRenderer::updateMaterialProxy(MaterialProxyPtr proxy, Vector<PassParameters> dirtyPassParams)
+	void BansheeRenderer::addToRenderQueue(CameraProxyPtr proxy, RenderQueuePtr renderQueue)
 	{
-		assert(proxy->passes.size() == dirtyPassParams.size());
+		RenderQueuePtr cameraRenderQueue = proxy->renderQueue;
 
-		for (UINT32 i = 0; i < (UINT32)proxy->passes.size(); i++)
+		const Vector<RenderQueueElement>& queueElements = renderQueue->getSortedElements();
+		for (auto& queueElement : queueElements)
 		{
-			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;
+			cameraRenderQueue->add(queueElement.material, queueElement.mesh, queueElement.worldPosition);
+		}
+	}
 
-			if (dirtyParams.mDomainParams != nullptr)
-				proxy->passes[i].domainProgParams = dirtyParams.mDomainParams;
+	void BansheeRenderer::updateMaterialProxy(MaterialProxyPtr proxy, Vector<MaterialProxy::ParamsBindInfo> dirtyParams)
+	{
+		for (UINT32 i = 0; i < (UINT32)dirtyParams.size(); i++)
+			proxy->params[dirtyParams[i].paramsIdx] = dirtyParams[i].params;
 
-			if (dirtyParams.mComputeParams != nullptr)
-				proxy->passes[i].computeProgParams = dirtyParams.mComputeParams;
-		}
+		for (auto& rendererBuffer : proxy->rendererBuffers)
+			proxy->params[rendererBuffer.paramsIdx]->setParamBlockBuffer(rendererBuffer.slotIdx, rendererBuffer.buffer);
 	}
 
-	void BansheeRenderer::renderAllCore()
+	void BansheeRenderer::renderAllCore(float time)
 	{
 		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
+		// Update global hardware buffers
+		mLitTexturedData.timeParam.set(time);
+
+		mLitTexturedData.staticParams->updateHardwareBuffers();
+		mLitTexturedData.perFrameParams->updateHardwareBuffers();
 
 		// Render everything, target by target
 		for (auto& renderTargetData : mRenderTargets)
@@ -497,45 +607,95 @@ namespace BansheeEngine
 
 		RenderSystem& rs = RenderSystem::instance();
 
+		Matrix4 projMatrixCstm = cameraProxy.projMatrix;
+		Matrix4 viewMatrixCstm = cameraProxy.viewMatrix;
+
+		Matrix4 viewProjMatrix = projMatrixCstm * viewMatrixCstm;
+
 		if (!cameraProxy.ignoreSceneRenderables)
 		{
-			// TODO - Do frustum culling
-			for (auto& renderableProxy : mRenderableElements)
+			// Update per-object param buffers and queue render elements
+			for (auto& proxy : mRenderableProxies)
 			{
-				// TODO - Apply world-view-proj matrix
+				for (auto& renderElem : proxy.second->renderableElements)
+				{
+					if (proxy.second->renderableType == RenType_LitTextured)
+					{
+						RenderLitTexturedPerObjectData* rendererData = any_cast_unsafe<RenderLitTexturedPerObjectData>(&renderElem->rendererData);
 
-				renderQueue->add(renderableProxy->material, renderableProxy->mesh, mWorldBounds[renderableProxy->id].getSphere().getCenter());
-				
-			}
-		}
+						if (rendererData->hasWVPParam)
+						{
+							Matrix4 worldViewProjMatrix = viewProjMatrix * renderElem->worldTransform;
+							rendererData->wvpParam.set(worldViewProjMatrix);
+						}
 
-		Matrix4 projMatrixCstm = cameraProxy.projMatrix;
-		Matrix4 viewMatrixCstm = cameraProxy.viewMatrix;
+						if (rendererData->perObjectParamBuffer != nullptr)
+						{
+							GpuParamBlockPtr paramBlock = rendererData->perObjectParamBuffer->getParamBlock();
+							if (paramBlock->isDirty())
+								paramBlock->uploadToBuffer(rendererData->perObjectParamBuffer);
+						}
+					}
 
-		Matrix4 viewProjMatrix = projMatrixCstm * viewMatrixCstm;
+					for (auto& param : renderElem->material->params)
+					{
+						param->updateHardwareBuffers();
+					}
+
+					// TODO - Do frustum culling
+					renderQueue->add(proxy.second, renderElem, mWorldBounds[renderElem->id].getSphere().getCenter());
+				}
+			}
+		}
 
 		renderQueue->sort();
 		const Vector<RenderQueueElement>& sortedRenderElements = renderQueue->getSortedElements();
 
 		for(auto iter = sortedRenderElements.begin(); iter != sortedRenderElements.end(); ++iter)
 		{
-			MaterialProxyPtr materialProxy = iter->material;
+			MaterialProxyPtr materialProxy = iter->renderElem->material;
+
+			if (iter->renderable != nullptr)
+				bindPerObjectBuffers(iter->renderable, iter->renderElem);
+
+			setPass(materialProxy, iter->passIdx);
+			draw(*iter->renderElem->mesh);
+		}
+	}
+
+	void BansheeRenderer::bindGlobalBuffers(const RenderableElement* element)
+	{
+		for (auto& rendererBuffer : element->material->rendererBuffers)
+		{
+			element->material->params[rendererBuffer.paramsIdx]->setParamBlockBuffer(rendererBuffer.slotIdx, rendererBuffer.buffer);
+		}
+	}
+
+	void BansheeRenderer::bindPerObjectBuffers(const RenderableProxyPtr& renderable, const RenderableElement* element)
+	{
+		if (renderable->renderableType != RenType_LitTextured)
+			return;
+
+		const RenderLitTexturedPerObjectData* rendererData = any_cast_unsafe<RenderLitTexturedPerObjectData>(&element->rendererData);
+		for (auto& perObjectBuffer : rendererData->perObjectBuffers)
+		{
+			GpuParamsPtr params = element->material->params[perObjectBuffer.paramsIdx];
 
-			setPass(materialProxy->passes[iter->passIdx]);
-			draw(*iter->mesh);
+			params->setParamBlockBuffer(perObjectBuffer.slotIdx, rendererData->perObjectParamBuffer);
 		}
 	}
 
-	void BansheeRenderer::setPass(const MaterialProxyPass& pass)
+	void BansheeRenderer::setPass(const MaterialProxyPtr& material, UINT32 passIdx)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
 		RenderSystem& rs = RenderSystem::instance();
 
+		const MaterialProxyPass& pass = material->passes[passIdx];
 		if (pass.vertexProg)
 		{
 			rs.bindGpuProgram(pass.vertexProg);
-			rs.bindGpuParams(GPT_VERTEX_PROGRAM, pass.vertexProgParams);
+			rs.bindGpuParams(GPT_VERTEX_PROGRAM, material->params[pass.vertexProgParamsIdx]);
 		}
 		else
 			rs.unbindGpuProgram(GPT_VERTEX_PROGRAM);
@@ -543,7 +703,7 @@ namespace BansheeEngine
 		if (pass.fragmentProg)
 		{
 			rs.bindGpuProgram(pass.fragmentProg);
-			rs.bindGpuParams(GPT_FRAGMENT_PROGRAM, pass.geometryProgParams);
+			rs.bindGpuParams(GPT_FRAGMENT_PROGRAM, material->params[pass.geometryProgParamsIdx]);
 		}
 		else
 			rs.unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
@@ -551,7 +711,7 @@ namespace BansheeEngine
 		if (pass.geometryProg)
 		{
 			rs.bindGpuProgram(pass.geometryProg);
-			rs.bindGpuParams(GPT_GEOMETRY_PROGRAM, pass.geometryProgParams);
+			rs.bindGpuParams(GPT_GEOMETRY_PROGRAM, material->params[pass.geometryProgParamsIdx]);
 		}
 		else
 			rs.unbindGpuProgram(GPT_GEOMETRY_PROGRAM);
@@ -559,7 +719,7 @@ namespace BansheeEngine
 		if (pass.hullProg)
 		{
 			rs.bindGpuProgram(pass.hullProg);
-			rs.bindGpuParams(GPT_HULL_PROGRAM, pass.hullProgParams);
+			rs.bindGpuParams(GPT_HULL_PROGRAM, material->params[pass.hullProgParamsIdx]);
 		}
 		else
 			rs.unbindGpuProgram(GPT_HULL_PROGRAM);
@@ -567,7 +727,7 @@ namespace BansheeEngine
 		if (pass.domainProg)
 		{
 			rs.bindGpuProgram(pass.domainProg);
-			rs.bindGpuParams(GPT_DOMAIN_PROGRAM, pass.domainProgParams);
+			rs.bindGpuParams(GPT_DOMAIN_PROGRAM, material->params[pass.domainProgParamsIdx]);
 		}
 		else
 			rs.unbindGpuProgram(GPT_DOMAIN_PROGRAM);
@@ -575,7 +735,7 @@ namespace BansheeEngine
 		if (pass.computeProg)
 		{
 			rs.bindGpuProgram(pass.computeProg);
-			rs.bindGpuParams(GPT_COMPUTE_PROGRAM, pass.computeProgParams);
+			rs.bindGpuParams(GPT_COMPUTE_PROGRAM, material->params[pass.computeProgParamsIdx]);
 		}
 		else
 			rs.unbindGpuProgram(GPT_COMPUTE_PROGRAM);

+ 4 - 38
Renderer.txt

@@ -1,25 +1,6 @@
-2. Gpu params update 
-
-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
-   - Add a way to create renderer gpu buffers
-   - Add a way to create handles to renderer gpu parameters (and store them in RenderableProxy)
-   - 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).
-
-GpuParamBlockBuffer and GpuParams::cloneForCore are very clumsy in how they deal in keeping two separate param blocks. Rethink this a bit.
-
-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
+Param matching missing:
+ - // TODO - Find parameter gpu name and hook up its handle and "hasWVP"
+ - Implement getDefaultShader in BansheeRenderer
 
 -----------------------------------------------------------
 NON TRIVIAL BUT SIMPLE
@@ -35,26 +16,11 @@ Finally
  - Document elements marked with TODO UNDOCUMENTED
  - Refactor/rename everything so it makes more sense. Possibly lay out a design diagram.
  - Get rid of Camera::getIgnoreSceneRenderables it can be doing using layers
- - Delete RenderOperation as I don't think I use it anymore
 
 Semantic/design issues:
  - DrawList is too similar to RenderQueue - Their names need to be more distinct
  - Consider removing SceneManager from Core? I two scene manager base classes.
-
--------------------------------------------------------
-
-Material compatibility:
-
-When renderer is first created we create a list of default materials, each corresponding to a single valid renderable type.
-When checking for material compatibility we compare parameter and param block descriptions between example
-and material we're comparing. This way I don't even have to check if shader has param block or not, I already
-know from the example material.
-
-When material proxy is bound to the renderer matching parameters are found, and the renderer will take care of filling them out.
- - If example material uses a param block but current material doesn't, even if parameters match we won't update them from renderer.
- - Material proxy will be updated with a helper structure describing the renderable type the material is created with
-    - It will contain values representing which semantics are active
-	- And pointers to those semantics buffers and param handles
+ - GpuParamBlockBuffer and GpuParams::cloneForCore are very clumsy in how they deal in keeping two separate param blocks. Rethink this a bit.
 
 ---------------------------