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

Added gpu params for basic data types
Fixed memory corruption with new way of allocating AsyncOps

Marko Pintera 12 лет назад
Родитель
Сommit
bbded86fda

+ 2 - 0
CamelotCore/CamelotCore.vcxproj

@@ -287,6 +287,7 @@
     <ClInclude Include="Include\CmGpuResource.h" />
     <ClInclude Include="Include\CmGpuResource.h" />
     <ClInclude Include="Include\CmGpuResourceDataRTTI.h" />
     <ClInclude Include="Include\CmGpuResourceDataRTTI.h" />
     <ClInclude Include="Include\CmGpuResourceRTTI.h" />
     <ClInclude Include="Include\CmGpuResourceRTTI.h" />
+    <ClInclude Include="Include\CmGpuParam.h" />
     <ClInclude Include="Include\CmInputFwd.h" />
     <ClInclude Include="Include\CmInputFwd.h" />
     <ClInclude Include="Include\CmOSInputHandler.h" />
     <ClInclude Include="Include\CmOSInputHandler.h" />
     <ClInclude Include="Include\CmPixelData.h" />
     <ClInclude Include="Include\CmPixelData.h" />
@@ -440,6 +441,7 @@
     <ClCompile Include="Source\CmGpuResource.cpp" />
     <ClCompile Include="Source\CmGpuResource.cpp" />
     <ClCompile Include="Source\CmGpuResourceData.cpp" />
     <ClCompile Include="Source\CmGpuResourceData.cpp" />
     <ClCompile Include="Source\CmHardwareBufferManager.cpp" />
     <ClCompile Include="Source\CmHardwareBufferManager.cpp" />
+    <ClCompile Include="Source\CmGpuParam.cpp" />
     <ClCompile Include="Source\CmImportOptions.cpp" />
     <ClCompile Include="Source\CmImportOptions.cpp" />
     <ClCompile Include="Source\CmIndexBuffer.cpp" />
     <ClCompile Include="Source\CmIndexBuffer.cpp" />
     <ClCompile Include="Source\CmIndexData.cpp" />
     <ClCompile Include="Source\CmIndexData.cpp" />

+ 6 - 0
CamelotCore/CamelotCore.vcxproj.filters

@@ -489,6 +489,9 @@
     <ClInclude Include="Include\CmBindableGpuParamBlock.h">
     <ClInclude Include="Include\CmBindableGpuParamBlock.h">
       <Filter>Header Files\RenderSystem</Filter>
       <Filter>Header Files\RenderSystem</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\CmGpuParam.h">
+      <Filter>Header Files\RenderSystem</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CmApplication.cpp">
     <ClCompile Include="Source\CmApplication.cpp">
@@ -761,5 +764,8 @@
     <ClCompile Include="Source\CmBindableGpuParamBlock.cpp">
     <ClCompile Include="Source\CmBindableGpuParamBlock.cpp">
       <Filter>Source Files\RenderSystem</Filter>
       <Filter>Source Files\RenderSystem</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Source\CmGpuParam.cpp">
+      <Filter>Source Files\RenderSystem</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 35 - 7
CamelotCore/Include/CmCommandQueue.h

@@ -61,38 +61,66 @@ namespace CamelotFramework
 	{
 	{
 #if CM_DEBUG_MODE
 #if CM_DEBUG_MODE
 		QueuedCommand(boost::function<void(AsyncOp&)> _callback, UINT32 _debugId, bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
 		QueuedCommand(boost::function<void(AsyncOp&)> _callback, UINT32 _debugId, bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
-			:callbackWithReturnValue(_callback), debugId(_debugId), returnsValue(true), notifyWhenComplete(_notifyWhenComplete), callbackId(_callbackId),
-			asyncOp(cm_new<AsyncOp>())
+			:callbackWithReturnValue(_callback), debugId(_debugId), returnsValue(true), notifyWhenComplete(_notifyWhenComplete), callbackId(_callbackId), asyncOp(cm_new<AsyncOp>()), ownsData(true)
 		{ }
 		{ }
 
 
 		QueuedCommand(boost::function<void()> _callback, UINT32 _debugId, bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
 		QueuedCommand(boost::function<void()> _callback, UINT32 _debugId, bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
-			:callback(_callback), debugId(_debugId), returnsValue(false), notifyWhenComplete(_notifyWhenComplete), callbackId(_callbackId), asyncOp(nullptr)
+			:callback(_callback), debugId(_debugId), returnsValue(false), notifyWhenComplete(_notifyWhenComplete), callbackId(_callbackId), asyncOp(nullptr), ownsData(true)
 		{ }
 		{ }
 
 
 		UINT32 debugId;
 		UINT32 debugId;
 #else
 #else
 		QueuedCommand(boost::function<void(AsyncOp&)> _callback, bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
 		QueuedCommand(boost::function<void(AsyncOp&)> _callback, bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
-			:callbackWithReturnValue(_callback), returnsValue(true), notifyWhenComplete(_notifyWhenComplete), callbackId(_callbackId),
-			asyncOp(cm_new<AsyncOp>())
+			:callbackWithReturnValue(_callback), returnsValue(true), notifyWhenComplete(_notifyWhenComplete), callbackId(_callbackId), asyncOp(cm_new<AsyncOp>()), ownsData(true)
 		{ }
 		{ }
 
 
 		QueuedCommand(boost::function<void()> _callback, bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
 		QueuedCommand(boost::function<void()> _callback, bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
-			:callback(_callback), returnsValue(false), notifyWhenComplete(_notifyWhenComplete), callbackId(_callbackId), asyncOp(nullptr)
+			:callback(_callback), returnsValue(false), notifyWhenComplete(_notifyWhenComplete), callbackId(_callbackId), asyncOp(nullptr), ownsData(true)
 		{ }
 		{ }
 #endif
 #endif
 
 
 		~QueuedCommand()
 		~QueuedCommand()
 		{
 		{
-			if(asyncOp != nullptr)
+			if(ownsData && asyncOp != nullptr)
 				cm_delete(asyncOp);
 				cm_delete(asyncOp);
 		}
 		}
 
 
+		QueuedCommand(const QueuedCommand& source)
+		{
+			ownsData = true;
+			source.ownsData = false;
+
+			callback = source.callback;
+			callbackWithReturnValue = source.callbackWithReturnValue;
+			asyncOp = source.asyncOp;
+			returnsValue = source.returnsValue;
+			callbackId = source.callbackId;
+			notifyWhenComplete = source.notifyWhenComplete;
+		}
+
+		QueuedCommand& operator=(const QueuedCommand& rhs)
+		{
+			ownsData = true;
+			rhs.ownsData = false;
+
+			callback = rhs.callback;
+			callbackWithReturnValue = rhs.callbackWithReturnValue;
+			asyncOp = rhs.asyncOp;
+			returnsValue = rhs.returnsValue;
+			callbackId = rhs.callbackId;
+			notifyWhenComplete = rhs.notifyWhenComplete;
+			
+			return *this;
+		}
+
 		boost::function<void()> callback;
 		boost::function<void()> callback;
 		boost::function<void(AsyncOp&)> callbackWithReturnValue;
 		boost::function<void(AsyncOp&)> callbackWithReturnValue;
 		AsyncOp* asyncOp;
 		AsyncOp* asyncOp;
 		bool returnsValue;
 		bool returnsValue;
 		UINT32 callbackId;
 		UINT32 callbackId;
 		bool notifyWhenComplete;
 		bool notifyWhenComplete;
+
+		mutable bool ownsData;
 	};
 	};
 
 
 	/**
 	/**

+ 136 - 0
CamelotCore/Include/CmGpuParam.h

@@ -0,0 +1,136 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+#include "CmDebug.h"
+#include "CmException.h"
+#include "CmMatrix3.h"
+#include "CmMatrix4.h"
+
+namespace CamelotFramework
+{
+	/**
+	 * @brief	A handle that allows you to set a GpuProgram parameter.
+	 * 			
+	 * @note	This is primarily used an as optimization is performance critical bits of code
+	 * 			where it is important to locate and set parameters quickly without any lookups.
+	 * 			You just retrieve the handle once and then set the parameter value many times 
+	 * 			with minimal performance impact.
+	 */
+	template<class T>
+	class CM_EXPORT GpuDataParamBase
+	{
+	private:
+		friend class GpuParams;
+
+		struct GpuDataParamData
+		{
+			GpuDataParamData(GpuParamDataDesc* paramDesc, GpuParamBlock** paramBlocks, bool transpose)
+				:paramDesc(paramDesc), paramBlocks(paramBlocks), transpose(transpose)
+			{ }
+
+			~GpuDataParamData()
+			{ }
+
+			GpuParamDataDesc* paramDesc;
+			GpuParamBlock** paramBlocks;
+			bool transpose;
+		};
+
+		template<class Type>
+		struct TransposePolicy
+		{
+			static Type transpose(const Type& value) { return value; }
+			static bool transposeEnabled(bool enabled) { return false; }
+		};
+
+		template<>
+		struct TransposePolicy<Matrix3>
+		{
+			static Matrix3 transpose(const Matrix3& value) { return value.transpose(); }
+			static bool transposeEnabled(bool enabled) { return enabled; }
+		};
+
+		template<>
+		struct TransposePolicy<Matrix4>
+		{
+			static Matrix4 transpose(const Matrix4& value) { return value.transpose(); }
+			static bool transposeEnabled(bool enabled) { return enabled; }
+		};
+
+	public:
+		GpuDataParamBase()
+		{ }
+
+		void set(const T& value, UINT32 arrayIdx = 0)
+		{
+			GpuParamDataDesc* paramDesc = mData->paramDesc;
+
+#if CM_DEBUG_MODE
+			if(arrayIdx >= paramDesc->arraySize)
+			{
+				CM_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " + 
+					toString(paramDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
+			}
+#endif
+
+			UINT32 sizeBytes = sizeof(T);
+			GpuParamBlock* paramBlock = mData->paramBlocks[paramDesc->paramBlockSlot];
+
+			if(TransposePolicy<T>::transposeEnabled(mData->transpose))
+			{
+				T transposed = TransposePolicy<T>::transpose(value);
+				paramBlock->write((paramDesc->cpuMemOffset + arrayIdx * paramDesc->arrayElementStride) * sizeof(UINT32), &transposed, sizeBytes);
+			}
+			else
+				paramBlock->write((paramDesc->cpuMemOffset + arrayIdx * paramDesc->arrayElementStride) * sizeof(UINT32), &value, sizeBytes);
+
+			// Set unused bytes to 0
+			UINT32 elementSizeBytes = paramDesc->elementSize * sizeof(UINT32);
+			if(sizeBytes < elementSizeBytes)
+			{
+				UINT32 diffSize = elementSizeBytes - sizeBytes;
+				paramBlock->zeroOut((paramDesc->cpuMemOffset + arrayIdx * paramDesc->arrayElementStride)  * sizeof(UINT32) + sizeBytes, diffSize);
+			}
+		}
+
+		T get(UINT32 arrayIdx = 0)
+		{
+			GpuParamDataDesc* paramDesc = mData->paramDesc;
+
+#if CM_DEBUG_MODE
+			if(arrayIdx >= paramDesc->arraySize)
+			{
+				CM_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " + 
+					toString(paramDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
+			}
+#endif
+
+			UINT32 sizeBytes = sizeof(T);
+			GpuParamBlock* paramBlock = mData->paramBlocks[paramDesc->paramBlockSlot];
+
+			T value;
+			paramBlock->read((paramDesc->cpuMemOffset + arrayIdx * paramDesc->arrayElementStride) * sizeof(UINT32), &value, sizeBytes);
+
+			if(TransposePolicy<T>::transposeEnabled(mData->transpose))
+				return TransposePolicy<T>::transpose(value);
+			else
+				return value;
+		}
+
+	private:
+		GpuDataParamBase(GpuParamDataDesc* paramDesc, GpuParamBlock** paramBlock, bool transpose)
+		{
+			mData = cm_shared_ptr<GpuDataParamData>(paramDesc, paramBlock, transpose);
+		}
+
+	private:
+		std::shared_ptr<GpuDataParamData> mData;
+	};
+
+	typedef GpuDataParamBase<float> GpuParamFloat;
+	typedef GpuDataParamBase<Vector2> GpuParamVec2;
+	typedef GpuDataParamBase<Vector3> GpuParamVec3;
+	typedef GpuDataParamBase<Vector4> GpuParamVec4;
+	typedef GpuDataParamBase<Matrix3> GpuParamMat3;
+	typedef GpuDataParamBase<Matrix4> GpuParamMat4;
+}

+ 1 - 0
CamelotCore/Include/CmGpuParamBlock.h

@@ -15,6 +15,7 @@ namespace CamelotFramework
 		virtual ~GpuParamBlock();
 		virtual ~GpuParamBlock();
 
 
 		void write(UINT32 offset, const void* data, UINT32 size);
 		void write(UINT32 offset, const void* data, UINT32 size);
+		void read(UINT32 offset, void* data, UINT32 size);
 		void zeroOut(UINT32 offset, UINT32 size);
 		void zeroOut(UINT32 offset, UINT32 size);
 
 
 		UINT32 getSize() const { return mSize; }
 		UINT32 getSize() const { return mSize; }

+ 79 - 12
CamelotCore/Include/CmGpuParams.h

@@ -1,6 +1,7 @@
 #pragma once
 #pragma once
 
 
 #include "CmPrerequisites.h"
 #include "CmPrerequisites.h"
+#include "CmGpuParam.h"
 #include "CmBindableGpuParams.h"
 #include "CmBindableGpuParams.h"
 
 
 namespace CamelotFramework
 namespace CamelotFramework
@@ -8,7 +9,7 @@ namespace CamelotFramework
 	class CM_EXPORT GpuParams
 	class CM_EXPORT GpuParams
 	{
 	{
 	public:
 	public:
-		GpuParams(GpuParamDesc& paramDesc);
+		GpuParams(GpuParamDesc& paramDesc, bool transposeMatrices);
 		~GpuParams();
 		~GpuParams();
 
 
 		void setParamBlockBuffer(UINT32 slot, GpuParamBlockBufferPtr paramBlockBuffer);
 		void setParamBlockBuffer(UINT32 slot, GpuParamBlockBufferPtr paramBlockBuffer);
@@ -22,15 +23,76 @@ namespace CamelotFramework
 		bool hasSamplerState(const String& name) const;
 		bool hasSamplerState(const String& name) const;
 		bool hasParamBlock(const String& name) const;
 		bool hasParamBlock(const String& name) const;
 
 
-		void setParam(const String& name, float value, UINT32 arrayIndex = 0);
-		void setParam(const String& name, int value, UINT32 arrayIndex = 0);
-		void setParam(const String& name, bool value, UINT32 arrayIndex = 0);
-		void setParam(const String& name, const Vector4& vec, UINT32 arrayIndex = 0);
-		void setParam(const String& name, const Vector3& vec, UINT32 arrayIndex = 0);
-		void setParam(const String& name, const Vector2& vec, UINT32 arrayIndex = 0);
-		void setParam(const String& name, const Matrix4& mat, UINT32 arrayIndex = 0);
-		void setParam(const String& name, const Matrix3& mat, UINT32 arrayIndex = 0);
-		void setParam(const String& name, const Color& color, UINT32 arrayIndex = 0);
+		template<class T> void getParam(const String& name, GpuDataParamBase<T>& output) const
+		{
+			CM_EXCEPT(InvalidParametersException, "Unsupported parameter type");
+		}
+
+		template<>
+		void getParam<float>(const String& name, GpuDataParamBase<float>& output) const
+		{
+			auto iterFind = mFloatParams.find(name);
+
+			if(iterFind == mFloatParams.end())
+				CM_EXCEPT(InvalidParametersException, "Cannot find float parameter with the name '" + name + "'");
+
+			output = iterFind->second;
+		}
+
+		template<>
+		void getParam<Vector2>(const String& name, GpuDataParamBase<Vector2>& output) const
+		{
+			auto iterFind = mVec2Params.find(name);
+
+			if(iterFind == mVec2Params.end())
+				CM_EXCEPT(InvalidParametersException, "Cannot find vector(2) parameter with the name '" + name + "'");
+
+			output = iterFind->second;
+		}
+
+		template<>
+		void getParam<Vector3>(const String& name, GpuDataParamBase<Vector3>& output) const
+		{
+			auto iterFind = mVec3Params.find(name);
+
+			if(iterFind == mVec3Params.end())
+				CM_EXCEPT(InvalidParametersException, "Cannot find vector(3) parameter with the name '" + name + "'");
+
+			output = iterFind->second;
+		}
+
+		template<>
+		void getParam<Vector4>(const String& name, GpuDataParamBase<Vector4>& output) const
+		{
+			auto iterFind = mVec4Params.find(name);
+
+			if(iterFind == mVec4Params.end())
+				CM_EXCEPT(InvalidParametersException, "Cannot find vector(4) parameter with the name '" + name + "'");
+
+			output = iterFind->second;
+		}
+
+		template<>
+		void getParam<Matrix3>(const String& name, GpuDataParamBase<Matrix3>& output) const
+		{
+			auto iterFind = mMat3Params.find(name);
+
+			if(iterFind == mMat3Params.end())
+				CM_EXCEPT(InvalidParametersException, "Cannot find matrix(3x3) parameter with the name '" + name + "'");
+
+			output = iterFind->second;
+		}
+
+		template<>
+		void getParam<Matrix4>(const String& name, GpuDataParamBase<Matrix4>& output) const
+		{
+			auto iterFind = mMat4Params.find(name);
+
+			if(iterFind == mMat4Params.end())
+				CM_EXCEPT(InvalidParametersException, "Cannot find matrix(4x4) parameter with the name '" + name + "'");
+
+			output = iterFind->second;
+		}
 
 
 		/**
 		/**
 		 * @brief	Sets a parameter.
 		 * @brief	Sets a parameter.
@@ -45,8 +107,6 @@ namespace CamelotFramework
 
 
 		void setTexture(const String& name, const HTexture& val);
 		void setTexture(const String& name, const HTexture& val);
 		void setSamplerState(const String& name, const HSamplerState& val);
 		void setSamplerState(const String& name, const HSamplerState& val);
-		
-		void setTransposeMatrices(bool transpose) { mTransposeMatrices = transpose; }
 
 
 		/**
 		/**
 		 * @brief	Creates the copy of this object in a special way. Should only be called
 		 * @brief	Creates the copy of this object in a special way. Should only be called
@@ -70,5 +130,12 @@ namespace CamelotFramework
 		GpuParamBlockBufferPtr* mParamBlockBuffers;
 		GpuParamBlockBufferPtr* mParamBlockBuffers;
 		HTexture* mTextures;
 		HTexture* mTextures;
 		HSamplerState* mSamplerStates;
 		HSamplerState* mSamplerStates;
+
+		mutable Map<String, GpuParamFloat>::type mFloatParams;
+		mutable Map<String, GpuParamVec2>::type mVec2Params;
+		mutable Map<String, GpuParamVec3>::type mVec3Params;
+		mutable Map<String, GpuParamVec4>::type mVec4Params;
+		mutable Map<String, GpuParamMat3>::type mMat3Params;
+		mutable Map<String, GpuParamMat4>::type mMat4Params;
 	};
 	};
 }
 }

+ 44 - 25
CamelotCore/Include/CmMaterial.h

@@ -2,6 +2,7 @@
 
 
 #include "CmPrerequisites.h"
 #include "CmPrerequisites.h"
 #include "CmResource.h"
 #include "CmResource.h"
+#include "CmGpuParam.h"
 #include "CmVector2.h"
 #include "CmVector2.h"
 #include "CmVector3.h"
 #include "CmVector3.h"
 #include "CmVector4.h"
 #include "CmVector4.h"
@@ -90,6 +91,7 @@ namespace CamelotFramework
 		Matrix3 getMat3(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;
 		Matrix4 getMat4(const String& name, UINT32 arrayIdx = 0) const;
 		const StructData& getStructData(const String& name, UINT32 arrayIdx = 0) const;
 		const StructData& getStructData(const String& name, UINT32 arrayIdx = 0) const;
+
 		INT16 getRenderQueue() const { return mRenderQueue; }
 		INT16 getRenderQueue() const { return mRenderQueue; }
 
 
 		UINT32 getNumPasses() const;
 		UINT32 getNumPasses() const;
@@ -100,6 +102,48 @@ namespace CamelotFramework
 
 
 		static HMaterial create();
 		static HMaterial create();
 		static HMaterial create(ShaderPtr shader);
 		static HMaterial create(ShaderPtr shader);
+	public:
+		/**
+		 * @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
+		 * 			without all the cost of extra lookups otherwise required.
+		 * 			
+		 * @note	All of these handles will be invalidated if material shader ever changes. It is up to the
+		 * 			caller to keep track of that.
+		 */
+		template <typename T>
+		void getParam(const String& name, GpuDataParamBase<T>& output) const
+		{
+			auto iterFind = mValidParams.find(name);
+			if(iterFind == mValidParams.end())
+			{
+				LOGWRN("Material doesn't have a parameter named " + name);
+				return;
+			}
+
+			const 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->getParam<T>(gpuVarName, output);
+							return;
+						}
+					}
+				}
+			}
+
+			CM_EXCEPT(InternalErrorException, "Shader has no parameter with the name: " + gpuVarName);
+		}
+
 	protected:
 	protected:
 		void destroy_internal();
 		void destroy_internal();
 
 
@@ -118,12 +162,6 @@ namespace CamelotFramework
 
 
 		// These maps aren't necessary as we can read these values from the GpuParams directly
 		// 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
 		// but they make many things (especially serializing and getting values) so much easier
-		Map<String, Vector<float>::type>::type mFloatValues;
-		Map<String, Vector<Vector2>::type>::type mVec2Values;
-		Map<String, Vector<Vector3>::type>::type mVec3Values;
-		Map<String, Vector<Vector4>::type>::type mVec4Values;
-		Map<String, Vector<Matrix3>::type>::type mMat3Values;
-		Map<String, Vector<Matrix4>::type>::type mMat4Values;
 		Map<String, Vector<StructData>::type>::type mStructValues;
 		Map<String, Vector<StructData>::type>::type mStructValues;
 		Map<String, HTexture>::type mTextureValues;
 		Map<String, HTexture>::type mTextureValues;
 		Map<String, HSamplerState>::type mSamplerValues;
 		Map<String, HSamplerState>::type mSamplerValues;
@@ -132,25 +170,6 @@ namespace CamelotFramework
 
 
 		void throwIfNotInitialized() const;
 		void throwIfNotInitialized() const;
 
 
-		template <typename T>
-		void setParam(const String& name, T& value, UINT32 arrayIdx)
-		{
-			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))
-							paramPtr->setParam(name, value, arrayIdx);
-					}
-				}
-			}
-		}
-
 		const Map<String, String>::type& getValidParamNames() const { return mValidParams; }
 		const Map<String, String>::type& getValidParamNames() const { return mValidParams; }
 
 
 		void initBestTechnique();
 		void initBestTechnique();

+ 1 - 0
CamelotCore/Source/CmGpuParam.cpp

@@ -0,0 +1 @@
+#include "CmGpuParam.h"

+ 14 - 0
CamelotCore/Source/CmGpuParamBlock.cpp

@@ -43,6 +43,20 @@ namespace CamelotFramework
 		mDirty = true;
 		mDirty = true;
 	}
 	}
 
 
+	void GpuParamBlock::read(UINT32 offset, void* data, UINT32 size)
+	{
+#if CM_DEBUG_MODE
+		if(offset < 0 || (offset + size) > mSize)
+		{
+			CM_EXCEPT(InvalidParametersException, "Wanted range is out of buffer bounds. " \
+				"Available range: 0 .. " + toString(mSize) + ". " \
+				"Wanted range: " + toString(offset) + " .. " + toString(offset + size) + ".");
+		}
+#endif
+
+		memcpy(data, mData + offset, size);
+	}
+
 	void GpuParamBlock::zeroOut(UINT32 offset, UINT32 size)
 	void GpuParamBlock::zeroOut(UINT32 offset, UINT32 size)
 	{
 	{
 #if CM_DEBUG_MODE
 #if CM_DEBUG_MODE

+ 37 - 72
CamelotCore/Source/CmGpuParams.cpp

@@ -9,26 +9,26 @@
 
 
 namespace CamelotFramework
 namespace CamelotFramework
 {
 {
-	GpuParams::GpuParams(GpuParamDesc& paramDesc)
-		:mParamDesc(paramDesc), mTransposeMatrices(false), mData(nullptr), mNumParamBlocks(0), mNumTextures(0), mNumSamplerStates(0),
+	GpuParams::GpuParams(GpuParamDesc& paramDesc, bool transposeMatrices)
+		:mParamDesc(paramDesc), mTransposeMatrices(transposeMatrices), mData(nullptr), mNumParamBlocks(0), mNumTextures(0), mNumSamplerStates(0),
 		mParamBlocks(nullptr), mParamBlockBuffers(nullptr), mTextures(nullptr), mSamplerStates(nullptr)
 		mParamBlocks(nullptr), mParamBlockBuffers(nullptr), mTextures(nullptr), mSamplerStates(nullptr)
 	{
 	{
-		for(auto iter = mParamDesc.paramBlocks.begin(); iter != mParamDesc.paramBlocks.end(); ++iter)
+		for(auto& paramBlock : mParamDesc.paramBlocks)
 		{
 		{
-			if((iter->second.slot + 1) > mNumParamBlocks)
-				mNumParamBlocks = iter->second.slot + 1;
+			if((paramBlock.second.slot + 1) > mNumParamBlocks)
+				mNumParamBlocks = paramBlock.second.slot + 1;
 		}
 		}
 
 
-		for(auto iter = mParamDesc.textures.begin(); iter != mParamDesc.textures.end(); ++iter)
+		for(auto& texture : mParamDesc.textures)
 		{
 		{
-			if((iter->second.slot + 1) > mNumTextures)
-				mNumTextures = iter->second.slot + 1;
+			if((texture.second.slot + 1) > mNumTextures)
+				mNumTextures = texture.second.slot + 1;
 		}
 		}
 
 
-		for(auto iter = mParamDesc.samplers.begin(); iter != mParamDesc.samplers.end(); ++iter)
+		for(auto& samplers : mParamDesc.samplers)
 		{
 		{
-			if((iter->second.slot + 1) > mNumSamplerStates)
-				mNumSamplerStates = iter->second.slot + 1;
+			if((samplers.second.slot + 1) > mNumSamplerStates)
+				mNumSamplerStates = samplers.second.slot + 1;
 		}
 		}
 
 
 		// Allocate everything in a single block of memory to get rid of extra memory allocations
 		// Allocate everything in a single block of memory to get rid of extra memory allocations
@@ -73,6 +73,32 @@ namespace CamelotFramework
 			HSamplerState* ptrToIdx = (&mSamplerStates[i]);
 			HSamplerState* ptrToIdx = (&mSamplerStates[i]);
 			ptrToIdx = new (&mSamplerStates[i]) HSamplerState();
 			ptrToIdx = new (&mSamplerStates[i]) HSamplerState();
 		}
 		}
+
+		// Create parameter handles
+		for(auto& param : mParamDesc.params)
+		{
+			switch(param.second.type)
+			{
+			case GPDT_FLOAT1:
+				mFloatParams[param.second.name] = GpuParamFloat(&param.second, mParamBlocks, mTransposeMatrices);
+				break;
+			case GPDT_FLOAT2:
+				mVec2Params[param.second.name] = GpuParamVec2(&param.second, mParamBlocks, mTransposeMatrices);
+				break;
+			case GPDT_FLOAT3:
+				mVec3Params[param.second.name] = GpuParamVec3(&param.second, mParamBlocks, mTransposeMatrices);
+				break;
+			case GPDT_FLOAT4:
+				mVec4Params[param.second.name] = GpuParamVec4(&param.second, mParamBlocks, mTransposeMatrices);
+				break;
+			case GPDT_MATRIX_3X3:
+				mMat3Params[param.second.name] = GpuParamMat3(&param.second, mParamBlocks, mTransposeMatrices);
+				break;
+			case GPDT_MATRIX_4X4:
+				mMat4Params[param.second.name] = GpuParamMat4(&param.second, mParamBlocks, mTransposeMatrices);
+				break;
+			}
+		}
 	}
 	}
 
 
 	GpuParams::~GpuParams()
 	GpuParams::~GpuParams()
@@ -168,67 +194,6 @@ namespace CamelotFramework
 		return false;
 		return false;
 	}
 	}
 
 
-	void GpuParams::setParam(const String& name, float value, UINT32 arrayIndex)
-	{
-		setParam(name, (void*)&value, 1 * sizeof(float), arrayIndex);
-	}
-
-	void GpuParams::setParam(const String& name, int value, UINT32 arrayIndex)
-	{
-		setParam(name, (void*)&value, 1 * sizeof(int), arrayIndex);
-	}
-
-	void GpuParams::setParam(const String& name, bool value, UINT32 arrayIndex)
-	{
-		setParam(name, (void*)&value, 1 * sizeof(bool), arrayIndex);
-	}
-
-	void GpuParams::setParam(const String& name, const Vector4& vec, UINT32 arrayIndex)
-	{
-		setParam(name, (void*)&vec, 4 * sizeof(float), arrayIndex);
-	}
-
-	void GpuParams::setParam(const String& name, const Vector3& vec, UINT32 arrayIndex)
-	{
-		setParam(name, (void*)&vec, 3 * sizeof(float), arrayIndex);
-	}
-
-	void GpuParams::setParam(const String& name, const Vector2& vec, UINT32 arrayIndex)
-	{
-		setParam(name, (void*)&vec, 2 * sizeof(float), arrayIndex);
-	}
-
-	void GpuParams::setParam(const String& name, const Matrix4& mat, UINT32 arrayIndex)
-	{
-		if (mTransposeMatrices)
-		{
-			Matrix4 transMat = mat.transpose();
-			setParam(name, (void*)&transMat, 16 * sizeof(float), arrayIndex);
-		}
-		else
-		{
-			setParam(name, (void*)&mat, 16 * sizeof(float), arrayIndex);
-		}
-	}
-
-	void GpuParams::setParam(const String& name, const Matrix3& mat, UINT32 arrayIndex)
-	{
-		if (mTransposeMatrices)
-		{
-			Matrix3 transMat = mat.transpose();
-			setParam(name, (void*)&transMat, 9 * sizeof(float), arrayIndex);
-		}
-		else
-		{
-			setParam(name, (void*)&mat, 9 * sizeof(float), arrayIndex);
-		}
-	}
-
-	void GpuParams::setParam(const String& name, const Color& color, UINT32 arrayIndex)
-	{
-		setParam(name, (void*)&color, 4 * sizeof(float), arrayIndex);
-	}
-
 	void GpuParams::setParam(const String& name, const void* value, UINT32 sizeBytes, UINT32 arrayIndex)
 	void GpuParams::setParam(const String& name, const void* value, UINT32 sizeBytes, UINT32 arrayIndex)
 	{
 	{
 		GpuParamDataDesc* desc = getParamDesc(name);
 		GpuParamDataDesc* desc = getParamDesc(name);

+ 1 - 1
CamelotCore/Source/CmGpuProgram.cpp

@@ -86,7 +86,7 @@ namespace CamelotFramework
 	//---------------------------------------------------------------------
 	//---------------------------------------------------------------------
 	GpuParamsPtr GpuProgram::createParameters(void)
 	GpuParamsPtr GpuProgram::createParameters(void)
 	{
 	{
-		return cm_shared_ptr<GpuParams, PoolAlloc>(std::ref(mParametersDesc));
+		return cm_shared_ptr<GpuParams, PoolAlloc>(std::ref(mParametersDesc), false);
 	}
 	}
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     const String& GpuProgram::getLanguage(void) const
     const String& GpuProgram::getLanguage(void) const

+ 40 - 134
CamelotCore/Source/CmMaterial.cpp

@@ -37,12 +37,6 @@ namespace CamelotFramework
 	{
 	{
 		mBestTechnique = nullptr;
 		mBestTechnique = nullptr;
 		mParametersPerPass.clear();
 		mParametersPerPass.clear();
-		mFloatValues.clear();
-		mVec2Values.clear();
-		mVec3Values.clear();
-		mVec4Values.clear();
-		mMat3Values.clear();
-		mMat4Values.clear();
 		mStructValues.clear();
 		mStructValues.clear();
 		mTextureValues.clear();
 		mTextureValues.clear();
 		mSamplerValues.clear();
 		mSamplerValues.clear();
@@ -187,29 +181,9 @@ namespace CamelotFramework
 
 
 				switch(iter->second.type)
 				switch(iter->second.type)
 				{
 				{
-				case GPDT_FLOAT1:
-					mFloatValues[iter->first].resize(iter->second.arraySize);
-					break;
-				case GPDT_FLOAT2:
-					mVec2Values[iter->first].resize(iter->second.arraySize);
-					break;
-				case GPDT_FLOAT3:
-					mVec3Values[iter->first].resize(iter->second.arraySize);
-					break;
-				case GPDT_FLOAT4:
-					mVec4Values[iter->first].resize(iter->second.arraySize);
-					break;
-				case GPDT_MATRIX_3X3:
-					mMat3Values[iter->first].resize(iter->second.arraySize);
-					break;
-				case GPDT_MATRIX_4X4:
-					mMat4Values[iter->first].resize(iter->second.arraySize);
-					break;
 				case GPDT_STRUCT:
 				case GPDT_STRUCT:
 					mStructValues[iter->first].resize(iter->second.arraySize);
 					mStructValues[iter->first].resize(iter->second.arraySize);
 					break;
 					break;
-				default:
-					CM_EXCEPT(InternalErrorException, "Unsupported data type.");
 				}
 				}
 			}
 			}
 
 
@@ -581,126 +555,70 @@ namespace CamelotFramework
 	{
 	{
 		throwIfNotInitialized();
 		throwIfNotInitialized();
 
 
-		auto iterFind = mValidParams.find(name);
-		if(iterFind == mValidParams.end())
-		{
-			LOGWRN("Material doesn't have a parameter named " + name);
-			return;
-		}
+		GpuDataParamBase<float> gpuParam;
+		getParam(name, gpuParam);
 
 
-		String& gpuVarName = iterFind->second;
-		setParam(gpuVarName, value, arrayIdx);
-
-		auto& savedValue = mFloatValues[name];
-		savedValue[arrayIdx] = value;
+		gpuParam.set(value, arrayIdx);
 	}
 	}
 
 
 	void Material::setColor(const String& name, const Color& value, UINT32 arrayIdx)
 	void Material::setColor(const String& name, const Color& value, UINT32 arrayIdx)
 	{
 	{
 		throwIfNotInitialized();
 		throwIfNotInitialized();
 
 
-		auto iterFind = mValidParams.find(name);
-		if(iterFind == mValidParams.end())
-		{
-			LOGWRN("Material doesn't have a parameter named " + name);
-			return;
-		}
-
-		String& gpuVarName = iterFind->second;
-		setParam(gpuVarName, value, arrayIdx);
+		GpuDataParamBase<Vector4> gpuParam;
+		getParam(name, gpuParam);
 
 
-		auto& savedValue = mVec4Values[name];
-		savedValue[arrayIdx] = Vector4(value.r, value.g, value.b, value.a);
+		gpuParam.set(Vector4(value.r, value.g, value.b, value.a), arrayIdx);
 	}
 	}
 
 
 	void Material::setVec2(const String& name, const Vector2& value, UINT32 arrayIdx)
 	void Material::setVec2(const String& name, const Vector2& value, UINT32 arrayIdx)
 	{
 	{
 		throwIfNotInitialized();
 		throwIfNotInitialized();
 
 
-		auto iterFind = mValidParams.find(name);
-		if(iterFind == mValidParams.end())
-		{
-			LOGWRN("Material doesn't have a parameter named " + name);
-			return;
-		}
-
-		String& gpuVarName = iterFind->second;
-		setParam(gpuVarName, value, arrayIdx);
+		GpuDataParamBase<Vector2> gpuParam;
+		getParam(name, gpuParam);
 
 
-		auto& savedValue = mVec2Values[name];
-		savedValue[arrayIdx] = value;
+		gpuParam.set(value, arrayIdx);
 	}
 	}
 
 
 	void Material::setVec3(const String& name, const Vector3& value, UINT32 arrayIdx)
 	void Material::setVec3(const String& name, const Vector3& value, UINT32 arrayIdx)
 	{
 	{
 		throwIfNotInitialized();
 		throwIfNotInitialized();
 
 
-		auto iterFind = mValidParams.find(name);
-		if(iterFind == mValidParams.end())
-		{
-			LOGWRN("Material doesn't have a parameter named " + name);
-			return;
-		}
-
-		String& gpuVarName = iterFind->second;
-		setParam(gpuVarName, value, arrayIdx);
+		GpuDataParamBase<Vector3> gpuParam;
+		getParam(name, gpuParam);
 
 
-		auto& savedValue = mVec3Values[name];
-		savedValue[arrayIdx] = value;
+		gpuParam.set(value, arrayIdx);
 	}
 	}
 
 
 	void Material::setVec4(const String& name, const Vector4& value, UINT32 arrayIdx)
 	void Material::setVec4(const String& name, const Vector4& value, UINT32 arrayIdx)
 	{
 	{
 		throwIfNotInitialized();
 		throwIfNotInitialized();
 
 
-		auto iterFind = mValidParams.find(name);
-		if(iterFind == mValidParams.end())
-		{
-			LOGWRN("Material doesn't have a parameter named " + name);
-			return;
-		}
-
-		String& gpuVarName = iterFind->second;
-		setParam(gpuVarName, value, arrayIdx);
+		GpuDataParamBase<Vector4> gpuParam;
+		getParam(name, gpuParam);
 
 
-		auto& savedValue = mVec4Values[name];
-		savedValue[arrayIdx] = value;
+		gpuParam.set(value, arrayIdx);
 	}
 	}
 
 
 	void Material::setMat3(const String& name, const Matrix3& value, UINT32 arrayIdx)
 	void Material::setMat3(const String& name, const Matrix3& value, UINT32 arrayIdx)
 	{
 	{
 		throwIfNotInitialized();
 		throwIfNotInitialized();
 
 
-		auto iterFind = mValidParams.find(name);
-		if(iterFind == mValidParams.end())
-		{
-			LOGWRN("Material doesn't have a parameter named " + name);
-			return;
-		}
+		GpuDataParamBase<Matrix3> gpuParam;
+		getParam(name, gpuParam);
 
 
-		String& gpuVarName = iterFind->second;
-		setParam(gpuVarName, value, arrayIdx);
-
-		auto& savedValue = mMat3Values[name];
-		savedValue[arrayIdx] = value;
+		gpuParam.set(value, arrayIdx);
 	}
 	}
 
 
 	void Material::setMat4(const String& name, const Matrix4& value, UINT32 arrayIdx)
 	void Material::setMat4(const String& name, const Matrix4& value, UINT32 arrayIdx)
 	{
 	{
 		throwIfNotInitialized();
 		throwIfNotInitialized();
 
 
-		auto iterFind = mValidParams.find(name);
-		if(iterFind == mValidParams.end())
-		{
-			LOGWRN("Material doesn't have a parameter named " + name);
-			return;
-		}
+		GpuDataParamBase<Matrix4> gpuParam;
+		getParam(name, gpuParam);
 
 
-		String& gpuVarName = iterFind->second;
-		setParam(gpuVarName, value, arrayIdx);
-
-		auto& savedValue = mMat4Values[name];
-		savedValue[arrayIdx] = value;
+		gpuParam.set(value, arrayIdx);
 	}
 	}
 
 
 	void Material::setStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx)
 	void Material::setStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx)
@@ -813,62 +731,50 @@ namespace CamelotFramework
 
 
 	float Material::getFloat(const String& name, UINT32 arrayIdx) const
 	float Material::getFloat(const String& name, UINT32 arrayIdx) const
 	{
 	{
-		auto iterFind = mFloatValues.find(name);
-
-		if(iterFind == mFloatValues.end())
-			CM_EXCEPT(InternalErrorException, "No float parameter with the name: " + name);
+		GpuDataParamBase<float> gpuParam;
+		getParam(name, gpuParam);
 
 
-		return iterFind->second.at(arrayIdx);
+		return gpuParam.get(arrayIdx);
 	}
 	}
 
 
 	Vector2 Material::getVec2(const String& name, UINT32 arrayIdx) const
 	Vector2 Material::getVec2(const String& name, UINT32 arrayIdx) const
 	{
 	{
-		auto iterFind = mVec2Values.find(name);
-
-		if(iterFind == mVec2Values.end())
-			CM_EXCEPT(InternalErrorException, "No float parameter with the name: " + name);
+		GpuDataParamBase<Vector2> gpuParam;
+		getParam(name, gpuParam);
 
 
-		return iterFind->second.at(arrayIdx);
+		return gpuParam.get(arrayIdx);
 	}
 	}
 
 
 	Vector3 Material::getVec3(const String& name, UINT32 arrayIdx) const
 	Vector3 Material::getVec3(const String& name, UINT32 arrayIdx) const
 	{
 	{
-		auto iterFind = mVec3Values.find(name);
-
-		if(iterFind == mVec3Values.end())
-			CM_EXCEPT(InternalErrorException, "No float parameter with the name: " + name);
+		GpuDataParamBase<Vector3> gpuParam;
+		getParam(name, gpuParam);
 
 
-		return iterFind->second.at(arrayIdx);
+		return gpuParam.get(arrayIdx);
 	}
 	}
 
 
 	Vector4 Material::getVec4(const String& name, UINT32 arrayIdx) const
 	Vector4 Material::getVec4(const String& name, UINT32 arrayIdx) const
 	{
 	{
-		auto iterFind = mVec4Values.find(name);
+		GpuDataParamBase<Vector4> gpuParam;
+		getParam(name, gpuParam);
 
 
-		if(iterFind == mVec4Values.end())
-			CM_EXCEPT(InternalErrorException, "No float parameter with the name: " + name);
-
-		return iterFind->second.at(arrayIdx);
+		return gpuParam.get(arrayIdx);
 	}
 	}
 
 
 	Matrix3 Material::getMat3(const String& name, UINT32 arrayIdx) const
 	Matrix3 Material::getMat3(const String& name, UINT32 arrayIdx) const
 	{
 	{
-		auto iterFind = mMat3Values.find(name);
+		GpuDataParamBase<Matrix3> gpuParam;
+		getParam(name, gpuParam);
 
 
-		if(iterFind == mMat3Values.end())
-			CM_EXCEPT(InternalErrorException, "No float parameter with the name: " + name);
-
-		return iterFind->second.at(arrayIdx);
+		return gpuParam.get(arrayIdx);
 	}
 	}
 
 
 	Matrix4 Material::getMat4(const String& name, UINT32 arrayIdx) const
 	Matrix4 Material::getMat4(const String& name, UINT32 arrayIdx) const
 	{
 	{
-		auto iterFind = mMat4Values.find(name);
+		GpuDataParamBase<Matrix4> gpuParam;
+		getParam(name, gpuParam);
 
 
-		if(iterFind == mMat4Values.end())
-			CM_EXCEPT(InternalErrorException, "No float parameter with the name: " + name);
-
-		return iterFind->second.at(arrayIdx);
+		return gpuParam.get(arrayIdx);
 	}
 	}
 
 
 	const Material::StructData& Material::getStructData(const String& name, UINT32 arrayIdx) const
 	const Material::StructData& Material::getStructData(const String& name, UINT32 arrayIdx) const
@@ -876,7 +782,7 @@ namespace CamelotFramework
 		auto iterFind = mStructValues.find(name);
 		auto iterFind = mStructValues.find(name);
 
 
 		if(iterFind == mStructValues.end())
 		if(iterFind == mStructValues.end())
-			CM_EXCEPT(InternalErrorException, "No float parameter with the name: " + name);
+			CM_EXCEPT(InternalErrorException, "No struct parameter with the name: " + name);
 
 
 		return iterFind->second.at(arrayIdx);
 		return iterFind->second.at(arrayIdx);
 	}
 	}

+ 1 - 2
CamelotD3D11RenderSystem/Source/CmD3D11HLSLProgram.cpp

@@ -169,8 +169,7 @@ namespace CamelotFramework
 
 
 	GpuParamsPtr D3D11HLSLProgram::createParameters()
 	GpuParamsPtr D3D11HLSLProgram::createParameters()
 	{
 	{
-		GpuParamsPtr params = cm_shared_ptr<GpuParams, PoolAlloc>(std::ref(mParametersDesc));
-		params->setTransposeMatrices(mColumnMajorMatrices);
+		GpuParamsPtr params = cm_shared_ptr<GpuParams, PoolAlloc>(std::ref(mParametersDesc), mColumnMajorMatrices);
 
 
 		return params;
 		return params;
 	}
 	}

+ 1 - 2
CamelotD3D9Renderer/Source/CmD3D9GpuProgram.cpp

@@ -136,8 +136,7 @@ namespace CamelotFramework {
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
 	GpuParamsPtr D3D9GpuProgram::createParameters()
 	GpuParamsPtr D3D9GpuProgram::createParameters()
 	{
 	{
-		GpuParamsPtr params = cm_shared_ptr<GpuParams, PoolAlloc>(std::ref(mParametersDesc));
-		params->setTransposeMatrices(mColumnMajorMatrices);
+		GpuParamsPtr params = cm_shared_ptr<GpuParams, PoolAlloc>(std::ref(mParametersDesc), mColumnMajorMatrices);
 
 
 		return params;
 		return params;
 	}
 	}

+ 1 - 2
CamelotD3D9Renderer/Source/CmD3D9HLSLProgram.cpp

@@ -243,8 +243,7 @@ namespace CamelotFramework {
 	//-----------------------------------------------------------------------
 	//-----------------------------------------------------------------------
 	GpuParamsPtr D3D9HLSLProgram::createParameters()
 	GpuParamsPtr D3D9HLSLProgram::createParameters()
 	{
 	{
-		GpuParamsPtr params = cm_shared_ptr<GpuParams, PoolAlloc>(std::ref(mParametersDesc));
-		params->setTransposeMatrices(mColumnMajorMatrices);
+		GpuParamsPtr params = cm_shared_ptr<GpuParams, PoolAlloc>(std::ref(mParametersDesc), mColumnMajorMatrices);
 
 
 		return params;
 		return params;
 	}
 	}

+ 12 - 13
Opts.txt

@@ -1,11 +1,10 @@
 Make sure to also update TextSprite and ImageSprite and anything else in UpdateMesh, then don't forget to find the issue that causes elements to get marked as dirty every single frame
 Make sure to also update TextSprite and ImageSprite and anything else in UpdateMesh, then don't forget to find the issue that causes elements to get marked as dirty every single frame
 
 
-Render:
-Each queued command has an AsyncOp which gets constructed whether it is used or not
+GpuParamBlock should be tied directly with GpuParamBlockBuffer
+  - Modify material so it always sets just the first GpuParams with a specific name. This will avoid updating same buffer multiple times.
+When GpuParams are destroyed (when another shader is set in Material for example), make sure to set all GpuParam internal data to null
+Add material parameter handles for texture, sampler state, and structs
 
 
-Strings when setting material params cause an allocation
- - Consider using normal char arrays
- - Or ensure materials are set using some smarter way, e.g. you get material param reference by name, you save it and then use that for setting the value
 
 
 FrameAlloc
 FrameAlloc
    Keeps two internal stacks
    Keeps two internal stacks
@@ -16,20 +15,20 @@ FrameAlloc
     - frees the previously active stack
     - frees the previously active stack
    During frame we call alloc()
    During frame we call alloc()
   
   
-Make sure BindableGpuParams are not copyable
-
-Refactor stack allocator so I don't need to manually initialize heaps
- - Use atomic variable counter?
-
- There is a shit-ton of allocations in CPUProfiler (especially report generation)
-  - Maybe attempt to cut down on them?
+ There are many allocations in CPUProfiler (especially report generation), and they aren't counted anywhere since they use
+ a special allocator.
 
 
 --------------------
 --------------------
 
 
 HardwareBuffer::lock (more exactly ImmediateContext::Map) is very slow, with 35 calls taking up almost 3ms. 
 HardwareBuffer::lock (more exactly ImmediateContext::Map) is very slow, with 35 calls taking up almost 3ms. 
  - First, mesh creates both vertex and index buffer whenever writeSubresource is called!!! It should instead just update them.
  - First, mesh creates both vertex and index buffer whenever writeSubresource is called!!! It should instead just update them.
+   - Never shrink mesh buffers. Add shrinkInternalBuffers property to MeshData that will force the buffers to shrink.
  - Second, mesh buffers are created with default buffer flags (static). Try changing it to dynamic
  - Second, mesh buffers are created with default buffer flags (static). Try changing it to dynamic
+   - Allow user to specify mesh buffer type during mesh construction
 
 
 When optimizing UpdateLayout make sure to mark elements that are fully culled as Culled
 When optimizing UpdateLayout make sure to mark elements that are fully culled as Culled
  - But in order to determine that I first need to update the sprite to find out the elements bounds which defeats the point
  - But in order to determine that I first need to update the sprite to find out the elements bounds which defeats the point
- - TODO - FIgure this out
+ - TODO - FIgure this out
+
+ -------------
+