Browse Source

Moved GLSL param parsing into a separate file
Added GLSL attribute parsing

Marko Pintera 13 years ago
parent
commit
c06e053b50

+ 42 - 42
CamelotClient/CamelotClient.cpp

@@ -26,8 +26,8 @@ using namespace CamelotEngine;
 
 
 int _tmain(int argc, _TCHAR* argv[])
 int _tmain(int argc, _TCHAR* argv[])
 {
 {
-	//gApplication().startUp("CamelotGLRenderSystem", "CamelotForwardRenderer");
-	gApplication().startUp("CamelotD3D9RenderSystem", "CamelotForwardRenderer");
+	gApplication().startUp("CamelotGLRenderSystem", "CamelotForwardRenderer");
+	//gApplication().startUp("CamelotD3D9RenderSystem", "CamelotForwardRenderer");
 
 
 	RenderSystem* renderSystem = RenderSystem::instancePtr();
 	RenderSystem* renderSystem = RenderSystem::instancePtr();
 	RenderWindowPtr renderWindow = gApplication().getPrimaryRenderWindow();
 	RenderWindowPtr renderWindow = gApplication().getPrimaryRenderWindow();
@@ -50,27 +50,27 @@ int _tmain(int argc, _TCHAR* argv[])
 	HighLevelGpuProgramPtr vertProg;
 	HighLevelGpuProgramPtr vertProg;
 
 
 	/////////////////// HLSL SHADERS //////////////////////////
 	/////////////////// HLSL SHADERS //////////////////////////
-	String fragShaderCode = "sampler2D tex;			\
-							float4 ps_main(float2 uv : TEXCOORD0) : COLOR0		\
-							{														\
-							float4 color = tex2D(tex, uv);				\
-							return color;										\
-							}";
-
-	fragProg =  HighLevelGpuProgram::create(fragShaderCode, "ps_main", "hlsl", GPT_FRAGMENT_PROGRAM, GPP_PS_2_0);
-
-	String vertShaderCode = "float4x4 matViewProjection;	\
-							void vs_main(										\
-							float4 inPos : POSITION,							\
-							float2 uv : TEXCOORD0,								\
-							out float4 oPosition : POSITION,					\
-							out float2 oUv : TEXCOORD0)							\
-							{														\
-							oPosition = mul(matViewProjection, inPos);			\
-							oUv = uv;											\
-							}";
-
-	vertProg =  HighLevelGpuProgram::create(vertShaderCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
+	//String fragShaderCode = "sampler2D tex;			\
+	//						float4 ps_main(float2 uv : TEXCOORD0) : COLOR0		\
+	//						{														\
+	//						float4 color = tex2D(tex, uv);				\
+	//						return color;										\
+	//						}";
+
+	//fragProg =  HighLevelGpuProgram::create(fragShaderCode, "ps_main", "hlsl", GPT_FRAGMENT_PROGRAM, GPP_PS_2_0);
+
+	//String vertShaderCode = "float4x4 matViewProjection;	\
+	//						void vs_main(										\
+	//						float4 inPos : POSITION,							\
+	//						float2 uv : TEXCOORD0,								\
+	//						out float4 oPosition : POSITION,					\
+	//						out float2 oUv : TEXCOORD0)							\
+	//						{														\
+	//						oPosition = mul(matViewProjection, inPos);			\
+	//						oUv = uv;											\
+	//						}";
+
+	//vertProg =  HighLevelGpuProgram::create(vertShaderCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
 
 
 	/////////////////// CG SHADERS //////////////////////////
 	/////////////////// CG SHADERS //////////////////////////
 	//String fragShaderCode = "sampler2D tex;					\
 	//String fragShaderCode = "sampler2D tex;					\
@@ -96,25 +96,25 @@ int _tmain(int argc, _TCHAR* argv[])
 	//vertProg =  HighLevelGpuProgram::create(vertShaderCode, "vs_main", "cg", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
 	//vertProg =  HighLevelGpuProgram::create(vertShaderCode, "vs_main", "cg", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
 
 
 	///////////////// GLSL SHADERS ////////////////////////////
 	///////////////// GLSL SHADERS ////////////////////////////
-	//String fragShaderCode = "uniform sampler2D tex; \
-	//							void main() \
-	//							  {\
-	//							  vec4 texColor = texture2D(tex,gl_TexCoord[0].st);\
-	//							  gl_FragColor = texColor; \
-	//							  }";
-
-	//fragProg = HighLevelGpuProgram::create(fragShaderCode, "main", "glsl", GPT_FRAGMENT_PROGRAM, GPP_PS_2_0);
-
-	//// TODO - Ogres GLSL parsing requires some strict parameter naming, can that be avoided?
-	//String vertShaderCode = "uniform mat4 matViewProjection; \
-	//							  attribute vec4 vertex; \
-	//						void main() \
-	//							  { \
-	//							  gl_TexCoord[0] = gl_MultiTexCoord0; \
-	//							  gl_Position = matViewProjection * vertex; \
-	//							  }";
-
-	//vertProg = HighLevelGpuProgram::create(vertShaderCode, "main", "glsl", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
+	String fragShaderCode = "uniform sampler2D tex; \
+								void main() \
+								  {\
+								  vec4 texColor = texture2D(tex,gl_TexCoord[0].st);\
+								  gl_FragColor = texColor; \
+								  }";
+
+	fragProg = HighLevelGpuProgram::create(fragShaderCode, "main", "glsl", GPT_FRAGMENT_PROGRAM, GPP_PS_2_0);
+
+	// TODO - Ogres GLSL parsing requires some strict parameter naming, can that be avoided?
+	String vertShaderCode = "uniform mat4 matViewProjection; \
+								  attribute vec4 vertex; \
+							void main() \
+								  { \
+								  gl_TexCoord[0] = gl_MultiTexCoord0; \
+								  gl_Position = matViewProjection * vertex; \
+								  }";
+
+	vertProg = HighLevelGpuProgram::create(vertShaderCode, "main", "glsl", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
 
 
 	HighLevelGpuProgramHandle vertProgRef(vertProg);
 	HighLevelGpuProgramHandle vertProgRef(vertProg);
 
 

+ 4 - 4
CamelotD3D11RenderSystem/Source/CmD3D11Mappings.cpp

@@ -378,13 +378,13 @@ namespace CamelotEngine
 		if( strcmp(sem, "BLENDWEIGHT") == 0 )
 		if( strcmp(sem, "BLENDWEIGHT") == 0 )
 			return VES_BLEND_WEIGHTS;
 			return VES_BLEND_WEIGHTS;
 		if( strcmp(sem, "COLOR") == 0 )
 		if( strcmp(sem, "COLOR") == 0 )
-			return VES_DIFFUSE;
+			return VES_COLOR;
 		if( strcmp(sem, "NORMAL") == 0 )
 		if( strcmp(sem, "NORMAL") == 0 )
 			return VES_NORMAL;
 			return VES_NORMAL;
 		if( strcmp(sem, "POSITION") == 0 )
 		if( strcmp(sem, "POSITION") == 0 )
 			return VES_POSITION;
 			return VES_POSITION;
 		if( strcmp(sem, "TEXCOORD") == 0 )
 		if( strcmp(sem, "TEXCOORD") == 0 )
-			return VES_TEXTURE_COORDINATES;
+			return VES_TEXCOORD;
 		if( strcmp(sem, "BINORMAL") == 0 )
 		if( strcmp(sem, "BINORMAL") == 0 )
 			return VES_BITANGENT;
 			return VES_BITANGENT;
 		if( strcmp(sem, "TANGENT") == 0 )
 		if( strcmp(sem, "TANGENT") == 0 )
@@ -410,7 +410,7 @@ namespace CamelotEngine
 		case VES_BLEND_WEIGHTS:
 		case VES_BLEND_WEIGHTS:
 			return "BLENDWEIGHT";
 			return "BLENDWEIGHT";
 			break;
 			break;
-		case VES_DIFFUSE:
+		case VES_COLOR:
 			return "COLOR"; // NB index will differentiate
 			return "COLOR"; // NB index will differentiate
 			break;
 			break;
 		case VES_SPECULAR:
 		case VES_SPECULAR:
@@ -422,7 +422,7 @@ namespace CamelotEngine
 		case VES_POSITION:
 		case VES_POSITION:
 			return "POSITION";
 			return "POSITION";
 			break;
 			break;
-		case VES_TEXTURE_COORDINATES:
+		case VES_TEXCOORD:
 			return "TEXCOORD";
 			return "TEXCOORD";
 			break;
 			break;
 		case VES_BITANGENT:
 		case VES_BITANGENT:

+ 2 - 2
CamelotD3D9Renderer/Source/CmD3D9Mappings.cpp

@@ -428,7 +428,7 @@ namespace CamelotEngine
 		case VES_BLEND_WEIGHTS:
 		case VES_BLEND_WEIGHTS:
 			return D3DDECLUSAGE_BLENDWEIGHT;
 			return D3DDECLUSAGE_BLENDWEIGHT;
 			break;
 			break;
-		case VES_DIFFUSE:
+		case VES_COLOR:
 			return D3DDECLUSAGE_COLOR; // NB index will differentiate
 			return D3DDECLUSAGE_COLOR; // NB index will differentiate
 			break;
 			break;
 		case VES_SPECULAR:
 		case VES_SPECULAR:
@@ -440,7 +440,7 @@ namespace CamelotEngine
 		case VES_POSITION:
 		case VES_POSITION:
 			return D3DDECLUSAGE_POSITION;
 			return D3DDECLUSAGE_POSITION;
 			break;
 			break;
-		case VES_TEXTURE_COORDINATES:
+		case VES_TEXCOORD:
 			return D3DDECLUSAGE_TEXCOORD;
 			return D3DDECLUSAGE_TEXCOORD;
 			break;
 			break;
 		case VES_BITANGENT:
 		case VES_BITANGENT:

+ 1 - 1
CamelotD3D9Renderer/Source/CmD3D9VertexDeclaration.cpp

@@ -133,7 +133,7 @@ namespace CamelotEngine {
 				{
 				{
 					d3delems[idx].UsageIndex = 1;
 					d3delems[idx].UsageIndex = 1;
 				}
 				}
-				else if (i->getSemantic() == VES_DIFFUSE)
+				else if (i->getSemantic() == VES_COLOR)
 				{
 				{
 					d3delems[idx].UsageIndex = 0;
 					d3delems[idx].UsageIndex = 0;
 				}
 				}

+ 3 - 3
CamelotFBXImporter/Source/CmFBXImporter.cpp

@@ -594,7 +594,7 @@ namespace CamelotEngine
 
 
 		if(vertexData->color)
 		if(vertexData->color)
 		{
 		{
-			meshData->declaration->addElement(0, offset, VET_COLOR, VES_DIFFUSE, 0);
+			meshData->declaration->addElement(0, offset, VET_COLOR, VES_COLOR, 0);
 			offset += VertexElement::getTypeSize(VET_COLOR);
 			offset += VertexElement::getTypeSize(VET_COLOR);
 		}
 		}
 
 
@@ -619,13 +619,13 @@ namespace CamelotEngine
 
 
 		if(vertexData->uv0)
 		if(vertexData->uv0)
 		{
 		{
-			meshData->declaration->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
+			meshData->declaration->addElement(0, offset, VET_FLOAT2, VES_TEXCOORD, 0);
 			offset += VertexElement::getTypeSize(VET_FLOAT2);
 			offset += VertexElement::getTypeSize(VET_FLOAT2);
 		}
 		}
 
 
 		if(vertexData->uv1)
 		if(vertexData->uv1)
 		{
 		{
-			meshData->declaration->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 1);
+			meshData->declaration->addElement(0, offset, VET_FLOAT2, VES_TEXCOORD, 1);
 			offset += VertexElement::getTypeSize(VET_FLOAT2);
 			offset += VertexElement::getTypeSize(VET_FLOAT2);
 		}
 		}
 	}
 	}

+ 1 - 0
CamelotGLRenderer/CamelotGLRenderer.vcxproj

@@ -174,6 +174,7 @@
     <ClInclude Include="Include\CmWin32Window.h" />
     <ClInclude Include="Include\CmWin32Window.h" />
     <ClInclude Include="Source\GLSL\include\CmGLSLExtSupport.h" />
     <ClInclude Include="Source\GLSL\include\CmGLSLExtSupport.h" />
     <ClInclude Include="Source\GLSL\include\CmGLSLGpuProgram.h" />
     <ClInclude Include="Source\GLSL\include\CmGLSLGpuProgram.h" />
+    <ClInclude Include="Source\GLSL\include\CmGLSLParamParser.h" />
     <ClInclude Include="Source\GLSL\include\CmGLSLPreprocessor.h" />
     <ClInclude Include="Source\GLSL\include\CmGLSLPreprocessor.h" />
     <ClInclude Include="Source\GLSL\include\CmGLSLProgram.h" />
     <ClInclude Include="Source\GLSL\include\CmGLSLProgram.h" />
     <ClInclude Include="Source\GLSL\include\CmGLSLProgramFactory.h" />
     <ClInclude Include="Source\GLSL\include\CmGLSLProgramFactory.h" />

+ 3 - 0
CamelotGLRenderer/CamelotGLRenderer.vcxproj.filters

@@ -117,6 +117,9 @@
     <ClInclude Include="Include\CmGLGpuParamBlock.h">
     <ClInclude Include="Include\CmGLGpuParamBlock.h">
       <Filter>Header Files</Filter>
       <Filter>Header Files</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Source\GLSL\include\CmGLSLParamParser.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\GLSL\src\CmGLSLExtSupport.cpp">
     <ClCompile Include="Source\GLSL\src\CmGLSLExtSupport.cpp">

+ 382 - 0
CamelotGLRenderer/Source/GLSL/include/CmGLSLParamParser.h

@@ -0,0 +1,382 @@
+#pragma once
+
+#include "CmGLPrerequisites.h"
+#include "CmVertexDeclaration.h"
+#include "CmDebug.h"
+#include "CmException.h"
+#include "CmGpuParamDesc.h"
+
+namespace CamelotEngine
+{
+	struct GLSLAttribute
+	{
+		GLSLAttribute(const String& name, VertexElementSemantic semantic)
+			:mName(name), mSemantic(semantic)
+		{ }
+
+		INT32 matchesName(const String& name);
+		VertexElementSemantic getSemantic() const { return mSemantic; }
+
+	private:
+		String mName;
+		VertexElementSemantic mSemantic;
+	};
+
+	INT32 GLSLAttribute::matchesName(const String& name)
+	{
+		if(name.length() >= mName.length())
+		{
+			if(name.substr(0, mName.length()) == mName)
+			{
+				String indexStr = name.substr(mName.length(), name.length());
+				return parseUnsignedInt(indexStr, -1);
+			}
+		}
+
+		return -1;
+	}
+
+	class GLSLParamParser
+	{
+	public:
+		void buildUniformDescriptions(GLuint glProgram, GpuParamDesc& returnParamDesc);
+		void buildVertexDeclaration(GLuint glProgram, VertexDeclaration& declaration);
+
+	private:
+		void determineParamInfo(GpuParamMemberDesc& 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
+		* 			so that we know what they are used for.
+		*
+		* @return	true if it succeeds, false if it fails.
+		*/
+		bool attribNameToElementSemantic(const String& name, VertexElementSemantic& semantic, UINT16& index);
+		VertexElementType glTypeToAttributeType(GLenum glType);
+	};
+
+	void GLSLParamParser::buildVertexDeclaration(GLuint glProgram, VertexDeclaration& declaration)
+	{
+		GLint numAttributes = 0;
+		glGetProgramiv(glProgram, GL_ACTIVE_ATTRIBUTES, &numAttributes);
+
+		GLint maxNameSize = 0;
+		glGetProgramiv(glProgram, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxNameSize);
+
+		GLchar* attributeName = new GLchar[maxNameSize];
+		UINT32 offset = 0;
+
+		for(GLint i = 0; i < numAttributes; i++)
+		{
+			GLint attribSize = 0;
+			GLenum attribType = 0;
+			glGetActiveAttrib(glProgram, i, maxNameSize, nullptr, &attribSize, &attribType, attributeName);
+
+			VertexElementSemantic semantic = VES_POSITION;
+			UINT16 index = 0;
+			if(attribNameToElementSemantic(attributeName, semantic, index))
+			{
+				VertexElementType type = glTypeToAttributeType(attribType);
+
+				declaration.addElement(index, offset, type, semantic, index);
+				offset += attribSize;
+			}
+			else
+			{
+				LOGWRN("Cannot determine vertex input attribute type for attribute: " + String(attributeName));
+			}
+		}
+
+		delete[] attributeName;
+	}
+
+	VertexElementType GLSLParamParser::glTypeToAttributeType(GLenum glType)
+	{
+		switch(glType)
+		{
+		case GL_FLOAT:
+			return VET_FLOAT1;
+		case GL_FLOAT_VEC2:
+			return VET_FLOAT2;
+		case GL_FLOAT_VEC3:
+			return VET_FLOAT3;
+		case GL_FLOAT_VEC4:
+			return VET_FLOAT4;
+		default:
+			CM_EXCEPT(NotImplementedException, "OpenGL render system currently only supports float parameters.");
+		}
+	}
+
+	bool GLSLParamParser::attribNameToElementSemantic(const String& name, VertexElementSemantic& semantic, UINT16& index)
+	{
+		static GLSLAttribute attributes[] = 
+		{
+			GLSLAttribute("position", VES_POSITION),
+			GLSLAttribute("normal", VES_NORMAL),
+			GLSLAttribute("tangent", VES_TANGENT),
+			GLSLAttribute("bitangent", VES_BITANGENT),
+			GLSLAttribute("texcoord", VES_TEXCOORD),
+			GLSLAttribute("color", VES_COLOR),
+			GLSLAttribute("blendweights", VES_BLEND_WEIGHTS),
+			GLSLAttribute("blendindices", VES_BLEND_INDICES)
+		};
+
+		static const UINT32 numAttribs = sizeof(attributes) / sizeof(attributes[0]);
+
+		for(UINT32 i = 0; i < numAttribs; i++)
+		{
+			INT32 attribIndex = attributes[i].matchesName(name);
+			if(attribIndex != -1)
+			{
+				index = attribIndex;
+				semantic = attributes[i].getSemantic();
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	void GLSLParamParser::buildUniformDescriptions(GLuint glProgram, GpuParamDesc& returnParamDesc)
+	{
+		// scan through the active uniforms and add them to the reference list
+		GLint maxBufferSize = 0;
+		glGetProgramiv(glProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxBufferSize);
+
+		GLint maxBlockNameBufferSize = 0;
+		glGetProgramiv(glProgram, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &maxBlockNameBufferSize);
+
+		if(maxBlockNameBufferSize > maxBufferSize)
+			maxBufferSize = maxBlockNameBufferSize;
+
+		GLchar* uniformName = new GLchar[maxBufferSize];
+
+		GpuParamBlockDesc globalBlockDesc;
+		globalBlockDesc.slot = 0;
+		globalBlockDesc.name = "CM_INTERNAL_Globals";
+		globalBlockDesc.blockSize = 0;
+
+		UINT32 textureSlot = 0;
+
+		returnParamDesc.paramBlocks[globalBlockDesc.name] = globalBlockDesc;
+
+		GLint uniformBlockCount = 0;
+		glGetProgramiv(glProgram, GL_ACTIVE_UNIFORM_BLOCKS, &uniformBlockCount);
+
+		map<UINT32, String>::type blockSlotToName;
+		for (GLuint index = 0; index < (GLuint)uniformBlockCount; index++)
+		{
+			GLsizei unusedSize = 0;
+			glGetActiveUniformBlockName(glProgram, index, maxBufferSize, &unusedSize, uniformName);
+
+			GpuParamBlockDesc newBlockDesc;
+			newBlockDesc.slot = index + 1;
+			newBlockDesc.name = uniformName;
+			newBlockDesc.blockSize = 0;
+
+			returnParamDesc.paramBlocks[newBlockDesc.name] = newBlockDesc;
+			blockSlotToName.insert(std::make_pair(newBlockDesc.slot, newBlockDesc.name));
+		}
+
+		// get the number of active uniforms
+		GLint uniformCount = 0;
+		glGetProgramiv(glProgram, GL_ACTIVE_UNIFORMS, &uniformCount);
+
+		// Loop over each of the active uniforms, and add them to the reference container
+		// only do this for user defined uniforms, ignore built in gl state uniforms
+		for (GLuint index = 0; index < (GLuint)uniformCount; index++)
+		{
+			GLsizei arraySize = 0;
+			glGetActiveUniformName(glProgram, index, maxBufferSize, &arraySize, uniformName);
+
+			String paramName = String(uniformName);
+
+			// If the uniform name has a "[" in it then its an array element uniform.
+			String::size_type arrayStart = paramName.find("[");
+			if (arrayStart != String::npos)
+			{
+				// if not the first array element then skip it and continue to the next uniform
+				if (paramName.compare(arrayStart, paramName.size() - 1, "[0]") != 0)
+					CM_EXCEPT(NotImplementedException, "No support for array parameters yet.");
+
+				paramName = paramName.substr(0, arrayStart);
+			}
+
+			GLint uniformType;
+			glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_TYPE, &uniformType);
+
+			bool isSampler = false;
+			switch(uniformType)
+			{
+			case GL_SAMPLER_1D:
+			case GL_SAMPLER_2D:
+			case GL_SAMPLER_3D:
+			case GL_SAMPLER_CUBE:
+				isSampler = true;
+			}
+
+			if(isSampler)
+			{
+				GpuParamSpecialDesc samplerParam;
+				samplerParam.name = paramName;
+				samplerParam.slot = glGetUniformLocation(glProgram, uniformName);
+
+				GpuParamSpecialDesc textureParam;
+				textureParam.name = paramName;
+				textureParam.slot = samplerParam.slot;
+
+				switch(uniformType)
+				{
+				case GL_SAMPLER_1D:
+					samplerParam.type = GST_SAMPLER1D;
+					textureParam.type = GST_TEXTURE1D;
+					break;
+				case GL_SAMPLER_2D:
+					samplerParam.type = GST_SAMPLER2D;
+					textureParam.type = GST_TEXTURE2D;
+					break;
+				case GL_SAMPLER_3D:
+					samplerParam.type = GST_SAMPLER3D;
+					textureParam.type = GST_TEXTURE3D;
+					break;
+				case GL_SAMPLER_CUBE:
+					samplerParam.type = GST_SAMPLERCUBE;
+					textureParam.type = GST_TEXTURECUBE;
+					break;
+				}
+
+				returnParamDesc.samplers.insert(std::make_pair(paramName, samplerParam));
+				returnParamDesc.textures.insert(std::make_pair(paramName, textureParam));
+			}
+			else
+			{
+				GpuParamMemberDesc gpuParam;
+				gpuParam.name = paramName;
+
+				GLint blockIndex;
+				glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_BLOCK_INDEX, &blockIndex);
+
+				determineParamInfo(gpuParam, paramName, glProgram, index);
+
+				if(blockIndex != -1)
+				{
+					GLint blockOffset;
+					glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_OFFSET, &blockOffset);
+					gpuParam.gpuMemOffset = blockOffset;
+
+					GLint arrayStride;
+					glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_ARRAY_STRIDE, &arrayStride);
+					gpuParam.elementSize = arrayStride;
+
+					gpuParam.paramBlockSlot = blockIndex + 1; // 0 is reserved for globals
+
+					String& blockName = blockSlotToName[gpuParam.paramBlockSlot];
+					GpuParamBlockDesc& curBlockDesc = returnParamDesc.paramBlocks[blockName];
+
+					gpuParam.cpuMemOffset = curBlockDesc.blockSize;
+					curBlockDesc.blockSize += gpuParam.elementSize * gpuParam.arraySize;
+				}
+				else
+				{
+					gpuParam.gpuMemOffset = glGetUniformLocationARB(glProgram, uniformName);
+					gpuParam.paramBlockSlot = 0;
+					gpuParam.cpuMemOffset = globalBlockDesc.blockSize;
+
+					globalBlockDesc.blockSize += gpuParam.elementSize * gpuParam.arraySize;
+				}
+
+				returnParamDesc.params.insert(std::make_pair(gpuParam.name, gpuParam));
+			}
+		}
+
+		delete[] uniformName;
+	}
+
+	void GLSLParamParser::determineParamInfo(GpuParamMemberDesc& desc, const String& paramName, GLuint programHandle, GLuint uniformIndex)
+	{
+		GLint arraySize;
+		glGetActiveUniformsiv(programHandle, 1, &uniformIndex, GL_UNIFORM_SIZE, &arraySize);
+		desc.arraySize = arraySize;
+
+		GLint uniformType;
+		glGetActiveUniformsiv(programHandle, 1, &uniformIndex, GL_UNIFORM_TYPE, &uniformType);
+
+		switch (uniformType)
+		{
+		case GL_BOOL:
+			desc.type = GMT_BOOL;
+			desc.elementSize = 1;
+			break;
+		case GL_FLOAT:
+			desc.type = GMT_FLOAT1;
+			desc.elementSize = 1;
+			break;
+		case GL_FLOAT_VEC2:
+			desc.type = GMT_FLOAT2;
+			desc.elementSize = 2;
+			break;
+		case GL_FLOAT_VEC3:
+			desc.type = GMT_FLOAT3;
+			desc.elementSize = 3;
+			break;
+		case GL_FLOAT_VEC4:
+			desc.type = GMT_FLOAT4;
+			desc.elementSize = 4;
+			break;
+		case GL_INT:
+			desc.type = GMT_INT1;
+			desc.elementSize = 1;
+			break;
+		case GL_INT_VEC2:
+			desc.type = GMT_INT2;
+			desc.elementSize = 2;
+			break;
+		case GL_INT_VEC3:
+			desc.type = GMT_INT3;
+			desc.elementSize = 3;
+			break;
+		case GL_INT_VEC4:
+			desc.type = GMT_INT4;
+			desc.elementSize = 4;
+			break;
+		case GL_FLOAT_MAT2:
+			desc.type = GMT_MATRIX_2X2;
+			desc.elementSize = 4;
+			break;
+		case GL_FLOAT_MAT3:
+			desc.type = GMT_MATRIX_3X3;
+			desc.elementSize = 9;
+			break;
+		case GL_FLOAT_MAT4:
+			desc.type = GMT_MATRIX_4X4;
+			desc.elementSize = 16;
+			break;
+		case GL_FLOAT_MAT2x3:
+			desc.type = GMT_MATRIX_2X3;
+			desc.elementSize = 6;
+			break;
+		case GL_FLOAT_MAT3x2:
+			desc.type = GMT_MATRIX_3X2;
+			desc.elementSize = 6;
+			break;
+		case GL_FLOAT_MAT2x4:
+			desc.type = GMT_MATRIX_2X4;
+			desc.elementSize = 8;
+			break;
+		case GL_FLOAT_MAT4x2:
+			desc.type = GMT_MATRIX_4X2;
+			desc.elementSize = 8;
+			break;
+		case GL_FLOAT_MAT3x4:
+			desc.type = GMT_MATRIX_3X4;
+			desc.elementSize = 12;
+			break;
+		case GL_FLOAT_MAT4x3:
+			desc.type = GMT_MATRIX_4X3;
+			desc.elementSize = 12;
+			break;
+		default:
+			CM_EXCEPT(InternalErrorException, "Invalid shader parameter type: " + toString(uniformType) + " for parameter " + paramName);
+		}
+	}
+}

+ 3 - 2
CamelotGLRenderer/Source/GLSL/include/CmGLSLProgram.h

@@ -58,7 +58,7 @@ namespace CamelotEngine {
     public:
     public:
 		~GLSLProgram();
 		~GLSLProgram();
 
 
-		const GLhandleARB getGLHandle() const { return mGLHandle; }
+		const GLuint getGLHandle() const { return mGLHandle; }
 
 
 		/** Sets the preprocessor defines use to compile the program. */
 		/** Sets the preprocessor defines use to compile the program. */
 		void setPreprocessorDefines(const String& defines) { mPreprocessorDefines = defines; }
 		void setPreprocessorDefines(const String& defines) { mPreprocessorDefines = defines; }
@@ -113,7 +113,7 @@ namespace CamelotEngine {
 
 
 	private:
 	private:
 		/// GL handle for shader object
 		/// GL handle for shader object
-		GLhandleARB mGLHandle;
+		GLuint mGLHandle;
 		/// flag indicating if shader object successfully compiled
 		/// flag indicating if shader object successfully compiled
 		GLint mCompiled;
 		GLint mCompiled;
 		/// The input operation type for this (geometry) program
 		/// The input operation type for this (geometry) program
@@ -124,6 +124,7 @@ namespace CamelotEngine {
 		int mMaxOutputVertices;
 		int mMaxOutputVertices;
 		/// Preprocessor options
 		/// Preprocessor options
 		String mPreprocessorDefines;
 		String mPreprocessorDefines;
+		VertexDeclaration mVertexDeclaration;
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								SERIALIZATION                      		*/
 		/* 								SERIALIZATION                      		*/

+ 3 - 253
CamelotGLRenderer/Source/GLSL/src/CmGLSLProgram.cpp

@@ -32,269 +32,18 @@ THE SOFTWARE.
 #include "CmHighLevelGpuProgramManager.h"
 #include "CmHighLevelGpuProgramManager.h"
 #include "CmException.h"
 #include "CmException.h"
 #include "CmVertexIndexData.h"
 #include "CmVertexIndexData.h"
+#include "CmDebug.h"
 
 
 #include "CmGLSLProgram.h"
 #include "CmGLSLProgram.h"
 #include "CmGLSLGpuProgram.h"
 #include "CmGLSLGpuProgram.h"
 #include "CmGLSLExtSupport.h"
 #include "CmGLSLExtSupport.h"
 #include "CmGLSLPreprocessor.h"
 #include "CmGLSLPreprocessor.h"
+#include "CmGLSLParamParser.h"
 
 
 #include "CmGLSLProgramRTTI.h"
 #include "CmGLSLProgramRTTI.h"
 
 
 namespace CamelotEngine 
 namespace CamelotEngine 
 {
 {
-	class GLSLParamParser
-	{
-	public:
-		void buildUniformDescriptions(GLuint glProgram, GpuParamDesc& returnParamDesc);
-		void buildVertexDeclaration(GLuint glProgram, VertexDeclaration& declaration);
-
-	private:
-		void determineParamInfo(GpuParamMemberDesc& desc, const String& paramName, GLuint programHandle, GLuint uniformIndex);
-	};
-
-	void GLSLParamParser::buildUniformDescriptions(GLuint glProgram, GpuParamDesc& returnParamDesc)
-	{
-		// scan through the active uniforms and add them to the reference list
-		GLint maxBufferSize = 0;
-		glGetProgramiv(glProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxBufferSize);
-
-		GLint maxBlockNameBufferSize = 0;
-		glGetProgramiv(glProgram, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &maxBlockNameBufferSize);
-
-		if(maxBlockNameBufferSize > maxBufferSize)
-			maxBufferSize = maxBlockNameBufferSize;
-
-		GLchar* uniformName = new GLchar[maxBufferSize];
-
-		GpuParamBlockDesc globalBlockDesc;
-		globalBlockDesc.slot = 0;
-		globalBlockDesc.name = "CM_INTERNAL_Globals";
-		globalBlockDesc.blockSize = 0;
-
-		UINT32 textureSlot = 0;
-
-		returnParamDesc.paramBlocks[globalBlockDesc.name] = globalBlockDesc;
-
-		GLint uniformBlockCount = 0;
-		glGetProgramiv(glProgram, GL_ACTIVE_UNIFORM_BLOCKS, &uniformBlockCount);
-
-		map<UINT32, String>::type blockSlotToName;
-		for (GLuint index = 0; index < (GLuint)uniformBlockCount; index++)
-		{
-			GLsizei unusedSize = 0;
-			glGetActiveUniformBlockName(glProgram, index, maxBufferSize, &unusedSize, uniformName);
-
-			GpuParamBlockDesc newBlockDesc;
-			newBlockDesc.slot = index + 1;
-			newBlockDesc.name = uniformName;
-			newBlockDesc.blockSize = 0;
-
-			returnParamDesc.paramBlocks[newBlockDesc.name] = newBlockDesc;
-			blockSlotToName.insert(std::make_pair(newBlockDesc.slot, newBlockDesc.name));
-		}
-
-		// get the number of active uniforms
-		GLint uniformCount = 0;
-		glGetProgramiv(glProgram, GL_ACTIVE_UNIFORMS, &uniformCount);
-
-		// Loop over each of the active uniforms, and add them to the reference container
-		// only do this for user defined uniforms, ignore built in gl state uniforms
-		for (GLuint index = 0; index < (GLuint)uniformCount; index++)
-		{
-			GLsizei arraySize = 0;
-			glGetActiveUniformName(glProgram, index, maxBufferSize, &arraySize, uniformName);
-
-			String paramName = String(uniformName);
-
-			// If the uniform name has a "[" in it then its an array element uniform.
-			String::size_type arrayStart = paramName.find("[");
-			if (arrayStart != String::npos)
-			{
-				// if not the first array element then skip it and continue to the next uniform
-				if (paramName.compare(arrayStart, paramName.size() - 1, "[0]") != 0)
-					CM_EXCEPT(NotImplementedException, "No support for array parameters yet.");
-
-				paramName = paramName.substr(0, arrayStart);
-			}
-
-			GLint uniformType;
-			glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_TYPE, &uniformType);
-
-			bool isSampler = false;
-			switch(uniformType)
-			{
-			case GL_SAMPLER_1D:
-			case GL_SAMPLER_2D:
-			case GL_SAMPLER_3D:
-			case GL_SAMPLER_CUBE:
-				isSampler = true;
-			}
-
-			if(isSampler)
-			{
-				GpuParamSpecialDesc samplerParam;
-				samplerParam.name = paramName;
-				samplerParam.slot = glGetUniformLocation(glProgram, uniformName);
-
-				GpuParamSpecialDesc textureParam;
-				textureParam.name = paramName;
-				textureParam.slot = samplerParam.slot;
-
-				switch(uniformType)
-				{
-				case GL_SAMPLER_1D:
-					samplerParam.type = GST_SAMPLER1D;
-					textureParam.type = GST_TEXTURE1D;
-					break;
-				case GL_SAMPLER_2D:
-					samplerParam.type = GST_SAMPLER2D;
-					textureParam.type = GST_TEXTURE2D;
-					break;
-				case GL_SAMPLER_3D:
-					samplerParam.type = GST_SAMPLER3D;
-					textureParam.type = GST_TEXTURE3D;
-					break;
-				case GL_SAMPLER_CUBE:
-					samplerParam.type = GST_SAMPLERCUBE;
-					textureParam.type = GST_TEXTURECUBE;
-					break;
-				}
-
-				returnParamDesc.samplers.insert(std::make_pair(paramName, samplerParam));
-				returnParamDesc.textures.insert(std::make_pair(paramName, textureParam));
-			}
-			else
-			{
-				GpuParamMemberDesc gpuParam;
-				gpuParam.name = paramName;
-
-				GLint blockIndex;
-				glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_BLOCK_INDEX, &blockIndex);
-
-				determineParamInfo(gpuParam, paramName, glProgram, index);
-
-				if(blockIndex != -1)
-				{
-					GLint blockOffset;
-					glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_OFFSET, &blockOffset);
-					gpuParam.gpuMemOffset = blockOffset;
-
-					GLint arrayStride;
-					glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_ARRAY_STRIDE, &arrayStride);
-					gpuParam.elementSize = arrayStride;
-
-					gpuParam.paramBlockSlot = blockIndex + 1; // 0 is reserved for globals
-
-					String& blockName = blockSlotToName[gpuParam.paramBlockSlot];
-					GpuParamBlockDesc& curBlockDesc = returnParamDesc.paramBlocks[blockName];
-
-					gpuParam.cpuMemOffset = curBlockDesc.blockSize;
-					curBlockDesc.blockSize += gpuParam.elementSize * gpuParam.arraySize;
-				}
-				else
-				{
-					gpuParam.gpuMemOffset = glGetUniformLocationARB(glProgram, uniformName);
-					gpuParam.paramBlockSlot = 0;
-					gpuParam.cpuMemOffset = globalBlockDesc.blockSize;
-
-					globalBlockDesc.blockSize += gpuParam.elementSize * gpuParam.arraySize;
-				}
-
-				returnParamDesc.params.insert(std::make_pair(gpuParam.name, gpuParam));
-			}
-		}
-
-		delete[] uniformName;
-	}
-
-	void GLSLParamParser::determineParamInfo(GpuParamMemberDesc& desc, const String& paramName, GLuint programHandle, GLuint uniformIndex)
-	{
-		GLint arraySize;
-		glGetActiveUniformsiv(programHandle, 1, &uniformIndex, GL_UNIFORM_SIZE, &arraySize);
-		desc.arraySize = arraySize;
-
-		GLint uniformType;
-		glGetActiveUniformsiv(programHandle, 1, &uniformIndex, GL_UNIFORM_TYPE, &uniformType);
-
-		switch (uniformType)
-		{
-		case GL_BOOL:
-			desc.type = GMT_BOOL;
-			desc.elementSize = 1;
-			break;
-		case GL_FLOAT:
-			desc.type = GMT_FLOAT1;
-			desc.elementSize = 1;
-			break;
-		case GL_FLOAT_VEC2:
-			desc.type = GMT_FLOAT2;
-			desc.elementSize = 2;
-			break;
-		case GL_FLOAT_VEC3:
-			desc.type = GMT_FLOAT3;
-			desc.elementSize = 3;
-			break;
-		case GL_FLOAT_VEC4:
-			desc.type = GMT_FLOAT4;
-			desc.elementSize = 4;
-			break;
-		case GL_INT:
-			desc.type = GMT_INT1;
-			desc.elementSize = 1;
-			break;
-		case GL_INT_VEC2:
-			desc.type = GMT_INT2;
-			desc.elementSize = 2;
-			break;
-		case GL_INT_VEC3:
-			desc.type = GMT_INT3;
-			desc.elementSize = 3;
-			break;
-		case GL_INT_VEC4:
-			desc.type = GMT_INT4;
-			desc.elementSize = 4;
-			break;
-		case GL_FLOAT_MAT2:
-			desc.type = GMT_MATRIX_2X2;
-			desc.elementSize = 4;
-			break;
-		case GL_FLOAT_MAT3:
-			desc.type = GMT_MATRIX_3X3;
-			desc.elementSize = 9;
-			break;
-		case GL_FLOAT_MAT4:
-			desc.type = GMT_MATRIX_4X4;
-			desc.elementSize = 16;
-			break;
-		case GL_FLOAT_MAT2x3:
-			desc.type = GMT_MATRIX_2X3;
-			desc.elementSize = 6;
-			break;
-		case GL_FLOAT_MAT3x2:
-			desc.type = GMT_MATRIX_3X2;
-			desc.elementSize = 6;
-			break;
-		case GL_FLOAT_MAT2x4:
-			desc.type = GMT_MATRIX_2X4;
-			desc.elementSize = 8;
-			break;
-		case GL_FLOAT_MAT4x2:
-			desc.type = GMT_MATRIX_4X2;
-			desc.elementSize = 8;
-			break;
-		case GL_FLOAT_MAT3x4:
-			desc.type = GMT_MATRIX_3X4;
-			desc.elementSize = 12;
-			break;
-		case GL_FLOAT_MAT4x3:
-			desc.type = GMT_MATRIX_4X3;
-			desc.elementSize = 12;
-			break;
-		default:
-			CM_EXCEPT(InternalErrorException, "Invalid shader parameter type: " + toString(uniformType) + " for parameter " + paramName);
-		}
-	}
-
     //---------------------------------------------------------------------------
     //---------------------------------------------------------------------------
     GLSLProgram::~GLSLProgram()
     GLSLProgram::~GLSLProgram()
     {
     {
@@ -420,6 +169,7 @@ namespace CamelotEngine
 
 
 		GLSLParamParser paramParser;
 		GLSLParamParser paramParser;
 		paramParser.buildUniformDescriptions(mGLHandle, mParametersDesc);
 		paramParser.buildUniformDescriptions(mGLHandle, mParametersDesc);
+		paramParser.buildVertexDeclaration(mGLHandle, mVertexDeclaration);
 	}
 	}
 	//---------------------------------------------------------------------------
 	//---------------------------------------------------------------------------
 	void GLSLProgram::unload_internal()
 	void GLSLProgram::unload_internal()

+ 2 - 2
CamelotRenderer/Include/CmVertexDeclaration.h

@@ -16,11 +16,11 @@ namespace CamelotEngine
 		/// Normal, 3 reals per vertex
 		/// Normal, 3 reals per vertex
 		VES_NORMAL = 4,
 		VES_NORMAL = 4,
 		/// Diffuse colours
 		/// Diffuse colours
-		VES_DIFFUSE = 5,
+		VES_COLOR = 5,
 		/// Specular colours
 		/// Specular colours
 		VES_SPECULAR = 6,
 		VES_SPECULAR = 6,
 		/// Texture coordinates
 		/// Texture coordinates
-		VES_TEXTURE_COORDINATES = 7,
+		VES_TEXCOORD = 7,
         /// Binormal (Y axis if normal is Z)
         /// Binormal (Y axis if normal is Z)
         VES_BITANGENT = 8,
         VES_BITANGENT = 8,
         /// Tangent (X axis if normal is Z)
         /// Tangent (X axis if normal is Z)

+ 4 - 4
CamelotRenderer/Source/CmMesh.cpp

@@ -110,7 +110,7 @@ namespace CamelotEngine
 						source = (UINT8*)vertexData->vertex;
 						source = (UINT8*)vertexData->vertex;
 
 
 					break;
 					break;
-				case VES_DIFFUSE:
+				case VES_COLOR:
 					if(vertexData->color)
 					if(vertexData->color)
 						source = (UINT8*)vertexData->color;
 						source = (UINT8*)vertexData->color;
 
 
@@ -130,7 +130,7 @@ namespace CamelotEngine
 						source = (UINT8*)vertexData->bitangent;	
 						source = (UINT8*)vertexData->bitangent;	
 
 
 					break;
 					break;
-				case VES_TEXTURE_COORDINATES:
+				case VES_TEXCOORD:
 					if(element->getIndex() == 0)
 					if(element->getIndex() == 0)
 					{
 					{
 						if(vertexData->uv0)
 						if(vertexData->uv0)
@@ -233,7 +233,7 @@ namespace CamelotEngine
 						dest = (UINT8*)vertexData->vertex;
 						dest = (UINT8*)vertexData->vertex;
 
 
 						break;
 						break;
-					case VES_DIFFUSE:
+					case VES_COLOR:
 						vertexData->color = new Color[meshData->vertexCount];
 						vertexData->color = new Color[meshData->vertexCount];
 						dest = (UINT8*)vertexData->color;
 						dest = (UINT8*)vertexData->color;
 
 
@@ -253,7 +253,7 @@ namespace CamelotEngine
 						dest = (UINT8*)vertexData->bitangent;	
 						dest = (UINT8*)vertexData->bitangent;	
 
 
 						break;
 						break;
-					case VES_TEXTURE_COORDINATES:
+					case VES_TEXCOORD:
 						if(element->getIndex() == 0)
 						if(element->getIndex() == 0)
 						{
 						{
 							vertexData->uv0 = new Vector2[meshData->vertexCount];
 							vertexData->uv0 = new Vector2[meshData->vertexCount];

+ 43 - 3
CamelotRenderer/TODO.txt

@@ -20,10 +20,50 @@
 -----------GpuProgramParameters/Pass/Material REFACTOR------------------------------
 -----------GpuProgramParameters/Pass/Material REFACTOR------------------------------
 
 
 Finish up GL port:
 Finish up GL port:
- - Remove those DefaultHardwareBuffermanagers as I don't think they serve a purpose anymore (OpenGL seems to only use them if API doesn't support hardware buffers, which won't happen on modern hardware)
- - Re-do GL attribute bindings (currently it parses program source manually)
  - Params aren't being initialized anywhere
  - Params aren't being initialized anywhere
- - Uniforms or uniform blocks aren't assigned anywhere
+
+Set up pipeline
+Assign vertex attributes
+ - When rendering, compare mesh vertec decl and shader decl and use only overlapping attribs
+Assign uniform buffers
+
+LinkProgramKey key;
+key.vertexProgKey = mActiveVertexGpuProgram != nullptr ? mActiveVertexGpuProgram->getProgramID() : 0;
+key.fragmentProgKey = mActiveFragmentGpuProgram != nullptr ? mActiveFragmentGpuProgram->getProgramID() : 0;
+key.geometryProgKey = mActiveGeometryGpuProgram != nullptr ? mActiveGeometryGpuProgram->getProgramID() : 0;
+key.hullProgKey = mActiveHullGpuProgram != nullptr ? mActiveHullGpuProgram->getProgramID() : 0;
+key.domainProgKey = mActiveDomainGpuProgram != nullptr ? mActiveDomainGpuProgram->getProgramID() : 0;
+
+template <class T>
+inline void hash_combine(std::size_t& seed, const T& v)
+{
+	std::hash<T> hasher;
+	seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
+}
+
+::std::size_t GLSLLinkProgramManager::LinkProgramKeyHashFunction::operator()(const GLSLLinkProgramManager::LinkProgramKey &key) const
+{
+	std::size_t seed = 0;
+	hash_combine(seed, key.vertexProgKey);
+	hash_combine(seed, key.fragmentProgKey);
+	hash_combine(seed, key.geometryProgKey);
+	hash_combine(seed, key.hullProgKey);
+	hash_combine(seed, key.domainProgKey);
+
+	return seed;
+}
+
+bool GLSLLinkProgramManager::LinkProgramKeyEqual::operator()(const GLSLLinkProgramManager::LinkProgramKey &a, const GLSLLinkProgramManager::LinkProgramKey &b) const
+{
+	return a.vertexProgKey == b.vertexProgKey && a.fragmentProgKey == b.fragmentProgKey && a.geometryProgKey == b.geometryProgKey &&
+		a.hullProgKey == b.hullProgKey && a.domainProgKey == b.domainProgKey;
+}
+
+typedef std::unordered_map<LinkProgramKey, GLSLLinkProgram*, LinkProgramKeyHashFunction, LinkProgramKeyEqual> LinkProgramMap;
+
+
+
+
 
 
 Get through capabilities and remove bool/int/float constant counters and instead add uniform, uniform block, input/output component counters
 Get through capabilities and remove bool/int/float constant counters and instead add uniform, uniform block, input/output component counters