Browse Source

Updating material proxies uses frame allocator

Marko Pintera 11 years ago
parent
commit
86f1d09e68

+ 12 - 1
BansheeCore/Include/BsGpuParamBlock.h

@@ -13,8 +13,18 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT GpuParamBlock
 	{
 	public:
+		/**
+		 * @brief	Construct a new parameter block with internal data allocated using the
+		 *			standard allocator.
+		 */
 		GpuParamBlock(UINT32 size);
-		GpuParamBlock(GpuParamBlock* otherBlock);
+
+		/**
+		 * @brief	Construct a new parameter block with internal data allocated using the
+		 *			provided frame allocator. Such blocks must be released the same frame
+		 *			they were allocated on.
+		 */
+		GpuParamBlock(FrameAlloc* alloc, UINT32 size);
 
 		virtual ~GpuParamBlock();
 
@@ -69,5 +79,6 @@ namespace BansheeEngine
 		UINT8* mData;
 		UINT32 mSize;
 		bool mDirty;
+		FrameAlloc* mAlloc;
 	};
 }

+ 3 - 21
BansheeCore/Include/BsGpuParamBlockBuffer.h

@@ -54,36 +54,18 @@ namespace BansheeEngine
 
 		/**
 		 * @brief	Returns	a parameter block buffer which is used for caching 
-		 *			the parameter information on the sim thread. Essentially a
-		 *			sim thread copy of the GPU buffer.
+		 *			the parameter information. Essentially a CPU copy of the GPU buffer.
 		 *
-		 * @note	Sim thread only.
+		 * @note	Thread safe but it's up to the caller to ensure this is only called from
+		 *			one thread.
 		 */
 		GpuParamBlockPtr getParamBlock() const { return mParamBlock; }
 
-		/**
-		 * @brief	Returns	a parameter block buffer which is used for caching 
-		 *			the parameter information on the core thread. Essentially a CPU
-		 *			core thread copy of the GPU buffer.
-		 *
-		 * @note	Core thread only.
-		 */
-		// TODO - Keeping a core param block along with a sim param block is redundant in some cases,
-		// as it might not be used (e.g. if gpu param block buffer is only accessed from core thread)
-		GpuParamBlockPtr getCoreParamBlock() const { return mCoreParamBlock; }
-
-		/**
-		 * @brief	Sets a reference to a core thread CPU buffer that may be used for buffering
-		 *			parameter data on the core thread, before actually writing it to the buffer.
-		 */
-		void setCoreParamBlock(const GpuParamBlockPtr& paramBlock) { mCoreParamBlock = paramBlock; }
-
 	protected:
 		GpuParamBlockUsage mUsage;
 		UINT32 mSize;
 
 		GpuParamBlockPtr mParamBlock;
-		GpuParamBlockPtr mCoreParamBlock;
 	};
 
 	/**

+ 15 - 6
BansheeCore/Include/BsGpuParams.h

@@ -237,14 +237,23 @@ namespace BansheeEngine
 		HSamplerState getSamplerState(UINT32 slot);
 
 		/**
-		 * @brief	Returns an exact copy of this object. Internal parameter buffers will also be cloned,
-		 *			but should only be used on the core thread.
+		 * @brief	Updates all internal data from the provided copy. Copy must have the same
+		 *			number of parameters as this object. Internal buffer contents will also be copied
+		 *			and their sizes must match as well.
+		 */
+		void _updateFromCopy(const GpuParamsPtr& copy);
+
+		/**
+		 * @brief	Returns an exact copy of this object. Internal parameter buffers will also be cloned.
 		 *
-		 * @note	Optional frame allocator to allocate the returned data with. If not specified
-		 *			allocation will be done using normal means.
-		 *			Internal method.
+		 * @param	frameAlloc			Optional frame allocator to allocate the returned data with. If not specified
+		 *								allocation will be done using normal means.
+		 * @param	onlyDirtyBlocks		If true, only dirty param blocks will be cloned and the non-dirty ones will
+		 *								be set to null.
+		 *			
+		 * @note	Internal method.
 		 */
-		GpuParamsPtr _cloneForCore(FrameAlloc* frameAlloc = nullptr) const;
+		GpuParamsPtr _clone(FrameAlloc* frameAlloc = nullptr, bool onlyDirtyBlocks = false) const;
 
 		/**
 		 * @brief	Checks is the core dirty flag set. This is used by external systems 

+ 4 - 1
BansheeCore/Include/BsMaterial.h

@@ -428,8 +428,11 @@ namespace BansheeEngine
 
 		/**
 		 * @brief	Returns updated GPU parameters since the last time the parameters were marked clean.
+		 *
+		 * @note	Returned data will be allocated with a frame allocator and must be released during the
+		 *			same frame it was allocated.
 		 */
-		Vector<MaterialProxy::ParamsBindInfo> _getDirtyProxyParams();
+		MaterialProxy::DirtyParamsInfo* _getDirtyProxyParams(FrameAlloc* frameAlloc);
 
 		/**
 		 * @brief	Creates a new core proxy from the currently set material data. Core proxies ensure

+ 14 - 3
BansheeCore/Include/BsMaterialProxy.h

@@ -56,14 +56,25 @@ namespace BansheeEngine
 		 */
 		struct BS_CORE_EXPORT ParamsBindInfo
 		{
-			ParamsBindInfo(UINT32 paramsIdx, const GpuParamsPtr& params)
-				:paramsIdx(paramsIdx), params(params)
-			{ }
+			// Note: Manually allocated. Must not have a constructor/destructor.
 
 			UINT32 paramsIdx;
 			GpuParamsPtr params;
 		};
 
+		/**
+		 * @brief	Contains a set of GPU params that need updating on the core thread.
+		 */
+		struct BS_CORE_EXPORT DirtyParamsInfo
+		{
+			// Note: Manually allocated. Must not have a constructor/destructor.
+
+			ParamsBindInfo* entries;
+			UINT32 numEntries;
+
+			FrameAlloc* owner;
+		};
+
 		Vector<MaterialProxyPass> passes;
 		Vector<GpuParamsPtr> params;
 

+ 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->_clone(gCoreThread().getFrameAlloc(), true)));
 	}
 
 	void CoreThreadAccessorBase::beginRender()

+ 14 - 12
BansheeCore/Source/BsGpuParamBlock.cpp

@@ -2,36 +2,38 @@
 #include "BsGpuParamDesc.h"
 #include "BsGpuParamBlockBuffer.h"
 #include "BsHardwareBufferManager.h"
+#include "BsFrameAlloc.h"
 #include "BsException.h"
 
 namespace BansheeEngine
 {
 	GpuParamBlock::GpuParamBlock(UINT32 size)
-		:mDirty(true), mData(nullptr), mSize(size)
+		:mDirty(true), mData(nullptr), mSize(size), mAlloc(nullptr)
 	{
 		if (mSize > 0)
-			mData = (UINT8*)bs_alloc<ScratchAlloc>(mSize);
+			mData = (UINT8*)bs_alloc(mSize);
 
 		memset(mData, 0, mSize);
 	}
 
-	GpuParamBlock::GpuParamBlock(GpuParamBlock* otherBlock)
+	GpuParamBlock::GpuParamBlock(FrameAlloc* alloc, UINT32 size)
+		:mDirty(true), mData(nullptr), mSize(size), mAlloc(alloc)
 	{
-		mSize = otherBlock->mSize;
-
 		if (mSize > 0)
-			mData = (UINT8*)bs_alloc<ScratchAlloc>(mSize);
-		else
-			mData = nullptr;
+			mData = alloc->alloc(mSize);
 
-		write(0, otherBlock->getData(), otherBlock->getSize());
-		mDirty = otherBlock->mDirty;
+		memset(mData, 0, mSize);
 	}
 
 	GpuParamBlock::~GpuParamBlock()
 	{
-		if(mData != nullptr)
-			bs_free<ScratchAlloc>(mData);
+		if (mData != nullptr)
+		{
+			if (mAlloc != nullptr)
+				mAlloc->dealloc(mData);
+			else
+				bs_free(mData);
+		}
 	}
 
 	void GpuParamBlock::write(UINT32 offset, const void* data, UINT32 size)

+ 1 - 1
BansheeCore/Source/BsGpuParamBlockBuffer.cpp

@@ -4,7 +4,7 @@
 namespace BansheeEngine
 {
 	GpuParamBlockBuffer::GpuParamBlockBuffer()
-		:mSize(0), mUsage(GPBU_DYNAMIC), mParamBlock(nullptr), mCoreParamBlock(nullptr)
+		:mSize(0), mUsage(GPBU_DYNAMIC)
 	{
 
 	}

+ 39 - 8
BansheeCore/Source/BsGpuParams.cpp

@@ -226,7 +226,34 @@ namespace BansheeEngine
 		}
 	}
 
-	GpuParamsPtr GpuParams::_cloneForCore(FrameAlloc* frameAlloc) const
+	void GpuParams::_updateFromCopy(const GpuParamsPtr& copy)
+	{
+		assert(copy->mInternalData->mNumParamBlocks == mInternalData->mNumParamBlocks);
+		assert(copy->mInternalData->mNumTextures == mInternalData->mNumTextures);
+		assert(copy->mInternalData->mNumSamplerStates == mInternalData->mNumSamplerStates);
+
+		for (UINT32 i = 0; i < mInternalData->mNumTextures; i++)
+		{
+			mInternalData->mTextures[i] = copy->mInternalData->mTextures[i];
+		}
+
+		for (UINT32 i = 0; i < mInternalData->mNumSamplerStates; i++)
+		{
+			mInternalData->mSamplerStates[i] = copy->mInternalData->mSamplerStates[i];
+		}
+
+		for (UINT32 i = 0; i < mInternalData->mNumParamBlocks; i++)
+		{
+			GpuParamBlockPtr destParamBlock = mInternalData->mParamBlocks[i];
+			GpuParamBlockPtr srcParamBlock = copy->mInternalData->mParamBlocks[i];
+			if (destParamBlock != nullptr && srcParamBlock != nullptr)
+			{
+				destParamBlock->write(0, srcParamBlock->getData(), srcParamBlock->getSize());
+			}
+		}
+	}
+
+	GpuParamsPtr GpuParams::_clone(FrameAlloc* frameAlloc, bool onlyDirtyBlocks) const
 	{
 		GpuParamsPtr myClone = nullptr;
 		
@@ -253,17 +280,21 @@ namespace BansheeEngine
 		for (UINT32 i = 0; i < mInternalData->mNumParamBlocks; i++)
 		{
 			GpuParamBlockBufferPtr buffer = mInternalData->mParamBlockBuffers[i];
-			if (buffer != nullptr)
+			if (buffer != nullptr && (!onlyDirtyBlocks || buffer->getParamBlock()->isDirty()))
 			{
-				if (buffer->getParamBlock()->isDirty())
+				GpuParamBlockPtr newBlock = nullptr;
+				if (frameAlloc != nullptr)
+				{
+					StdFrameAlloc<GpuParams> myAlloc(frameAlloc);
+					newBlock = std::allocate_shared<GpuParamBlock>(myAlloc, frameAlloc, buffer->getSize());
+				}
+				else
 				{
-					GpuParamBlockPtr newBlock = bs_shared_ptr<GpuParamBlock>(buffer->getSize());
-					memcpy(newBlock->getData(), buffer->getParamBlock()->getData(), buffer->getSize());
-					buffer->setCoreParamBlock(newBlock);
-					buffer->getParamBlock()->setDirty(false);
+					newBlock = bs_shared_ptr<GpuParamBlock>(buffer->getSize());;
 				}
 
-				myClone->mInternalData->mParamBlocks[i] = buffer->getCoreParamBlock();
+				newBlock->write(0, buffer->getParamBlock()->getData(), buffer->getSize());
+				myClone->mInternalData->mParamBlocks[i] = newBlock;
 			}
 			else
 				myClone->mInternalData->mParamBlocks[i] = nullptr;

+ 64 - 29
BansheeCore/Source/BsMaterial.cpp

@@ -12,6 +12,7 @@
 #include "BsMaterialManager.h"
 #include "BsDebug.h"
 #include "BsResources.h"
+#include "BsFrameAlloc.h"
 
 namespace BansheeEngine
 {
@@ -745,67 +746,101 @@ namespace BansheeEngine
 		}
 	}
 
-	Vector<MaterialProxy::ParamsBindInfo> Material::_getDirtyProxyParams()
+	MaterialProxy::DirtyParamsInfo* Material::_getDirtyProxyParams(FrameAlloc* frameAlloc)
 	{
-		Vector<MaterialProxy::ParamsBindInfo> dirtyParams;
-		UINT32 idx = 0;
-
+		UINT32 numDirtyParams = 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 (pass->hasVertexProgram() && params->mVertParams->_isCoreDirty())
+				numDirtyParams++;
+
+			if (pass->hasFragmentProgram() && params->mFragParams->_isCoreDirty())
+				numDirtyParams++;
+
+			if (pass->hasGeometryProgram() && params->mGeomParams->_isCoreDirty())
+				numDirtyParams++;
+
+			if (pass->hasHullProgram() && params->mHullParams->_isCoreDirty())
+				numDirtyParams++;
+
+			if (pass->hasDomainProgram() && params->mDomainParams->_isCoreDirty())
+				numDirtyParams++;
+
+			if (pass->hasComputeProgram() && params->mComputeParams->_isCoreDirty())
+				numDirtyParams++;
+		}
+
+		UINT32 sizeRequired = sizeof(MaterialProxy::DirtyParamsInfo) + numDirtyParams * sizeof(MaterialProxy::ParamsBindInfo);
+		UINT8* buffer = (UINT8*)frameAlloc->alloc(sizeRequired);
+
+		MaterialProxy::DirtyParamsInfo* dirtyParamsInfo = (MaterialProxy::DirtyParamsInfo*)buffer;
+		dirtyParamsInfo->numEntries = numDirtyParams;
+		dirtyParamsInfo->owner = frameAlloc;
+		
+		buffer += sizeof(MaterialProxy::DirtyParamsInfo);
+		MaterialProxy::ParamsBindInfo* paramsInfoArray = (MaterialProxy::ParamsBindInfo*)buffer;
+		dirtyParamsInfo->entries = paramsInfoArray;
+
+		UINT32 idx = 0;
+		for (UINT32 i = 0; i < numPasses; i++)
+		{
+			PassParametersPtr params = mParametersPerPass[i];
+			PassPtr pass = mShader->getBestTechnique()->getPass(i);
+
+			if (pass->hasVertexProgram() && params->mVertParams->_isCoreDirty())
 			{
-				if (params->mVertParams->_isCoreDirty())
-					dirtyParams.push_back(MaterialProxy::ParamsBindInfo(idx, params->mVertParams));
+				paramsInfoArray[idx].paramsIdx = idx;
+				paramsInfoArray[idx].params = params->mVertParams->_clone(frameAlloc);
 
 				idx++;
 			}
 
-			if (pass->hasFragmentProgram())
+			if (pass->hasFragmentProgram() && params->mFragParams->_isCoreDirty())
 			{
-				if (params->mFragParams->_isCoreDirty())
-					dirtyParams.push_back(MaterialProxy::ParamsBindInfo(idx, params->mFragParams));
+				paramsInfoArray[idx].paramsIdx = idx;
+				paramsInfoArray[idx].params = params->mFragParams->_clone(frameAlloc);
 
 				idx++;
 			}
 
-			if (pass->hasGeometryProgram())
+			if (pass->hasGeometryProgram() && params->mGeomParams->_isCoreDirty())
 			{
-				if (params->mGeomParams->_isCoreDirty())
-					dirtyParams.push_back(MaterialProxy::ParamsBindInfo(idx, params->mGeomParams));
+				paramsInfoArray[idx].paramsIdx = idx;
+				paramsInfoArray[idx].params = params->mGeomParams->_clone(frameAlloc);
 
 				idx++;
 			}
 
-			if (pass->hasHullProgram())
+			if (pass->hasHullProgram() && params->mHullParams->_isCoreDirty())
 			{
-				if (params->mHullParams->_isCoreDirty())
-					dirtyParams.push_back(MaterialProxy::ParamsBindInfo(idx, params->mHullParams));
+				paramsInfoArray[idx].paramsIdx = idx;
+				paramsInfoArray[idx].params = params->mHullParams->_clone(frameAlloc);
 
 				idx++;
 			}
 
-			if (pass->hasDomainProgram())
+			if (pass->hasDomainProgram() && params->mDomainParams->_isCoreDirty())
 			{
-				if (params->mDomainParams->_isCoreDirty())
-					dirtyParams.push_back(MaterialProxy::ParamsBindInfo(idx, params->mDomainParams));
+				paramsInfoArray[idx].paramsIdx = idx;
+				paramsInfoArray[idx].params = params->mDomainParams->_clone(frameAlloc);
 
 				idx++;
 			}
 
-			if (pass->hasComputeProgram())
+			if (pass->hasComputeProgram() && params->mComputeParams->_isCoreDirty())
 			{
-				if (params->mComputeParams->_isCoreDirty())
-					dirtyParams.push_back(MaterialProxy::ParamsBindInfo(idx, params->mComputeParams));
+				paramsInfoArray[idx].paramsIdx = idx;
+				paramsInfoArray[idx].params = params->mComputeParams->_clone(frameAlloc);
 
 				idx++;
 			}
 		}
 
-		return dirtyParams;
+		return dirtyParamsInfo;
 	}
 
 	MaterialProxyPtr Material::_createProxy()
@@ -827,7 +862,7 @@ namespace BansheeEngine
 			{
 				passData.vertexProg = pass->getVertexProgram();
 				passData.vertexProgParamsIdx = (UINT32)proxy->params.size();
-				proxy->params.push_back(params->mVertParams->_cloneForCore());
+				proxy->params.push_back(params->mVertParams->_clone());
 			}
 			else
 				passData.vertexProgParamsIdx = 0;
@@ -836,7 +871,7 @@ namespace BansheeEngine
 			{
 				passData.fragmentProg = pass->getFragmentProgram();
 				passData.fragmentProgParamsIdx = (UINT32)proxy->params.size();
-				proxy->params.push_back(params->mFragParams->_cloneForCore());
+				proxy->params.push_back(params->mFragParams->_clone());
 			}
 			else
 				passData.fragmentProgParamsIdx = 0;
@@ -845,7 +880,7 @@ namespace BansheeEngine
 			{
 				passData.geometryProg = pass->getGeometryProgram();
 				passData.geometryProgParamsIdx = (UINT32)proxy->params.size();
-				proxy->params.push_back(params->mGeomParams->_cloneForCore());
+				proxy->params.push_back(params->mGeomParams->_clone());
 			}
 			else
 				passData.geometryProgParamsIdx = 0;
@@ -854,7 +889,7 @@ namespace BansheeEngine
 			{
 				passData.hullProg = pass->getHullProgram();
 				passData.hullProgParamsIdx = (UINT32)proxy->params.size();
-				proxy->params.push_back(params->mHullParams->_cloneForCore());
+				proxy->params.push_back(params->mHullParams->_clone());
 			}
 			else
 				passData.hullProgParamsIdx = 0;
@@ -863,7 +898,7 @@ namespace BansheeEngine
 			{
 				passData.domainProg = pass->getDomainProgram();
 				passData.domainProgParamsIdx = (UINT32)proxy->params.size();
-				proxy->params.push_back(params->mDomainParams->_cloneForCore());
+				proxy->params.push_back(params->mDomainParams->_clone());
 			}
 			else
 				passData.domainProgParamsIdx = 0;
@@ -872,7 +907,7 @@ namespace BansheeEngine
 			{
 				passData.computeProg = pass->getComputeProgram();
 				passData.computeProgParamsIdx = (UINT32)proxy->params.size();
-				proxy->params.push_back(params->mComputeParams->_cloneForCore());
+				proxy->params.push_back(params->mComputeParams->_clone());
 			}
 			else
 				passData.computeProgParamsIdx = 0;

+ 2 - 2
BansheeRenderer/Include/BsBansheeRenderer.h

@@ -131,7 +131,7 @@ namespace BansheeEngine
 		 *
 		 * @note	Core thread only.
 		 */
-		void updateMaterialProxy(MaterialProxyPtr proxy, Vector<MaterialProxy::ParamsBindInfo> dirtyParams);
+		void updateMaterialProxy(MaterialProxyPtr proxy, MaterialProxy::DirtyParamsInfo* dirtyParams);
 
 		/**
 		 * @brief	Performs rendering over all camera proxies.
@@ -160,7 +160,7 @@ namespace BansheeEngine
 		 *
 		 * @note	Core thread only.
 		 */
-		void setPass(const MaterialProxyPtr& material, UINT32 passIdx);
+		void setPass(const MaterialProxy& material, UINT32 passIdx);
 
 		/**
 		 * @brief	Draws the specified mesh proxy with last set pass.

+ 33 - 13
BansheeRenderer/Source/BsBansheeRenderer.cpp

@@ -29,6 +29,7 @@
 #include "BsShaderProxy.h"
 #include "BsBansheeLitTexRenderableHandler.h"
 #include "BsTime.h"
+#include "BsFrameAlloc.h"
 
 using namespace std::placeholders;
 
@@ -213,6 +214,7 @@ namespace BansheeEngine
 		Vector<HSceneObject> dirtySceneObjects;
 		Vector<HRenderable> dirtyRenderables;
 
+		FrameAlloc* frameAlloc = gCoreThread().getFrameAlloc();
 		for (auto& renderable : allRenderables)
 		{
 			bool addedNewProxy = false;
@@ -249,7 +251,8 @@ namespace BansheeEngine
 					HMaterial mat = renderable->getMaterial(i);
 					if (mat != nullptr && mat.isLoaded() && mat->_isCoreDirty(MaterialDirtyFlag::Params))
 					{
-						gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::updateMaterialProxy, this, proxy->renderableElements[i]->material, mat->_getDirtyProxyParams()));
+						gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::updateMaterialProxy, this, 
+							proxy->renderableElements[i]->material, mat->_getDirtyProxyParams(frameAlloc)));
 						mat->_markCoreClean(MaterialDirtyFlag::Params);
 					}
 				}
@@ -331,6 +334,9 @@ namespace BansheeEngine
 			const Vector<DrawOperation>& drawOps = drawList->getDrawOperations();
 			for (auto& drawOp : drawOps)
 			{
+				// TODO - Created proxies should be temporary and only last one frame, and should
+				// be allocated using the frame allocator
+
 				if (drawOp.material->_isCoreDirty(MaterialDirtyFlag::Proxy))
 				{
 					drawOp.material->_setActiveProxy(drawOp.material->_createProxy());
@@ -362,13 +368,27 @@ namespace BansheeEngine
 		cameraRenderQueue->add(*renderQueue);
 	}
 
-	void BansheeRenderer::updateMaterialProxy(MaterialProxyPtr proxy, Vector<MaterialProxy::ParamsBindInfo> dirtyParams)
+	void BansheeRenderer::updateMaterialProxy(MaterialProxyPtr proxy, MaterialProxy::DirtyParamsInfo* dirtyParams)
 	{
-		for (UINT32 i = 0; i < (UINT32)dirtyParams.size(); i++)
-			proxy->params[dirtyParams[i].paramsIdx] = dirtyParams[i].params;
+		for (UINT32 i = 0; i < (UINT32)dirtyParams->numEntries; i++)
+		{
+			UINT32 paramsIdx = dirtyParams->entries[i].paramsIdx;
+
+			if (proxy->params[paramsIdx] == nullptr) 
+			{
+				assert(false); // This shouldn't happen. New params can only be added due to shader 
+							   // change and that should trigger new material proxy creation
+				continue;
+			}
+
+			proxy->params[dirtyParams->entries[i].paramsIdx]->_updateFromCopy(dirtyParams->entries[i].params);
+		}
 
+		// Refresh buffers set by renderer in case any were changed
 		for (auto& rendererBuffer : proxy->rendererBuffers)
 			proxy->params[rendererBuffer.paramsIdx]->setParamBlockBuffer(rendererBuffer.slotIdx, rendererBuffer.buffer);
+
+		dirtyParams->owner->dealloc((UINT8*)dirtyParams);
 	}
 
 	void BansheeRenderer::renderAllCore(float time)
@@ -468,24 +488,24 @@ namespace BansheeEngine
 		{
 			MaterialProxyPtr materialProxy = iter->material;
 
-			setPass(materialProxy, iter->passIdx);
+			setPass(*materialProxy, iter->passIdx);
 			draw(*iter->mesh);
 		}
 
 		renderQueue->clear();
 	}
 
-	void BansheeRenderer::setPass(const MaterialProxyPtr& material, UINT32 passIdx)
+	void BansheeRenderer::setPass(const MaterialProxy& material, UINT32 passIdx)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
 		RenderSystem& rs = RenderSystem::instance();
 
-		const MaterialProxyPass& pass = material->passes[passIdx];
+		const MaterialProxyPass& pass = material.passes[passIdx];
 		if (pass.vertexProg)
 		{
 			rs.bindGpuProgram(pass.vertexProg);
-			rs.bindGpuParams(GPT_VERTEX_PROGRAM, material->params[pass.vertexProgParamsIdx]);
+			rs.bindGpuParams(GPT_VERTEX_PROGRAM, material.params[pass.vertexProgParamsIdx]);
 		}
 		else
 			rs.unbindGpuProgram(GPT_VERTEX_PROGRAM);
@@ -493,7 +513,7 @@ namespace BansheeEngine
 		if (pass.fragmentProg)
 		{
 			rs.bindGpuProgram(pass.fragmentProg);
-			rs.bindGpuParams(GPT_FRAGMENT_PROGRAM, material->params[pass.fragmentProgParamsIdx]);
+			rs.bindGpuParams(GPT_FRAGMENT_PROGRAM, material.params[pass.fragmentProgParamsIdx]);
 		}
 		else
 			rs.unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
@@ -501,7 +521,7 @@ namespace BansheeEngine
 		if (pass.geometryProg)
 		{
 			rs.bindGpuProgram(pass.geometryProg);
-			rs.bindGpuParams(GPT_GEOMETRY_PROGRAM, material->params[pass.geometryProgParamsIdx]);
+			rs.bindGpuParams(GPT_GEOMETRY_PROGRAM, material.params[pass.geometryProgParamsIdx]);
 		}
 		else
 			rs.unbindGpuProgram(GPT_GEOMETRY_PROGRAM);
@@ -509,7 +529,7 @@ namespace BansheeEngine
 		if (pass.hullProg)
 		{
 			rs.bindGpuProgram(pass.hullProg);
-			rs.bindGpuParams(GPT_HULL_PROGRAM, material->params[pass.hullProgParamsIdx]);
+			rs.bindGpuParams(GPT_HULL_PROGRAM, material.params[pass.hullProgParamsIdx]);
 		}
 		else
 			rs.unbindGpuProgram(GPT_HULL_PROGRAM);
@@ -517,7 +537,7 @@ namespace BansheeEngine
 		if (pass.domainProg)
 		{
 			rs.bindGpuProgram(pass.domainProg);
-			rs.bindGpuParams(GPT_DOMAIN_PROGRAM, material->params[pass.domainProgParamsIdx]);
+			rs.bindGpuParams(GPT_DOMAIN_PROGRAM, material.params[pass.domainProgParamsIdx]);
 		}
 		else
 			rs.unbindGpuProgram(GPT_DOMAIN_PROGRAM);
@@ -525,7 +545,7 @@ namespace BansheeEngine
 		if (pass.computeProg)
 		{
 			rs.bindGpuProgram(pass.computeProg);
-			rs.bindGpuParams(GPT_COMPUTE_PROGRAM, material->params[pass.computeProgParamsIdx]);
+			rs.bindGpuParams(GPT_COMPUTE_PROGRAM, material.params[pass.computeProgParamsIdx]);
 		}
 		else
 			rs.unbindGpuProgram(GPT_COMPUTE_PROGRAM);

+ 6 - 6
SceneView.txt

@@ -3,13 +3,13 @@ TODO:
  - Core thread gets stuck on shutdown when OpenGL is used...Somewhere in kernel
 
 Weekend:
- - Set up grid material and hook it up to renderer (+ actually instantiate it in EditorApplication)
+ - SceneGrid is very ugly. Consider using default lines for now and come back with a better approach later.
 
-TODO - Think about:
- - How will I allow user from C# to draw gizmos and handles?
- - Unity uses immediate mode
- - I should probably focus more on implementing a nice C# drawing interface so I don't constantly have to go and use C++
-    - Although this might be overkill for this point - I think even Unitys handles/gizmos are C++ in the end
+Sending GPU parameters to core thread:
+ - MaterialProxy needs to be allocatable via frame alloc
+ - MeshProxy needs to be allocatable via frame alloc
+
+do _markAsClean on GpuParams even with transient stuff? If I update the buffer it should be safe
 
 ----------------------------------------------------------------------
 Handles