Browse Source

Added shader params
Fixed an issue with OpenGL failing when testing valid FBO textures

Marko Pintera 13 years ago
parent
commit
4ec92954ca
35 changed files with 1043 additions and 428 deletions
  1. 54 51
      CamelotClient/CamelotClient.cpp
  2. 3 3
      CamelotD3D11RenderSystem/Include/CmD3D11GpuParamBlock.h
  3. 2 2
      CamelotD3D11RenderSystem/Include/CmD3D11HardwareBufferManager.h
  4. 4 4
      CamelotD3D11RenderSystem/Source/CmD3D11GpuParamBlock.cpp
  5. 43 38
      CamelotD3D11RenderSystem/Source/CmD3D11HLSLParamParser.cpp
  6. 2 2
      CamelotD3D11RenderSystem/Source/CmD3D11HardwareBufferManager.cpp
  7. 1 1
      CamelotD3D11RenderSystem/Source/CmD3D11RenderSystem.cpp
  8. 32 31
      CamelotD3D9Renderer/Include/CmD3D9HLSLParamParser.h
  9. 2 2
      CamelotD3D9Renderer/Include/CmD3D9HardwareBufferManager.h
  10. 2 2
      CamelotD3D9Renderer/Source/CmD3D9HardwareBufferManager.cpp
  11. 40 40
      CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp
  12. 4 3
      CamelotGLRenderer/Include/CmGLGpuParamBlock.h
  13. 2 2
      CamelotGLRenderer/Include/CmGLHardwareBufferManager.h
  14. 5 0
      CamelotGLRenderer/Include/CmGLRenderSystem.h
  15. 4 4
      CamelotGLRenderer/Source/CmGLGpuParamBlock.cpp
  16. 2 2
      CamelotGLRenderer/Source/CmGLHardwareBufferManager.cpp
  17. 41 4
      CamelotGLRenderer/Source/CmGLRenderSystem.cpp
  18. 12 31
      CamelotGLRenderer/Source/CmGLRenderTexture.cpp
  19. 33 31
      CamelotGLRenderer/Source/GLSL/include/CmGLSLParamParser.h
  20. 6 6
      CamelotRenderer/CamelotRenderer.vcxproj.filters
  21. 55 0
      CamelotRenderer/Include/CmCommonEnums.h
  22. 6 5
      CamelotRenderer/Include/CmGpuParamBlock.h
  23. 10 56
      CamelotRenderer/Include/CmGpuParamDesc.h
  24. 7 6
      CamelotRenderer/Include/CmGpuParams.h
  25. 2 0
      CamelotRenderer/Include/CmGpuProgram.h
  26. 1 1
      CamelotRenderer/Include/CmHardwareBufferManager.h
  27. 16 3
      CamelotRenderer/Include/CmMaterial.h
  28. 4 3
      CamelotRenderer/Include/CmPrerequisites.h
  29. 37 0
      CamelotRenderer/Include/CmShader.h
  30. 10 10
      CamelotRenderer/Source/CmGpuParamBlock.cpp
  31. 20 13
      CamelotRenderer/Source/CmGpuParams.cpp
  32. 519 34
      CamelotRenderer/Source/CmMaterial.cpp
  33. 18 18
      CamelotRenderer/Source/CmMaterialRTTI.cpp
  34. 40 0
      CamelotRenderer/Source/CmShader.cpp
  35. 4 20
      CamelotRenderer/TODO.txt

+ 54 - 51
CamelotClient/CamelotClient.cpp

@@ -26,9 +26,9 @@ using namespace CamelotEngine;
 
 int _tmain(int argc, _TCHAR* argv[])
 {
-	//gApplication().startUp("CamelotGLRenderSystem", "CamelotForwardRenderer");
+	gApplication().startUp("CamelotGLRenderSystem", "CamelotForwardRenderer");
 	//gApplication().startUp("CamelotD3D9RenderSystem", "CamelotForwardRenderer");
-	gApplication().startUp("CamelotD3D11RenderSystem", "CamelotForwardRenderer");
+	//gApplication().startUp("CamelotD3D11RenderSystem", "CamelotForwardRenderer");
 
 	RenderSystem* renderSystem = RenderSystem::instancePtr();
 	RenderWindowPtr renderWindow = gApplication().getPrimaryRenderWindow();
@@ -74,28 +74,28 @@ int _tmain(int argc, _TCHAR* argv[])
 	//vertProg =  HighLevelGpuProgram::create(vertShaderCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
 
 	/////////////////// HLSL 11 SHADERS //////////////////////////
-	String fragShaderCode = "SamplerState samp : register(s0);			\
-							Texture2D tex : register(t0); \
-							float4 ps_main(in float4 inPos : SV_Position, float2 uv : TEXCOORD0) : SV_Target		\
-							{														\
-							float4 color = tex.Sample(samp, uv);				\
-							return color;										\
-							}";
-
-	fragProg =  HighLevelGpuProgram::create(fragShaderCode, "ps_main", "hlsl", GPT_FRAGMENT_PROGRAM, GPP_PS_4_0);
-
-	String vertShaderCode = "float4x4 matViewProjection;	\
-							void vs_main(										\
-							in float4 inPos : POSITION,							\
-							in float2 uv : TEXCOORD0,								\
-							out float4 oPosition : SV_Position,					\
-							out float2 oUv : TEXCOORD0)							\
-							{														\
-							oPosition = mul(matViewProjection, inPos);			\
-							oUv = uv;											\
-							}";
-
-	vertProg =  HighLevelGpuProgram::create(vertShaderCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
+	//String fragShaderCode = "SamplerState samp : register(s0);			\
+	//						Texture2D tex : register(t0); \
+	//						float4 ps_main(in float4 inPos : SV_Position, float2 uv : TEXCOORD0) : SV_Target		\
+	//						{														\
+	//						float4 color = tex.Sample(samp, uv);				\
+	//						return color;										\
+	//						}";
+
+	//fragProg =  HighLevelGpuProgram::create(fragShaderCode, "ps_main", "hlsl", GPT_FRAGMENT_PROGRAM, GPP_PS_4_0);
+
+	//String vertShaderCode = "float4x4 matViewProjection;	\
+	//						void vs_main(										\
+	//						in float4 inPos : POSITION,							\
+	//						in float2 uv : TEXCOORD0,								\
+	//						out float4 oPosition : SV_Position,					\
+	//						out float2 oUv : TEXCOORD0)							\
+	//						{														\
+	//						oPosition = mul(matViewProjection, inPos);			\
+	//						oUv = uv;											\
+	//						}";
+
+	//vertProg =  HighLevelGpuProgram::create(vertShaderCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
 
 	/////////////////// CG SHADERS //////////////////////////
 	//String fragShaderCode = "sampler2D tex;					\
@@ -121,31 +121,31 @@ int _tmain(int argc, _TCHAR* argv[])
 	//vertProg =  HighLevelGpuProgram::create(vertShaderCode, "vs_main", "cg", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
 
 	///////////////// GLSL SHADERS ////////////////////////////
-	//String fragShaderCode = " #version 400 \n \
-	//						  uniform sampler2D tex; \
-	//						  in vec2 texcoord0; \
-	//						  out vec4 fragColor; \
-	//						  void main() \
-	//						  {\
-	//							  vec4 texColor = texture2D(tex, texcoord0.st);\
-	//							  fragColor = texColor; \
-	//						  }";
-
-	//fragProg = HighLevelGpuProgram::create(fragShaderCode, "main", "glsl", GPT_FRAGMENT_PROGRAM, GPP_PS_2_0);
-
-	//// TODO - Make sure to document the strict input parameter naming. (Exact supported names are in GLSLParamParser)
-	//String vertShaderCode = "#version 400 \n \
-	//						 uniform mainFragBlock { mat4 matViewProjection; }; \
-	//						 in vec4 cm_position; \
-	//						 in vec2 cm_texcoord0; \
-	//						 out vec2 texcoord0; \
-	//						 void main() \
-	//						 { \
-	//							texcoord0 = cm_texcoord0; \
-	//							gl_Position = cm_position * matViewProjection; \
-	//						 }";
-
-	//vertProg = HighLevelGpuProgram::create(vertShaderCode, "main", "glsl", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
+	String fragShaderCode = " #version 400 \n \
+							  uniform sampler2D tex; \
+							  in vec2 texcoord0; \
+							  out vec4 fragColor; \
+							  void main() \
+							  {\
+								  vec4 texColor = texture2D(tex, texcoord0.st);\
+								  fragColor = texColor; \
+							  }";
+
+	fragProg = HighLevelGpuProgram::create(fragShaderCode, "main", "glsl", GPT_FRAGMENT_PROGRAM, GPP_PS_2_0);
+
+	// TODO - Make sure to document the strict input parameter naming. (Exact supported names are in GLSLParamParser)
+	String vertShaderCode = "#version 400 \n \
+							 uniform mainFragBlock { mat4 matViewProjection; }; \
+							 in vec4 cm_position; \
+							 in vec2 cm_texcoord0; \
+							 out vec2 texcoord0; \
+							 void main() \
+							 { \
+								texcoord0 = cm_texcoord0; \
+								gl_Position = cm_position * matViewProjection; \
+							 }";
+
+	vertProg = HighLevelGpuProgram::create(vertShaderCode, "main", "glsl", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
 
 	HighLevelGpuProgramHandle vertProgRef(vertProg);
 
@@ -158,6 +158,9 @@ int _tmain(int argc, _TCHAR* argv[])
 	fragProgRef = static_resource_cast<HighLevelGpuProgram>(gResources().load("C:\\fragProgCg.vprog"));
 
 	ShaderPtr testShader = ShaderPtr(new Shader("TestShader"));
+	testShader->addParameter("matViewProjection", "matViewProjection", GPDT_MATRIX_4X4);
+	testShader->addParameter("samp", "samp", GPOT_SAMPLER2D);
+	testShader->addParameter("tex", "tex", GPOT_TEXTURE2D);
 	TechniquePtr newTechniqueGL = testShader->addTechnique("GLRenderSystem", "ForwardRenderer");
 	PassPtr newPassGL = newTechniqueGL->addPass();
 	newPassGL->setVertexProgram(vertProgRef);
@@ -193,9 +196,9 @@ int _tmain(int argc, _TCHAR* argv[])
 	dbgMesh = static_resource_cast<Mesh>(gResources().load("C:\\ExportMesh.mesh"));
 
 	testMaterial->setTexture("tex", testTex);
-	gResources().create(testMaterial, "C:\\ExportMaterial.mat", true);
+	//gResources().create(testMaterial, "C:\\ExportMaterial.mat", true);
 
-	testMaterial = gResources().load("C:\\ExportMaterial.mat");
+	//testMaterial = gResources().load("C:\\ExportMaterial.mat");
 
 	//_ASSERT(_CrtCheckMemory());
 

+ 3 - 3
CamelotD3D11RenderSystem/Include/CmD3D11GpuParamBlock.h

@@ -5,7 +5,7 @@
 
 namespace CamelotEngine
 {
-	class CM_D3D11_EXPORT D3D11GpuParamBlock : public GpuParamBlockBuffer
+	class CM_D3D11_EXPORT D3D11GpuParamBlock : public GpuParamBlock
 	{
 	private:
 		struct D3D11GpuParamBlockSharedData
@@ -14,11 +14,11 @@ namespace CamelotEngine
 		};
 
 	public:
-		D3D11GpuParamBlock(const GpuParamBlockDesc& desc);
+		D3D11GpuParamBlock(const GpuParamBlockDesc& desc, GpuParamBlockUsage usage);
 		~D3D11GpuParamBlock();
 
 		virtual void updateIfDirty();
-		virtual GpuParamBlockBufferPtr clone() const;
+		virtual GpuParamBlockPtr clone() const;
 
 		ID3D11Buffer* getD3D11Buffer() const;
 

+ 2 - 2
CamelotD3D11RenderSystem/Include/CmD3D11HardwareBufferManager.h

@@ -21,8 +21,8 @@ namespace CamelotEngine
 		 */
 		IndexBufferPtr createIndexBuffer(IndexBuffer::IndexType itype, UINT32 numIndexes, GpuBufferUsage usage);
 
-		/** @copydoc HardwareBufferManagerInterface::createGpuParamBlockBuffer */
-		GpuParamBlockBufferPtr createGpuParamBlockBuffer(const GpuParamBlockDesc& paramDesc);
+		/** @copydoc HardwareBufferManagerInterface::createGpuParamBlock */
+		GpuParamBlockPtr createGpuParamBlock(const GpuParamBlockDesc& paramDesc, GpuParamBlockUsage usage = GPBU_STATIC);
 
 		/**
 		 * @copydoc HardwareBufferManagerInterface::createGpuBuffer

+ 4 - 4
CamelotD3D11RenderSystem/Source/CmD3D11GpuParamBlock.cpp

@@ -5,8 +5,8 @@
 
 namespace CamelotEngine
 {
-	D3D11GpuParamBlock::D3D11GpuParamBlock(const GpuParamBlockDesc& desc)
-		:GpuParamBlockBuffer(desc), mD3D11SharedData(nullptr)
+	D3D11GpuParamBlock::D3D11GpuParamBlock(const GpuParamBlockDesc& desc, GpuParamBlockUsage usage)
+		:GpuParamBlock(desc, usage), mD3D11SharedData(nullptr)
 	{
 		mD3D11SharedData = new D3D11GpuParamBlockSharedData();
 	}
@@ -37,10 +37,10 @@ namespace CamelotEngine
 			mD3D11SharedData->mBuffer->writeData(0, mSize, mData, true);
 		}
 
-		GpuParamBlockBuffer::updateIfDirty();
+		GpuParamBlock::updateIfDirty();
 	}
 
-	GpuParamBlockBufferPtr D3D11GpuParamBlock::clone() const
+	GpuParamBlockPtr D3D11GpuParamBlock::clone() const
 	{
 		std::shared_ptr<D3D11GpuParamBlock> clonedParamBlock(new D3D11GpuParamBlock(*this));
 		clonedParamBlock->mData = new UINT8[mSize];

+ 43 - 38
CamelotD3D11RenderSystem/Source/CmD3D11HLSLParamParser.cpp

@@ -85,74 +85,79 @@ namespace CamelotEngine
 				blockDesc.slot = resourceDesc.BindPoint + i;
 				blockDesc.blockSize = 0; // Calculated manually as we add parameters
 
+				if(resourceDesc.Name == "$Global" || resourceDesc.Name == "$Param") // Special buffers, as defined by DX11 docs
+					blockDesc.isShareable = false;
+				else
+					blockDesc.isShareable = true;
+
 				desc.paramBlocks.insert(std::make_pair(blockDesc.name, blockDesc));
 			}
 			else
 			{
-				GpuParamSpecialDesc memberDesc;
+				GpuParamObjectDesc memberDesc;
 				memberDesc.name = resourceDesc.Name;
 				memberDesc.slot = resourceDesc.BindPoint + i;
-				memberDesc.type = GST_UNKNOWN;
+				memberDesc.type = GPOT_UNKNOWN;
 
 				switch(resourceDesc.Type)
 				{
 				case D3D_SIT_SAMPLER:
-					memberDesc.type = GST_SAMPLER2D; // Actual dimension of the sampler doesn't matter
+					memberDesc.type = GPOT_SAMPLER2D; // Actual dimension of the sampler doesn't matter
 					desc.samplers.insert(std::make_pair(memberDesc.name, memberDesc));
 					break;
 				case D3D_SIT_TEXTURE:
 					switch(resourceDesc.Dimension)
 					{
 					case D3D_SRV_DIMENSION_TEXTURE1D:
-						memberDesc.type = GST_TEXTURE1D;
+						memberDesc.type = GPOT_TEXTURE1D;
 						break;
 					case D3D_SRV_DIMENSION_TEXTURE2D:
-						memberDesc.type = GST_TEXTURE2D;
+						memberDesc.type = GPOT_TEXTURE2D;
 						break;
 					case D3D_SRV_DIMENSION_TEXTURE3D:
-						memberDesc.type = GST_TEXTURE3D;
+						memberDesc.type = GPOT_TEXTURE3D;
 						break;
 					case D3D_SRV_DIMENSION_TEXTURECUBE:
-						memberDesc.type = GST_TEXTURECUBE;
+						memberDesc.type = GPOT_TEXTURECUBE;
 						break;
 					default:
 						LOGWRN("Skipping texture because it has unsupported dimension: " + toString(resourceDesc.Dimension));
 					}
 
-					if(memberDesc.type != GST_UNKNOWN)
+					if(memberDesc.type != GPOT_UNKNOWN)
 						desc.textures.insert(std::make_pair(memberDesc.name, memberDesc));
 
 					break;
 				case D3D_SIT_STRUCTURED:
-					memberDesc.type = GST_STRUCTURED_BUFFER;
+					memberDesc.type = GPOT_STRUCTURED_BUFFER;
 					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
 					break;
 				case D3D_SIT_BYTEADDRESS:
-					memberDesc.type = GST_BYTE_BUFFER;
+					memberDesc.type = GPOT_BYTE_BUFFER;
 					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
 					break;
 				case D3D11_SIT_UAV_RWTYPED:
-					memberDesc.type = GST_RWTYPED_BUFFER;
+					memberDesc.type = GPOT_RWTYPED_BUFFER;
 					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
 					break;
 				case D3D11_SIT_UAV_RWSTRUCTURED:
-					memberDesc.type = GST_RWSTRUCTURED_BUFFER;
+					memberDesc.type = GPOT_RWSTRUCTURED_BUFFER;
 					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
 					break;
 				case D3D11_SIT_UAV_RWBYTEADDRESS:
-					memberDesc.type = GST_RWBYTE_BUFFER;
+					memberDesc.type = GPOT_RWBYTE_BUFFER;
 					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
 					break;
 				case D3D_SIT_UAV_APPEND_STRUCTURED:
-					memberDesc.type = GST_RWAPPEND_BUFFER;
+					memberDesc.type = GPOT_RWAPPEND_BUFFER;
 					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
 					break;
 				case D3D_SIT_UAV_CONSUME_STRUCTURED:
-					memberDesc.type = GST_RWCONSUME_BUFFER;
+					memberDesc.type = GPOT_RWCONSUME_BUFFER;
 					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
 					break;
 				case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER:
-					memberDesc.type = GST_RWSTRUCTURED_BUFFER_WITH_COUNTER;
+					memberDesc.type = GPOT_RWSTRUCTURED_BUFFER_WITH_COUNTER;
 					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
 					break;
 				default:
@@ -206,7 +211,7 @@ namespace CamelotEngine
 
 	void D3D11HLSLParamParser::parseVariable(D3D11_SHADER_TYPE_DESC& varTypeDesc, D3D11_SHADER_VARIABLE_DESC& varDesc, GpuParamDesc& desc, GpuParamBlockDesc& paramBlock)
 	{
-		GpuParamMemberDesc memberDesc;
+		GpuParamDataDesc memberDesc;
 		memberDesc.name = varDesc.Name;
 		memberDesc.paramBlockSlot = paramBlock.slot;
 		memberDesc.arraySize = varTypeDesc.Elements == 0 ? 1 : varTypeDesc.Elements;
@@ -223,13 +228,13 @@ namespace CamelotEngine
 				switch(varTypeDesc.Type)
 				{
 				case D3D_SVT_BOOL:
-					memberDesc.type = GMT_BOOL;
+					memberDesc.type = GPDT_BOOL;
 					break;
 				case D3D_SVT_INT:
-					memberDesc.type = GMT_INT1;
+					memberDesc.type = GPDT_INT1;
 					break;
 				case D3D_SVT_FLOAT:
-					memberDesc.type = GMT_FLOAT1;
+					memberDesc.type = GPDT_FLOAT1;
 					break;
 				default:
 					LOGWRN("Skipping variable because it has unsupported type: " + toString(varTypeDesc.Type));
@@ -245,16 +250,16 @@ namespace CamelotEngine
 						switch(varTypeDesc.Columns)
 						{
 						case 1:
-							memberDesc.type = GMT_INT1;
+							memberDesc.type = GPDT_INT1;
 							break;
 						case 2:
-							memberDesc.type = GMT_INT2;
+							memberDesc.type = GPDT_INT2;
 							break;
 						case 3:
-							memberDesc.type = GMT_INT3;
+							memberDesc.type = GPDT_INT3;
 							break;
 						case 4:
-							memberDesc.type = GMT_INT4;
+							memberDesc.type = GPDT_INT4;
 							break;
 						}
 					}
@@ -265,16 +270,16 @@ namespace CamelotEngine
 						switch(varTypeDesc.Columns)
 						{
 						case 1:
-							memberDesc.type = GMT_FLOAT1;
+							memberDesc.type = GPDT_FLOAT1;
 							break;
 						case 2:
-							memberDesc.type = GMT_FLOAT2;
+							memberDesc.type = GPDT_FLOAT2;
 							break;
 						case 3:
-							memberDesc.type = GMT_FLOAT3;
+							memberDesc.type = GPDT_FLOAT3;
 							break;
 						case 4:
-							memberDesc.type = GMT_FLOAT4;
+							memberDesc.type = GPDT_FLOAT4;
 							break;
 						}
 					}
@@ -291,13 +296,13 @@ namespace CamelotEngine
 				switch(varTypeDesc.Columns)
 				{
 				case 2:
-					memberDesc.type = GMT_MATRIX_2X2;
+					memberDesc.type = GPDT_MATRIX_2X2;
 					break;
 				case 3:
-					memberDesc.type = GMT_MATRIX_2X3;
+					memberDesc.type = GPDT_MATRIX_2X3;
 					break;
 				case 4:
-					memberDesc.type = GMT_MATRIX_2X4;
+					memberDesc.type = GPDT_MATRIX_2X4;
 					break;
 				}
 				break;
@@ -305,13 +310,13 @@ namespace CamelotEngine
 				switch(varTypeDesc.Columns)
 				{
 				case 2:
-					memberDesc.type = GMT_MATRIX_3X2;
+					memberDesc.type = GPDT_MATRIX_3X2;
 					break;
 				case 3:
-					memberDesc.type = GMT_MATRIX_3X3;
+					memberDesc.type = GPDT_MATRIX_3X3;
 					break;
 				case 4:
-					memberDesc.type = GMT_MATRIX_3X4;
+					memberDesc.type = GPDT_MATRIX_3X4;
 					break;
 				}
 				break;
@@ -319,20 +324,20 @@ namespace CamelotEngine
 				switch(varTypeDesc.Columns)
 				{
 				case 2:
-					memberDesc.type = GMT_MATRIX_4X2;
+					memberDesc.type = GPDT_MATRIX_4X2;
 					break;
 				case 3:
-					memberDesc.type = GMT_MATRIX_4X3;
+					memberDesc.type = GPDT_MATRIX_4X3;
 					break;
 				case 4:
-					memberDesc.type = GMT_MATRIX_4X4;
+					memberDesc.type = GPDT_MATRIX_4X4;
 					break;
 				}
 				break;
 			}
 			break;
 		case D3D_SVC_STRUCT:
-			memberDesc.type = GMT_STRUCT;
+			memberDesc.type = GPDT_STRUCT;
 			break;
 		default:
 			LOGWRN("Skipping variable because it has unsupported class: " + toString(varTypeDesc.Class));

+ 2 - 2
CamelotD3D11RenderSystem/Source/CmD3D11HardwareBufferManager.cpp

@@ -44,9 +44,9 @@ namespace CamelotEngine
 		return IndexBufferPtr(idx);
 	}
 
-	GpuParamBlockBufferPtr D3D11HardwareBufferManager::createGpuParamBlockBuffer(const GpuParamBlockDesc& blockDesc)
+	GpuParamBlockPtr D3D11HardwareBufferManager::createGpuParamBlock(const GpuParamBlockDesc& blockDesc, GpuParamBlockUsage usage)
 	{
-		return GpuParamBlockBufferPtr(new D3D11GpuParamBlock(blockDesc));
+		return GpuParamBlockPtr(new D3D11GpuParamBlock(blockDesc, usage));
 	}
 
 	GpuBufferPtr D3D11HardwareBufferManager::createGpuBuffer(UINT32 elementCount, UINT32 elementSize, 

+ 1 - 1
CamelotD3D11RenderSystem/Source/CmD3D11RenderSystem.cpp

@@ -464,7 +464,7 @@ namespace CamelotEngine
 
 		for(auto iter = paramDesc.paramBlocks.begin(); iter != paramDesc.paramBlocks.end(); ++iter)
 		{
-			GpuParamBlockBufferPtr currentBlock = params->getParamBlock(iter->second.slot);
+			GpuParamBlockPtr currentBlock = params->getParamBlock(iter->second.slot);
 
 			if(currentBlock != nullptr)
 			{

+ 32 - 31
CamelotD3D9Renderer/Include/CmD3D9HLSLParamParser.h

@@ -15,7 +15,7 @@ namespace CamelotEngine
 
 	private:
 		void processParameter(GpuParamBlockDesc& blockDesc, D3DXHANDLE parent, String prefix, UINT32 index);
-		void populateParamMemberDesc(GpuParamMemberDesc& memberDesc, D3DXCONSTANT_DESC& d3dDesc);
+		void populateParamMemberDesc(GpuParamDataDesc& memberDesc, D3DXCONSTANT_DESC& d3dDesc);
 
 	private:
 		LPD3DXCONSTANTTABLE mpConstTable;
@@ -41,6 +41,7 @@ namespace CamelotEngine
 		blockDesc.name = name;
 		blockDesc.slot = 0;
 		blockDesc.blockSize = 0;
+		blockDesc.isShareable = false;
 
 		// Iterate over the constants
 		for (UINT32 i = 0; i < desc.Constants; ++i)
@@ -91,7 +92,7 @@ namespace CamelotEngine
 			// Process params
 			if (desc.Type == D3DXPT_FLOAT || desc.Type == D3DXPT_INT || desc.Type == D3DXPT_BOOL)
 			{
-				GpuParamMemberDesc memberDesc;
+				GpuParamDataDesc memberDesc;
 				memberDesc.gpuMemOffset = desc.RegisterIndex;
 				memberDesc.cpuMemOffset = blockDesc.blockSize;
 				memberDesc.paramBlockSlot = blockDesc.slot;
@@ -107,31 +108,31 @@ namespace CamelotEngine
 			}
 			else if(desc.Type == D3DXPT_SAMPLER1D || desc.Type == D3DXPT_SAMPLER2D || desc.Type == D3DXPT_SAMPLER3D || desc.Type == D3DXPT_SAMPLERCUBE)
 			{
-				GpuParamSpecialDesc samplerDesc;
+				GpuParamObjectDesc samplerDesc;
 				samplerDesc.name = paramName;
 				samplerDesc.slot = desc.RegisterIndex;
 
-				GpuParamSpecialDesc textureDesc;
+				GpuParamObjectDesc textureDesc;
 				textureDesc.name = paramName;
 				textureDesc.slot = desc.RegisterIndex;
 
 				switch(desc.Type)
 				{
 				case D3DXPT_SAMPLER1D:
-					samplerDesc.type = GST_SAMPLER1D;
-					textureDesc.type = GST_TEXTURE1D;
+					samplerDesc.type = GPOT_SAMPLER1D;
+					textureDesc.type = GPOT_TEXTURE1D;
 					break;
 				case D3DXPT_SAMPLER2D:
-					samplerDesc.type = GST_SAMPLER2D;
-					textureDesc.type = GST_TEXTURE2D;
+					samplerDesc.type = GPOT_SAMPLER2D;
+					textureDesc.type = GPOT_TEXTURE2D;
 					break;
 				case D3DXPT_SAMPLER3D:
-					samplerDesc.type = GST_SAMPLER3D;
-					textureDesc.type = GST_TEXTURE3D;
+					samplerDesc.type = GPOT_SAMPLER3D;
+					textureDesc.type = GPOT_TEXTURE3D;
 					break;
 				case D3DXPT_SAMPLERCUBE:
-					samplerDesc.type = GST_SAMPLERCUBE;
-					textureDesc.type = GST_TEXTURECUBE;
+					samplerDesc.type = GPOT_SAMPLERCUBE;
+					textureDesc.type = GPOT_TEXTURECUBE;
 					break;
 				default:
 					CM_EXCEPT(InternalErrorException, "Invalid sampler type: " + toString(desc.Type) + " for parameter " + paramName);
@@ -147,7 +148,7 @@ namespace CamelotEngine
 		}
 	}
 
-	void D3D9HLSLParamParser::populateParamMemberDesc(GpuParamMemberDesc& memberDesc, D3DXCONSTANT_DESC& d3dDesc)
+	void D3D9HLSLParamParser::populateParamMemberDesc(GpuParamDataDesc& memberDesc, D3DXCONSTANT_DESC& d3dDesc)
 	{
 		memberDesc.arraySize = d3dDesc.Elements;
 		switch(d3dDesc.Type)
@@ -156,19 +157,19 @@ namespace CamelotEngine
 			switch(d3dDesc.Columns)
 			{
 			case 1:
-				memberDesc.type = GMT_INT1;
+				memberDesc.type = GPDT_INT1;
 				memberDesc.elementSize = 4;
 				break;
 			case 2:
-				memberDesc.type = GMT_INT2;
+				memberDesc.type = GPDT_INT2;
 				memberDesc.elementSize = 4;
 				break;
 			case 3:
-				memberDesc.type = GMT_INT3;
+				memberDesc.type = GPDT_INT3;
 				memberDesc.elementSize = 4;
 				break;
 			case 4:
-				memberDesc.type = GMT_INT4;
+				memberDesc.type = GPDT_INT4;
 				memberDesc.elementSize = 4;
 				break;
 			} // columns
@@ -193,15 +194,15 @@ namespace CamelotEngine
 						switch(secondDim)
 						{
 						case 2:
-							memberDesc.type = GMT_MATRIX_2X2;
+							memberDesc.type = GPDT_MATRIX_2X2;
 							memberDesc.elementSize = 8; // HLSL always packs
 							break;
 						case 3:
-							memberDesc.type = GMT_MATRIX_2X3;
+							memberDesc.type = GPDT_MATRIX_2X3;
 							memberDesc.elementSize = 8; // HLSL always packs
 							break;
 						case 4:
-							memberDesc.type = GMT_MATRIX_2X4;
+							memberDesc.type = GPDT_MATRIX_2X4;
 							memberDesc.elementSize = 8; 
 							break;
 						} // columns
@@ -210,15 +211,15 @@ namespace CamelotEngine
 						switch(secondDim)
 						{
 						case 2:
-							memberDesc.type = GMT_MATRIX_3X2;
+							memberDesc.type = GPDT_MATRIX_3X2;
 							memberDesc.elementSize = 12; // HLSL always packs
 							break;
 						case 3:
-							memberDesc.type = GMT_MATRIX_3X3;
+							memberDesc.type = GPDT_MATRIX_3X3;
 							memberDesc.elementSize = 12; // HLSL always packs
 							break;
 						case 4:
-							memberDesc.type = GMT_MATRIX_3X4;
+							memberDesc.type = GPDT_MATRIX_3X4;
 							memberDesc.elementSize = 12; 
 							break;
 						} // columns
@@ -227,15 +228,15 @@ namespace CamelotEngine
 						switch(secondDim)
 						{
 						case 2:
-							memberDesc.type = GMT_MATRIX_4X2;
+							memberDesc.type = GPDT_MATRIX_4X2;
 							memberDesc.elementSize = 16; // HLSL always packs
 							break;
 						case 3:
-							memberDesc.type = GMT_MATRIX_4X3;
+							memberDesc.type = GPDT_MATRIX_4X3;
 							memberDesc.elementSize = 16; // HLSL always packs
 							break;
 						case 4:
-							memberDesc.type = GMT_MATRIX_4X4;
+							memberDesc.type = GPDT_MATRIX_4X4;
 							memberDesc.elementSize = 16; 
 							break;
 						} // secondDim
@@ -249,19 +250,19 @@ namespace CamelotEngine
 				switch(d3dDesc.Columns)
 				{
 				case 1:
-					memberDesc.type = GMT_FLOAT1;
+					memberDesc.type = GPDT_FLOAT1;
 					memberDesc.elementSize = 4;
 					break;
 				case 2:
-					memberDesc.type = GMT_FLOAT2;
+					memberDesc.type = GPDT_FLOAT2;
 					memberDesc.elementSize = 4;
 					break;
 				case 3:
-					memberDesc.type = GMT_FLOAT3;
+					memberDesc.type = GPDT_FLOAT3;
 					memberDesc.elementSize = 4;
 					break;
 				case 4:
-					memberDesc.type = GMT_FLOAT4;
+					memberDesc.type = GPDT_FLOAT4;
 					memberDesc.elementSize = 4;
 					break;
 				} // columns
@@ -269,7 +270,7 @@ namespace CamelotEngine
 			}
 			break;
 		case D3DXPT_BOOL:
-			memberDesc.type = GMT_BOOL;
+			memberDesc.type = GPDT_BOOL;
 			memberDesc.elementSize = 1;
 			break;
 		default:

+ 2 - 2
CamelotD3D9Renderer/Include/CmD3D9HardwareBufferManager.h

@@ -56,8 +56,8 @@ namespace CamelotEngine {
 		 */
 		IndexBufferPtr createIndexBuffer(IndexBuffer::IndexType itype, UINT32 numIndexes, GpuBufferUsage usage);
 
-		/** @copydoc HardwareBufferManager::createGpuParamBlockBuffer */
-		GpuParamBlockBufferPtr createGpuParamBlockBuffer(const GpuParamBlockDesc& paramDesc);
+		/** @copydoc HardwareBufferManager::createGpuParamBlock */
+		GpuParamBlockPtr createGpuParamBlock(const GpuParamBlockDesc& paramDesc, GpuParamBlockUsage usage = GPBU_STATIC);
 
 		/**
 		 * @copydoc HardwareBufferManager::createGenericBuffer

+ 2 - 2
CamelotD3D9Renderer/Source/CmD3D9HardwareBufferManager.cpp

@@ -67,9 +67,9 @@ namespace CamelotEngine {
             
     }
 	//-----------------------------------------------------------------------
-	GpuParamBlockBufferPtr D3D9HardwareBufferManager::createGpuParamBlockBuffer(const GpuParamBlockDesc& paramDesc)
+	GpuParamBlockPtr D3D9HardwareBufferManager::createGpuParamBlock(const GpuParamBlockDesc& paramDesc, GpuParamBlockUsage usage)
 	{
-		return GpuParamBlockBufferPtr(new GpuParamBlockBuffer(paramDesc));
+		return GpuParamBlockPtr(new GpuParamBlock(paramDesc, usage));
 	}
 	//-----------------------------------------------------------------------
 	GpuBufferPtr D3D9HardwareBufferManager::createGpuBuffer(UINT32 elementCount, UINT32 elementSize, 

+ 40 - 40
CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp

@@ -359,26 +359,26 @@ namespace CamelotEngine
 			{
 				for(auto iter = paramDesc.params.begin(); iter != paramDesc.params.end(); ++iter)
 				{
-					const GpuParamMemberDesc& paramDesc = iter->second;
+					const GpuParamDataDesc& paramDesc = iter->second;
 
-					GpuParamBlockBufferPtr paramBlock = params->getParamBlock(paramDesc.paramBlockSlot);
+					GpuParamBlockPtr paramBlock = params->getParamBlock(paramDesc.paramBlockSlot);
 					const UINT8* ptrData = paramBlock->getDataPtr(paramDesc.cpuMemOffset * sizeof(UINT32));
 
 					switch(paramDesc.type)
 					{
-					case GMT_FLOAT1:
-					case GMT_FLOAT2:
-					case GMT_FLOAT3:
-					case GMT_FLOAT4:
-					case GMT_MATRIX_2X2:
-					case GMT_MATRIX_2X3:
-					case GMT_MATRIX_2X4:
-					case GMT_MATRIX_3X2:
-					case GMT_MATRIX_3X3:
-					case GMT_MATRIX_3X4:
-					case GMT_MATRIX_4X2:
-					case GMT_MATRIX_4X3:
-					case GMT_MATRIX_4X4:
+					case GPDT_FLOAT1:
+					case GPDT_FLOAT2:
+					case GPDT_FLOAT3:
+					case GPDT_FLOAT4:
+					case GPDT_MATRIX_2X2:
+					case GPDT_MATRIX_2X3:
+					case GPDT_MATRIX_2X4:
+					case GPDT_MATRIX_3X2:
+					case GPDT_MATRIX_3X3:
+					case GPDT_MATRIX_3X4:
+					case GPDT_MATRIX_4X2:
+					case GPDT_MATRIX_4X3:
+					case GPDT_MATRIX_4X4:
 						{
 							UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
 							assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
@@ -387,10 +387,10 @@ namespace CamelotEngine
 								CM_EXCEPT(RenderingAPIException, "Unable to upload vertex shader float parameters.");
 							break;
 						}
-					case GMT_INT1:
-					case GMT_INT2:
-					case GMT_INT3:
-					case GMT_INT4:
+					case GPDT_INT1:
+					case GPDT_INT2:
+					case GPDT_INT3:
+					case GPDT_INT4:
 						{
 							UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
 							assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
@@ -399,7 +399,7 @@ namespace CamelotEngine
 								CM_EXCEPT(RenderingAPIException, "Unable to upload vertex shader int parameters.");
 							break;
 						}
-					case GMT_BOOL:
+					case GPDT_BOOL:
 						if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantB(paramDesc.gpuMemOffset, (const BOOL*)ptrData, paramDesc.arraySize))) 
 							CM_EXCEPT(RenderingAPIException, "Unable to upload vertex shader bool parameters.");
 						break;
@@ -411,26 +411,26 @@ namespace CamelotEngine
 			{
 				for(auto iter = paramDesc.params.begin(); iter != paramDesc.params.end(); ++iter)
 				{
-					const GpuParamMemberDesc& paramDesc = iter->second;
+					const GpuParamDataDesc& paramDesc = iter->second;
 
-					GpuParamBlockBufferPtr paramBlock = params->getParamBlock(paramDesc.paramBlockSlot);
+					GpuParamBlockPtr paramBlock = params->getParamBlock(paramDesc.paramBlockSlot);
 					const UINT8* ptrData = paramBlock->getDataPtr(paramDesc.cpuMemOffset * sizeof(UINT32));
 
 					switch(paramDesc.type)
 					{
-					case GMT_FLOAT1:
-					case GMT_FLOAT2:
-					case GMT_FLOAT3:
-					case GMT_FLOAT4:
-					case GMT_MATRIX_2X2:
-					case GMT_MATRIX_2X3:
-					case GMT_MATRIX_2X4:
-					case GMT_MATRIX_3X2:
-					case GMT_MATRIX_3X3:
-					case GMT_MATRIX_3X4:
-					case GMT_MATRIX_4X2:
-					case GMT_MATRIX_4X3:
-					case GMT_MATRIX_4X4:
+					case GPDT_FLOAT1:
+					case GPDT_FLOAT2:
+					case GPDT_FLOAT3:
+					case GPDT_FLOAT4:
+					case GPDT_MATRIX_2X2:
+					case GPDT_MATRIX_2X3:
+					case GPDT_MATRIX_2X4:
+					case GPDT_MATRIX_3X2:
+					case GPDT_MATRIX_3X3:
+					case GPDT_MATRIX_3X4:
+					case GPDT_MATRIX_4X2:
+					case GPDT_MATRIX_4X3:
+					case GPDT_MATRIX_4X4:
 						{
 							UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
 							assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
@@ -439,10 +439,10 @@ namespace CamelotEngine
 								CM_EXCEPT(RenderingAPIException, "Unable to upload pixel shader float parameters.");
 							break;
 						}
-					case GMT_INT1:
-					case GMT_INT2:
-					case GMT_INT3:
-					case GMT_INT4:
+					case GPDT_INT1:
+					case GPDT_INT2:
+					case GPDT_INT3:
+					case GPDT_INT4:
 						{
 							UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
 							assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
@@ -451,7 +451,7 @@ namespace CamelotEngine
 								CM_EXCEPT(RenderingAPIException, "Unable to upload pixel shader int parameters.");
 							break;
 						}
-					case GMT_BOOL:
+					case GPDT_BOOL:
 						if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantB(paramDesc.gpuMemOffset, (const BOOL*)ptrData, paramDesc.arraySize))) 
 							CM_EXCEPT(RenderingAPIException, "Unable to upload pixel shader bool parameters.");
 						break;

+ 4 - 3
CamelotGLRenderer/Include/CmGLGpuParamBlock.h

@@ -2,10 +2,11 @@
 
 #include "CmGLPrerequisites.h"
 #include "CmGpuParamBlock.h"
+#include "CmCommonEnums.h"
 
 namespace CamelotEngine
 {
-	class CM_RSGL_EXPORT GLGpuParamBlock : public GpuParamBlockBuffer
+	class CM_RSGL_EXPORT GLGpuParamBlock : public GpuParamBlock
 	{
 	private:
 		struct GLGpuParamBlockSharedData
@@ -14,11 +15,11 @@ namespace CamelotEngine
 		};
 
 	public:
-		GLGpuParamBlock(const GpuParamBlockDesc& desc);
+		GLGpuParamBlock(const GpuParamBlockDesc& desc, GpuParamBlockUsage usage);
 		~GLGpuParamBlock();
 
 		virtual void updateIfDirty();
-		virtual GpuParamBlockBufferPtr clone() const;
+		virtual GpuParamBlockPtr clone() const;
 
 		GLuint getGLHandle() const { return mGLSharedData->mGLHandle; }
 

+ 2 - 2
CamelotGLRenderer/Include/CmGLHardwareBufferManager.h

@@ -62,8 +62,8 @@ namespace CamelotEngine {
             IndexBuffer::IndexType itype, UINT32 numIndexes, 
             GpuBufferUsage usage);
 
-		/** @copydoc HardwareBufferManager::createGpuParamBlockBuffer */
-		GpuParamBlockBufferPtr createGpuParamBlockBuffer(const GpuParamBlockDesc& paramDesc);
+		/** @copydoc HardwareBufferManager::createGpuParamBlock */
+		GpuParamBlockPtr createGpuParamBlock(const GpuParamBlockDesc& paramDesc, GpuParamBlockUsage usage = GPBU_STATIC);
 
 		/**
 		 * @copydoc HardwareBufferManager::createGenericBuffer

+ 5 - 0
CamelotGLRenderer/Include/CmGLRenderSystem.h

@@ -550,6 +550,11 @@ namespace CamelotEngine {
         */
         void switchContext(GLContext *context);
 
+		/**
+		 * @brief	Checks if there are any OpenGL errors and prints them to the log.
+		 */
+		bool checkForErrors() const;
+
 		/**
 		 * @brief	OpenGL shares all texture slots, but the engine prefers to keep textures
 		 * 			separate per-stage. This will convert texture unit that is set per stage

+ 4 - 4
CamelotGLRenderer/Source/CmGLGpuParamBlock.cpp

@@ -2,8 +2,8 @@
 
 namespace CamelotEngine
 {
-	GLGpuParamBlock::GLGpuParamBlock(const GpuParamBlockDesc& desc)
-		:GpuParamBlockBuffer(desc), mGLSharedData(nullptr)
+	GLGpuParamBlock::GLGpuParamBlock(const GpuParamBlockDesc& desc, GpuParamBlockUsage usage)
+		:GpuParamBlock(desc, usage), mGLSharedData(nullptr)
 	{
 		mGLSharedData = new GLGpuParamBlockSharedData();
 	}
@@ -36,10 +36,10 @@ namespace CamelotEngine
 			glBindBuffer(GL_UNIFORM_BUFFER, 0);
 		}
 
-		GpuParamBlockBuffer::updateIfDirty();
+		GpuParamBlock::updateIfDirty();
 	}
 
-	GpuParamBlockBufferPtr GLGpuParamBlock::clone() const
+	GpuParamBlockPtr GLGpuParamBlock::clone() const
 	{
 		std::shared_ptr<GLGpuParamBlock> clonedParamBlock(new GLGpuParamBlock(*this));
 		clonedParamBlock->mData = new UINT8[mSize];

+ 2 - 2
CamelotGLRenderer/Source/CmGLHardwareBufferManager.cpp

@@ -104,9 +104,9 @@ namespace CamelotEngine {
 		return IndexBufferPtr(buf);
     }
 	//---------------------------------------------------------------------
-	GpuParamBlockBufferPtr GLHardwareBufferManager::createGpuParamBlockBuffer(const GpuParamBlockDesc& paramDesc)
+	GpuParamBlockPtr GLHardwareBufferManager::createGpuParamBlock(const GpuParamBlockDesc& paramDesc, GpuParamBlockUsage usage)
 	{
-		return GpuParamBlockBufferPtr(new GLGpuParamBlock(paramDesc));
+		return GpuParamBlockPtr(new GLGpuParamBlock(paramDesc, usage));
 	}
 	//---------------------------------------------------------------------
 	GpuBufferPtr GLHardwareBufferManager::createGpuBuffer(UINT32 elementCount, UINT32 elementSize, 

+ 41 - 4
CamelotGLRenderer/Source/CmGLRenderSystem.cpp

@@ -341,7 +341,7 @@ namespace CamelotEngine
 			if(iter->second.slot == 0)
 				continue;
 
-			GpuParamBlockBufferPtr paramBlock = params->getParamBlock(iter->second.slot);
+			GpuParamBlockPtr paramBlock = params->getParamBlock(iter->second.slot);
 			if(paramBlock == nullptr)
 				continue;
 
@@ -356,9 +356,9 @@ namespace CamelotEngine
 
 		for(auto iter = paramDesc.params.begin(); iter != paramDesc.params.end(); ++iter)
 		{
-			const GpuParamMemberDesc& paramDesc = iter->second;
+			const GpuParamDataDesc& paramDesc = iter->second;
 
-			GpuParamBlockBufferPtr paramBlock = params->getParamBlock(paramDesc.paramBlockSlot);
+			GpuParamBlockPtr paramBlock = params->getParamBlock(paramDesc.paramBlockSlot);
 			
 			if(paramDesc.paramBlockSlot != 0) // 0 means uniforms are not in a block
 				continue;
@@ -427,7 +427,7 @@ namespace CamelotEngine
 			case GCT_INT4:
 				glProgramUniform4iv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLint*)ptrData);
 				break;
-			case GMT_BOOL:
+			case GPDT_BOOL:
 				glProgramUniform1uiv(glProgram, paramDesc.gpuMemOffset, paramDesc.arraySize, (GLuint*)ptrData);
 				break;
 			case GCT_UNKNOWN:
@@ -1385,6 +1385,8 @@ namespace CamelotEngine
 			// set up glew and GLSupport
 			initialiseContext(context);
 
+			checkForErrors();
+
 			std::vector<CamelotEngine::String> tokens = StringUtil::split(mGLSupport->getGLVersion(), ".");
 
 			if (!tokens.empty())
@@ -1399,13 +1401,20 @@ namespace CamelotEngine
 			// Initialise GL after the first window has been created
 			// TODO: fire this from emulation options, and don't duplicate float and Current capabilities
 			mCurrentCapabilities = createRenderSystemCapabilities();
+			checkForErrors();
 
 			initialiseFromRenderSystemCapabilities(mCurrentCapabilities);
+			checkForErrors();
 
 			// Initialise the main context
 			oneTimeContextInitialization();
+			checkForErrors();
+
 			if(mCurrentContext)
+			{
 				mCurrentContext->setInitialized();
+				checkForErrors();
+			}
 		}
 	}
 	//---------------------------------------------------------------------
@@ -1732,6 +1741,28 @@ namespace CamelotEngine
 		glColor4f(1,1,1,1);
 	}
 	//-----------------------------------------------------------------------
+	bool GLRenderSystem::checkForErrors() const
+	{
+		GLenum glErr = glGetError();
+		bool errorsFound = false;
+		String msg;
+		while (glErr != GL_NO_ERROR)
+		{
+			const char* glerrStr = (const char*)gluErrorString(glErr);
+			if (glerrStr)
+			{
+				msg += String(glerrStr);
+			}
+			glErr = glGetError();
+			errorsFound = true;
+		}
+
+		if(errorsFound)
+			LOGWRN("OpenGL error: " + msg);
+
+		return errorsFound;
+	}
+	//-----------------------------------------------------------------------
 	GLint GLRenderSystem::getGLDrawMode() const
 	{
 		GLint primType;
@@ -1807,15 +1838,18 @@ namespace CamelotEngine
 		}
 
 		HardwareBufferManager::startUp(new GLHardwareBufferManager);
+		checkForErrors();
 
 		// GPU Program Manager setup
 		GpuProgramManager::startUp(new GLGpuProgramManager());
+		checkForErrors();
 
 		if(caps->isShaderProfileSupported("glsl"))
 		{
 			// NFZ - check for GLSL vertex and fragment shader support successful
 			mGLSLProgramFactory = new GLSLProgramFactory();
 			HighLevelGpuProgramManager::instance().addFactory(mGLSLProgramFactory);
+			checkForErrors();
 		}
 
 		if(caps->isShaderProfileSupported("cg"))
@@ -1823,6 +1857,7 @@ namespace CamelotEngine
 			// NFZ - check for GLSL vertex and fragment shader support successful
 			mCgProgramFactory = new CgProgramFactory();
 			HighLevelGpuProgramManager::instance().addFactory(mCgProgramFactory);
+			checkForErrors();
 		}
 
 		if(caps->hasCapability(RSC_HWOCCLUSION))
@@ -1855,6 +1890,7 @@ namespace CamelotEngine
 			{
 				// Create FBO manager
 				GLRTTManager::startUp(new GLRTTManager());
+				checkForErrors();
 			}
 		}
 		else
@@ -1902,6 +1938,7 @@ namespace CamelotEngine
 
 		/// Create the texture manager        
 		TextureManager::startUp(new GLTextureManager(*mGLSupport)); 
+		checkForErrors();
 
 		mGLInitialised = true;
 	}

+ 12 - 31
CamelotGLRenderer/Source/CmGLRenderTexture.cpp

@@ -82,39 +82,24 @@ namespace CamelotEngine
 /// Size of probe texture
 #define PROBE_SIZE 16
 
-/// Stencil and depth formats to be tried
-static const GLenum stencilFormats[] =
-{
-    GL_NONE,                    // No stencil
-    GL_STENCIL_INDEX1_EXT,
-    GL_STENCIL_INDEX4_EXT,
-    GL_STENCIL_INDEX8_EXT,
-    GL_STENCIL_INDEX16_EXT
-};
-static const UINT32 stencilBits[] =
-{
-    0, 1, 4, 8, 16
-};
-#define STENCILFORMAT_COUNT (sizeof(stencilFormats)/sizeof(GLenum))
-
 static const GLenum depthFormats[] =
 {
     GL_NONE,
     GL_DEPTH_COMPONENT16,
-    GL_DEPTH_COMPONENT24,    // Prefer 24 bit depth
     GL_DEPTH_COMPONENT32,
-    GL_DEPTH24_STENCIL8_EXT // packed depth / stencil
+    GL_DEPTH24_STENCIL8, // packed depth / stencil
+	GL_DEPTH32F_STENCIL8
 };
 static const UINT32 depthBits[] =
 {
-    0,16,24,32,24
+    0,16,32,24,32
 };
 #define DEPTHFORMAT_COUNT (sizeof(depthFormats)/sizeof(GLenum))
 
 	GLRTTManager::GLRTTManager()
     {
 		detectFBOFormats();
-
+		
         glGenFramebuffersEXT(1, &mTempFBO);
     }
 
@@ -251,7 +236,7 @@ static const UINT32 depthBits[] =
             // Create and attach framebuffer
             glGenFramebuffersEXT(1, &fb);
             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
-            if (fmt!=GL_NONE)
+            if (fmt!=GL_NONE && !PixelUtil::isDepth((PixelFormat)x))
             {
 				// Create and attach texture
 				glGenTextures(1, &tid);
@@ -288,19 +273,15 @@ static const UINT32 depthBits[] =
                 // For each depth/stencil formats
                 for (UINT32 depth = 0; depth < DEPTHFORMAT_COUNT; ++depth)
                 {
-                    if (depthFormats[depth] != GL_DEPTH24_STENCIL8_EXT)
+                    if (depthFormats[depth] != GL_DEPTH24_STENCIL8_EXT && depthFormats[depth] != GL_DEPTH32F_STENCIL8)
                     {
-                        // General depth/stencil combination
-                        for (UINT32 stencil = 0; stencil < STENCILFORMAT_COUNT; ++stencil)
+                        if (_tryFormat(depthFormats[depth], GL_NONE))
                         {
-                            if (_tryFormat(depthFormats[depth], stencilFormats[stencil]))
-                            {
-                                /// Add mode to allowed modes
-                                FormatProperties::Mode mode;
-                                mode.depth = depth;
-                                mode.stencil = stencil;
-                                mProps[x].modes.push_back(mode);
-                            }
+                            /// Add mode to allowed modes
+                            FormatProperties::Mode mode;
+                            mode.depth = depth;
+                            mode.stencil = 0;
+                            mProps[x].modes.push_back(mode);
                         }
                     }
                     else

+ 33 - 31
CamelotGLRenderer/Source/GLSL/include/CmGLSLParamParser.h

@@ -43,7 +43,7 @@ namespace CamelotEngine
 		void buildVertexDeclaration(GLuint glProgram, VertexDeclaration& declaration);
 
 	private:
-		void determineParamInfo(GpuParamMemberDesc& desc, const String& paramName, GLuint programHandle, GLuint uniformIndex);
+		void determineParamInfo(GpuParamDataDesc& desc, const String& paramName, GLuint programHandle, GLuint uniformIndex);
 
 		/**
 		* @brief	GLSL has no concept of semantics, so we require all shaders to use specific names for attributes
@@ -153,6 +153,7 @@ namespace CamelotEngine
 		newGlobalBlockDesc.slot = 0;
 		newGlobalBlockDesc.name = "CM_INTERNAL_Globals";
 		newGlobalBlockDesc.blockSize = 0;
+		newGlobalBlockDesc.isShareable = false;
 
 		UINT32 textureSlot = 0;
 
@@ -172,6 +173,7 @@ namespace CamelotEngine
 			newBlockDesc.slot = index + 1;
 			newBlockDesc.name = uniformName;
 			newBlockDesc.blockSize = 0;
+			newBlockDesc.isShareable = true;
 
 			returnParamDesc.paramBlocks[newBlockDesc.name] = newBlockDesc;
 			blockSlotToName.insert(std::make_pair(newBlockDesc.slot, newBlockDesc.name));
@@ -216,31 +218,31 @@ namespace CamelotEngine
 
 			if(isSampler)
 			{
-				GpuParamSpecialDesc samplerParam;
+				GpuParamObjectDesc samplerParam;
 				samplerParam.name = paramName;
 				samplerParam.slot = glGetUniformLocation(glProgram, uniformName);
 
-				GpuParamSpecialDesc textureParam;
+				GpuParamObjectDesc textureParam;
 				textureParam.name = paramName;
 				textureParam.slot = samplerParam.slot;
 
 				switch(uniformType)
 				{
 				case GL_SAMPLER_1D:
-					samplerParam.type = GST_SAMPLER1D;
-					textureParam.type = GST_TEXTURE1D;
+					samplerParam.type = GPOT_SAMPLER1D;
+					textureParam.type = GPOT_TEXTURE1D;
 					break;
 				case GL_SAMPLER_2D:
-					samplerParam.type = GST_SAMPLER2D;
-					textureParam.type = GST_TEXTURE2D;
+					samplerParam.type = GPOT_SAMPLER2D;
+					textureParam.type = GPOT_TEXTURE2D;
 					break;
 				case GL_SAMPLER_3D:
-					samplerParam.type = GST_SAMPLER3D;
-					textureParam.type = GST_TEXTURE3D;
+					samplerParam.type = GPOT_SAMPLER3D;
+					textureParam.type = GPOT_TEXTURE3D;
 					break;
 				case GL_SAMPLER_CUBE:
-					samplerParam.type = GST_SAMPLERCUBE;
-					textureParam.type = GST_TEXTURECUBE;
+					samplerParam.type = GPOT_SAMPLERCUBE;
+					textureParam.type = GPOT_TEXTURECUBE;
 					break;
 				}
 
@@ -249,7 +251,7 @@ namespace CamelotEngine
 			}
 			else
 			{
-				GpuParamMemberDesc gpuParam;
+				GpuParamDataDesc gpuParam;
 				gpuParam.name = paramName;
 
 				GLint blockIndex;
@@ -315,7 +317,7 @@ namespace CamelotEngine
 		delete[] uniformName;
 	}
 
-	void GLSLParamParser::determineParamInfo(GpuParamMemberDesc& desc, const String& paramName, GLuint programHandle, GLuint uniformIndex)
+	void GLSLParamParser::determineParamInfo(GpuParamDataDesc& desc, const String& paramName, GLuint programHandle, GLuint uniformIndex)
 	{
 		GLint arraySize;
 		glGetActiveUniformsiv(programHandle, 1, &uniformIndex, GL_UNIFORM_SIZE, &arraySize);
@@ -327,75 +329,75 @@ namespace CamelotEngine
 		switch (uniformType)
 		{
 		case GL_BOOL:
-			desc.type = GMT_BOOL;
+			desc.type = GPDT_BOOL;
 			desc.elementSize = 1;
 			break;
 		case GL_FLOAT:
-			desc.type = GMT_FLOAT1;
+			desc.type = GPDT_FLOAT1;
 			desc.elementSize = 1;
 			break;
 		case GL_FLOAT_VEC2:
-			desc.type = GMT_FLOAT2;
+			desc.type = GPDT_FLOAT2;
 			desc.elementSize = 2;
 			break;
 		case GL_FLOAT_VEC3:
-			desc.type = GMT_FLOAT3;
+			desc.type = GPDT_FLOAT3;
 			desc.elementSize = 3;
 			break;
 		case GL_FLOAT_VEC4:
-			desc.type = GMT_FLOAT4;
+			desc.type = GPDT_FLOAT4;
 			desc.elementSize = 4;
 			break;
 		case GL_INT:
-			desc.type = GMT_INT1;
+			desc.type = GPDT_INT1;
 			desc.elementSize = 1;
 			break;
 		case GL_INT_VEC2:
-			desc.type = GMT_INT2;
+			desc.type = GPDT_INT2;
 			desc.elementSize = 2;
 			break;
 		case GL_INT_VEC3:
-			desc.type = GMT_INT3;
+			desc.type = GPDT_INT3;
 			desc.elementSize = 3;
 			break;
 		case GL_INT_VEC4:
-			desc.type = GMT_INT4;
+			desc.type = GPDT_INT4;
 			desc.elementSize = 4;
 			break;
 		case GL_FLOAT_MAT2:
-			desc.type = GMT_MATRIX_2X2;
+			desc.type = GPDT_MATRIX_2X2;
 			desc.elementSize = 4;
 			break;
 		case GL_FLOAT_MAT3:
-			desc.type = GMT_MATRIX_3X3;
+			desc.type = GPDT_MATRIX_3X3;
 			desc.elementSize = 9;
 			break;
 		case GL_FLOAT_MAT4:
-			desc.type = GMT_MATRIX_4X4;
+			desc.type = GPDT_MATRIX_4X4;
 			desc.elementSize = 16;
 			break;
 		case GL_FLOAT_MAT2x3:
-			desc.type = GMT_MATRIX_2X3;
+			desc.type = GPDT_MATRIX_2X3;
 			desc.elementSize = 6;
 			break;
 		case GL_FLOAT_MAT3x2:
-			desc.type = GMT_MATRIX_3X2;
+			desc.type = GPDT_MATRIX_3X2;
 			desc.elementSize = 6;
 			break;
 		case GL_FLOAT_MAT2x4:
-			desc.type = GMT_MATRIX_2X4;
+			desc.type = GPDT_MATRIX_2X4;
 			desc.elementSize = 8;
 			break;
 		case GL_FLOAT_MAT4x2:
-			desc.type = GMT_MATRIX_4X2;
+			desc.type = GPDT_MATRIX_4X2;
 			desc.elementSize = 8;
 			break;
 		case GL_FLOAT_MAT3x4:
-			desc.type = GMT_MATRIX_3X4;
+			desc.type = GPDT_MATRIX_3X4;
 			desc.elementSize = 12;
 			break;
 		case GL_FLOAT_MAT4x3:
-			desc.type = GMT_MATRIX_4X3;
+			desc.type = GPDT_MATRIX_4X3;
 			desc.elementSize = 12;
 			break;
 		default:

+ 6 - 6
CamelotRenderer/CamelotRenderer.vcxproj.filters

@@ -329,9 +329,6 @@
     <ClInclude Include="Include\CmGpuParams.h">
       <Filter>Header Files\RenderSystem</Filter>
     </ClInclude>
-    <ClInclude Include="Include\CmGpuParamBlock.h">
-      <Filter>Header Files\RenderSystem</Filter>
-    </ClInclude>
     <ClInclude Include="Include\CmVertexDeclaration.h">
       <Filter>Header Files\RenderSystem</Filter>
     </ClInclude>
@@ -365,6 +362,9 @@
     <ClInclude Include="Include\CmVertexData.h">
       <Filter>Header Files\RenderSystem</Filter>
     </ClInclude>
+    <ClInclude Include="Include\CmGpuParamBlock.h">
+      <Filter>Header Files\RenderSystem</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CamelotRenderer.cpp">
@@ -520,9 +520,6 @@
     <ClCompile Include="Source\CmGpuParams.cpp">
       <Filter>Source Files\RenderSystem</Filter>
     </ClCompile>
-    <ClCompile Include="Source\CmGpuParamBlock.cpp">
-      <Filter>Source Files\RenderSystem</Filter>
-    </ClCompile>
     <ClCompile Include="Source\CmVertexDeclaration.cpp">
       <Filter>Source Files\RenderSystem</Filter>
     </ClCompile>
@@ -553,5 +550,8 @@
     <ClCompile Include="Source\CmVertexData.cpp">
       <Filter>Source Files\RenderSystem</Filter>
     </ClCompile>
+    <ClCompile Include="Source\CmGpuParamBlock.cpp">
+      <Filter>Source Files\RenderSystem</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 55 - 0
CamelotRenderer/Include/CmCommonEnums.h

@@ -256,6 +256,61 @@ namespace CamelotEngine {
 		GVU_RANDOMWRITE = 0x08
 	};
 
+	enum GpuParamBlockUsage
+	{
+		GPBU_STATIC,
+		GPBU_DYNAMIC
+	};
+
+	enum GpuParamDataType
+	{
+		GPDT_FLOAT1 = 1,
+		GPDT_FLOAT2 = 2,
+		GPDT_FLOAT3 = 3,
+		GPDT_FLOAT4 = 4,
+		GPDT_MATRIX_2X2 = 11,
+		GPDT_MATRIX_2X3 = 12,
+		GPDT_MATRIX_2X4 = 13,
+		GPDT_MATRIX_3X2 = 14,
+		GPDT_MATRIX_3X3 = 15,
+		GPDT_MATRIX_3X4 = 16,
+		GPDT_MATRIX_4X2 = 17,
+		GPDT_MATRIX_4X3 = 18,
+		GPDT_MATRIX_4X4 = 19,
+		GPDT_INT1 = 20,
+		GPDT_INT2 = 21,
+		GPDT_INT3 = 22,
+		GPDT_INT4 = 23,
+		GPDT_BOOL = 24,
+		GPDT_STRUCT = 25,
+		GPDT_UNKNOWN = 0xffff
+	};
+
+	enum GpuParamObjectType
+	{
+		GPOT_SAMPLER1D = 1,
+		GPOT_SAMPLER2D = 2,
+		GPOT_SAMPLER3D = 3,
+		GPOT_SAMPLERCUBE = 4,
+		GPOT_TEXTURE1D = 11,
+		GPOT_TEXTURE2D = 12,
+		GPOT_TEXTURE3D = 13,
+		GPOT_TEXTURECUBE = 14,
+		GPOT_RWTEXTURE1D = 21,
+		GPOT_RWTEXTURE2D = 22,
+		GPOT_RWTEXTURE3D = 23,
+		GPOT_BYTE_BUFFER = 32,
+		GPOT_STRUCTURED_BUFFER = 33,
+		GPOT_RWTYPED_BUFFER = 41,
+		GPOT_RWBYTE_BUFFER = 42,
+		GPOT_RWSTRUCTURED_BUFFER = 43,
+		GPOT_RWSTRUCTURED_BUFFER_WITH_COUNTER = 44,
+		GPOT_RWAPPEND_BUFFER = 45,
+		GPOT_RWCONSUME_BUFFER = 46,
+		GPOT_UNKNOWN = 0xffff
+	};
+
+
 	/** Texture addressing mode for each texture coordinate. */
 	struct UVWAddressingMode
 	{

+ 6 - 5
CamelotRenderer/Include/CmGpuParamBlock.h

@@ -1,10 +1,11 @@
 #pragma once
 
 #include "CmPrerequisites.h"
+#include "CmCommonEnums.h"
 
 namespace CamelotEngine
 {
-	class CM_EXPORT GpuParamBlockBuffer
+	class CM_EXPORT GpuParamBlock
 	{
 	private:
 		struct GpuParamBlockSharedData
@@ -14,8 +15,8 @@ namespace CamelotEngine
 		};
 
 	public:
-		GpuParamBlockBuffer(const GpuParamBlockDesc& desc);
-		virtual ~GpuParamBlockBuffer();
+		GpuParamBlock(const GpuParamBlockDesc& desc, GpuParamBlockUsage usage);
+		virtual ~GpuParamBlock();
 
 		void write(UINT32 offset, const void* data, UINT32 size);
 		void zeroOut(UINT32 offset, UINT32 size);
@@ -25,9 +26,9 @@ namespace CamelotEngine
 
 		virtual void updateIfDirty();
 
-		virtual GpuParamBlockBufferPtr clone() const;
+		virtual GpuParamBlockPtr clone() const;
 		
-		static GpuParamBlockBufferPtr create(const GpuParamBlockDesc& desc);
+		static GpuParamBlockPtr create(const GpuParamBlockDesc& desc);
 	protected:
 		GpuParamBlockSharedData* sharedData;
 		bool mOwnsSharedData;

+ 10 - 56
CamelotRenderer/Include/CmGpuParamDesc.h

@@ -1,74 +1,27 @@
 #pragma once
 
 #include "CmPrerequisites.h"
+#include "CmCommonEnums.h"
 #include "CmGpuProgramParams.h" // TODO - Only here because I need some type definitions (GpuConstantType) - Remove later
 
 namespace CamelotEngine
 {
-	enum GpuMemberType
-	{
-		GMT_FLOAT1 = 1,
-		GMT_FLOAT2 = 2,
-		GMT_FLOAT3 = 3,
-		GMT_FLOAT4 = 4,
-		GMT_MATRIX_2X2 = 11,
-		GMT_MATRIX_2X3 = 12,
-		GMT_MATRIX_2X4 = 13,
-		GMT_MATRIX_3X2 = 14,
-		GMT_MATRIX_3X3 = 15,
-		GMT_MATRIX_3X4 = 16,
-		GMT_MATRIX_4X2 = 17,
-		GMT_MATRIX_4X3 = 18,
-		GMT_MATRIX_4X4 = 19,
-		GMT_INT1 = 20,
-		GMT_INT2 = 21,
-		GMT_INT3 = 22,
-		GMT_INT4 = 23,
-		GMT_BOOL = 24,
-		GMT_STRUCT = 25,
-		GMT_UNKNOWN = 0xffff
-	};
-
-	enum GpuSpecialType
-	{
-		GST_SAMPLER1D = 1,
-		GST_SAMPLER2D = 2,
-		GST_SAMPLER3D = 3,
-		GST_SAMPLERCUBE = 4,
-		GST_TEXTURE1D = 11,
-		GST_TEXTURE2D = 12,
-		GST_TEXTURE3D = 13,
-		GST_TEXTURECUBE = 14,
-		GST_RWTEXTURE1D = 21,
-		GST_RWTEXTURE2D = 22,
-		GST_RWTEXTURE3D = 23,
-		GST_BYTE_BUFFER = 32,
-		GST_STRUCTURED_BUFFER = 33,
-		GST_RWTYPED_BUFFER = 41,
-		GST_RWBYTE_BUFFER = 42,
-		GST_RWSTRUCTURED_BUFFER = 43,
-		GST_RWSTRUCTURED_BUFFER_WITH_COUNTER = 44,
-		GST_RWAPPEND_BUFFER = 45,
-		GST_RWCONSUME_BUFFER = 46,
-		GST_UNKNOWN = 0xffff
-	};
-
-	struct GpuParamMemberDesc
+	struct GpuParamDataDesc
 	{
 		String name;
 		UINT32 elementSize; // Multiple of 4 bytes
 		UINT32 arraySize;
-		GpuMemberType type;
+		GpuParamDataType type;
 
 		UINT32 paramBlockSlot;
 		UINT32 gpuMemOffset;
 		UINT32 cpuMemOffset;
 	};
 
-	struct GpuParamSpecialDesc
+	struct GpuParamObjectDesc
 	{
 		String name;
-		GpuSpecialType type;
+		GpuParamObjectType type;
 
 		UINT32 slot;
 	};
@@ -78,15 +31,16 @@ namespace CamelotEngine
 		String name;
 		UINT32 slot;
 		UINT32 blockSize;
+		bool isShareable;
 	};
 
 	struct GpuParamDesc
 	{
 		map<String, GpuParamBlockDesc>::type paramBlocks;
-		map<String, GpuParamMemberDesc>::type params;
+		map<String, GpuParamDataDesc>::type params;
 
-		map<String, GpuParamSpecialDesc>::type samplers;
-		map<String, GpuParamSpecialDesc>::type textures;
-		map<String, GpuParamSpecialDesc>::type buffers;
+		map<String, GpuParamObjectDesc>::type samplers;
+		map<String, GpuParamObjectDesc>::type textures;
+		map<String, GpuParamObjectDesc>::type buffers;
 	};
 }

+ 7 - 6
CamelotRenderer/Include/CmGpuParams.h

@@ -9,17 +9,18 @@ namespace CamelotEngine
 	public:
 		GpuParams(GpuParamDesc& paramDesc);
 
-		GpuParamBlockBufferPtr getParamBlock(UINT32 slot) const;
-		GpuParamBlockBufferPtr getParamBlock(const String& name) const;
+		GpuParamBlockPtr getParamBlock(UINT32 slot) const;
+		GpuParamBlockPtr getParamBlock(const String& name) const;
 
-		void setParamBlock(UINT32 slot, GpuParamBlockBufferPtr paramBlock);
-		void setParamBlock(const String& name, GpuParamBlockBufferPtr paramBlock);
+		void setParamBlock(UINT32 slot, GpuParamBlockPtr paramBlock);
+		void setParamBlock(const String& name, GpuParamBlockPtr paramBlock);
 
 		const GpuParamDesc& getParamDesc() const { return mParamDesc; }
 
 		bool hasParam(const String& name) const;
 		bool hasTexture(const String& name) const;
 		bool hasSamplerState(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);
@@ -57,9 +58,9 @@ namespace CamelotEngine
 		GpuParamDesc& mParamDesc;
 		bool mTransposeMatrices;
 
-		GpuParamMemberDesc* getParamDesc(const String& name) const;
+		GpuParamDataDesc* getParamDesc(const String& name) const;
 
-		vector<GpuParamBlockBufferPtr>::type mParamBlocks;
+		vector<GpuParamBlockPtr>::type mParamBlocks;
 		vector<TextureHandle>::type mTextures;
 		vector<SamplerStatePtr>::type mSamplerStates;
 	};

+ 2 - 0
CamelotRenderer/Include/CmGpuProgram.h

@@ -142,6 +142,8 @@ namespace CamelotEngine {
         */
 		virtual GpuParamsPtr createParameters();
 
+		const GpuParamDesc& getParamDesc() const { return mParametersDesc; }
+
 		/** Returns a string that specifies the language of the gpu programs as specified
         in a material script. ie: asm, cg, hlsl, glsl
         */

+ 1 - 1
CamelotRenderer/Include/CmHardwareBufferManager.h

@@ -109,7 +109,7 @@ namespace CamelotEngine {
 		 *
 		 * @return	The new GPU parameter block.
 		 */
-		virtual GpuParamBlockBufferPtr createGpuParamBlockBuffer(const GpuParamBlockDesc& paramDesc) = 0;
+		virtual GpuParamBlockPtr createGpuParamBlock(const GpuParamBlockDesc& paramDesc, GpuParamBlockUsage usage = GPBU_STATIC) = 0;
 
 		/**
 		 * @brief	Creates a generic buffer that can be passed as a parameter to a shader.

+ 16 - 3
CamelotRenderer/Include/CmMaterial.h

@@ -2,7 +2,7 @@
 
 #include "CmPrerequisites.h"
 #include "CmResource.h"
-#include "CmGpuParams.h"
+#include "CmCommonEnums.h"
 
 namespace CamelotEngine
 {
@@ -60,6 +60,8 @@ namespace CamelotEngine
 		void setMat3(const String& name, const Matrix3& value);
 		void setMat4(const String& name, const Matrix4& value);
 
+		void setParamBlock(const String& name, GpuParamBlockPtr paramBlock);
+
 		UINT32 getNumPasses() const;
 
 		PassPtr getPass(UINT32 passIdx) const;
@@ -69,14 +71,18 @@ namespace CamelotEngine
 	private:
 		ShaderPtr mShader;
 		TechniquePtr mBestTechnique;
-		vector<PassParametersPtr>::type mParameters;
+
+		set<String>::type mValidShareableParamBlocks;
+		set<String>::type mValidParams;
+
+		vector<PassParametersPtr>::type mParametersPerPass;
 
 		void throwIfNotInitialized() const;
 
 		template <typename T>
 		void setParam(const String& name, T& value)
 		{
-			for(auto iter = mParameters.begin(); iter != mParameters.end(); ++iter)
+			for(auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
 			{
 				PassParametersPtr params = *iter;
 
@@ -94,6 +100,13 @@ namespace CamelotEngine
 
 		void initBestTechnique();
 
+		set<String>::type determineValidParameters(const vector<const GpuParamDesc*>::type& paramDescs) const;
+		set<String>::type determineValidShareableParamBlocks(const vector<const GpuParamDesc*>::type& paramDescs) const;
+		map<String, String>::type determineParameterToBlockMapping(const vector<const GpuParamDesc*>::type& paramDescs);
+
+		bool areParamsEqual(const GpuParamDataDesc& paramA, const GpuParamDataDesc& paramB, bool ignoreBufferOffsets = false) const;
+		bool areParamsEqual(const GpuParamObjectDesc& paramA, const GpuParamObjectDesc& paramB) const;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/

+ 4 - 3
CamelotRenderer/Include/CmPrerequisites.h

@@ -135,10 +135,11 @@ namespace CamelotEngine {
 	class RenderStateManager;
 	class RasterizerState;
 	class BlendState;
-	class GpuParamBlockBuffer;
+	class GpuParamBlock;
 	class GpuParams;
 	struct GpuParamDesc;
-	struct GpuParamMemberDesc;
+	struct GpuParamDataDesc;
+	struct GpuParamObjectDesc;
 	struct GpuParamBlockDesc;
 	class TextureView;
 	// Asset import
@@ -197,7 +198,7 @@ namespace CamelotEngine
 	typedef std::shared_ptr<RenderTarget> RenderTargetPtr;
 	typedef std::shared_ptr<RenderTexture> RenderTexturePtr;
 	typedef std::shared_ptr<MultiRenderTexture> MultiRenderTexturePtr;
-	typedef std::shared_ptr<GpuParamBlockBuffer> GpuParamBlockBufferPtr;
+	typedef std::shared_ptr<GpuParamBlock> GpuParamBlockPtr;
 	typedef std::shared_ptr<GpuParams> GpuParamsPtr;
 	typedef std::shared_ptr<TextureView> TextureViewPtr;
 }

+ 37 - 0
CamelotRenderer/Include/CmShader.h

@@ -2,9 +2,33 @@
 
 #include "CmPrerequisites.h"
 #include "CmResource.h"
+#include "CmCommonEnums.h"
 
 namespace CamelotEngine
 {
+	struct CM_EXPORT SHADER_DATA_PARAM_DESC
+	{
+		String name;
+		String gpuVariableName;
+		GpuParamDataType type;
+		UINT32 arraySize;
+		bool hidden;
+	};
+
+	struct CM_EXPORT SHADER_OBJECT_PARAM_DESC
+	{
+		String name;
+		String gpuVariableName;
+		GpuParamObjectType type;
+		bool hidden;
+	};
+
+	struct CM_EXPORT SHADER_PARAM_BLOCK_DESC
+	{
+		bool shared;
+		GpuParamBlockUsage usage;
+	};
+
 	/**
 	 * @brief	Shader represents a collection of techniques. They are used in Materials,
 	 * 			which can be considered as instances of a Shader. Multiple materials
@@ -37,10 +61,23 @@ namespace CamelotEngine
 		 */
 		TechniquePtr getBestTechnique() const;
 
+		void addParameter(const String& name, const String& gpuVariableName, GpuParamDataType type, UINT32 arraySize = 1, bool hidden = false);
+		void addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, bool hidden = false);
+		void removeParameter(const String& name);
+		void setParamBlockAttribs(const String& name, bool shared, GpuParamBlockUsage usage);
+
+		const map<String, SHADER_DATA_PARAM_DESC>::type& getDataParams() const { return mDataParams; }
+		const map<String, SHADER_OBJECT_PARAM_DESC>::type& getObjectParams() const { return mObjectParams; }
+		const map<String, SHADER_PARAM_BLOCK_DESC>::type& getParamBlocks() const { return mParamBlocks; }
+
 	private:
 		String mName;
 		vector<TechniquePtr>::type mTechniques;
 
+		map<String, SHADER_DATA_PARAM_DESC>::type mDataParams;
+		map<String, SHADER_OBJECT_PARAM_DESC>::type mObjectParams;
+		map<String, SHADER_PARAM_BLOCK_DESC>::type mParamBlocks;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/

+ 10 - 10
CamelotRenderer/Source/CmGpuParamBlock.cpp

@@ -5,7 +5,7 @@
 
 namespace CamelotEngine
 {
-	GpuParamBlockBuffer::GpuParamBlockBuffer(const GpuParamBlockDesc& desc)
+	GpuParamBlock::GpuParamBlock(const GpuParamBlockDesc& desc, GpuParamBlockUsage usage)
 		:mSize(desc.blockSize * sizeof(UINT32)), mOwnsSharedData(true)
 	{
 		mData = new UINT8[mSize];
@@ -16,7 +16,7 @@ namespace CamelotEngine
 		sharedData->mInitialized = false;
 	}
 
-	GpuParamBlockBuffer::~GpuParamBlockBuffer()
+	GpuParamBlock::~GpuParamBlock()
 	{
 		delete [] mData;
 
@@ -24,7 +24,7 @@ namespace CamelotEngine
 			delete sharedData;
 	}
 
-	void GpuParamBlockBuffer::write(UINT32 offset, const void* data, UINT32 size)
+	void GpuParamBlock::write(UINT32 offset, const void* data, UINT32 size)
 	{
 #if CM_DEBUG_MODE
 		if(offset < 0 || (offset + size) > mSize)
@@ -40,7 +40,7 @@ namespace CamelotEngine
 		sharedData->mDirty = true;
 	}
 
-	void GpuParamBlockBuffer::zeroOut(UINT32 offset, UINT32 size)
+	void GpuParamBlock::zeroOut(UINT32 offset, UINT32 size)
 	{
 #if CM_DEBUG_MODE
 		if(offset < 0 || (offset + size) > mSize)
@@ -56,7 +56,7 @@ namespace CamelotEngine
 		sharedData->mDirty = true;
 	}
 
-	const UINT8* GpuParamBlockBuffer::getDataPtr(UINT32 offset) const
+	const UINT8* GpuParamBlock::getDataPtr(UINT32 offset) const
 	{
 #if CM_DEBUG_MODE
 		if(offset < 0 || offset >= mSize)
@@ -70,16 +70,16 @@ namespace CamelotEngine
 		return &mData[offset];
 	}
 
-	void GpuParamBlockBuffer::updateIfDirty()
+	void GpuParamBlock::updateIfDirty()
 	{
 		sharedData->mDirty = false;
 
 		// Do nothing
 	}
 
-	GpuParamBlockBufferPtr GpuParamBlockBuffer::clone() const
+	GpuParamBlockPtr GpuParamBlock::clone() const
 	{
-		GpuParamBlockBufferPtr clonedParamBlock(new GpuParamBlockBuffer(*this));
+		GpuParamBlockPtr clonedParamBlock(new GpuParamBlock(*this));
 		clonedParamBlock->mData = new UINT8[mSize];
 		clonedParamBlock->mSize = mSize;
 		clonedParamBlock->mOwnsSharedData = false;
@@ -88,8 +88,8 @@ namespace CamelotEngine
 		return clonedParamBlock;
 	}
 
-	GpuParamBlockBufferPtr GpuParamBlockBuffer::create(const GpuParamBlockDesc& desc)
+	GpuParamBlockPtr GpuParamBlock::create(const GpuParamBlockDesc& desc)
 	{
-		return HardwareBufferManager::instance().createGpuParamBlockBuffer(desc);
+		return HardwareBufferManager::instance().createGpuParamBlock(desc);
 	}
 }

+ 20 - 13
CamelotRenderer/Source/CmGpuParams.cpp

@@ -19,11 +19,6 @@ namespace CamelotEngine
 
 		mParamBlocks.resize(numParamBlockSlots);
 
-		for(auto iter = mParamDesc.paramBlocks.begin(); iter != mParamDesc.paramBlocks.end(); ++iter)
-		{
-			mParamBlocks[iter->second.slot] = GpuParamBlockBuffer::create(iter->second);
-		}
-
 		UINT32 numTextureSlots = 0;
 		for(auto iter = mParamDesc.textures.begin(); iter != mParamDesc.textures.end(); ++iter)
 		{
@@ -43,7 +38,7 @@ namespace CamelotEngine
 		mSamplerStates.resize(numSamplerSlots);
 	}
 
-	GpuParamBlockBufferPtr GpuParams::getParamBlock(UINT32 slot) const
+	GpuParamBlockPtr GpuParams::getParamBlock(UINT32 slot) const
 	{
 		if(slot < 0 || slot >= (UINT32)mParamBlocks.size())
 		{
@@ -54,7 +49,7 @@ namespace CamelotEngine
 		return mParamBlocks[slot];
 	}
 
-	GpuParamBlockBufferPtr GpuParams::getParamBlock(const String& name) const
+	GpuParamBlockPtr GpuParams::getParamBlock(const String& name) const
 	{
 		auto iterFind = mParamDesc.paramBlocks.find(name);
 
@@ -67,7 +62,7 @@ namespace CamelotEngine
 		return mParamBlocks[iterFind->second.slot];
 	}
 
-	void GpuParams::setParamBlock(UINT32 slot, GpuParamBlockBufferPtr paramBlock)
+	void GpuParams::setParamBlock(UINT32 slot, GpuParamBlockPtr paramBlock)
 	{
 		if(slot < 0 || slot >= (UINT32)mParamBlocks.size())
 		{
@@ -78,7 +73,7 @@ namespace CamelotEngine
 		mParamBlocks[slot] = paramBlock;
 	}
 
-	void GpuParams::setParamBlock(const String& name, GpuParamBlockBufferPtr paramBlock)
+	void GpuParams::setParamBlock(const String& name, GpuParamBlockPtr paramBlock)
 	{
 		auto iterFind = mParamDesc.paramBlocks.find(name);
 
@@ -114,6 +109,15 @@ namespace CamelotEngine
 		return false;
 	}
 
+	bool GpuParams::hasParamBlock(const String& name) const
+	{
+		auto paramBlockIter = mParamDesc.paramBlocks.find(name);
+		if(paramBlockIter != mParamDesc.paramBlocks.end())
+			return true;
+
+		return false;
+	}
+
 	void GpuParams::setParam(const String& name, float value, UINT32 arrayIndex)
 	{
 		setParam(name, (void*)&value, 1 * sizeof(float), arrayIndex);
@@ -177,7 +181,7 @@ namespace CamelotEngine
 
 	void GpuParams::setParam(const String& name, const void* value, UINT32 sizeBytes, UINT32 arrayIndex)
 	{
-		GpuParamMemberDesc* desc = getParamDesc(name);
+		GpuParamDataDesc* desc = getParamDesc(name);
 
 		if(desc == nullptr)
 		{
@@ -198,7 +202,7 @@ namespace CamelotEngine
 				toString(elementSizeBytes) + ". Supplied size: " + toString(sizeBytes));
 		}
 
-		GpuParamBlockBufferPtr paramBlock = mParamBlocks[desc->paramBlockSlot];
+		GpuParamBlockPtr paramBlock = mParamBlocks[desc->paramBlockSlot];
 
 		if(paramBlock == nullptr)
 		{
@@ -278,10 +282,13 @@ namespace CamelotEngine
 	void GpuParams::updateIfDirty()
 	{
 		for(size_t i = 0; i < mParamBlocks.size(); i++)
-			mParamBlocks[i]->updateIfDirty();
+		{
+			if(mParamBlocks[i] != nullptr)
+				mParamBlocks[i]->updateIfDirty();
+		}
 	}
 
-	GpuParamMemberDesc* GpuParams::getParamDesc(const String& name) const
+	GpuParamDataDesc* GpuParams::getParamDesc(const String& name) const
 	{
 		auto paramIter = mParamDesc.params.find(name);
 		if(paramIter != mParamDesc.params.end())

+ 519 - 34
CamelotRenderer/Source/CmMaterial.cpp

@@ -5,8 +5,11 @@
 #include "CmPass.h"
 #include "CmRenderSystem.h"
 #include "CmGpuProgramParams.h"
+#include "CmHardwareBufferManager.h"
 #include "CmGpuProgram.h"
+#include "CmGpuParamDesc.h"
 #include "CmMaterialRTTI.h"
+#include "CmDebug.h"
 
 namespace CamelotEngine
 {
@@ -31,65 +34,451 @@ namespace CamelotEngine
 	void Material::initBestTechnique()
 	{
 		mBestTechnique = nullptr;
-		mParameters.clear();
+		mParametersPerPass.clear();
 
 		if(mShader)
 		{
 			mBestTechnique = mShader->getBestTechnique();
 
-			if(mBestTechnique)
+			if(mBestTechnique == nullptr)
+				return;
+
+			mValidShareableParamBlocks.clear();
+			mValidParams.clear();
+
+			vector<const GpuParamDesc*>::type allParamDescs;
+
+			// Make sure all gpu programs are fully loaded
+			for(UINT32 i = 0; i < mBestTechnique->getNumPasses(); i++)
+			{
+				PassPtr curPass = mBestTechnique->getPass(i);
+
+				GpuProgramHandle vertProgram = curPass->getVertexProgram();
+				if(vertProgram)
+				{
+					vertProgram.waitUntilLoaded();
+					allParamDescs.push_back(&vertProgram->getParamDesc());
+				}
+
+				GpuProgramHandle fragProgram = curPass->getFragmentProgram();
+				if(fragProgram)
+				{
+					fragProgram.waitUntilLoaded();
+					allParamDescs.push_back(&fragProgram->getParamDesc());
+				}
+
+				GpuProgramHandle geomProgram = curPass->getGeometryProgram();
+				if(geomProgram)
+				{
+					geomProgram.waitUntilLoaded();
+					allParamDescs.push_back(&geomProgram->getParamDesc());
+				}
+
+				GpuProgramHandle hullProgram = curPass->getHullProgram();
+				if(hullProgram)
+				{
+					hullProgram.waitUntilLoaded();
+					allParamDescs.push_back(&hullProgram->getParamDesc());
+				}
+
+				GpuProgramHandle domainProgram = curPass->getDomainProgram();
+				if(domainProgram)
+				{
+					domainProgram.waitUntilLoaded();
+					allParamDescs.push_back(&domainProgram->getParamDesc());
+				}
+
+				GpuProgramHandle computeProgram = curPass->getComputeProgram();
+				if(computeProgram)
+				{
+					computeProgram.waitUntilLoaded();
+					allParamDescs.push_back(&computeProgram->getParamDesc());
+				}
+			}
+
+			set<String>::type validParameters = determineValidParameters(allParamDescs);
+			set<String>::type validShareableParamBlocks = determineValidShareableParamBlocks(allParamDescs);
+			map<String, String>::type paramToParamBlockMap = determineParameterToBlockMapping(allParamDescs);
+			map<String, GpuParamBlockPtr>::type paramBlocks;
+
+			// Create param blocks
+			const map<String, SHADER_PARAM_BLOCK_DESC>::type& shaderDesc = mShader->getParamBlocks();
+			for(auto iter = validShareableParamBlocks.begin(); iter != validShareableParamBlocks.end(); ++iter)
+			{
+				bool isShared = false;
+				GpuParamBlockUsage usage = GPBU_STATIC;
+
+				auto iterFind = shaderDesc.find(*iter);
+				if(iterFind != shaderDesc.end())
+				{
+					isShared = iterFind->second.shared;
+					usage = iterFind->second.usage;
+				}
+
+				GpuParamBlockDesc blockDesc;
+				for(auto iter2 = allParamDescs.begin(); iter2 != allParamDescs.end(); ++iter2)
+				{
+					auto findParamBlockDesc = (*iter2)->paramBlocks.find(*iter);
+
+					if(findParamBlockDesc != (*iter2)->paramBlocks.end())
+					{
+						blockDesc = findParamBlockDesc->second;
+						break;
+					}
+				}
+
+				GpuParamBlockPtr newParamBlockBuffer;
+				if(!isShared)
+					newParamBlockBuffer = HardwareBufferManager::instance().createGpuParamBlock(blockDesc, usage);
+
+				paramBlocks[*iter] = newParamBlockBuffer;
+				mValidShareableParamBlocks.insert(*iter);
+			}
+
+			// Create data param mappings
+			const map<String, SHADER_DATA_PARAM_DESC>::type& dataParamDesc = mShader->getDataParams();
+			for(auto iter = dataParamDesc.begin(); iter != dataParamDesc.end(); ++iter)
+			{
+				auto findIter = validParameters.find(iter->first);
+
+				// Not valid so we skip it
+				if(findIter == validParameters.end())
+					continue;
+
+				auto findBlockIter = paramToParamBlockMap.find(iter->first);
+
+				if(findBlockIter == paramToParamBlockMap.end())
+					CM_EXCEPT(InternalErrorException, "Parameter doesn't exist in param to param block map but exists in valid param map.");
+
+				String& paramBlockName = findBlockIter->second;
+				mValidParams.insert(iter->first);
+			}
+
+			// Create object param mappings
+			const map<String, SHADER_OBJECT_PARAM_DESC>::type& objectParamDesc = mShader->getObjectParams();
+			for(auto iter = objectParamDesc.begin(); iter != objectParamDesc.end(); ++iter)
+			{
+				auto findIter = validParameters.find(iter->first);
+
+				// Not valid so we skip it
+				if(findIter == validParameters.end())
+					continue;
+
+				mValidParams.insert(iter->first);
+			}
+
+			for(UINT32 i = 0; i < mBestTechnique->getNumPasses(); i++)
 			{
-				for(UINT32 i = 0; i < mBestTechnique->getNumPasses(); i++)
+				PassPtr curPass = mBestTechnique->getPass(i);
+				PassParametersPtr params = PassParametersPtr(new PassParameters());
+
+				GpuProgramHandle vertProgram = curPass->getVertexProgram();
+				if(vertProgram)
+					params->mVertParams = vertProgram->createParameters();
+
+				GpuProgramHandle fragProgram = curPass->getFragmentProgram();
+				if(fragProgram)
+					params->mFragParams = fragProgram->createParameters();
+
+				GpuProgramHandle geomProgram = curPass->getGeometryProgram();
+				if(geomProgram)
+					params->mGeomParams = geomProgram->createParameters();	
+
+				GpuProgramHandle hullProgram = curPass->getHullProgram();
+				if(hullProgram)
+					params->mHullParams = hullProgram->createParameters();
+
+				GpuProgramHandle domainProgram = curPass->getDomainProgram();
+				if(domainProgram)
+					params->mDomainParams = domainProgram->createParameters();
+
+				GpuProgramHandle computeProgram = curPass->getComputeProgram();
+				if(computeProgram)
+					params->mComputeParams = computeProgram->createParameters();	
+
+				mParametersPerPass.push_back(params);
+			}
+
+			// Assign param block buffers
+			for(auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+			{
+				PassParametersPtr params = *iter;
+
+				for(UINT32 i = 0; i < params->getNumParams(); i++)
 				{
-					PassPtr curPass = mBestTechnique->getPass(i);
-					PassParametersPtr params = PassParametersPtr(new PassParameters());
+					GpuParamsPtr& paramPtr = params->getParamByIdx(i);
+					if(paramPtr)
+					{
+						// Assign shareable buffers
+						for(auto iterBlock = mValidShareableParamBlocks.begin(); iterBlock != mValidShareableParamBlocks.end(); ++iterBlock)
+						{
+							const String& paramBlockName = *iterBlock;
+							if(paramPtr->hasParamBlock(paramBlockName))
+							{
+								GpuParamBlockPtr blockBuffer = paramBlocks[paramBlockName];
+
+								paramPtr->setParamBlock(paramBlockName, blockBuffer);
+							}
+						}
+
+						// Create non-shareable ones
+						const GpuParamDesc& desc = paramPtr->getParamDesc();
+						for(auto iterBlockDesc = desc.paramBlocks.begin(); iterBlockDesc != desc.paramBlocks.end(); ++iterBlockDesc)
+						{
+							if(!iterBlockDesc->second.isShareable)
+							{
+								GpuParamBlockPtr newParamBlockBuffer = HardwareBufferManager::instance().createGpuParamBlock(iterBlockDesc->second);
+								paramPtr->setParamBlock(iterBlockDesc->first, newParamBlockBuffer);
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	set<String>::type Material::determineValidParameters(const vector<const GpuParamDesc*>::type& paramDescs) const
+	{
+		map<String, const GpuParamDataDesc*>::type foundDataParams;
+		map<String, const GpuParamObjectDesc*>::type foundObjectParams;
+
+		set<String>::type validParameters;
 
-					GpuProgramHandle vertProgram = curPass->getVertexProgram();
-					if(vertProgram)
+		for(auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
+		{
+			const GpuParamDesc& curDesc = **iter;
+
+			// Check regular data params
+			for(auto iter2 = curDesc.params.begin(); iter2 != curDesc.params.end(); ++iter2)
+			{
+				bool isParameterValid = true;
+				const GpuParamDataDesc& curParam = iter2->second;
+
+				auto objectFindIter = foundObjectParams.find(iter2->first);
+				if(objectFindIter != foundObjectParams.end())
+					isParameterValid = false; // Data param but we found another as object param with the same name
+
+				if(isParameterValid)
+				{
+					auto dataFindIter = foundDataParams.find(iter2->first);
+					if(dataFindIter == foundDataParams.end())
+						validParameters.insert(iter2->first);
+					else
 					{
-						vertProgram.waitUntilLoaded();
-						params->mVertParams = vertProgram->createParameters();
+						const GpuParamDataDesc* otherParam = dataFindIter->second;
+						if(!areParamsEqual(curParam, *otherParam, true))
+							isParameterValid = false;
 					}
+				}
+
+				if(!isParameterValid)
+					validParameters.erase(iter2->first);
+			}
+
+			// Check sampler params
+			for(auto iter2 = curDesc.samplers.begin(); iter2 != curDesc.samplers.end(); ++iter2)
+			{
+				bool isParameterValid = true;
+				const GpuParamObjectDesc& curParam = iter2->second;
+
+				auto dataFindIter = foundDataParams.find(iter2->first);
+				if(dataFindIter != foundDataParams.end())
+					isParameterValid = false; // Object param but we found another as data param with the same name
+
+				if(isParameterValid)
+				{
+					auto objectFindIter = foundObjectParams.find(iter2->first);
+					if(objectFindIter == foundObjectParams.end())
+						validParameters.insert(iter2->first);
+					else
+					{
+						const GpuParamObjectDesc* otherParam = objectFindIter->second;
+						if(!areParamsEqual(curParam, *otherParam))
+							isParameterValid = false;
+					}
+				}
+
+				if(!isParameterValid)
+					validParameters.erase(iter2->first);
+			}
+
+			// Check texture params
+			for(auto iter2 = curDesc.textures.begin(); iter2 != curDesc.textures.end(); ++iter2)
+			{
+				bool isParameterValid = true;
+				const GpuParamObjectDesc& curParam = iter2->second;
+
+				auto dataFindIter = foundDataParams.find(iter2->first);
+				if(dataFindIter != foundDataParams.end())
+					isParameterValid = false; // Object param but we found another as data param with the same name
+
+				if(isParameterValid)
+				{
+					auto objectFindIter = foundObjectParams.find(iter2->first);
+					if(objectFindIter == foundObjectParams.end())
+						validParameters.insert(iter2->first);
+					else
+					{
+						const GpuParamObjectDesc* otherParam = objectFindIter->second;
+						if(!areParamsEqual(curParam, *otherParam))
+							isParameterValid = false;
+					}
+				}
+
+				if(!isParameterValid)
+					validParameters.erase(iter2->first);
+			}
+
+			// Check buffer params
+			for(auto iter2 = curDesc.buffers.begin(); iter2 != curDesc.buffers.end(); ++iter2)
+			{
+				bool isParameterValid = true;
+				const GpuParamObjectDesc& curParam = iter2->second;
 
-					GpuProgramHandle fragProgram = curPass->getFragmentProgram();
-					if(fragProgram)
+				auto dataFindIter = foundDataParams.find(iter2->first);
+				if(dataFindIter != foundDataParams.end())
+					isParameterValid = false; // Object param but we found another as data param with the same name
+
+				if(isParameterValid)
+				{
+					auto objectFindIter = foundObjectParams.find(iter2->first);
+					if(objectFindIter == foundObjectParams.end())
+						validParameters.insert(iter2->first);
+					else
 					{
-						fragProgram.waitUntilLoaded();
-						params->mFragParams = fragProgram->createParameters();
+						const GpuParamObjectDesc* otherParam = objectFindIter->second;
+						if(!areParamsEqual(curParam, *otherParam))
+							isParameterValid = false;
 					}
+				}
 
-					GpuProgramHandle geomProgram = curPass->getGeometryProgram();
-					if(geomProgram)
+				if(!isParameterValid)
+				{
+					auto validParamIter = validParameters.find(iter2->first);
+
+					if(validParamIter != validParameters.end()) // Do this check so we only report this error once
 					{
-						geomProgram.waitUntilLoaded();
-						params->mGeomParams = geomProgram->createParameters();	
+						LOGWRN("Found two parameters with the same name but different contents: " + iter2->first);
+						validParameters.erase(validParamIter);
 					}
+				}
+			}
+		}
+
+		return validParameters;
+	}
+
+	set<String>::type Material::determineValidShareableParamBlocks(const vector<const GpuParamDesc*>::type& paramDescs) const
+	{
+		// Make sure param blocks with the same name actually are the same
+		map<String, std::pair<String, const GpuParamDesc*>>::type uniqueParamBlocks;
+		set<String>::type validParamBlocks;
+
+		for(auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
+		{
+			const GpuParamDesc& curDesc = **iter;
+			for(auto blockIter = curDesc.paramBlocks.begin(); blockIter != curDesc.paramBlocks.end(); ++blockIter)
+			{
+				bool isBlockValid = true;
+				const GpuParamBlockDesc& curBlock = blockIter->second;
+
+				if(!curBlock.isShareable) // Non-shareable buffers are handled differently, they're allowed same names
+					continue;
+
+				auto iterFind = uniqueParamBlocks.find(blockIter->first);
+				if(iterFind == uniqueParamBlocks.end())
+				{
+					uniqueParamBlocks[blockIter->first] = std::make_pair(blockIter->first, *iter);
+					validParamBlocks.insert(blockIter->first);
+					continue;
+				}
+
+				String otherBlockName = iterFind->second.first;
+				const GpuParamDesc* otherDesc = iterFind->second.second;
 
-					GpuProgramHandle hullProgram = curPass->getHullProgram();
-					if(hullProgram)
+				for(auto myParamIter = curDesc.params.begin(); myParamIter != curDesc.params.end(); ++myParamIter)
+				{
+					const GpuParamDataDesc& myParam = myParamIter->second;
+
+					if(myParam.paramBlockSlot != curBlock.slot)
+						continue; // Param is in another block, so we will check it when its time for that block
+
+					auto otherParamFind = otherDesc->params.find(myParamIter->first);
+
+					// Cannot find other param, blocks aren't equal
+					if(otherParamFind == otherDesc->params.end())
 					{
-						hullProgram.waitUntilLoaded();
-						params->mHullParams = hullProgram->createParameters();
+						isBlockValid = false;
+						break;
 					}
 
-					GpuProgramHandle domainProgram = curPass->getDomainProgram();
-					if(domainProgram)
+					const GpuParamDataDesc& otherParam = otherParamFind->second;
+
+					if(!areParamsEqual(myParam, otherParam) || curBlock.name != otherBlockName)
 					{
-						domainProgram.waitUntilLoaded();
-						params->mDomainParams = domainProgram->createParameters();
+						isBlockValid = false;
+						break;
 					}
+				}
 
-					GpuProgramHandle computeProgram = curPass->getComputeProgram();
-					if(computeProgram)
+				if(!isBlockValid)
+				{
+					auto blockValidIter = validParamBlocks.find(blockIter->first);
+
+					if(blockValidIter != validParamBlocks.end()) // Do this check so we only report this error once
 					{
-						computeProgram.waitUntilLoaded();
-						params->mComputeParams = computeProgram->createParameters();	
+						LOGWRN("Found two param blocks with the same name but different contents: " + blockIter->first);
+						validParamBlocks.erase(blockValidIter);
 					}
+				}
+			}
+		}
+
+		return validParamBlocks;
+	}
 
-					mParameters.push_back(params);
+	map<String, String>::type Material::determineParameterToBlockMapping(const vector<const GpuParamDesc*>::type& paramDescs)
+	{
+		map<String, String>::type paramToParamBlock;
+
+		for(auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
+		{
+			const GpuParamDesc& curDesc = **iter;
+			for(auto iter2 = curDesc.params.begin(); iter2 != curDesc.params.end(); ++iter2)
+			{
+				const GpuParamDataDesc& curParam = iter2->second;
+				
+				auto iterFind = paramToParamBlock.find(curParam.name);
+				if(iterFind != paramToParamBlock.end())
+					continue;
+
+				for(auto iterBlock = curDesc.paramBlocks.begin(); iterBlock != curDesc.paramBlocks.end(); ++iterBlock)
+				{
+					if(iterBlock->second.slot == curParam.paramBlockSlot)
+					{
+						paramToParamBlock[curParam.name] = iterBlock->second.name;
+						break;
+					}
 				}
 			}
 		}
+
+		return paramToParamBlock;
+	}
+
+	bool Material::areParamsEqual(const GpuParamDataDesc& paramA, const GpuParamDataDesc& paramB, bool ignoreBufferOffsets) const
+	{
+		bool equal = paramA.arraySize == paramB.arraySize && paramA.elementSize == paramB.elementSize && paramA.type == paramB.type;
+
+		if(!ignoreBufferOffsets)
+			equal &= paramA.cpuMemOffset == paramB.cpuMemOffset && paramA.gpuMemOffset == paramB.gpuMemOffset;
+
+		return equal;
+	}
+
+	bool Material::areParamsEqual(const GpuParamObjectDesc& paramA, const GpuParamObjectDesc& paramB) const
+	{
+		return paramA.type == paramB.type;
 	}
 
 	void Material::throwIfNotInitialized() const
@@ -109,7 +498,14 @@ namespace CamelotEngine
 	{
 		throwIfNotInitialized();
 
-		for(auto iter = mParameters.begin(); iter != mParameters.end(); ++iter)
+		auto iterFind = mValidParams.find(name);
+		if(iterFind == mValidParams.end())
+		{
+			LOGWRN("Material doesn't have a parameter named " + name);
+			return;
+		}
+
+		for(auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
 		{
 			PassParametersPtr params = *iter;
 
@@ -129,7 +525,14 @@ namespace CamelotEngine
 	{
 		throwIfNotInitialized();
 
-		for(auto iter = mParameters.begin(); iter != mParameters.end(); ++iter)
+		auto iterFind = mValidParams.find(name);
+		if(iterFind == mValidParams.end())
+		{
+			LOGWRN("Material doesn't have a parameter named " + name);
+			return;
+		}
+
+		for(auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
 		{
 			PassParametersPtr params = *iter;
 
@@ -148,45 +551,127 @@ namespace CamelotEngine
 	void Material::setFloat(const String& name, float value)
 	{
 		throwIfNotInitialized();
+
+		auto iterFind = mValidParams.find(name);
+		if(iterFind == mValidParams.end())
+		{
+			LOGWRN("Material doesn't have a parameter named " + name);
+			return;
+		}
+
 		setParam(name, value);
 	}
 
 	void Material::setColor(const String& name, const Color& value)
 	{
 		throwIfNotInitialized();
+
+		auto iterFind = mValidParams.find(name);
+		if(iterFind == mValidParams.end())
+		{
+			LOGWRN("Material doesn't have a parameter named " + name);
+			return;
+		}
+
 		setParam(name, value);
 	}
 
 	void Material::setVec2(const String& name, const Vector2& value)
 	{
 		throwIfNotInitialized();
+
+		auto iterFind = mValidParams.find(name);
+		if(iterFind == mValidParams.end())
+		{
+			LOGWRN("Material doesn't have a parameter named " + name);
+			return;
+		}
+
 		setParam(name, value);
 	}
 
 	void Material::setVec3(const String& name, const Vector3& value)
 	{
 		throwIfNotInitialized();
+
+		auto iterFind = mValidParams.find(name);
+		if(iterFind == mValidParams.end())
+		{
+			LOGWRN("Material doesn't have a parameter named " + name);
+			return;
+		}
+
 		setParam(name, value);
 	}
 
 	void Material::setVec4(const String& name, const Vector4& value)
 	{
 		throwIfNotInitialized();
+
+		auto iterFind = mValidParams.find(name);
+		if(iterFind == mValidParams.end())
+		{
+			LOGWRN("Material doesn't have a parameter named " + name);
+			return;
+		}
+
 		setParam(name, value);
 	}
 
 	void Material::setMat3(const String& name, const Matrix3& value)
 	{
 		throwIfNotInitialized();
+
+		auto iterFind = mValidParams.find(name);
+		if(iterFind == mValidParams.end())
+		{
+			LOGWRN("Material doesn't have a parameter named " + name);
+			return;
+		}
+
 		setParam(name, value);
 	}
 
 	void Material::setMat4(const String& name, const Matrix4& value)
 	{
 		throwIfNotInitialized();
+
+		auto iterFind = mValidParams.find(name);
+		if(iterFind == mValidParams.end())
+		{
+			LOGWRN("Material doesn't have a parameter named " + name);
+			return;
+		}
+
 		setParam(name, value);
 	}
 
+
+	void Material::setParamBlock(const String& name, GpuParamBlockPtr paramBlock)
+	{
+		auto iterFind = mValidShareableParamBlocks.find(name);
+		if(iterFind == mValidShareableParamBlocks.end())
+		{
+			LOGWRN("Material doesn't have a parameter block named " + name);
+			return;
+		}
+
+		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->hasParamBlock(name))
+						paramPtr->setParam(name, paramBlock);
+				}
+			}
+		}
+	}
+
 	UINT32 Material::getNumPasses() const
 	{
 		throwIfNotInitialized();
@@ -204,10 +689,10 @@ namespace CamelotEngine
 
 	PassParametersPtr Material::getPassParameters(UINT32 passIdx) const
 	{
-		if(passIdx < 0 || passIdx >= mParameters.size())
+		if(passIdx < 0 || passIdx >= mParametersPerPass.size())
 			CM_EXCEPT(InvalidParametersException, "Invalid pass index.");
 
-		return mParameters[passIdx];
+		return mParametersPerPass[passIdx];
 	}
 
 	RTTITypeBase* Material::getRTTIStatic()

+ 18 - 18
CamelotRenderer/Source/CmMaterialRTTI.cpp

@@ -19,17 +19,17 @@ namespace CamelotEngine
 		std::shared_ptr<MaterialParams> params = std::shared_ptr<MaterialParams>(new MaterialParams());
 
 		vector<GpuParamsPtr>::type allParams;
-		for(size_t i = 0; i < material->mParameters.size(); i++)
-		{
-			if(material->mParameters[i]->mFragParams != nullptr)
-				allParams.push_back(material->mParameters[i]->mFragParams);
+		//for(size_t i = 0; i < material->mParameters.size(); i++)
+		//{
+		//	if(material->mParameters[i]->mFragParams != nullptr)
+		//		allParams.push_back(material->mParameters[i]->mFragParams);
 
-			if(material->mParameters[i]->mVertParams != nullptr)
-				allParams.push_back(material->mParameters[i]->mVertParams);
+		//	if(material->mParameters[i]->mVertParams != nullptr)
+		//		allParams.push_back(material->mParameters[i]->mVertParams);
 
-			if(material->mParameters[i]->mGeomParams != nullptr)
-				allParams.push_back(material->mParameters[i]->mGeomParams);
-		}
+		//	if(material->mParameters[i]->mGeomParams != nullptr)
+		//		allParams.push_back(material->mParameters[i]->mGeomParams);
+		//}
 
 		for(size_t i = 0; i < allParams.size(); i++)
 		{
@@ -128,17 +128,17 @@ namespace CamelotEngine
 		std::shared_ptr<MaterialParams> params = boost::any_cast<std::shared_ptr<MaterialParams>>(material->mRTTIData);
 
 		vector<GpuParamsPtr>::type allParams;
-		for(size_t i = 0; i < material->mParameters.size(); i++)
-		{
-			if(material->mParameters[i]->mFragParams != nullptr)
-				allParams.push_back(material->mParameters[i]->mFragParams);
+		//for(size_t i = 0; i < material->mParameters.size(); i++)
+		//{
+		//	if(material->mParameters[i]->mFragParams != nullptr)
+		//		allParams.push_back(material->mParameters[i]->mFragParams);
 
-			if(material->mParameters[i]->mVertParams != nullptr)
-				allParams.push_back(material->mParameters[i]->mVertParams);
+		//	if(material->mParameters[i]->mVertParams != nullptr)
+		//		allParams.push_back(material->mParameters[i]->mVertParams);
 
-			if(material->mParameters[i]->mGeomParams != nullptr)
-				allParams.push_back(material->mParameters[i]->mGeomParams);
-		}
+		//	if(material->mParameters[i]->mGeomParams != nullptr)
+		//		allParams.push_back(material->mParameters[i]->mGeomParams);
+		//}
 
 		for(size_t i = 0; i < allParams.size(); i++)
 		{

+ 40 - 0
CamelotRenderer/Source/CmShader.cpp

@@ -64,6 +64,46 @@ namespace CamelotEngine
 		// TODO - Low priority. Instead of throwing an exception use an extremely simple technique that will be supported almost everywhere as a fallback.
 	}
 
+	void Shader::addParameter(const String& name, const String& gpuVariableName, GpuParamDataType type, UINT32 arraySize, bool hidden)
+	{
+		SHADER_DATA_PARAM_DESC desc;
+		desc.name = name;
+		desc.gpuVariableName = gpuVariableName;
+		desc.type = type;
+		desc.arraySize = arraySize;
+		desc.hidden = hidden;
+
+		mDataParams[name] = desc;
+		mObjectParams.erase(name);
+	}
+
+	void Shader::addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, bool hidden)
+	{
+		SHADER_OBJECT_PARAM_DESC desc;
+		desc.name = name;
+		desc.gpuVariableName = gpuVariableName;
+		desc.type = type;
+		desc.hidden = hidden;
+
+		mObjectParams[name] = desc;
+		mDataParams.erase(name);
+	}
+
+	void Shader::removeParameter(const String& name)
+	{
+		mDataParams.erase(name);
+		mObjectParams.erase(name);
+	}
+
+	void Shader::setParamBlockAttribs(const String& name, bool shared, GpuParamBlockUsage usage)
+	{
+		SHADER_PARAM_BLOCK_DESC desc;
+		desc.shared = shared;
+		desc.usage = usage;
+
+		mParamBlocks[name] = desc;
+	}
+
 	RTTITypeBase* Shader::getRTTIStatic()
 	{
 		return ShaderRTTI::instance();

+ 4 - 20
CamelotRenderer/TODO.txt

@@ -50,6 +50,10 @@ Stuff that needs destroy():
   - Shader
   - Technique
 
+GpuParamBlock usage is provided in the constructor but isn't used anywhere
+DX9 will have the same name for sampler and texture. This will cause an error in Material param checking.
+DX9 might have problems with checking if buffers are equal. Probably need to ignore "Global" param block
+
 
 Add support for include file resource
 Make sure we can add an include file to a HighLevelGpuProgram, and make sure it uses it
@@ -58,26 +62,6 @@ Make sure we can add an include file to a HighLevelGpuProgram, and make sure it
 Make Raster/DepthStencil/Blend/Sampler states resources
 Make Shader a resource
 
-Make GpuParamBlock a resource
- - Static/Dynamic usage for GpuParamBlock
- - rename current GpuParamBlock into GpuParamBlockBuffer
- - add new class GpuParamBlock that has addParameter(name, gpuProgramVariable, type, visible)
- - it stores data on per-parameter basis
- - it is a Resource and is serializable
- - in Material when an actual technique is chosen, GpuParamBlockBuffer is bound to GpuParamBlock
-
-Shader::addParamBlock(name, GPU_PARAM_BLOCK_DESC, bool shared)
- - If its shared it won't be instantiated manually when material chooses an actual technique
- - When this method is called we check if any parameter rules are broken:
-   - Ignore missing variables from a param block (weaker techniques might not need them all)
-   - Throw an error if the specified variables come from two different param blocks
-   - Global block should be special to accomodate DX9 shaders
-Shader::addParameter(name, gpuVariableName, type, visible) - Only for objects like textures/buffers/samplers
-
-Material::setParameter - does what it did so far
-Material::setSharedGpuParamBlock(name, GpuParamBlock) - makes he specified block share the data
-
-
  Refactor how we handle RenderTargets (no attach/detach, and no waitForVSync propery in RenderSystem)
  waitForVsync can probably be moved somewhere other than being directly in RenderSystem? (where is it in DX11?)