Explorar o código

GpuParamBlock is now initialized like any other CoreGpuObject
GpuParamBlock data is now more gracefully switched between render and other threads

Marko Pintera %!s(int64=13) %!d(string=hai) anos
pai
achega
db092c1e82
Modificáronse 25 ficheiros con 320 adicións e 239 borrados
  1. 17 12
      CamelotD3D11RenderSystem/Include/CmD3D11GpuParamBlock.h
  2. 1 1
      CamelotD3D11RenderSystem/Include/CmD3D11HardwareBufferManager.h
  3. 22 41
      CamelotD3D11RenderSystem/Source/CmD3D11GpuParamBlock.cpp
  4. 2 2
      CamelotD3D11RenderSystem/Source/CmD3D11HardwareBufferManager.cpp
  5. 3 4
      CamelotD3D11RenderSystem/Source/CmD3D11RenderSystem.cpp
  6. 1 1
      CamelotD3D9Renderer/Include/CmD3D9HardwareBufferManager.h
  7. 2 2
      CamelotD3D9Renderer/Source/CmD3D9HardwareBufferManager.cpp
  8. 6 4
      CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp
  9. 15 1
      CamelotForwardRenderer/Source/CmForwardRenderer.cpp
  10. 18 13
      CamelotGLRenderer/Include/CmGLGpuParamBlock.h
  11. 1 1
      CamelotGLRenderer/Include/CmGLHardwareBufferManager.h
  12. 21 41
      CamelotGLRenderer/Source/CmGLGpuParamBlock.cpp
  13. 2 2
      CamelotGLRenderer/Source/CmGLHardwareBufferManager.cpp
  14. 6 5
      CamelotGLRenderer/Source/CmGLRenderSystem.cpp
  15. 17 4
      CamelotRenderer/Include/CmCoreGpuObject.h
  16. 66 15
      CamelotRenderer/Include/CmGpuParamBlock.h
  17. 1 2
      CamelotRenderer/Include/CmGpuParams.h
  18. 1 1
      CamelotRenderer/Include/CmHardwareBufferManager.h
  19. 12 8
      CamelotRenderer/Source/CmCoreGpuObject.cpp
  20. 1 2
      CamelotRenderer/Source/CmDeferredRenderContext.cpp
  21. 80 33
      CamelotRenderer/Source/CmGpuParamBlock.cpp
  22. 2 15
      CamelotRenderer/Source/CmGpuParams.cpp
  23. 5 1
      CamelotRenderer/Source/CmHardwareBufferManager.cpp
  24. 9 1
      CamelotRenderer/Source/CmMaterial.cpp
  25. 9 27
      CamelotRenderer/TODO.txt

+ 17 - 12
CamelotD3D11RenderSystem/Include/CmD3D11GpuParamBlock.h

@@ -5,24 +5,29 @@
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
-	class CM_D3D11_EXPORT D3D11GpuParamBlock : public GpuParamBlock
+	class CM_D3D11_EXPORT D3D11GpuParamBlockBuffer : public GpuParamBlockBuffer
 	{
 	{
-	private:
-		struct D3D11GpuParamBlockSharedData
-		{
-			D3D11HardwareBuffer* mBuffer;
-		};
-
 	public:
 	public:
-		D3D11GpuParamBlock(const GpuParamBlockDesc& desc, GpuParamBlockUsage usage);
-		~D3D11GpuParamBlock();
+		D3D11GpuParamBlockBuffer(UINT32 size, GpuParamBlockUsage usage);
+		~D3D11GpuParamBlockBuffer();
 
 
-		virtual void updateIfDirty();
-		virtual GpuParamBlockPtr clone() const;
+		/**
+		 * @copydoc CpuParamBlockBuffer::writeAll.
+		 */
+		void writeAll(const void* data);
 
 
 		ID3D11Buffer* getD3D11Buffer() const;
 		ID3D11Buffer* getD3D11Buffer() const;
 
 
 	private:
 	private:
-		D3D11GpuParamBlockSharedData* mD3D11SharedData;
+		D3D11HardwareBuffer* mBuffer;
+	};
+
+	class CM_D3D11_EXPORT D3D11GpuParamBlock : public GpuParamBlock
+	{
+	protected:
+		/**
+		 * @copydoc GpuParamBlock::createBuffer.
+		 */
+		GpuParamBlockBuffer* createBuffer() const;
 	};
 	};
 }
 }

+ 1 - 1
CamelotD3D11RenderSystem/Include/CmD3D11HardwareBufferManager.h

@@ -25,7 +25,7 @@ namespace CamelotEngine
 		IndexBuffer* createIndexBufferImpl(IndexBuffer::IndexType itype, UINT32 numIndexes, GpuBufferUsage usage);
 		IndexBuffer* createIndexBufferImpl(IndexBuffer::IndexType itype, UINT32 numIndexes, GpuBufferUsage usage);
 
 
 		/** @copydoc HardwareBufferManager::createGpuParamBlock */
 		/** @copydoc HardwareBufferManager::createGpuParamBlock */
-		GpuParamBlock* createGpuParamBlockImpl(const GpuParamBlockDesc& paramDesc, GpuParamBlockUsage usage = GPBU_STATIC);
+		GpuParamBlock* createGpuParamBlockImpl();
 
 
 		/**
 		/**
 		 * @copydoc HardwareBufferManager::createGenericBufferImpl
 		 * @copydoc HardwareBufferManager::createGenericBufferImpl

+ 22 - 41
CamelotD3D11RenderSystem/Source/CmD3D11GpuParamBlock.cpp

@@ -5,59 +5,40 @@
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
-	D3D11GpuParamBlock::D3D11GpuParamBlock(const GpuParamBlockDesc& desc, GpuParamBlockUsage usage)
-		:GpuParamBlock(desc, usage), mD3D11SharedData(nullptr)
+	D3D11GpuParamBlockBuffer::D3D11GpuParamBlockBuffer(UINT32 size, GpuParamBlockUsage usage)
+		:GpuParamBlockBuffer(size, usage), mBuffer(nullptr)
 	{
 	{
-		mD3D11SharedData = new D3D11GpuParamBlockSharedData();
+		D3D11RenderSystem* d3d11rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
+		D3D11Device& device = d3d11rs->getPrimaryDevice();
+
+		if(mUsage == GPBU_STATIC)
+			mBuffer = new D3D11HardwareBuffer(D3D11HardwareBuffer::BT_CONSTANT, GBU_STATIC, 1, mSize, device);
+		else if(mUsage == GPBU_DYNAMIC)
+			mBuffer = new D3D11HardwareBuffer(D3D11HardwareBuffer::BT_CONSTANT, GBU_DYNAMIC, 1, mSize, device);
+		else
+			CM_EXCEPT(InternalErrorException, "Invalid gpu param block usage.");
 	}
 	}
 
 
-	D3D11GpuParamBlock::~D3D11GpuParamBlock()
+	D3D11GpuParamBlockBuffer::~D3D11GpuParamBlockBuffer()
 	{
 	{
-		if(mOwnsSharedData)
-		{
-			delete mD3D11SharedData->mBuffer;
-			delete mD3D11SharedData;
-		}
+		if(mBuffer != nullptr)
+			delete mBuffer;
 	}
 	}
 
 
-	void D3D11GpuParamBlock::updateIfDirty()
+	ID3D11Buffer* D3D11GpuParamBlockBuffer::getD3D11Buffer() const
 	{
 	{
-		if(!sharedData->mInitialized)
-		{
-			D3D11RenderSystem* d3d11rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
-			D3D11Device& device = d3d11rs->getPrimaryDevice();
-
-			if(mUsage == GPBU_STATIC)
-				mD3D11SharedData->mBuffer = new D3D11HardwareBuffer(D3D11HardwareBuffer::BT_CONSTANT, GBU_STATIC, 1, mSize, device);
-			else if(mUsage == GPBU_DYNAMIC)
-				mD3D11SharedData->mBuffer = new D3D11HardwareBuffer(D3D11HardwareBuffer::BT_CONSTANT, GBU_DYNAMIC, 1, mSize, device);
-			else
-				CM_EXCEPT(InternalErrorException, "Invalid gpu param block usage.");
-
-			sharedData->mInitialized = true;
-		}
-
-		if(sharedData->mDirty)
-		{
-			mD3D11SharedData->mBuffer->writeData(0, mSize, mData, true);
-		}
-
-		GpuParamBlock::updateIfDirty();
+		return mBuffer->getD3DBuffer();
 	}
 	}
 
 
-	GpuParamBlockPtr D3D11GpuParamBlock::clone() const
+	void D3D11GpuParamBlockBuffer::writeAll(const void* data)
 	{
 	{
-		std::shared_ptr<D3D11GpuParamBlock> clonedParamBlock(new D3D11GpuParamBlock(*this));
-		clonedParamBlock->mData = new UINT8[mSize];
-		clonedParamBlock->mOwnsSharedData = false;
-		clonedParamBlock->mD3D11SharedData = mD3D11SharedData;
-		memcpy(clonedParamBlock->mData, mData, mSize);
+		mBuffer->writeData(0, mSize, data, true);
 
 
-		return clonedParamBlock;
+		GpuParamBlockBuffer::writeAll(data);
 	}
 	}
 
 
-	ID3D11Buffer* D3D11GpuParamBlock::getD3D11Buffer() const 
-	{ 
-		return mD3D11SharedData->mBuffer->getD3DBuffer(); 
+	GpuParamBlockBuffer* D3D11GpuParamBlock::createBuffer() const
+	{
+		return new D3D11GpuParamBlockBuffer(mSize, mUsage);
 	}
 	}
 }
 }

+ 2 - 2
CamelotD3D11RenderSystem/Source/CmD3D11HardwareBufferManager.cpp

@@ -28,9 +28,9 @@ namespace CamelotEngine
 		return new D3D11IndexBuffer(mDevice, this, itype, numIndexes, usage, false);
 		return new D3D11IndexBuffer(mDevice, this, itype, numIndexes, usage, false);
 	}
 	}
 
 
-	GpuParamBlock* D3D11HardwareBufferManager::createGpuParamBlockImpl(const GpuParamBlockDesc& blockDesc, GpuParamBlockUsage usage)
+	GpuParamBlock* D3D11HardwareBufferManager::createGpuParamBlockImpl()
 	{
 	{
-		return new D3D11GpuParamBlock(blockDesc, usage);
+		return new D3D11GpuParamBlock();
 	}
 	}
 
 
 	GpuBuffer* D3D11HardwareBufferManager::createGpuBufferImpl(UINT32 elementCount, UINT32 elementSize, 
 	GpuBuffer* D3D11HardwareBufferManager::createGpuBufferImpl(UINT32 elementCount, UINT32 elementSize, 

+ 3 - 4
CamelotD3D11RenderSystem/Source/CmD3D11RenderSystem.cpp

@@ -440,8 +440,6 @@ namespace CamelotEngine
 	{
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 		THROW_IF_NOT_RENDER_THREAD;
 
 
-		params->updateIfDirty();
-
 		const GpuParamDesc& paramDesc = params->getParamDesc();
 		const GpuParamDesc& paramDesc = params->getParamDesc();
 
 
 		for(auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
 		for(auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
@@ -474,8 +472,9 @@ namespace CamelotEngine
 
 
 			if(currentBlock != nullptr)
 			if(currentBlock != nullptr)
 			{
 			{
-				D3D11GpuParamBlock* d3d11paramBlock = static_cast<D3D11GpuParamBlock*>(currentBlock.get());
-				bufferArray[0] = d3d11paramBlock->getD3D11Buffer();
+				const GpuParamBlockBuffer* currentBlockBuffer = currentBlock->getBindableBuffer();
+				const D3D11GpuParamBlockBuffer* d3d11paramBlockBuffer = static_cast<const D3D11GpuParamBlockBuffer*>(currentBlockBuffer);
+				bufferArray[0] = d3d11paramBlockBuffer->getD3D11Buffer();
 			}
 			}
 			else
 			else
 				bufferArray[0] = nullptr;
 				bufferArray[0] = nullptr;

+ 1 - 1
CamelotD3D9Renderer/Include/CmD3D9HardwareBufferManager.h

@@ -55,7 +55,7 @@ namespace CamelotEngine {
 		IndexBuffer* createIndexBufferImpl(IndexBuffer::IndexType itype, UINT32 numIndexes, GpuBufferUsage usage);
 		IndexBuffer* createIndexBufferImpl(IndexBuffer::IndexType itype, UINT32 numIndexes, GpuBufferUsage usage);
 
 
 		/** @copydoc HardwareBufferManager::createGpuParamBlock */
 		/** @copydoc HardwareBufferManager::createGpuParamBlock */
-		GpuParamBlock* createGpuParamBlockImpl(const GpuParamBlockDesc& paramDesc, GpuParamBlockUsage usage = GPBU_STATIC);
+		GpuParamBlock* createGpuParamBlockImpl();
 
 
 		/**
 		/**
 		 * @copydoc HardwareBufferManager::createGenericBufferImpl
 		 * @copydoc HardwareBufferManager::createGenericBufferImpl

+ 2 - 2
CamelotD3D9Renderer/Source/CmD3D9HardwareBufferManager.cpp

@@ -59,9 +59,9 @@ namespace CamelotEngine
             
             
     }
     }
 	//-----------------------------------------------------------------------
 	//-----------------------------------------------------------------------
-	GpuParamBlock* D3D9HardwareBufferManager::createGpuParamBlockImpl(const GpuParamBlockDesc& paramDesc, GpuParamBlockUsage usage)
+	GpuParamBlock* D3D9HardwareBufferManager::createGpuParamBlockImpl()
 	{
 	{
-		return new GpuParamBlock(paramDesc, usage);
+		return new GpuParamBlock();
 	}
 	}
 	//-----------------------------------------------------------------------
 	//-----------------------------------------------------------------------
 	GpuBuffer* D3D9HardwareBufferManager::createGpuBufferImpl(UINT32 elementCount, UINT32 elementSize, 
 	GpuBuffer* D3D9HardwareBufferManager::createGpuBufferImpl(UINT32 elementCount, UINT32 elementSize, 

+ 6 - 4
CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp

@@ -330,8 +330,6 @@ namespace CamelotEngine
 	{
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 		THROW_IF_NOT_RENDER_THREAD;
 
 
-		params->updateIfDirty();
-
 		const GpuParamDesc& paramDesc = params->getParamDesc();
 		const GpuParamDesc& paramDesc = params->getParamDesc();
 
 
 		for(auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
 		for(auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
@@ -365,7 +363,9 @@ namespace CamelotEngine
 					const GpuParamDataDesc& paramDesc = iter->second;
 					const GpuParamDataDesc& paramDesc = iter->second;
 
 
 					GpuParamBlockPtr paramBlock = params->getParamBlock(paramDesc.paramBlockSlot);
 					GpuParamBlockPtr paramBlock = params->getParamBlock(paramDesc.paramBlockSlot);
-					const UINT8* ptrData = paramBlock->getDataPtr(paramDesc.cpuMemOffset * sizeof(UINT32));
+					const GpuParamBlockBuffer* currentBlockBuffer = paramBlock->getBindableBuffer();
+
+					const UINT8* ptrData = currentBlockBuffer->getDataPtr(paramDesc.cpuMemOffset * sizeof(UINT32));
 
 
 					switch(paramDesc.type)
 					switch(paramDesc.type)
 					{
 					{
@@ -417,7 +417,9 @@ namespace CamelotEngine
 					const GpuParamDataDesc& paramDesc = iter->second;
 					const GpuParamDataDesc& paramDesc = iter->second;
 
 
 					GpuParamBlockPtr paramBlock = params->getParamBlock(paramDesc.paramBlockSlot);
 					GpuParamBlockPtr paramBlock = params->getParamBlock(paramDesc.paramBlockSlot);
-					const UINT8* ptrData = paramBlock->getDataPtr(paramDesc.cpuMemOffset * sizeof(UINT32));
+					const GpuParamBlockBuffer* currentBlockBuffer = paramBlock->getBindableBuffer();
+
+					const UINT8* ptrData = currentBlockBuffer->getDataPtr(paramDesc.cpuMemOffset * sizeof(UINT32));
 
 
 					switch(paramDesc.type)
 					switch(paramDesc.type)
 					{
 					{

+ 15 - 1
CamelotForwardRenderer/Source/CmForwardRenderer.cpp

@@ -76,7 +76,9 @@ namespace CamelotEngine
 			for(UINT32 i = 0; i < material->getNumPasses(); i++)
 			for(UINT32 i = 0; i < material->getNumPasses(); i++)
 			{
 			{
 				setPass(material->getPass(i));
 				setPass(material->getPass(i));
-				setPassParameters(material->getPassParameters(i));
+
+				PassParametersPtr paramsPtr = material->getPassParameters(i);
+				setPassParameters(paramsPtr);
 
 
 				renderContext->render(mesh->getRenderOperation());
 				renderContext->render(mesh->getRenderOperation());
 			}
 			}
@@ -177,5 +179,17 @@ namespace CamelotEngine
 		GpuProgramHandle geomProgram = mActivePass->getGeometryProgram();
 		GpuProgramHandle geomProgram = mActivePass->getGeometryProgram();
 		if(geomProgram)
 		if(geomProgram)
 			renderContext->bindGpuParams(GPT_GEOMETRY_PROGRAM, params->mGeomParams);
 			renderContext->bindGpuParams(GPT_GEOMETRY_PROGRAM, params->mGeomParams);
+
+		GpuProgramHandle hullProgram = mActivePass->getHullProgram();
+		if(hullProgram)
+			renderContext->bindGpuParams(GPT_HULL_PROGRAM, params->mHullParams);
+
+		GpuProgramHandle domainProgram = mActivePass->getDomainProgram();
+		if(domainProgram)
+			renderContext->bindGpuParams(GPT_DOMAIN_PROGRAM, params->mDomainParams);
+
+		GpuProgramHandle computeProgram = mActivePass->getComputeProgram();
+		if(computeProgram)
+			renderContext->bindGpuParams(GPT_COMPUTE_PROGRAM, params->mComputeParams);
 	}
 	}
 }
 }

+ 18 - 13
CamelotGLRenderer/Include/CmGLGpuParamBlock.h

@@ -6,24 +6,29 @@
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
-	class CM_RSGL_EXPORT GLGpuParamBlock : public GpuParamBlock
+	class CM_RSGL_EXPORT GLGpuParamBlockBuffer : public GpuParamBlockBuffer
 	{
 	{
-	private:
-		struct GLGpuParamBlockSharedData
-		{
-			GLuint mGLHandle;
-		};
-
 	public:
 	public:
-		GLGpuParamBlock(const GpuParamBlockDesc& desc, GpuParamBlockUsage usage);
-		~GLGpuParamBlock();
+		GLGpuParamBlockBuffer(UINT32 size, GpuParamBlockUsage usage);
+		~GLGpuParamBlockBuffer();
 
 
-		virtual void updateIfDirty();
-		virtual GpuParamBlockPtr clone() const;
+		/**
+		 * @copydoc CpuParamBlockBuffer::writeAll.
+		 */
+		void writeAll(const void* data);
 
 
-		GLuint getGLHandle() const { return mGLSharedData->mGLHandle; }
+		GLuint getGLHandle() const { return mGLHandle; }
 
 
 	private:
 	private:
-		GLGpuParamBlockSharedData* mGLSharedData;
+		GLuint mGLHandle;
+	};
+
+	class CM_RSGL_EXPORT GLGpuParamBlock : public GpuParamBlock
+	{
+	protected:
+		/**
+		 * @copydoc GpuParamBlock::createBuffer.
+		 */
+		GpuParamBlockBuffer* createBuffer() const;
 	};
 	};
 }
 }

+ 1 - 1
CamelotGLRenderer/Include/CmGLHardwareBufferManager.h

@@ -86,7 +86,7 @@ namespace CamelotEngine {
             GpuBufferUsage usage);
             GpuBufferUsage usage);
 
 
 		/** @copydoc HardwareBufferManager::createGpuParamBlockImpl */
 		/** @copydoc HardwareBufferManager::createGpuParamBlockImpl */
-		GpuParamBlock* createGpuParamBlockImpl(const GpuParamBlockDesc& paramDesc, GpuParamBlockUsage usage = GPBU_STATIC);
+		GpuParamBlock* createGpuParamBlockImpl();
 
 
 		/**
 		/**
 		 * @copydoc HardwareBufferManager::createGenericBufferImpl
 		 * @copydoc HardwareBufferManager::createGenericBufferImpl

+ 21 - 41
CamelotGLRenderer/Source/CmGLGpuParamBlock.cpp

@@ -3,57 +3,37 @@
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
-	GLGpuParamBlock::GLGpuParamBlock(const GpuParamBlockDesc& desc, GpuParamBlockUsage usage)
-		:GpuParamBlock(desc, usage), mGLSharedData(nullptr)
+	GLGpuParamBlockBuffer::GLGpuParamBlockBuffer(UINT32 size, GpuParamBlockUsage usage)
+		:GpuParamBlockBuffer(size, usage)
 	{
 	{
-		mGLSharedData = new GLGpuParamBlockSharedData();
+		glGenBuffers(1, &mGLHandle);
+		glBindBuffer(GL_UNIFORM_BUFFER, mGLHandle);
+		if(mUsage == GPBU_STATIC)
+			glBufferData(GL_UNIFORM_BUFFER, mSize, (GLvoid*)mData, GL_STATIC_DRAW);
+		else if(mUsage == GPBU_DYNAMIC)
+			glBufferData(GL_UNIFORM_BUFFER, mSize, (GLvoid*)mData, GL_DYNAMIC_DRAW);
+		else
+			CM_EXCEPT(InternalErrorException, "Invalid gpu param block usage.");
+
+		glBindBuffer(GL_UNIFORM_BUFFER, 0);
 	}
 	}
 
 
-	GLGpuParamBlock::~GLGpuParamBlock()
+	GLGpuParamBlockBuffer::~GLGpuParamBlockBuffer()
 	{
 	{
-		if(mOwnsSharedData)
-		{
-			glDeleteBuffers(1, &mGLSharedData->mGLHandle);
-			delete mGLSharedData;
-		}
+		glDeleteBuffers(1, &mGLHandle);
 	}
 	}
 
 
-	void GLGpuParamBlock::updateIfDirty()
+	void GLGpuParamBlockBuffer::writeAll(const void* data)
 	{
 	{
-		if(!sharedData->mInitialized)
-		{
-			glGenBuffers(1, &mGLSharedData->mGLHandle);
-			glBindBuffer(GL_UNIFORM_BUFFER, mGLSharedData->mGLHandle);
-			if(mUsage == GPBU_STATIC)
-				glBufferData(GL_UNIFORM_BUFFER, mSize, (GLvoid*)mData, GL_STATIC_DRAW);
-			else if(mUsage == GPBU_DYNAMIC)
-				glBufferData(GL_UNIFORM_BUFFER, mSize, (GLvoid*)mData, GL_DYNAMIC_DRAW);
-			else
-				CM_EXCEPT(InternalErrorException, "Invalid gpu param block usage.");
+		glBindBuffer(GL_UNIFORM_BUFFER, mGLHandle);
+		glBufferSubData(GL_UNIFORM_BUFFER, 0 , mSize, data);
+		glBindBuffer(GL_UNIFORM_BUFFER, 0);
 
 
-			glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
-			sharedData->mInitialized = true;
-		}
-
-		if(sharedData->mDirty)
-		{
-			glBindBuffer(GL_UNIFORM_BUFFER, mGLSharedData->mGLHandle);
-			glBufferSubData(GL_UNIFORM_BUFFER, 0 , mSize, mData);
-			glBindBuffer(GL_UNIFORM_BUFFER, 0);
-		}
-
-		GpuParamBlock::updateIfDirty();
+		GpuParamBlockBuffer::writeAll(data);
 	}
 	}
 
 
-	GpuParamBlockPtr GLGpuParamBlock::clone() const
+	GpuParamBlockBuffer* GLGpuParamBlock::createBuffer() const
 	{
 	{
-		std::shared_ptr<GLGpuParamBlock> clonedParamBlock(new GLGpuParamBlock(*this));
-		clonedParamBlock->mData = new UINT8[mSize];
-		clonedParamBlock->mOwnsSharedData = false;
-		clonedParamBlock->mGLSharedData = mGLSharedData;
-		memcpy(clonedParamBlock->mData, mData, mSize);
-
-		return clonedParamBlock;
+		return new GLGpuParamBlockBuffer(mSize, mUsage);
 	}
 	}
 }
 }

+ 2 - 2
CamelotGLRenderer/Source/CmGLHardwareBufferManager.cpp

@@ -94,9 +94,9 @@ namespace CamelotEngine {
 		return new GLIndexBuffer(this, itype, numIndexes, usage);
 		return new GLIndexBuffer(this, itype, numIndexes, usage);
     }
     }
 	//---------------------------------------------------------------------
 	//---------------------------------------------------------------------
-	GpuParamBlock* GLHardwareBufferManager::createGpuParamBlockImpl(const GpuParamBlockDesc& paramDesc, GpuParamBlockUsage usage)
+	GpuParamBlock* GLHardwareBufferManager::createGpuParamBlockImpl()
 	{
 	{
-		return new GLGpuParamBlock(paramDesc, usage);
+		return new GLGpuParamBlock();
 	}
 	}
 	//---------------------------------------------------------------------
 	//---------------------------------------------------------------------
 	GpuBuffer* GLHardwareBufferManager::createGpuBufferImpl(UINT32 elementCount, UINT32 elementSize, 
 	GpuBuffer* GLHardwareBufferManager::createGpuBufferImpl(UINT32 elementCount, UINT32 elementSize, 

+ 6 - 5
CamelotGLRenderer/Source/CmGLRenderSystem.cpp

@@ -281,8 +281,6 @@ namespace CamelotEngine
 	{
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 		THROW_IF_NOT_RENDER_THREAD;
 
 
-		params->updateIfDirty();
-
 		const GpuParamDesc& paramDesc = params->getParamDesc();
 		const GpuParamDesc& paramDesc = params->getParamDesc();
 		GLSLGpuProgram* activeProgram = getActiveProgram(gptype);
 		GLSLGpuProgram* activeProgram = getActiveProgram(gptype);
 		GLuint glProgram = activeProgram->getGLSLProgram()->getGLHandle();
 		GLuint glProgram = activeProgram->getGLSLProgram()->getGLHandle();
@@ -323,10 +321,12 @@ namespace CamelotEngine
 				continue;
 				continue;
 
 
 			GLGpuParamBlockPtr glParamBlock = std::static_pointer_cast<GLGpuParamBlock>(paramBlock);
 			GLGpuParamBlockPtr glParamBlock = std::static_pointer_cast<GLGpuParamBlock>(paramBlock);
+			const GpuParamBlockBuffer* paramBlockBuffer = glParamBlock->getBindableBuffer();
+			const GLGpuParamBlockBuffer* glParamBlockBuffer = static_cast<const GLGpuParamBlockBuffer*>(paramBlockBuffer);
 
 
 			UINT32 globalBlockBinding = getGLUniformBlockBinding(gptype, blockBinding);
 			UINT32 globalBlockBinding = getGLUniformBlockBinding(gptype, blockBinding);
 			glUniformBlockBinding(glProgram, iter->second.slot - 1, globalBlockBinding);
 			glUniformBlockBinding(glProgram, iter->second.slot - 1, globalBlockBinding);
-			glBindBufferRange(GL_UNIFORM_BUFFER, globalBlockBinding, glParamBlock->getGLHandle(), 0, glParamBlock->getSize());
+			glBindBufferRange(GL_UNIFORM_BUFFER, globalBlockBinding, glParamBlockBuffer->getGLHandle(), 0, glParamBlockBuffer->getSize());
 
 
 			blockBinding++;
 			blockBinding++;
 		}
 		}
@@ -336,11 +336,12 @@ namespace CamelotEngine
 			const GpuParamDataDesc& paramDesc = iter->second;
 			const GpuParamDataDesc& paramDesc = iter->second;
 
 
 			GpuParamBlockPtr paramBlock = params->getParamBlock(paramDesc.paramBlockSlot);
 			GpuParamBlockPtr paramBlock = params->getParamBlock(paramDesc.paramBlockSlot);
-			
+			const GpuParamBlockBuffer* paramBlockBuffer = paramBlock->getBindableBuffer();
+
 			if(paramDesc.paramBlockSlot != 0) // 0 means uniforms are not in a block
 			if(paramDesc.paramBlockSlot != 0) // 0 means uniforms are not in a block
 				continue;
 				continue;
 
 
-			const UINT8* ptrData = paramBlock->getDataPtr(paramDesc.cpuMemOffset * sizeof(UINT32));
+			const UINT8* ptrData = paramBlockBuffer->getDataPtr(paramDesc.cpuMemOffset * sizeof(UINT32));
 
 
 			switch(paramDesc.type)
 			switch(paramDesc.type)
 			{
 			{

+ 17 - 4
CamelotRenderer/Include/CmCoreGpuObject.h

@@ -88,17 +88,30 @@ o		 *
 		 */
 		 */
 		virtual void initialize_internal();
 		virtual void initialize_internal();
 
 
+		/**
+		 * @brief	Returns a shared_ptr version of "this" pointer.
+		 */
+		std::shared_ptr<CoreGpuObject> getThisPtr() const { return mThis.lock(); }
+
 		/**
 		/**
 		 * @brief	Queues a command to be executed on the render thread, without a return value.
 		 * @brief	Queues a command to be executed on the render thread, without a return value.
+		 * 			
+		 * @note	Requires a shared pointer to the object this function will be executed on, in order to 
+		 * 			make sure the object is not deleted before the command executes. Can be null if the 
+		 * 			function is static or global.
 		 */
 		 */
-		static void queueGpuCommand(std::shared_ptr<CoreGpuObject> obj, boost::function<void(CoreGpuObject*)> func);
+		static void queueGpuCommand(std::shared_ptr<CoreGpuObject>& obj, boost::function<void()> func);
 
 
 		/**
 		/**
 		 * @brief	Queues a command to be executed on the render thread, with a return value in the form of AsyncOp.
 		 * @brief	Queues a command to be executed on the render thread, with a return value in the form of AsyncOp.
 		 * 			
 		 * 			
 		 * @see		AsyncOp
 		 * @see		AsyncOp
+		 * 			
+		 * @note	Requires a shared pointer to the object this function will be executed on, in order to
+		 * 			make sure the object is not deleted before the command executes. Can be null if the
+		 * 			function is static or global.
 		 */
 		 */
-		static AsyncOp queueReturnGpuCommand(std::shared_ptr<CoreGpuObject> obj, boost::function<void(CoreGpuObject*, AsyncOp&)> func);
+		static AsyncOp queueReturnGpuCommand(std::shared_ptr<CoreGpuObject>& obj, boost::function<void(AsyncOp&)> func);
 
 
 		/**
 		/**
 		 * @brief	Returns an unique identifier for this object.
 		 * @brief	Returns an unique identifier for this object.
@@ -121,7 +134,7 @@ o		 *
 		CM_STATIC_THREAD_SYNCHRONISER(mCoreGpuObjectLoadedCondition)
 		CM_STATIC_THREAD_SYNCHRONISER(mCoreGpuObjectLoadedCondition)
 		CM_STATIC_MUTEX(mCoreGpuObjectLoadedMutex)
 		CM_STATIC_MUTEX(mCoreGpuObjectLoadedMutex)
 
 
-		static void executeGpuCommand(std::shared_ptr<CoreGpuObject> obj, boost::function<void(CoreGpuObject*)> func);
-		static void executeReturnGpuCommand(std::shared_ptr<CoreGpuObject> obj, boost::function<void(CoreGpuObject*, AsyncOp&)> func, AsyncOp& op); 
+		static void executeGpuCommand(std::shared_ptr<CoreGpuObject>& obj, boost::function<void()> func);
+		static void executeReturnGpuCommand(std::shared_ptr<CoreGpuObject>& obj, boost::function<void(AsyncOp&)> func, AsyncOp& op); 
 	};
 	};
 }
 }

+ 66 - 15
CamelotRenderer/Include/CmGpuParamBlock.h

@@ -2,38 +2,89 @@
 
 
 #include "CmPrerequisites.h"
 #include "CmPrerequisites.h"
 #include "CmCommonEnums.h"
 #include "CmCommonEnums.h"
+#include "CmCoreGpuObject.h"
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
-	class CM_EXPORT GpuParamBlock
+	/**
+	 * @brief	Represents an actual GPU buffer. 
+	 * 			Should only be accessed directly from render thread.
+	 */
+	class CM_EXPORT GpuParamBlockBuffer
 	{
 	{
-	private:
-		struct GpuParamBlockSharedData
-		{
-			bool mDirty;
-			bool mInitialized;
-		};
+	public:
+		GpuParamBlockBuffer(UINT32 size, GpuParamBlockUsage usage);
+		virtual ~GpuParamBlockBuffer();
+
+		/**
+		 * @brief	Writes all of the data to the buffer.
+		 * 			Data size must be the same size as the buffer;
+		 */
+		virtual void writeAll(const void* data);
+
+		const UINT8* getDataPtr(UINT32 offset) const;
+		UINT32 getSize() const { return mSize; }
+
+	protected:
+		GpuParamBlockUsage mUsage;
+		UINT8* mData;
+		UINT32 mSize;
+	};
 
 
+	class CM_EXPORT GpuParamBlock : public CoreGpuObject
+	{
 	public:
 	public:
-		GpuParamBlock(const GpuParamBlockDesc& desc, GpuParamBlockUsage usage);
+		GpuParamBlock();
 		virtual ~GpuParamBlock();
 		virtual ~GpuParamBlock();
 
 
+		void initialize(const GpuParamBlockDesc& desc, GpuParamBlockUsage usage);
+
 		void write(UINT32 offset, const void* data, UINT32 size);
 		void write(UINT32 offset, const void* data, UINT32 size);
 		void zeroOut(UINT32 offset, UINT32 size);
 		void zeroOut(UINT32 offset, UINT32 size);
 
 
-		const UINT8* getDataPtr(UINT32 offset) const;
-		UINT32 getSize() const { return mSize; }
+		/**
+		 * @brief	Returns a buffer that may be bound as a material parameter.
+		 */
+		const GpuParamBlockBuffer* getBindableBuffer() const { return mBuffer; }
 
 
-		virtual void updateIfDirty();
+		/**
+		 * @brief	Updates the internal buffer. You must call this if you want the buffer to be
+		 * 			up to date after making changes to it. Buffer won't be touched if there were no changes
+		 * 			so feel free to call this often.
+		 * 			
+		 * @note	This will only queue the buffer update on the render thread.
+		 */
+		void updateBuffer();
 
 
-		virtual GpuParamBlockPtr clone() const;
-		
 		static GpuParamBlockPtr create(const GpuParamBlockDesc& desc);
 		static GpuParamBlockPtr create(const GpuParamBlockDesc& desc);
 	protected:
 	protected:
-		GpuParamBlockSharedData* sharedData;
+		friend class HardwareBufferManager;
+
+		GpuParamBlockBuffer* mBuffer;
 		GpuParamBlockUsage mUsage;
 		GpuParamBlockUsage mUsage;
-		bool mOwnsSharedData;
+
 		UINT8* mData;
 		UINT8* mData;
 		UINT32 mSize;
 		UINT32 mSize;
+		bool mDirty;
+
+		/**
+		 * @copydoc CoreGpuObject::initialize_internal.
+		 */
+		virtual void initialize_internal();
+
+		/**
+		 * @copydoc CoreGpuObject::destroy_internal.
+		 */
+		virtual void destroy_internal();
+
+		/**
+		 * @brief	Creates new GPU parameter buffer. Derived classes should
+		 * 			return their own specific buffer implementations.
+		 * 			
+		 * @note	Should only be called from the render thread.
+		 */
+		virtual GpuParamBlockBuffer* createBuffer() const;
+
+		void updateBuffer_internal(UINT8* data);
 	};
 	};
 }
 }

+ 1 - 2
CamelotRenderer/Include/CmGpuParams.h

@@ -51,8 +51,7 @@ namespace CamelotEngine
 
 
 		void setTransposeMatrices(bool transpose) { mTransposeMatrices = transpose; }
 		void setTransposeMatrices(bool transpose) { mTransposeMatrices = transpose; }
 
 
-		GpuParamsPtr clone() const;
-		void updateIfDirty();
+		void updateParamBuffers();
 
 
 	private:
 	private:
 		GpuParamDesc& mParamDesc;
 		GpuParamDesc& mParamDesc;

+ 1 - 1
CamelotRenderer/Include/CmHardwareBufferManager.h

@@ -119,7 +119,7 @@ namespace CamelotEngine {
 		virtual VertexDeclaration* createVertexDeclarationImpl();
 		virtual VertexDeclaration* createVertexDeclarationImpl();
 		virtual VertexBuffer* createVertexBufferImpl(UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage, bool streamOut = false) = 0;
 		virtual VertexBuffer* createVertexBufferImpl(UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage, bool streamOut = false) = 0;
 		virtual IndexBuffer* createIndexBufferImpl(IndexBuffer::IndexType itype, UINT32 numIndexes, GpuBufferUsage usage) = 0;
 		virtual IndexBuffer* createIndexBufferImpl(IndexBuffer::IndexType itype, UINT32 numIndexes, GpuBufferUsage usage) = 0;
-		virtual GpuParamBlock* createGpuParamBlockImpl(const GpuParamBlockDesc& paramDesc, GpuParamBlockUsage usage = GPBU_STATIC) = 0;
+		virtual GpuParamBlock* createGpuParamBlockImpl() = 0;
 		virtual GpuBuffer* createGpuBufferImpl(UINT32 elementCount, UINT32 elementSize, GpuBufferType type, GpuBufferUsage usage, 
 		virtual GpuBuffer* createGpuBufferImpl(UINT32 elementCount, UINT32 elementSize, GpuBufferType type, GpuBufferUsage usage, 
 			bool randomGpuWrite = false, bool useCounter = false) = 0;
 			bool randomGpuWrite = false, bool useCounter = false) = 0;
 	};
 	};

+ 12 - 8
CamelotRenderer/Source/CmCoreGpuObject.cpp

@@ -39,7 +39,7 @@ namespace CamelotEngine
 		setScheduledToBeDeleted(true);
 		setScheduledToBeDeleted(true);
 		CoreGpuObjectManager::instance().registerObjectToDestroy(mThis.lock());
 		CoreGpuObjectManager::instance().registerObjectToDestroy(mThis.lock());
 
 
-		queueGpuCommand(mThis.lock(), &CoreGpuObject::destroy_internal);
+		queueGpuCommand(mThis.lock(), boost::bind(&CoreGpuObject::destroy_internal, this));
 	}
 	}
 
 
 	void CoreGpuObject::destroy_internal()
 	void CoreGpuObject::destroy_internal()
@@ -66,7 +66,7 @@ namespace CamelotEngine
 
 
 		setScheduledToBeInitialized(true);
 		setScheduledToBeInitialized(true);
 
 
-		queueGpuCommand(mThis.lock(), &CoreGpuObject::initialize_internal);
+		queueGpuCommand(mThis.lock(), boost::bind(&CoreGpuObject::initialize_internal, this));
 	}
 	}
 
 
 	void CoreGpuObject::initialize_internal()
 	void CoreGpuObject::initialize_internal()
@@ -139,7 +139,7 @@ namespace CamelotEngine
 		}
 		}
 	}
 	}
 
 
-	void CoreGpuObject::queueGpuCommand(std::shared_ptr<CoreGpuObject> obj, boost::function<void(CoreGpuObject*)> func)
+	void CoreGpuObject::queueGpuCommand(std::shared_ptr<CoreGpuObject>& obj, boost::function<void()> func)
 	{
 	{
 		// We call another internal method and go through an additional layer of abstraction in order to keep an active
 		// We call another internal method and go through an additional layer of abstraction in order to keep an active
 		// reference to the obj (saved in the bound function).
 		// reference to the obj (saved in the bound function).
@@ -148,19 +148,23 @@ namespace CamelotEngine
 		RenderSystem::instancePtr()->queueCommand(boost::bind(&CoreGpuObject::executeGpuCommand, obj, func));
 		RenderSystem::instancePtr()->queueCommand(boost::bind(&CoreGpuObject::executeGpuCommand, obj, func));
 	}
 	}
 
 
-	AsyncOp CoreGpuObject::queueReturnGpuCommand(std::shared_ptr<CoreGpuObject> obj, boost::function<void(CoreGpuObject*, AsyncOp&)> func)
+	AsyncOp CoreGpuObject::queueReturnGpuCommand(std::shared_ptr<CoreGpuObject>& obj, boost::function<void(AsyncOp&)> func)
 	{
 	{
 		// See queueGpuCommand
 		// See queueGpuCommand
 		return RenderSystem::instancePtr()->queueReturnCommand(boost::bind(&CoreGpuObject::executeReturnGpuCommand, obj, func, _1));
 		return RenderSystem::instancePtr()->queueReturnCommand(boost::bind(&CoreGpuObject::executeReturnGpuCommand, obj, func, _1));
 	}
 	}
 
 
-	void CoreGpuObject::executeGpuCommand(std::shared_ptr<CoreGpuObject> obj, boost::function<void(CoreGpuObject*)> func)
+	void CoreGpuObject::executeGpuCommand(std::shared_ptr<CoreGpuObject>& obj, boost::function<void()> func)
 	{
 	{
-		func(obj.get());
+		volatile std::shared_ptr<CoreGpuObject> objParam = obj; // Makes sure obj isn't optimized out?
+
+		func();
 	}
 	}
 
 
-	void CoreGpuObject::executeReturnGpuCommand(std::shared_ptr<CoreGpuObject> obj, boost::function<void(CoreGpuObject*, AsyncOp&)> func, AsyncOp& op)
+	void CoreGpuObject::executeReturnGpuCommand(std::shared_ptr<CoreGpuObject>& obj, boost::function<void(AsyncOp&)> func, AsyncOp& op)
 	{
 	{
-		func(obj.get(), op);
+		volatile std::shared_ptr<CoreGpuObject> objParam = obj; // Makes sure obj isn't optimized out?
+
+		func(op);
 	}
 	}
 }
 }

+ 1 - 2
CamelotRenderer/Source/CmDeferredRenderContext.cpp

@@ -129,8 +129,7 @@ namespace CamelotEngine
 
 
 	void DeferredRenderContext::bindGpuParams(GpuProgramType gptype, GpuParamsPtr params)
 	void DeferredRenderContext::bindGpuParams(GpuProgramType gptype, GpuParamsPtr params)
 	{
 	{
-		GpuParamsPtr paramCopy = params->clone();
-		mCommandQueue->queue(boost::bind(&RenderSystem::bindGpuParams, mRenderSystem, gptype, paramCopy));
+		mCommandQueue->queue(boost::bind(&RenderSystem::bindGpuParams, mRenderSystem, gptype, params));
 	}
 	}
 
 
 	void DeferredRenderContext::setRenderTarget(RenderTarget* target)
 	void DeferredRenderContext::setRenderTarget(RenderTarget* target)

+ 80 - 33
CamelotRenderer/Source/CmGpuParamBlock.cpp

@@ -5,42 +5,80 @@
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
-	GpuParamBlock::GpuParamBlock(const GpuParamBlockDesc& desc, GpuParamBlockUsage usage)
-		:mSize(desc.blockSize * sizeof(UINT32)), mOwnsSharedData(true), mUsage(usage)
+	GpuParamBlockBuffer::GpuParamBlockBuffer(UINT32 size, GpuParamBlockUsage usage)
+		:mData(new UINT8[size]), mSize(size), mUsage(usage)
 	{
 	{
-		mData = new UINT8[mSize];
 		memset(mData, 0, mSize);
 		memset(mData, 0, mSize);
-
-		sharedData = new GpuParamBlockSharedData();
-		sharedData->mDirty = true;
-		sharedData->mInitialized = false;
 	}
 	}
 
 
-	GpuParamBlock::~GpuParamBlock()
+	GpuParamBlockBuffer::~GpuParamBlockBuffer()
 	{
 	{
-		delete [] mData;
+		if(mData != nullptr)
+			delete[] mData;
+	}
 
 
-		if(mOwnsSharedData)
-			delete sharedData;
+	void GpuParamBlockBuffer::writeAll(const void* data)
+	{
+		memcpy(mData, data, mSize);
 	}
 	}
 
 
-	void GpuParamBlock::write(UINT32 offset, const void* data, UINT32 size)
+	const UINT8* GpuParamBlockBuffer::getDataPtr(UINT32 offset) const
 	{
 	{
 #if CM_DEBUG_MODE
 #if CM_DEBUG_MODE
-		if(offset < 0 || (offset + size) > mSize)
+		if(offset < 0 || offset >= mSize)
 		{
 		{
 			CM_EXCEPT(InvalidParametersException, "Wanted range is out of buffer bounds. " \
 			CM_EXCEPT(InvalidParametersException, "Wanted range is out of buffer bounds. " \
 				"Available range: 0 .. " + toString(mSize) + ". " \
 				"Available range: 0 .. " + toString(mSize) + ". " \
-				"Wanted range: " + toString(offset) + " .. " + toString(offset + size) + ".");
+				"Wanted range: " + toString(offset) + " .. " + toString(offset) + ".");
 		}
 		}
 #endif
 #endif
 
 
-		memcpy(mData + offset, data, size);
+		return &mData[offset];
+	}
 
 
-		sharedData->mDirty = true;
+	GpuParamBlock::GpuParamBlock()
+		:mDirty(true), mUsage(GPBU_DYNAMIC), mData(nullptr), mBuffer(nullptr)
+	{
 	}
 	}
 
 
-	void GpuParamBlock::zeroOut(UINT32 offset, UINT32 size)
+	GpuParamBlock::~GpuParamBlock()
+	{
+		if(mData != nullptr)
+			delete [] mData;
+	}
+
+	void GpuParamBlock::initialize(const GpuParamBlockDesc& desc, GpuParamBlockUsage usage)
+	{
+		mSize = desc.blockSize * sizeof(UINT32);
+		mData = new UINT8[mSize];
+		memset(mData, 0, mSize);
+
+		mUsage = usage;
+
+		CoreGpuObject::initialize();
+	}
+
+	void GpuParamBlock::initialize_internal()
+	{
+		mBuffer = createBuffer();
+
+		CoreGpuObject::initialize_internal();
+	}
+
+	void GpuParamBlock::destroy_internal()
+	{
+		if(mBuffer != nullptr)
+			delete mBuffer;
+
+		CoreGpuObject::destroy_internal();
+	}
+
+	GpuParamBlockBuffer* GpuParamBlock::createBuffer() const
+	{
+		return new GpuParamBlockBuffer(mSize, mUsage);
+	}
+
+	void GpuParamBlock::write(UINT32 offset, const void* data, UINT32 size)
 	{
 	{
 #if CM_DEBUG_MODE
 #if CM_DEBUG_MODE
 		if(offset < 0 || (offset + size) > mSize)
 		if(offset < 0 || (offset + size) > mSize)
@@ -51,41 +89,50 @@ namespace CamelotEngine
 		}
 		}
 #endif
 #endif
 
 
-		memset(mData + offset, 0, size);
+		memcpy(mData + offset, data, size);
 
 
-		sharedData->mDirty = true;
+		mDirty = true;
 	}
 	}
 
 
-	const UINT8* GpuParamBlock::getDataPtr(UINT32 offset) const
+	void GpuParamBlock::zeroOut(UINT32 offset, UINT32 size)
 	{
 	{
 #if CM_DEBUG_MODE
 #if CM_DEBUG_MODE
-		if(offset < 0 || offset >= mSize)
+		if(offset < 0 || (offset + size) > mSize)
 		{
 		{
 			CM_EXCEPT(InvalidParametersException, "Wanted range is out of buffer bounds. " \
 			CM_EXCEPT(InvalidParametersException, "Wanted range is out of buffer bounds. " \
 				"Available range: 0 .. " + toString(mSize) + ". " \
 				"Available range: 0 .. " + toString(mSize) + ". " \
-				"Wanted range: " + toString(offset) + " .. " + toString(offset) + ".");
+				"Wanted range: " + toString(offset) + " .. " + toString(offset + size) + ".");
 		}
 		}
 #endif
 #endif
 
 
-		return &mData[offset];
+		memset(mData + offset, 0, size);
+
+		mDirty = true;
 	}
 	}
 
 
-	void GpuParamBlock::updateIfDirty()
+	void GpuParamBlock::updateBuffer()
 	{
 	{
-		sharedData->mDirty = false;
+		if(mDirty)
+		{
+			mDirty = false;
 
 
-		// Do nothing
+			// Need to copy the data, as non-render threads might modify
+			// the data before render thread has a chance to process it
+			// TODO - Use an allocator
+			UINT8* dataCopy = new UINT8[mSize];
+			memcpy(dataCopy, mData, mSize);
+
+			queueGpuCommand(getThisPtr(), boost::bind(&GpuParamBlock::updateBuffer_internal, this, dataCopy));
+		}
 	}
 	}
 
 
-	GpuParamBlockPtr GpuParamBlock::clone() const
+	void GpuParamBlock::updateBuffer_internal(UINT8* data)
 	{
 	{
-		GpuParamBlockPtr clonedParamBlock(new GpuParamBlock(*this));
-		clonedParamBlock->mData = new UINT8[mSize];
-		clonedParamBlock->mSize = mSize;
-		clonedParamBlock->mOwnsSharedData = false;
-		memcpy(clonedParamBlock->mData, mData, mSize);
+		assert(mBuffer != nullptr);
+
+		mBuffer->writeAll(data);
 
 
-		return clonedParamBlock;
+		delete[] data;
 	}
 	}
 
 
 	GpuParamBlockPtr GpuParamBlock::create(const GpuParamBlockDesc& desc)
 	GpuParamBlockPtr GpuParamBlock::create(const GpuParamBlockDesc& desc)

+ 2 - 15
CamelotRenderer/Source/CmGpuParams.cpp

@@ -266,25 +266,12 @@ namespace CamelotEngine
 		return mSamplerStates[slot];
 		return mSamplerStates[slot];
 	}
 	}
 
 
-	GpuParamsPtr GpuParams::clone() const
+	void GpuParams::updateParamBuffers()
 	{
 	{
-		GpuParamsPtr clonedParams(new GpuParams(*this));
-		
 		for(size_t i = 0; i < mParamBlocks.size(); i++)
 		for(size_t i = 0; i < mParamBlocks.size(); i++)
 		{
 		{
 			if(mParamBlocks[i] != nullptr)
 			if(mParamBlocks[i] != nullptr)
-				clonedParams->mParamBlocks[i] = mParamBlocks[i]->clone();
-		}
-
-		return clonedParams;
-	}
-
-	void GpuParams::updateIfDirty()
-	{
-		for(size_t i = 0; i < mParamBlocks.size(); i++)
-		{
-			if(mParamBlocks[i] != nullptr)
-				mParamBlocks[i]->updateIfDirty();
+				mParamBlocks[i]->updateBuffer();
 		}
 		}
 	}
 	}
 
 

+ 5 - 1
CamelotRenderer/Source/CmHardwareBufferManager.cpp

@@ -73,7 +73,11 @@ namespace CamelotEngine {
 	//-----------------------------------------------------------------------
 	//-----------------------------------------------------------------------
 	GpuParamBlockPtr HardwareBufferManager::createGpuParamBlock(const GpuParamBlockDesc& paramDesc, GpuParamBlockUsage usage)
 	GpuParamBlockPtr HardwareBufferManager::createGpuParamBlock(const GpuParamBlockDesc& paramDesc, GpuParamBlockUsage usage)
 	{
 	{
-		return GpuParamBlockPtr(createGpuParamBlockImpl(paramDesc, usage));
+		GpuParamBlockPtr paramBlockPtr(createGpuParamBlockImpl(), &CoreGpuObject::_deleteDelayed);
+		paramBlockPtr->setThisPtr(paramBlockPtr);
+		paramBlockPtr->initialize(paramDesc, usage);
+
+		return paramBlockPtr;
 	}
 	}
 	//-----------------------------------------------------------------------
 	//-----------------------------------------------------------------------
 	GpuBufferPtr HardwareBufferManager::createGpuBuffer(UINT32 elementCount, UINT32 elementSize, 
 	GpuBufferPtr HardwareBufferManager::createGpuBuffer(UINT32 elementCount, UINT32 elementSize, 

+ 9 - 1
CamelotRenderer/Source/CmMaterial.cpp

@@ -735,7 +735,15 @@ namespace CamelotEngine
 		if(passIdx < 0 || passIdx >= mParametersPerPass.size())
 		if(passIdx < 0 || passIdx >= mParametersPerPass.size())
 			CM_EXCEPT(InvalidParametersException, "Invalid pass index.");
 			CM_EXCEPT(InvalidParametersException, "Invalid pass index.");
 
 
-		return mParametersPerPass[passIdx];
+		PassParametersPtr params = mParametersPerPass[passIdx];
+
+		for(UINT32 i = 0; i < params->getNumParams(); i++)
+		{
+			if(params->getParamByIdx(i) != nullptr)
+				params->getParamByIdx(i)->updateParamBuffers();
+		}
+
+		return params;
 	}
 	}
 
 
 	TextureHandle Material::getTexture(const String& name) const
 	TextureHandle Material::getTexture(const String& name) const

+ 9 - 27
CamelotRenderer/TODO.txt

@@ -2,9 +2,6 @@
 -----------------------LONGTERM TODO----------------------------------------------------------------
 -----------------------LONGTERM TODO----------------------------------------------------------------
  - Debug tools 
  - Debug tools 
    - Camera controls + world grid
    - Camera controls + world grid
- - Renderable (contains mesh/material)
- - RenderManager (iterated through Renderables and displays them on screen)
-   - And its plugin implementation ForwardRenderingManager
  - Integrate with Camelot Editor
  - Integrate with Camelot Editor
  - SceneManager plugin
  - SceneManager plugin
    - Frustum culling and octree (or some other) acceleration structure
    - Frustum culling and octree (or some other) acceleration structure
@@ -17,9 +14,6 @@ Pass
  - A way to bind buffers to a Pass, while specifying buffer range
  - A way to bind buffers to a Pass, while specifying buffer range
  - GpuParams support for bools, buffers, structs
  - GpuParams support for bools, buffers, structs
 
 
-GpuParamBlock - Needs to derive from CoreGpuObject and needs to be initialized better
- - HardwareBufferManager::createGpuParamBlock needs &CoreGpuObject::_deleteDelayed added as a deleted to shared_ptr
-
 Support loading of compound objects:
 Support loading of compound objects:
    - Loading Material also loads attached Shader and Textures/Samplers
    - Loading Material also loads attached Shader and Textures/Samplers
 
 
@@ -32,6 +26,7 @@ Make sure we can add an include file to a HighLevelGpuProgram, and make sure it
 
 
 Go through RenderSystem classes and make sure we don't hold any raw pointer references.
 Go through RenderSystem classes and make sure we don't hold any raw pointer references.
 Seems there is a possible deadlock when starting the render thread, while waiting for the thread to be started
 Seems there is a possible deadlock when starting the render thread, while waiting for the thread to be started
+Get rid of resource handlers in Resources?
 
 
 Can be delayed:
 Can be delayed:
  Make sure that I am able to blit contents from render textures on all render systems
  Make sure that I am able to blit contents from render textures on all render systems
@@ -77,14 +72,7 @@ So final solution:
     - Not ALL methods need to be moved, only those that are resource heavy
     - Not ALL methods need to be moved, only those that are resource heavy
     - Smaller methods may remain and always stay async, but keep internal state?
     - Smaller methods may remain and always stay async, but keep internal state?
  - Resource creation on DX11 should be direct though, without a queue (especially if we manage to populate a resource in the same step)
  - Resource creation on DX11 should be direct though, without a queue (especially if we manage to populate a resource in the same step)
- - (Make sure to update GpuParamBlock implementations as they do their copying internally)
-
-
-<<<<Issue of setting individual parameters on a material>>>
- - Material can contain multiple techniques
- - How do I ensure parameters are valid for all techniques?
- - Require user to create a Material parameter specification?
- - Also need a way to avoid displaying internal parameters used by the active renderer
+ - Remove & replace internal data copying in GpuParamBlock (or just use a allocator instead of new())
 
 
 <<<<RenderSystem needed modifications>>>>
 <<<<RenderSystem needed modifications>>>>
   - Texture resource views (Specifying just a subresource of a texture as a shader parameter)
   - Texture resource views (Specifying just a subresource of a texture as a shader parameter)
@@ -128,22 +116,17 @@ Editor IMPORTANT:
 -----------------------BACKLOG TODO---------------------------------------------------------------
 -----------------------BACKLOG TODO---------------------------------------------------------------
 
 
 HIGH PRIORITY TODO:
 HIGH PRIORITY TODO:
- - Issue with deserialization and value types:
-  - Value types are only set at the end of deserialization, because I want to be sure all of their fields are initialized. However there is nothing stopping a custom RTTI method from accessing a (yet uninitialized) value in a ptr field. (See CmMaterialRTTI, setTexParam). I need to initialize fields in a better order.
-   - Solution?: Set (empty) ptr values immediately, and only load them later
  - GetRenderOperation doesn't consider sub-meshes
  - GetRenderOperation doesn't consider sub-meshes
 
 
 Mid priority TODO:
 Mid priority TODO:
  - monitorIndex is ignored in DX11
  - monitorIndex is ignored in DX11
- - Make sure to queue up mesh deletion to make sure it gets destroyed on the render thread
  - Add a field that tracks % of resource deserialization in BinarySerializer
  - Add a field that tracks % of resource deserialization in BinarySerializer
  - Mesh loading:
  - Mesh loading:
   - Example Freefall mesh has one index per vertex, and there are 17k+ vertices. I think I need a post-process step that optimizes them.
   - Example Freefall mesh has one index per vertex, and there are 17k+ vertices. I think I need a post-process step that optimizes them.
   - Imported FBX meshes are too big
   - Imported FBX meshes are too big
-  - Search for all remaining "TODO PORT" comments and fix them
-  - Ogre performed special DDS loading. I removed that. I'm not sure if I'll need to re-add it?
-  - My log is not thread safe yet it is being called from multiple threads.
-  - Handling of shader array parameters? This needs testing
+ - Ogre performed special DDS loading. I removed that. I'm not sure if I'll need to re-add it?
+ - My log is not thread safe yet it is being called from multiple threads.
+ - Handling of shader array parameters? This needs testing
    - I'm currently ignoring array elements in GL due to the name their names are handled
    - I'm currently ignoring array elements in GL due to the name their names are handled
  - RTTI:
  - RTTI:
      When defining RTTIType like so: 
      When defining RTTIType like so: 
@@ -151,12 +134,8 @@ Mid priority TODO:
      I need to make sure that HighLevelGpuProgram class has valid RTTI type as well. Otherwise the inheritance hierarchy will not be correct. Right now this isn't checked anywhere.
      I need to make sure that HighLevelGpuProgram class has valid RTTI type as well. Otherwise the inheritance hierarchy will not be correct. Right now this isn't checked anywhere.
 
 
 Low priority TODO:
 Low priority TODO:
- - Can I assign a RenderTexture to a Pass?
  - Mesh loading:
  - Mesh loading:
   - Sub-meshes aren't being transformed by world matrices of their nodes
   - Sub-meshes aren't being transformed by world matrices of their nodes
- - Are resource getting properly unloaded? e.g. when shared_ptr destroys a texture is it removed from gpu?
-  - Make sure resources only get properly unloaded at end of every frame. This is because a lot of RenderSystem stuff holds raw ptrs
-	to resources, and it keeps them throughout the frame (especially with deferred rendering). Plus this can only be done on the render thread anyway.
  - Remove template from RTTIType and move it to IReflectable? This way i can hopefully move GetRTTITypeStatic and GetRTTIType to IReflectable so I don't
  - Remove template from RTTIType and move it to IReflectable? This way i can hopefully move GetRTTITypeStatic and GetRTTIType to IReflectable so I don't
    need to manually implement those for every method.
    need to manually implement those for every method.
  - Viewport needs to be updated when I call RenderTarget::setFullscreen/finishSwitchingFullscreen/updateWindowRect/windowMovedOrResized. Currently it's not
  - Viewport needs to be updated when I call RenderTarget::setFullscreen/finishSwitchingFullscreen/updateWindowRect/windowMovedOrResized. Currently it's not
@@ -167,7 +146,6 @@ Low priority TODO:
    if pointer is saved/loaded as a plain field. I need to add a check that ensures the type is POD. 
    if pointer is saved/loaded as a plain field. I need to add a check that ensures the type is POD. 
    See: http://www.boost.org/doc/libs/1_51_0/boost/mpi/datatype.hpp for a possible implementation of a compile time check.
    See: http://www.boost.org/doc/libs/1_51_0/boost/mpi/datatype.hpp for a possible implementation of a compile time check.
  - Fix up WorkQueue as it doesn't lock when initializing, to make sure threads are actually started before returning
  - Fix up WorkQueue as it doesn't lock when initializing, to make sure threads are actually started before returning
- - DepthStencilBuffer & Texture should possibly share the same interface instead of being two separate classes? I'll need to assign DepthStencil to shaders sometimes. Not possible in DX9 but possible in DX11.
  - CPU reading or writing to a render texture in OpenGL is not supported. (CmGLHardwarePixelBuffer::upload/download). 
  - CPU reading or writing to a render texture in OpenGL is not supported. (CmGLHardwarePixelBuffer::upload/download). 
  - When saving a resource, make sure resource is properly loaded before saving
  - When saving a resource, make sure resource is properly loaded before saving
    - Add doc to Resources::save that says it will block until render thread updates the resource
    - Add doc to Resources::save that says it will block until render thread updates the resource
@@ -185,6 +163,10 @@ Optional TODO:
  - Extend texture copy so it accepts different subregions & subresources (currently only entire resource can be copied)
  - Extend texture copy so it accepts different subregions & subresources (currently only entire resource can be copied)
  - Need a way to convert MSAA render texture into a normal render texture
  - Need a way to convert MSAA render texture into a normal render texture
  - Vertex buffer start offset is not supported when calling Draw methods
  - Vertex buffer start offset is not supported when calling Draw methods
+ - Issue with deserialization and value types:
+  - Value types are only set at the end of deserialization, because I want to be sure all of their fields are initialized. 
+     However there is nothing stopping a custom RTTI method from accessing a (yet uninitialized) value in a ptr field. 
+	 (See CmMaterialRTTI, setTexParam). I need to initialize fields in a better order.)
 
 
  -----------------------------------------------------------------------------------------------
  -----------------------------------------------------------------------------------------------