فهرست منبع

Finished material parameter handles

Marko Pintera 12 سال پیش
والد
کامیت
6ed43791cd

+ 118 - 7
CamelotCore/Include/CmGpuParam.h

@@ -1,6 +1,8 @@
 #pragma once
 
 #include "CmPrerequisites.h"
+#include "CmGpuParamDesc.h"
+#include "CmGpuParamBlock.h"
 #include "CmDebug.h"
 #include "CmException.h"
 #include "CmMatrix3.h"
@@ -22,18 +24,19 @@ namespace CamelotFramework
 	private:
 		friend class GpuParams;
 
-		struct GpuDataParamData
+		struct InternalData
 		{
-			GpuDataParamData(GpuParamDataDesc* paramDesc, GpuParamBlock** paramBlocks, bool transpose)
-				:paramDesc(paramDesc), paramBlocks(paramBlocks), transpose(transpose)
+			InternalData(GpuParamDataDesc* paramDesc, GpuParamBlock** paramBlocks, bool transpose)
+				:paramDesc(paramDesc), paramBlocks(paramBlocks), transpose(transpose), isDestroyed(false)
 			{ }
 
-			~GpuDataParamData()
+			~InternalData()
 			{ }
 
 			GpuParamDataDesc* paramDesc;
 			GpuParamBlock** paramBlocks;
 			bool transpose;
+			bool isDestroyed;
 		};
 
 		template<class Type>
@@ -63,6 +66,9 @@ namespace CamelotFramework
 
 		void set(const T& value, UINT32 arrayIdx = 0)
 		{
+			if(mData->isDestroyed)
+				CM_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
+
 			GpuParamDataDesc* paramDesc = mData->paramDesc;
 
 #if CM_DEBUG_MODE
@@ -95,6 +101,9 @@ namespace CamelotFramework
 
 		T get(UINT32 arrayIdx = 0)
 		{
+			if(mData->isDestroyed)
+				CM_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
+
 			GpuParamDataDesc* paramDesc = mData->paramDesc;
 
 #if CM_DEBUG_MODE
@@ -117,14 +126,19 @@ namespace CamelotFramework
 				return value;
 		}
 
+		void destroy()
+		{
+			mData->isDestroyed = true;
+		}
+
 	private:
-		GpuDataParamBase(GpuParamDataDesc* paramDesc, GpuParamBlock** paramBlock, bool transpose)
+		GpuDataParamBase(GpuParamDataDesc* paramDesc, GpuParamBlock** paramBlocks, bool transpose)
 		{
-			mData = cm_shared_ptr<GpuDataParamData>(paramDesc, paramBlock, transpose);
+			mData = cm_shared_ptr<InternalData>(paramDesc, paramBlocks, transpose);
 		}
 
 	private:
-		std::shared_ptr<GpuDataParamData> mData;
+		std::shared_ptr<InternalData> mData;
 	};
 
 	typedef GpuDataParamBase<float> GpuParamFloat;
@@ -133,4 +147,101 @@ namespace CamelotFramework
 	typedef GpuDataParamBase<Vector4> GpuParamVec4;
 	typedef GpuDataParamBase<Matrix3> GpuParamMat3;
 	typedef GpuDataParamBase<Matrix4> GpuParamMat4;
+
+	/**
+	 * @copydoc GpuDataParamBase
+	 */
+	class CM_EXPORT GpuParamStruct
+	{
+	private:
+		friend class GpuParams;
+
+		struct InternalData
+		{
+			InternalData(GpuParamDataDesc* paramDesc, GpuParamBlock** paramBlocks);
+			~InternalData();
+
+			GpuParamDataDesc* paramDesc;
+			GpuParamBlock** paramBlocks;
+			bool isDestroyed;
+		};
+
+	public:
+		GpuParamStruct();
+
+		void set(const void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0);
+		void get(void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0);
+		UINT32 getElementSize() const;
+
+		void destroy();
+	private:
+		GpuParamStruct(GpuParamDataDesc* paramDesc, GpuParamBlock** paramBlocks);
+
+	private:
+		std::shared_ptr<InternalData> mData;
+	};
+
+	/**
+	 * @copydoc GpuDataParamBase
+	 */
+	class CM_EXPORT GpuParamTexture
+	{
+	private:
+		friend class GpuParams;
+
+		struct InternalData
+		{
+			InternalData(GpuParamObjectDesc* paramDesc, HTexture* textures);
+			~InternalData();
+
+			GpuParamObjectDesc* paramDesc;
+			HTexture* textures;
+			bool isDestroyed;
+		};
+
+	public:
+		GpuParamTexture();
+
+		void set(const HTexture& texture);
+		HTexture get();
+
+		void destroy();
+	private:
+		GpuParamTexture(GpuParamObjectDesc* paramDesc, HTexture* textures);
+
+	private:
+		std::shared_ptr<InternalData> mData;
+	};
+
+	/**
+	 * @copydoc GpuDataParamBase
+	 */
+	class CM_EXPORT GpuParamSampState
+	{
+	private:
+		friend class GpuParams;
+
+		struct InternalData
+		{
+			InternalData(GpuParamObjectDesc* paramDesc, HSamplerState* samplerStates);
+			~InternalData();
+
+			GpuParamObjectDesc* paramDesc;
+			HSamplerState* samplerStates;
+			bool isDestroyed;
+		};
+
+	public:
+		GpuParamSampState();
+
+		void set(const HSamplerState& texture);
+		HSamplerState get();
+
+		void destroy();
+	private:
+		GpuParamSampState(GpuParamObjectDesc* paramDesc, HSamplerState* samplerStates);
+
+	private:
+		std::shared_ptr<InternalData> mData;
+	};
 }

+ 6 - 13
CamelotCore/Include/CmGpuParams.h

@@ -94,19 +94,9 @@ namespace CamelotFramework
 			output = iterFind->second;
 		}
 
-		/**
-		 * @brief	Sets a parameter.
-		 *
-		 * @param	name	  	Name of the parameter.
-		 * @param	value	  	Parameter data.
-		 * @param	size	  	Size of the provided data. It can be exact size or lower than the exact size of the wanted field.
-		 * 						If it's lower unused bytes will be set to 0. 
-		 * @param	arrayIndex	(optional) zero-based index of the array.
-		 */
-		void setParam(const String& name, const void* value, UINT32 sizeBytes, UINT32 arrayIndex = 0);
-
-		void setTexture(const String& name, const HTexture& val);
-		void setSamplerState(const String& name, const HSamplerState& val);
+		void getStructParam(const String& name, GpuParamStruct& output) const;
+		void getTextureParam(const String& name, GpuParamTexture& output) const;
+		void getSamplerStateParam(const String& name, GpuParamSampState& output) const;
 
 		/**
 		 * @brief	Creates the copy of this object in a special way. Should only be called
@@ -137,5 +127,8 @@ namespace CamelotFramework
 		mutable Map<String, GpuParamVec4>::type mVec4Params;
 		mutable Map<String, GpuParamMat3>::type mMat3Params;
 		mutable Map<String, GpuParamMat4>::type mMat4Params;
+		mutable Map<String, GpuParamStruct>::type mStructParams;
+		mutable Map<String, GpuParamTexture>::type mTextureParams;
+		mutable Map<String, GpuParamSampState>::type mSampStateParams;
 	};
 }

+ 44 - 48
CamelotCore/Include/CmMaterial.h

@@ -43,10 +43,14 @@ namespace CamelotFramework
 				:size(0), data(nullptr)
 			{ }
 
-			StructData(void* _data, UINT32 _size)
+			StructData(UINT32 _size)
 				:size(_size)
 			{
 				data = std::shared_ptr<void>(cm_alloc<ScratchAlloc>(_size), &cm_free<ScratchAlloc>);
+			}
+
+			void write(void* _data)
+			{
 				memcpy(data.get(), _data, size);
 			}
 
@@ -68,29 +72,39 @@ namespace CamelotFramework
 
 		ShaderPtr getShader() const { return mShader; }
 
-		void setTexture(const String& name, const HTexture& value);
-		void setSamplerState(const String& name, const HSamplerState& samplerState);
-		void setFloat(const String& name, float value, UINT32 arrayIdx = 0);
+		void setTexture(const String& name, const HTexture& value)								{ return getParamTexture(name).set(value); }
+		void setSamplerState(const String& name, const HSamplerState& value)					{ return getParamSamplerState(name).set(value); }
+		void setFloat(const String& name, float value, UINT32 arrayIdx = 0)						{ return getParamFloat(name).set(value, arrayIdx); }
 		void setColor(const String& name, const Color& value, UINT32 arrayIdx = 0);
-		void setVec2(const String& name, const Vector2& value, UINT32 arrayIdx = 0);
-		void setVec3(const String& name, const Vector3& value, UINT32 arrayIdx = 0);
-		void setVec4(const String& name, const Vector4& value, UINT32 arrayIdx = 0);
-		void setMat3(const String& name, const Matrix3& value, UINT32 arrayIdx = 0);
-		void setMat4(const String& name, const Matrix4& value, UINT32 arrayIdx = 0);
-		void setStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx = 0);
+		void setVec2(const String& name, const Vector2& value, UINT32 arrayIdx = 0)				{ return getParamVec2(name).set(value, arrayIdx); }
+		void setVec3(const String& name, const Vector3& value, UINT32 arrayIdx = 0)				{ return getParamVec3(name).set(value, arrayIdx); }
+		void setVec4(const String& name, const Vector4& value, UINT32 arrayIdx = 0)				{ return getParamVec4(name).set(value, arrayIdx); }
+		void setMat3(const String& name, const Matrix3& value, UINT32 arrayIdx = 0)				{ return getParamMat3(name).set(value, arrayIdx); }
+		void setMat4(const String& name, const Matrix4& value, UINT32 arrayIdx = 0)				{ return getParamMat4(name).set(value, arrayIdx); }
+		void setStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx = 0)	{ return getParamStruct(name).set(value, size, arrayIdx); }
 		void setRenderQueue(INT16 renderQueue) { mRenderQueue = renderQueue; }
 
 		//void setParamBlock(const String& name, GpuParamBlockPtr paramBlock);
 
-		HTexture getTexture(const String& name) const;
-		HSamplerState getSamplerState(const String& name) const;
-		float getFloat(const String& name, UINT32 arrayIdx = 0) const;
-		Vector2 getVec2(const String& name, UINT32 arrayIdx = 0) const;
-		Vector3 getVec3(const String& name, UINT32 arrayIdx = 0) const;
-		Vector4 getVec4(const String& name, UINT32 arrayIdx = 0) const;
-		Matrix3 getMat3(const String& name, UINT32 arrayIdx = 0) const;
-		Matrix4 getMat4(const String& name, UINT32 arrayIdx = 0) const;
-		const StructData& getStructData(const String& name, UINT32 arrayIdx = 0) const;
+		HTexture getTexture(const String& name) const										{ return getParamTexture(name).get(); }
+		HSamplerState getSamplerState(const String& name) const								{ return getParamSamplerState(name).get(); }
+		float getFloat(const String& name, UINT32 arrayIdx = 0) const						{ return getParamFloat(name).get(arrayIdx); }
+		Vector2 getVec2(const String& name, UINT32 arrayIdx = 0) const						{ return getParamVec2(name).get(arrayIdx); }
+		Vector3 getVec3(const String& name, UINT32 arrayIdx = 0) const						{ return getParamVec3(name).get(arrayIdx); }
+		Vector4 getVec4(const String& name, UINT32 arrayIdx = 0) const						{ return getParamVec4(name).get(arrayIdx); }
+		Matrix3 getMat3(const String& name, UINT32 arrayIdx = 0) const						{ return getParamMat3(name).get(arrayIdx); }
+		Matrix4 getMat4(const String& name, UINT32 arrayIdx = 0) const						{ return getParamMat4(name).get(arrayIdx); }
+		StructData getStructData(const String& name, UINT32 arrayIdx = 0) const;
+
+		GpuParamFloat getParamFloat(const String& name) const;
+		GpuParamVec2 getParamVec2(const String& name) const;
+		GpuParamVec3 getParamVec3(const String& name) const;
+		GpuParamVec4 getParamVec4(const String& name) const;
+		GpuParamMat3 getParamMat3(const String& name) const;
+		GpuParamMat4 getParamMat4(const String& name) const;
+		GpuParamStruct getParamStruct(const String& name) const;
+		GpuParamTexture getParamTexture(const String& name) const;
+		GpuParamSampState getParamSamplerState(const String& name) const;
 
 		INT16 getRenderQueue() const { return mRenderQueue; }
 
@@ -102,7 +116,9 @@ namespace CamelotFramework
 
 		static HMaterial create();
 		static HMaterial create(ShaderPtr shader);
-	public:
+	protected:
+		void destroy_internal();
+
 		/**
 		 * @brief	Allows you to retrieve a handle to a parameter that you can then use for quickly
 		 * 			setting and retrieving parameter data. This allows you to set/get parameter data
@@ -114,6 +130,8 @@ namespace CamelotFramework
 		template <typename T>
 		void getParam(const String& name, GpuDataParamBase<T>& output) const
 		{
+			throwIfNotInitialized();
+
 			auto iterFind = mValidParams.find(name);
 			if(iterFind == mValidParams.end())
 			{
@@ -122,31 +140,11 @@ namespace CamelotFramework
 			}
 
 			const String& gpuVarName = iterFind->second;
+			GpuParamsPtr params = findParamsWithName(gpuVarName);
 
-			for(auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-			{
-				PassParametersPtr params = *iter;
-
-				for(UINT32 i = 0; i < params->getNumParams(); i++)
-				{
-					GpuParamsPtr& paramPtr = params->getParamByIdx(i);
-					if(paramPtr)
-					{
-						if(paramPtr->hasParam(gpuVarName))
-						{
-							paramPtr->getParam<T>(gpuVarName, output);
-							return;
-						}
-					}
-				}
-			}
-
-			CM_EXCEPT(InternalErrorException, "Shader has no parameter with the name: " + gpuVarName);
+			params->getParam<T>(gpuVarName, output);
 		}
 
-	protected:
-		void destroy_internal();
-
 	private:
 		friend class MaterialManager;
 
@@ -160,12 +158,6 @@ namespace CamelotFramework
 		Vector<PassParametersPtr>::type mParametersPerPass;
 		Vector<GpuParamBlockBufferPtr>::type mParamBuffers;
 
-		// These maps aren't necessary as we can read these values from the GpuParams directly
-		// but they make many things (especially serializing and getting values) so much easier
-		Map<String, Vector<StructData>::type>::type mStructValues;
-		Map<String, HTexture>::type mTextureValues;
-		Map<String, HSamplerState>::type mSamplerValues;
-
 		Material();
 
 		void throwIfNotInitialized() const;
@@ -183,6 +175,10 @@ namespace CamelotFramework
 
 		void freeParamBuffers();
 
+		GpuParamsPtr findParamsWithName(const String& name) const;
+		GpuParamsPtr findTexWithName(const String& name) const;
+		GpuParamsPtr findSamplerStateWithName(const String& name) const;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/

+ 3 - 1
CamelotCore/Include/CmMaterialRTTI.h

@@ -360,7 +360,9 @@ namespace CamelotFramework
 
 		void setValue(MaterialStructParam* obj, ManagedDataBlock value) 
 		{ 
-			obj->value = Material::StructData(value.getData(), value.getSize()); 
+			obj->value = Material::StructData(value.getSize()); 
+			obj->value.write(value.getData());
+			
 		}
 
 		UINT32& getArrayIdx(MaterialStructParam* obj) { return obj->arrayIdx; }

+ 177 - 1
CamelotCore/Source/CmGpuParam.cpp

@@ -1 +1,177 @@
-#include "CmGpuParam.h"
+#include "CmGpuParam.h"
+
+namespace CamelotFramework
+{
+	/************************************************************************/
+	/* 									STRUCT	                     		*/
+	/************************************************************************/
+
+	GpuParamStruct::InternalData::InternalData(GpuParamDataDesc* paramDesc, GpuParamBlock** paramBlocks)
+		:paramDesc(paramDesc), paramBlocks(paramBlocks), isDestroyed(false)
+	{ }
+
+	GpuParamStruct::InternalData::~InternalData()
+	{ }
+
+	GpuParamStruct::GpuParamStruct()
+	{ }
+
+	GpuParamStruct::GpuParamStruct(GpuParamDataDesc* paramDesc, GpuParamBlock** paramBlocks)
+	{
+		mData = cm_shared_ptr<InternalData>(paramDesc, paramBlocks);
+	}
+
+	void GpuParamStruct::set(const void* value, UINT32 sizeBytes, UINT32 arrayIdx)
+	{
+		if(mData->isDestroyed)
+			CM_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
+
+		GpuParamDataDesc* paramDesc = mData->paramDesc;
+		UINT32 elementSizeBytes = paramDesc->elementSize * sizeof(UINT32);
+
+#if CM_DEBUG_MODE
+		if(sizeBytes > elementSizeBytes)
+		{
+			CM_EXCEPT(InvalidParametersException, "Provided element size larger than maximum element size. Maximum size: " + 
+				toString(elementSizeBytes) + ". Supplied size: " + toString(sizeBytes));
+		}
+
+		if(arrayIdx >= paramDesc->arraySize)
+		{
+			CM_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " + 
+				toString(paramDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
+		}
+#endif
+
+		GpuParamBlock* paramBlock = mData->paramBlocks[paramDesc->paramBlockSlot];
+		paramBlock->write((paramDesc->cpuMemOffset + arrayIdx * paramDesc->arrayElementStride) * sizeof(UINT32), value, sizeBytes);
+
+		// Set unused bytes to 0
+		if(sizeBytes < elementSizeBytes)
+		{
+			UINT32 diffSize = elementSizeBytes - sizeBytes;
+			paramBlock->zeroOut((paramDesc->cpuMemOffset + arrayIdx * paramDesc->arrayElementStride)  * sizeof(UINT32) + sizeBytes, diffSize);
+		}
+	}
+
+	void GpuParamStruct::get(void* value, UINT32 sizeBytes, UINT32 arrayIdx)
+	{
+		if(mData->isDestroyed)
+			CM_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
+
+		GpuParamDataDesc* paramDesc = mData->paramDesc;
+		UINT32 elementSizeBytes = paramDesc->elementSize * sizeof(UINT32);
+
+#if CM_DEBUG_MODE
+		if(sizeBytes > elementSizeBytes)
+		{
+			CM_EXCEPT(InvalidParametersException, "Provided element size larger than maximum element size. Maximum size: " + 
+				toString(elementSizeBytes) + ". Supplied size: " + toString(sizeBytes));
+		}
+
+		if(arrayIdx >= paramDesc->arraySize)
+		{
+			CM_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " + 
+				toString(paramDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
+		}
+#endif
+
+		GpuParamBlock* paramBlock = mData->paramBlocks[paramDesc->paramBlockSlot];
+
+		paramBlock->read((paramDesc->cpuMemOffset + arrayIdx * paramDesc->arrayElementStride) * sizeof(UINT32), value, sizeBytes);
+	}
+
+	UINT32 GpuParamStruct::getElementSize() const
+	{
+		if(mData->isDestroyed)
+			CM_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
+
+		GpuParamDataDesc* paramDesc = mData->paramDesc;
+		return paramDesc->elementSize * sizeof(UINT32);
+	}
+
+	void GpuParamStruct::destroy()
+	{
+		mData->isDestroyed = true;
+	}
+
+	/************************************************************************/
+	/* 								TEXTURE		                     		*/
+	/************************************************************************/
+
+	GpuParamTexture::InternalData::InternalData(GpuParamObjectDesc* paramDesc, HTexture* textures)
+		:paramDesc(paramDesc), textures(textures), isDestroyed(false)
+	{ }
+
+	GpuParamTexture::InternalData::~InternalData()
+	{ }
+
+	GpuParamTexture::GpuParamTexture()
+	{ }
+
+	GpuParamTexture::GpuParamTexture(GpuParamObjectDesc* paramDesc, HTexture* textures)
+	{
+		mData = cm_shared_ptr<InternalData>(paramDesc, textures);
+	}
+
+	void GpuParamTexture::set(const HTexture& texture)
+	{
+		if(mData->isDestroyed)
+			CM_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
+
+		mData->textures[mData->paramDesc->slot] = texture;
+	}
+
+	HTexture GpuParamTexture::get()
+	{
+		if(mData->isDestroyed)
+			CM_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
+
+		return mData->textures[mData->paramDesc->slot];
+	}
+
+	void GpuParamTexture::destroy()
+	{
+		mData->isDestroyed = true;
+	}
+
+	/************************************************************************/
+	/* 								SAMPLER STATE                      		*/
+	/************************************************************************/
+
+	GpuParamSampState::InternalData::InternalData(GpuParamObjectDesc* paramDesc, HSamplerState* samplerStates)
+		:paramDesc(paramDesc), samplerStates(samplerStates), isDestroyed(false)
+	{ }
+
+	GpuParamSampState::InternalData::~InternalData()
+	{ }
+
+	GpuParamSampState::GpuParamSampState()
+	{ }
+
+	GpuParamSampState::GpuParamSampState(GpuParamObjectDesc* paramDesc, HSamplerState* samplerStates)
+	{
+		mData = cm_shared_ptr<InternalData>(paramDesc, samplerStates);
+	}
+
+	void GpuParamSampState::set(const HSamplerState& samplerState)
+	{
+		if(mData->isDestroyed)
+			CM_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
+
+		mData->samplerStates[mData->paramDesc->slot] = samplerState;
+	}
+
+	HSamplerState GpuParamSampState::get()
+	{
+		if(mData->isDestroyed)
+			CM_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
+
+		return mData->samplerStates[mData->paramDesc->slot];
+	}
+
+	void GpuParamSampState::destroy()
+	{
+		mData->isDestroyed = true;
+	}
+}

+ 57 - 55
CamelotCore/Source/CmGpuParams.cpp

@@ -25,10 +25,10 @@ namespace CamelotFramework
 				mNumTextures = texture.second.slot + 1;
 		}
 
-		for(auto& samplers : mParamDesc.samplers)
+		for(auto& sampler : mParamDesc.samplers)
 		{
-			if((samplers.second.slot + 1) > mNumSamplerStates)
-				mNumSamplerStates = samplers.second.slot + 1;
+			if((sampler.second.slot + 1) > mNumSamplerStates)
+				mNumSamplerStates = sampler.second.slot + 1;
 		}
 
 		// Allocate everything in a single block of memory to get rid of extra memory allocations
@@ -97,12 +97,49 @@ namespace CamelotFramework
 			case GPDT_MATRIX_4X4:
 				mMat4Params[param.second.name] = GpuParamMat4(&param.second, mParamBlocks, mTransposeMatrices);
 				break;
+			case GPDT_STRUCT:
+				mStructParams[param.second.name] = GpuParamStruct(&param.second, mParamBlocks);
+				break;
 			}
 		}
+
+		for(auto& texture : mParamDesc.textures)
+			mTextureParams[texture.second.name] = GpuParamTexture(&texture.second, mTextures);
+
+		for(auto& sampler : mParamDesc.samplers)
+			mSampStateParams[sampler.second.name] = GpuParamSampState(&sampler.second, mSamplerStates);
 	}
 
 	GpuParams::~GpuParams()
 	{
+		// Free params
+		for(auto& param : mFloatParams)
+			param.second.destroy();
+
+		for(auto& param : mVec2Params)
+			param.second.destroy();
+
+		for(auto& param : mVec3Params)
+			param.second.destroy();
+
+		for(auto& param : mVec4Params)
+			param.second.destroy();
+
+		for(auto& param : mMat3Params)
+			param.second.destroy();
+
+		for(auto& param : mMat4Params)
+			param.second.destroy();
+
+		for(auto& param : mStructParams)
+			param.second.destroy();
+
+		for(auto& param : mTextureParams)
+			param.second.destroy();
+
+		for(auto& param : mSampStateParams)
+			param.second.destroy();
+
 		// Ensure everything is destructed
 		for(UINT32 i = 0; i < mNumParamBlocks; i++)
 		{
@@ -194,69 +231,34 @@ namespace CamelotFramework
 		return false;
 	}
 
-	void GpuParams::setParam(const String& name, const void* value, UINT32 sizeBytes, UINT32 arrayIndex)
+	void GpuParams::getStructParam(const String& name, GpuParamStruct& output) const
 	{
-		GpuParamDataDesc* desc = getParamDesc(name);
-
-		if(desc == nullptr)
-		{
-			LOGWRN("Cannot find parameter with the name '" + name + "'");
-			return;
-		}
+		auto iterFind = mStructParams.find(name);
 
-		if(arrayIndex >= desc->arraySize)
-		{
-			CM_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " + 
-				toString(desc->arraySize) + ". Requested size: " + toString(arrayIndex));
-		}
+		if(iterFind == mStructParams.end())
+			CM_EXCEPT(InvalidParametersException, "Cannot find struct parameter with the name '" + name + "'");
 
-		UINT32 elementSizeBytes = desc->elementSize * sizeof(UINT32);
-		if(sizeBytes > elementSizeBytes)
-		{
-			CM_EXCEPT(InvalidParametersException, "Provided element size larger than maximum element size. Maximum size: " + 
-				toString(elementSizeBytes) + ". Supplied size: " + toString(sizeBytes));
-		}
-
-		GpuParamBlock* paramBlock = mParamBlocks[desc->paramBlockSlot];
-
-		if(paramBlock == nullptr)
-		{
-			LOGWRN("Parameter exists but there is no ParamBlock set.");
-			return;
-		}
-
-		paramBlock->write((desc->cpuMemOffset + arrayIndex * desc->arrayElementStride) * sizeof(UINT32), value, sizeBytes);
-
-		// Set unused bytes to 0
-		if(sizeBytes < elementSizeBytes)
-		{
-			UINT32 diffSize = elementSizeBytes - sizeBytes;
-			paramBlock->zeroOut((desc->cpuMemOffset + arrayIndex * desc->arrayElementStride)  * sizeof(UINT32) + sizeBytes, diffSize);
-		}
+		output = iterFind->second;
 	}
 
-	void GpuParams::setTexture(const String& name, const HTexture& val)
+	void GpuParams::getTextureParam(const String& name, GpuParamTexture& output) const
 	{
-		auto paramIter = mParamDesc.textures.find(name);
-		if(paramIter == mParamDesc.textures.end())
-		{
-			LOGWRN("Texture with the name '" + name + "' doesn't exist.");
-			return;
-		}
+		auto iterFind = mTextureParams.find(name);
+
+		if(iterFind == mTextureParams.end())
+			CM_EXCEPT(InvalidParametersException, "Cannot find texture parameter with the name '" + name + "'");
 
-		mTextures[paramIter->second.slot] = val;
+		output = iterFind->second;
 	}
 
-	void GpuParams::setSamplerState(const String& name, const HSamplerState& val)
+	void GpuParams::getSamplerStateParam(const String& name, GpuParamSampState& output) const
 	{
-		auto paramIter = mParamDesc.samplers.find(name);
-		if(paramIter == mParamDesc.samplers.end())
-		{
-			LOGWRN("Sampler with the name '" + name + "' doesn't exist.");
-			return;
-		}
+		auto iterFind = mSampStateParams.find(name);
+
+		if(iterFind == mSampStateParams.end())
+			CM_EXCEPT(InvalidParametersException, "Cannot find sampler state parameter with the name '" + name + "'");
 
-		mSamplerStates[paramIter->second.slot] = val;
+		output = iterFind->second;
 	}
 
 	GpuParamDataDesc* GpuParams::getParamDesc(const String& name) const

+ 135 - 225
CamelotCore/Source/CmMaterial.cpp

@@ -37,9 +37,6 @@ namespace CamelotFramework
 	{
 		mBestTechnique = nullptr;
 		mParametersPerPass.clear();
-		mStructValues.clear();
-		mTextureValues.clear();
-		mSamplerValues.clear();
 		freeParamBuffers();
 
 		if(mShader)
@@ -178,13 +175,6 @@ namespace CamelotFramework
 
 				String& paramBlockName = findBlockIter->second;
 				mValidParams[iter->first] = iter->second.gpuVariableName;
-
-				switch(iter->second.type)
-				{
-				case GPDT_STRUCT:
-					mStructValues[iter->first].resize(iter->second.arraySize);
-					break;
-				}
 			}
 
 			// Create object param mappings
@@ -198,23 +188,6 @@ namespace CamelotFramework
 					continue;
 
 				mValidParams[iter->first] = iter->second.gpuVariableName;
-
-				if(Shader::isSampler(iter->second.type))
-				{
-					mSamplerValues[iter->first] = HSamplerState();
-				}
-				else if(Shader::isTexture(iter->second.type))
-				{
-					mTextureValues[iter->first] = HTexture();
-				}
-				else if(Shader::isBuffer(iter->second.type))
-				{
-					// TODO
-
-					CM_EXCEPT(NotImplementedException, "Buffers not implemented.");
-				}
-				else
-					CM_EXCEPT(InternalErrorException, "Invalid object param type.");
 			}
 
 			for(UINT32 i = 0; i < mBestTechnique->getNumPasses(); i++)
@@ -491,172 +464,9 @@ namespace CamelotFramework
 		}
 	}
 
-	void Material::setTexture(const String& name, const HTexture& value)
-	{
-		throwIfNotInitialized();
-
-		auto iterFind = mValidParams.find(name);
-		if(iterFind == mValidParams.end())
-		{
-			LOGWRN("Material doesn't have a parameter named " + name);
-			return;
-		}
-
-		String& gpuVarName = iterFind->second;
-		for(auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-		{
-			PassParametersPtr params = *iter;
-
-			for(UINT32 i = 0; i < params->getNumParams(); i++)
-			{
-				GpuParamsPtr& paramPtr = params->getParamByIdx(i);
-				if(paramPtr)
-				{
-					if(paramPtr->hasTexture(gpuVarName))
-						paramPtr->setTexture(gpuVarName, value);
-				}
-			}
-		}
-
-		mTextureValues[name] = value;
-	}
-
-	void Material::setSamplerState(const String& name, const HSamplerState& samplerState)
-	{
-		throwIfNotInitialized();
-
-		auto iterFind = mValidParams.find(name);
-		if(iterFind == mValidParams.end())
-		{
-			LOGWRN("Material doesn't have a parameter named " + name);
-			return;
-		}
-
-		String& gpuVarName = iterFind->second;
-		for(auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-		{
-			PassParametersPtr params = *iter;
-
-			for(UINT32 i = 0; i < params->getNumParams(); i++)
-			{
-				GpuParamsPtr& paramPtr = params->getParamByIdx(i);
-				if(paramPtr)
-				{
-					if(paramPtr->hasSamplerState(gpuVarName))
-						paramPtr->setSamplerState(gpuVarName, samplerState);
-				}
-			}
-		}
-
-		mSamplerValues[name] = samplerState;
-	}
-
-	void Material::setFloat(const String& name, float value, UINT32 arrayIdx)
-	{
-		throwIfNotInitialized();
-
-		GpuDataParamBase<float> gpuParam;
-		getParam(name, gpuParam);
-
-		gpuParam.set(value, arrayIdx);
-	}
-
-	void Material::setColor(const String& name, const Color& value, UINT32 arrayIdx)
-	{
-		throwIfNotInitialized();
-
-		GpuDataParamBase<Vector4> gpuParam;
-		getParam(name, gpuParam);
-
-		gpuParam.set(Vector4(value.r, value.g, value.b, value.a), arrayIdx);
-	}
-
-	void Material::setVec2(const String& name, const Vector2& value, UINT32 arrayIdx)
-	{
-		throwIfNotInitialized();
-
-		GpuDataParamBase<Vector2> gpuParam;
-		getParam(name, gpuParam);
-
-		gpuParam.set(value, arrayIdx);
-	}
-
-	void Material::setVec3(const String& name, const Vector3& value, UINT32 arrayIdx)
-	{
-		throwIfNotInitialized();
-
-		GpuDataParamBase<Vector3> gpuParam;
-		getParam(name, gpuParam);
-
-		gpuParam.set(value, arrayIdx);
-	}
-
-	void Material::setVec4(const String& name, const Vector4& value, UINT32 arrayIdx)
-	{
-		throwIfNotInitialized();
-
-		GpuDataParamBase<Vector4> gpuParam;
-		getParam(name, gpuParam);
-
-		gpuParam.set(value, arrayIdx);
-	}
-
-	void Material::setMat3(const String& name, const Matrix3& value, UINT32 arrayIdx)
-	{
-		throwIfNotInitialized();
-
-		GpuDataParamBase<Matrix3> gpuParam;
-		getParam(name, gpuParam);
-
-		gpuParam.set(value, arrayIdx);
-	}
-
-	void Material::setMat4(const String& name, const Matrix4& value, UINT32 arrayIdx)
-	{
-		throwIfNotInitialized();
-
-		GpuDataParamBase<Matrix4> gpuParam;
-		getParam(name, gpuParam);
-
-		gpuParam.set(value, arrayIdx);
-	}
-
-	void Material::setStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx)
-	{
-		throwIfNotInitialized();
-
-		auto iterFind = mValidParams.find(name);
-		if(iterFind == mValidParams.end())
-		{
-			LOGWRN("Material doesn't have a parameter named " + name);
-			return;
-		}
-
-		const SHADER_DATA_PARAM_DESC& desc = mShader->getDataParamDesc(name);
-		if(desc.elementSize != size)
-		{
-			CM_EXCEPT(InvalidParametersException,
-				"Invalid size when writing a struct. Expected: " + toString(desc.elementSize) + ". Got: " + toString(size));
-		}
-
-		String& gpuVarName = iterFind->second;
-		for(auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-		{
-			PassParametersPtr params = *iter;
-
-			for(UINT32 i = 0; i < params->getNumParams(); i++)
-			{
-				GpuParamsPtr& paramPtr = params->getParamByIdx(i);
-				if(paramPtr)
-				{
-					if(paramPtr->hasParam(gpuVarName))
-						paramPtr->setParam(gpuVarName, value, size, arrayIdx);
-				}
-			}
-		}
-
-		auto& savedValue = mStructValues[name];
-		savedValue[arrayIdx] = StructData(value, size);
+	void Material::setColor(const String& name, const Color& value, UINT32 arrayIdx)				
+	{ 
+		return getParamVec4(name).set(Vector4(value.r, value.g, value.b, value.a), arrayIdx); 
 	}
 
 	//void Material::setParamBlock(const String& name, GpuParamBlockPtr paramBlock)
@@ -709,82 +519,182 @@ namespace CamelotFramework
 		return params;
 	}
 
-	HTexture Material::getTexture(const String& name) const
+	Material::StructData Material::getStructData(const String& name, UINT32 arrayIdx) const
 	{
-		auto iterFind = mTextureValues.find(name);
+		GpuParamStruct structParam = getParamStruct(name);
 
-		if(iterFind == mTextureValues.end())
-			CM_EXCEPT(InternalErrorException, "No texture parameter with the name: " + name);
+		StructData data(structParam.getElementSize());
+		structParam.get(data.data.get(), structParam.getElementSize(), arrayIdx);
 
-		return iterFind->second;
+		return data;
 	}
 
-	HSamplerState Material::getSamplerState(const String& name) const
-	{
-		auto iterFind = mSamplerValues.find(name);
-
-		if(iterFind == mSamplerValues.end())
-			CM_EXCEPT(InternalErrorException, "No sampler state parameter with the name: " + name);
-
-		return iterFind->second;
-	}
-
-	float Material::getFloat(const String& name, UINT32 arrayIdx) const
+	GpuParamFloat Material::getParamFloat(const String& name) const
 	{
 		GpuDataParamBase<float> gpuParam;
 		getParam(name, gpuParam);
 
-		return gpuParam.get(arrayIdx);
+		return gpuParam;
 	}
 
-	Vector2 Material::getVec2(const String& name, UINT32 arrayIdx) const
+	GpuParamVec2 Material::getParamVec2(const String& name) const
 	{
 		GpuDataParamBase<Vector2> gpuParam;
 		getParam(name, gpuParam);
 
-		return gpuParam.get(arrayIdx);
+		return gpuParam;
 	}
 
-	Vector3 Material::getVec3(const String& name, UINT32 arrayIdx) const
+	GpuParamVec3 Material::getParamVec3(const String& name) const
 	{
 		GpuDataParamBase<Vector3> gpuParam;
 		getParam(name, gpuParam);
 
-		return gpuParam.get(arrayIdx);
+		return gpuParam;
 	}
 
-	Vector4 Material::getVec4(const String& name, UINT32 arrayIdx) const
+	GpuParamVec4 Material::getParamVec4(const String& name) const
 	{
 		GpuDataParamBase<Vector4> gpuParam;
 		getParam(name, gpuParam);
 
-		return gpuParam.get(arrayIdx);
+		return gpuParam;
 	}
 
-	Matrix3 Material::getMat3(const String& name, UINT32 arrayIdx) const
+	GpuParamMat3 Material::getParamMat3(const String& name) const
 	{
 		GpuDataParamBase<Matrix3> gpuParam;
 		getParam(name, gpuParam);
 
-		return gpuParam.get(arrayIdx);
+		return gpuParam;
 	}
 
-	Matrix4 Material::getMat4(const String& name, UINT32 arrayIdx) const
+	GpuParamMat4 Material::getParamMat4(const String& name) const
 	{
 		GpuDataParamBase<Matrix4> gpuParam;
 		getParam(name, gpuParam);
 
-		return gpuParam.get(arrayIdx);
+		return gpuParam;
+	}
+
+	GpuParamStruct Material::getParamStruct(const String& name) const
+	{
+		throwIfNotInitialized();
+
+		GpuParamStruct gpuParam;
+
+		auto iterFind = mValidParams.find(name);
+		if(iterFind == mValidParams.end())
+		{
+			LOGWRN("Material doesn't have a parameter named " + name);
+			return gpuParam;
+		}
+
+		const String& gpuVarName = iterFind->second;
+		GpuParamsPtr params = findParamsWithName(gpuVarName);
+
+		params->getStructParam(gpuVarName, gpuParam);
+		return gpuParam;
+	}
+
+	GpuParamTexture Material::getParamTexture(const String& name) const
+	{
+		throwIfNotInitialized();
+
+		GpuParamTexture gpuParam;
+
+		auto iterFind = mValidParams.find(name);
+		if(iterFind == mValidParams.end())
+		{
+			LOGWRN("Material doesn't have a parameter named " + name);
+			return gpuParam;
+		}
+
+		const String& gpuVarName = iterFind->second;
+		GpuParamsPtr params = findTexWithName(gpuVarName);
+
+		params->getTextureParam(gpuVarName, gpuParam);
+		return gpuParam;
 	}
 
-	const Material::StructData& Material::getStructData(const String& name, UINT32 arrayIdx) const
+	GpuParamSampState Material::getParamSamplerState(const String& name) const
 	{
-		auto iterFind = mStructValues.find(name);
+		throwIfNotInitialized();
 
-		if(iterFind == mStructValues.end())
-			CM_EXCEPT(InternalErrorException, "No struct parameter with the name: " + name);
+		GpuParamSampState gpuParam;
+
+		auto iterFind = mValidParams.find(name);
+		if(iterFind == mValidParams.end())
+		{
+			LOGWRN("Material doesn't have a parameter named " + name);
+			return gpuParam;
+		}
+
+		const String& gpuVarName = iterFind->second;
+		GpuParamsPtr params = findSamplerStateWithName(gpuVarName);
+
+		params->getSamplerStateParam(gpuVarName, gpuParam);
+		return gpuParam;
+	}
+
+	GpuParamsPtr Material::findParamsWithName(const String& name) const
+	{
+		for(auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+		{
+			PassParametersPtr params = *iter;
+
+			for(UINT32 i = 0; i < params->getNumParams(); i++)
+			{
+				GpuParamsPtr& paramPtr = params->getParamByIdx(i);
+				if(paramPtr)
+				{
+					if(paramPtr->hasParam(name))
+						return paramPtr;
+				}
+			}
+		}
+
+		CM_EXCEPT(InternalErrorException, "Shader has no parameter with the name: " + name);
+	}
+
+	GpuParamsPtr Material::findTexWithName(const String& name) const
+	{
+		for(auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+		{
+			PassParametersPtr params = *iter;
+
+			for(UINT32 i = 0; i < params->getNumParams(); i++)
+			{
+				GpuParamsPtr& paramPtr = params->getParamByIdx(i);
+				if(paramPtr)
+				{
+					if(paramPtr->hasTexture(name))
+						return paramPtr;
+				}
+			}
+		}
+
+		CM_EXCEPT(InternalErrorException, "Shader has no parameter with the name: " + name);
+	}
+
+	GpuParamsPtr Material::findSamplerStateWithName(const String& name) const
+	{
+		for(auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+		{
+			PassParametersPtr params = *iter;
+
+			for(UINT32 i = 0; i < params->getNumParams(); i++)
+			{
+				GpuParamsPtr& paramPtr = params->getParamByIdx(i);
+				if(paramPtr)
+				{
+					if(paramPtr->hasSamplerState(name))
+						return paramPtr;
+				}
+			}
+		}
 
-		return iterFind->second.at(arrayIdx);
+		CM_EXCEPT(InternalErrorException, "Shader has no parameter with the name: " + name);
 	}
 
 	void Material::destroy_internal()