ソースを参照

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

Marko Pintera 13 年 前
コミット
4ec92954ca
35 ファイル変更1043 行追加428 行削除
  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?)