Pārlūkot izejas kodu

All shaders are loaded from files
Added includes to GpuProgramImportOptions

Marko Pintera 13 gadi atpakaļ
vecāks
revīzija
89658aa9eb
32 mainītis faili ar 173 papildinājumiem un 155 dzēšanām
  1. 75 111
      CamelotClient/CamelotClient.cpp
  2. 1 1
      CamelotD3D11RenderSystem/Include/CmD3D11HLSLProgram.h
  3. 1 1
      CamelotD3D11RenderSystem/Include/CmD3D11HLSLProgramFactory.h
  4. 2 1
      CamelotD3D11RenderSystem/Source/CmD3D11HLSLParamParser.cpp
  5. 1 1
      CamelotD3D11RenderSystem/Source/CmD3D11HLSLProgram.cpp
  6. 1 1
      CamelotD3D11RenderSystem/Source/CmD3D11HLSLProgramFactory.cpp
  7. 1 1
      CamelotD3D9Renderer/Include/CmD3D9HLSLProgram.h
  8. 1 1
      CamelotD3D9Renderer/Include/CmD3D9HLSLProgramFactory.h
  9. 1 1
      CamelotD3D9Renderer/Source/CmD3D9HLSLProgram.cpp
  10. 1 1
      CamelotD3D9Renderer/Source/CmD3D9HLSLProgramFactory.cpp
  11. 1 1
      CamelotGLRenderer/Source/GLSL/include/CmGLSLGpuProgram.h
  12. 48 4
      CamelotGLRenderer/Source/GLSL/include/CmGLSLParamParser.h
  13. 1 1
      CamelotGLRenderer/Source/GLSL/include/CmGLSLProgram.h
  14. 1 1
      CamelotGLRenderer/Source/GLSL/include/CmGLSLProgramFactory.h
  15. 1 1
      CamelotGLRenderer/Source/GLSL/src/CmGLSLGpuProgram.cpp
  16. 1 1
      CamelotGLRenderer/Source/GLSL/src/CmGLSLProgram.cpp
  17. 1 1
      CamelotGLRenderer/Source/GLSL/src/CmGLSLProgramFactory.cpp
  18. 1 1
      CamelotRenderer/Include/CmCgProgram.h
  19. 1 1
      CamelotRenderer/Include/CmCgProgramFactory.h
  20. 1 1
      CamelotRenderer/Include/CmGpuProgram.h
  21. 3 0
      CamelotRenderer/Include/CmGpuProgramImportOptions.h
  22. 7 0
      CamelotRenderer/Include/CmGpuProgramImportOptionsRTTI.h
  23. 2 2
      CamelotRenderer/Include/CmHighLevelGpuProgram.h
  24. 2 2
      CamelotRenderer/Include/CmHighLevelGpuProgramManager.h
  25. 1 1
      CamelotRenderer/Source/CmCgProgram.cpp
  26. 1 1
      CamelotRenderer/Source/CmCgProgramFactory.cpp
  27. 1 1
      CamelotRenderer/Source/CmGpuProgram.cpp
  28. 2 1
      CamelotRenderer/Source/CmGpuProgramImporter.cpp
  29. 2 2
      CamelotRenderer/Source/CmHighLevelGpuProgram.cpp
  30. 2 2
      CamelotRenderer/Source/CmHighLevelGpuProgramManager.cpp
  31. 2 2
      CamelotRenderer/Source/CmMaterial.cpp
  32. 6 8
      CamelotRenderer/TODO.txt

+ 75 - 111
CamelotClient/CamelotClient.cpp

@@ -65,34 +65,45 @@ int CALLBACK WinMain(
 
 #if defined DX9
 	///////////////// HLSL 9 SHADERS //////////////////////////
-	String fragShaderCode = "sampler2D tex;			\
-							float4 ps_main(float2 uv : TEXCOORD0) : COLOR0		\
-							{														\
-							float4 color = tex2D(tex, uv);				\
-							return color;										\
-							}";
-
-	HighLevelGpuProgramHandle fragProgRef =  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;											\
-							}";
-
-	HighLevelGpuProgramHandle vertProgRef =  HighLevelGpuProgram::create(vertShaderCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
+	String dx9psLoc = "C:\\Projects\\CamelotRenderer\\Data\\hlsl9_ps.gpuprog";
+	String dx9vsLoc = "C:\\Projects\\CamelotRenderer\\Data\\hlsl9_vs.gpuprog";
+
+	ImportOptionsPtr gpuProgImportOptions = Importer::instance().createImportOptions(dx9psLoc);
+	if(rtti_is_of_type<GpuProgramImportOptions>(gpuProgImportOptions))
+	{
+		GpuProgramImportOptions* importOptions = static_cast<GpuProgramImportOptions*>(gpuProgImportOptions.get());
+
+		importOptions->setEntryPoint("ps_main");
+		importOptions->setLanguage("hlsl");
+		importOptions->setProfile(GPP_PS_2_0);
+		importOptions->setType(GPT_FRAGMENT_PROGRAM);
+	}
+
+	HighLevelGpuProgramHandle fragProgRef = Importer::instance().import(dx9psLoc, gpuProgImportOptions);
+
+	gpuProgImportOptions = Importer::instance().createImportOptions(dx9vsLoc);
+	if(rtti_is_of_type<GpuProgramImportOptions>(gpuProgImportOptions))
+	{
+		GpuProgramImportOptions* importOptions = static_cast<GpuProgramImportOptions*>(gpuProgImportOptions.get());
+
+		importOptions->setEntryPoint("vs_main");
+		importOptions->setLanguage("hlsl");
+		importOptions->setProfile(GPP_VS_2_0);
+		importOptions->setType(GPT_VERTEX_PROGRAM);
+	}
+
+	HighLevelGpuProgramHandle vertProgRef = Importer::instance().import(dx9vsLoc, gpuProgImportOptions);
 
 #elif defined DX11
 
 	GpuProgIncludeHandle gpuProgInclude = Importer::instance().import("C:\\testInclude.gpuproginc");
 	const String& debugString = gpuProgInclude->getString();
+	
+	/////////////////// HLSL 11 SHADERS //////////////////////////
+	String dx11psLoc = "C:\\Projects\\CamelotRenderer\\Data\\hlsl11_ps.gpuprog";
+	String dx11vsLoc = "C:\\Projects\\CamelotRenderer\\Data\\hlsl11_vs.gpuprog";
 
-	ImportOptionsPtr gpuProgImportOptions = Importer::instance().createImportOptions("C:\\testGpuProg.gpuprog");
+	ImportOptionsPtr gpuProgImportOptions = Importer::instance().createImportOptions(dx11psLoc);
 	if(rtti_is_of_type<GpuProgramImportOptions>(gpuProgImportOptions))
 	{
 		GpuProgramImportOptions* importOptions = static_cast<GpuProgramImportOptions*>(gpuProgImportOptions.get());
@@ -103,79 +114,51 @@ int CALLBACK WinMain(
 		importOptions->setType(GPT_FRAGMENT_PROGRAM);
 	}
 
-	HighLevelGpuProgramHandle importedGpuProgram = Importer::instance().import("C:\\testGpuProg.gpuprog", gpuProgImportOptions);
+	HighLevelGpuProgramHandle fragProgRef = Importer::instance().import(dx11psLoc, gpuProgImportOptions);
 
-	/////////////////// 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;										\
-							}";
-
-	HighLevelGpuProgramHandle fragProgRef =  HighLevelGpuProgram::create(fragShaderCode, "ps_main", "hlsl", GPT_FRAGMENT_PROGRAM, GPP_PS_4_0);
-
-	String vertShaderCode = "struct InputStruct									\
-							{													\
-								float matMultiplier;							\
-								float uvMultiplier;									\
-							};													\
-																				\
-							float test1; \
-							InputStruct input[2];								\
-							float4x4 matViewProjection;							\
-														float test2; \
-							void vs_main(										\
-							in float4 inPos : POSITION,							\
-							in float2 uv : TEXCOORD0,							\
-							out float4 oPosition : SV_Position,					\
-							out float2 oUv : TEXCOORD0)							\
-							{													\
-							oPosition = mul(matViewProjection * input[1].matMultiplier, inPos);	\
-							oUv = uv * input[1].uvMultiplier;						\
-							}";
-
-	HighLevelGpuProgramHandle vertProgRef =  HighLevelGpuProgram::create(vertShaderCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
+	gpuProgImportOptions = Importer::instance().createImportOptions(dx11vsLoc);
+	if(rtti_is_of_type<GpuProgramImportOptions>(gpuProgImportOptions))
+	{
+		GpuProgramImportOptions* importOptions = static_cast<GpuProgramImportOptions*>(gpuProgImportOptions.get());
+
+		importOptions->setEntryPoint("vs_main");
+		importOptions->setLanguage("hlsl");
+		importOptions->setProfile(GPP_VS_4_0);
+		importOptions->setType(GPT_VERTEX_PROGRAM);
+	}
+
+	HighLevelGpuProgramHandle vertProgRef = Importer::instance().import(dx11vsLoc, gpuProgImportOptions);
+	
 #else
 	///////////////// 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; \
-							  }";
-
-	HighLevelGpuProgramHandle fragProgRef = 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									\
-							struct InputStruct									\
-							{													\
-								float matMultiplier[2];							\
-								float uvMultiplier;								\
-							};													\
-																				\
-							 uniform mainFragBlock								\
-							 {													\
-							 float test1;										\
-							 mat4 matViewProjection;							\
-							 float test2;										\
-							 };													\
-							 uniform InputStruct input[2];						\
-							 in vec4 cm_position; \
-							 in vec2 cm_texcoord0; \
-							 out vec2 texcoord0; \
-							 void main() \
-							 { \
-							 texcoord0 = cm_texcoord0 * input[1].uvMultiplier; \
-							 gl_Position = cm_position * (matViewProjection * input[1].matMultiplier[1]); \
-							 }";
-
-	HighLevelGpuProgramHandle vertProgRef= HighLevelGpuProgram::create(vertShaderCode, "main", "glsl", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
+	String glslpsLoc = "C:\\Projects\\CamelotRenderer\\Data\\glsl_ps.gpuprog";
+	String glslvsLoc = "C:\\Projects\\CamelotRenderer\\Data\\glsl_vs.gpuprog";
+
+	ImportOptionsPtr gpuProgImportOptions = Importer::instance().createImportOptions(glslpsLoc);
+	if(rtti_is_of_type<GpuProgramImportOptions>(gpuProgImportOptions))
+	{
+		GpuProgramImportOptions* importOptions = static_cast<GpuProgramImportOptions*>(gpuProgImportOptions.get());
+
+		importOptions->setEntryPoint("main");
+		importOptions->setLanguage("glsl");
+		importOptions->setProfile(GPP_PS_2_0);
+		importOptions->setType(GPT_FRAGMENT_PROGRAM);
+	}
+
+	HighLevelGpuProgramHandle fragProgRef = Importer::instance().import(glslpsLoc, gpuProgImportOptions);
+
+	gpuProgImportOptions = Importer::instance().createImportOptions(glslvsLoc);
+	if(rtti_is_of_type<GpuProgramImportOptions>(gpuProgImportOptions))
+	{
+		GpuProgramImportOptions* importOptions = static_cast<GpuProgramImportOptions*>(gpuProgImportOptions.get());
+
+		importOptions->setEntryPoint("main");
+		importOptions->setLanguage("glsl");
+		importOptions->setProfile(GPP_VS_2_0);
+		importOptions->setType(GPT_VERTEX_PROGRAM);
+	}
+
+	HighLevelGpuProgramHandle vertProgRef = Importer::instance().import(glslvsLoc, gpuProgImportOptions);
 #endif
 
 	gResources().create(vertProgRef, "C:\\vertProgCg.vprog", true);
@@ -194,10 +177,6 @@ int CALLBACK WinMain(
 	testShader->addParameter("input", "input", GPDT_STRUCT, 2, 8);
 #endif
 
-#if defined GL
-	testShader->addParameter("input", "input", GPDT_STRUCT, 2, 12);
-#endif
-
 	testShader->addParameter("samp", "samp", GPOT_SAMPLER2D);
 	testShader->addParameter("tex", "tex", GPOT_TEXTURE2D);
 	TechniquePtr newTechniqueGL = testShader->addTechnique("GLRenderSystem", "ForwardRenderer");
@@ -238,21 +217,6 @@ int CALLBACK WinMain(
 	testMaterial->setStructData("input", dbgMultipliers2, sizeof(dbgMultipliers2), 1);
 #endif
 
-#if defined GL
-	float dbgMultipliers1[3];
-	dbgMultipliers1[0] = 0.0f;
-	dbgMultipliers1[1] = 0.0f;
-	dbgMultipliers1[2] = 0.0f;
-
-	float dbgMultipliers2[3];
-	dbgMultipliers2[0] = 0.0f;
-	dbgMultipliers2[1] = 1.0f;
-	dbgMultipliers2[2] = 1.0f;
-
-	testMaterial->setStructData("input", dbgMultipliers1, sizeof(dbgMultipliers1), 0);
-	testMaterial->setStructData("input", dbgMultipliers2, sizeof(dbgMultipliers2), 1);
-#endif
-
 	//testMaterialRef = gResources().load("C:\\testMaterial.mat");
 	//testMaterialRef.waitUntilLoaded();
 

+ 1 - 1
CamelotD3D11RenderSystem/Include/CmD3D11HLSLProgram.h

@@ -35,7 +35,7 @@ namespace CamelotEngine
 		friend class D3D11HLSLProgramFactory;
 
 		D3D11HLSLProgram(const String& source, const String& entryPoint, const String& language, 
-			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes, 
+			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes, 
 			bool isAdjacencyInfoRequired = false);
 
         /**

+ 1 - 1
CamelotD3D11RenderSystem/Include/CmD3D11HLSLProgramFactory.h

@@ -15,7 +15,7 @@ namespace CamelotEngine
 
 		const String& getLanguage(void) const;
 		HighLevelGpuProgram* create(const String& source, const String& entryPoint, GpuProgramType gptype, 
-			GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes);
+			GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes);
 		HighLevelGpuProgram* create();
 	};
 }

+ 2 - 1
CamelotD3D11RenderSystem/Source/CmD3D11HLSLParamParser.cpp

@@ -201,7 +201,8 @@ namespace CamelotEngine
 		}
 
 		// Buffer always needs to be a multiple of 4, so make it so
-		blockDesc.blockSize += (4 - (blockDesc.blockSize % 4));
+		if(blockDesc.blockSize % 4 != 0)
+			blockDesc.blockSize += (4 - (blockDesc.blockSize % 4));
 
 #if CM_DEBUG_MODE
 		if(constantBufferDesc.Size != (blockDesc.blockSize * 4))

+ 1 - 1
CamelotD3D11RenderSystem/Source/CmD3D11HLSLProgram.cpp

@@ -16,7 +16,7 @@ namespace CamelotEngine
 	UINT32 D3D11HLSLProgram::globalProgramId = 0;
 
 	D3D11HLSLProgram::D3D11HLSLProgram(const String& source, const String& entryPoint, const String& language, 
-		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes, bool isAdjacencyInfoRequired)
+		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes, bool isAdjacencyInfoRequired)
 		: HighLevelGpuProgram(source, entryPoint, language, gptype, profile, includes, isAdjacencyInfoRequired),
 		mColumnMajorMatrices(true), mEnableBackwardsCompatibility(false), mProgramId(0)
 	{

+ 1 - 1
CamelotD3D11RenderSystem/Source/CmD3D11HLSLProgramFactory.cpp

@@ -19,7 +19,7 @@ namespace CamelotEngine
     }
 
 	HighLevelGpuProgram* D3D11HLSLProgramFactory::create(const String& source, const String& entryPoint, 
-		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes)
+		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes)
     {
 		D3D11HLSLProgram* prog = new D3D11HLSLProgram(source, entryPoint, sLanguageName, gptype, profile, includes);
 

+ 1 - 1
CamelotD3D9Renderer/Include/CmD3D9HLSLProgram.h

@@ -89,7 +89,7 @@ namespace CamelotEngine {
 		friend class D3D9HLSLProgramFactory;
 
 		D3D9HLSLProgram(const String& source, const String& entryPoint, const String& language, 
-			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes, 
+			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes, 
 			bool isAdjacencyInfoRequired = false);
  
 		/**

+ 1 - 1
CamelotD3D9Renderer/Include/CmD3D9HLSLProgramFactory.h

@@ -44,7 +44,7 @@ namespace CamelotEngine
 		/// Get the name of the language this factory creates programs for
 		const String& getLanguage(void) const;
         HighLevelGpuProgram* create(const String& source, const String& entryPoint, GpuProgramType gptype, 
-			GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes);
+			GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes);
 		HighLevelGpuProgram* create();
     };
 }

+ 1 - 1
CamelotD3D9Renderer/Source/CmD3D9HLSLProgram.cpp

@@ -38,7 +38,7 @@ THE SOFTWARE.
 namespace CamelotEngine {
 	//-----------------------------------------------------------------------
 	D3D9HLSLProgram::D3D9HLSLProgram(const String& source, const String& entryPoint, const String& language, 
-		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes, bool isAdjacencyInfoRequired)
+		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes, bool isAdjacencyInfoRequired)
 		: HighLevelGpuProgram(source, entryPoint, language, gptype, profile, includes, isAdjacencyInfoRequired)
 		, mPreprocessorDefines()
 		, mColumnMajorMatrices(true)

+ 1 - 1
CamelotD3D9Renderer/Source/CmD3D9HLSLProgramFactory.cpp

@@ -48,7 +48,7 @@ namespace CamelotEngine {
     }
     //-----------------------------------------------------------------------
 	HighLevelGpuProgram* D3D9HLSLProgramFactory::create(const String& source, const String& entryPoint, 
-		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes)
+		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes)
     {
 		D3D9HLSLProgram* prog = new D3D9HLSLProgram(source, entryPoint, sLanguageName, gptype, profile, includes);
 

+ 1 - 1
CamelotGLRenderer/Source/GLSL/include/CmGLSLGpuProgram.h

@@ -61,7 +61,7 @@ namespace CamelotEngine {
 		friend class GLGpuProgramManager;
 
 		GLSLGpuProgram(const String& source, const String& entryPoint, const String& language, 
-			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes);
+			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes);
 
 		/// GL Handle for the shader object
 		GLSLProgram* mGLSLProgram;

+ 48 - 4
CamelotGLRenderer/Source/GLSL/include/CmGLSLParamParser.h

@@ -36,6 +36,11 @@ namespace CamelotEngine
 		return -1;
 	}
 
+	struct GLSLParamArrayData
+	{
+		vector<UINT32>::type arrayIndices;
+	};
+
 	class GLSLParamParser
 	{
 	public:
@@ -181,6 +186,7 @@ namespace CamelotEngine
 			blockNames.insert(newBlockDesc.name);
 		}
 
+		map<String, UINT32>::type foundFirstArrayIndex; 
 		map<String, GpuParamDataDesc>::type foundStructs;
 
 		// get the number of active uniforms
@@ -259,6 +265,39 @@ namespace CamelotEngine
 				}
 			}
 
+			if(inStruct)	
+			{
+				// OpenGL makes struct management really difficult, which is why I have given up on implementing this so far
+				// Some of the issues I encountered:
+				//  - Elements will be optimized out if they are not used. This makes it hard to determine proper structure size.
+				//     - If struct is within a Uniform buffer block, then it is possible because the element won't be optimized out of the buffer
+				//     - If the struct is within a global buffer, it is impossible to determine actual size, since the element will be optimized out of the buffer too
+				//     - Same issue happens with arrays, as OpenGL will optimize out array elements. With global buffers this makes it impossible to determine
+				//       actual array size (e.g. suppose OpenGL optimized out few last elements)
+				//        - Normal arrays work fine as OpenGL has utilities for reporting their actual size, but those do not work with structs
+
+				CM_EXCEPT(NotImplementedException, "Structs are not supported.")
+			}
+
+			// GLSL will optimize out unused array indexes, so there's no guarantee that 0 is the first,
+			// so we store the first one here
+			int firstArrayIndex = 0;
+			if(isInArray)
+			{
+				String& nameToSearch = cleanParamName;
+				if(inStruct)
+					nameToSearch = structName;
+
+				auto arrayIndexFind = foundFirstArrayIndex.find(nameToSearch);
+				if(arrayIndexFind == foundFirstArrayIndex.end())
+				{
+					foundFirstArrayIndex[nameToSearch] = arrayIdx;
+				}
+
+				firstArrayIndex = foundFirstArrayIndex[nameToSearch];
+			}
+
+
 			GLint uniformType;
 			glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_TYPE, &uniformType);
 
@@ -378,16 +417,17 @@ namespace CamelotEngine
 				GpuParamDataDesc& structDesc = foundStructs[structName];
 				
 				assert(gpuParam.cpuMemOffset >= structDesc.cpuMemOffset);
-				if(arrayIdx == 0)
+				if(arrayIdx == firstArrayIndex) // Determine element size only using the first array element
 				{
 					structDesc.elementSize = std::max(structDesc.elementSize, (gpuParam.cpuMemOffset - structDesc.cpuMemOffset) + gpuParam.arrayElementStride * gpuParam.arraySize);
 					structDesc.arrayElementStride = structDesc.elementSize;
 				}
 
 				// New array element reached, determine arrayElementStride
-				if(arrayIdx > 0 && structDesc.arraySize == 1)
+				if(arrayIdx != firstArrayIndex)
 				{
-					structDesc.arrayElementStride = gpuParam.cpuMemOffset - structDesc.cpuMemOffset; 
+					UINT32 numElements = arrayIdx - firstArrayIndex;
+					structDesc.arrayElementStride = (gpuParam.cpuMemOffset - structDesc.cpuMemOffset) / numElements; 
 				}
 
 				structDesc.arraySize = std::max(structDesc.arraySize, arrayIdx + 1);
@@ -401,7 +441,9 @@ namespace CamelotEngine
 		for(auto iter = returnParamDesc.paramBlocks.begin(); iter != returnParamDesc.paramBlocks.end(); ++iter)
 		{
 			GpuParamBlockDesc& blockDesc = iter->second;
-			blockDesc.blockSize += (4 - (blockDesc.blockSize % 4));
+
+			if(blockDesc.blockSize % 4 != 0)
+				blockDesc.blockSize += (4 - (blockDesc.blockSize % 4));
 		}
 
 #if CM_DEBUG_MODE
@@ -523,6 +565,8 @@ namespace CamelotEngine
 
 				desc.arrayElementStride = arrayStride / 4;
 			}
+			else
+				desc.arrayElementStride = desc.elementSize;
 		}
 		else
 			desc.arrayElementStride = desc.elementSize;

+ 1 - 1
CamelotGLRenderer/Source/GLSL/include/CmGLSLProgram.h

@@ -102,7 +102,7 @@ namespace CamelotEngine {
 		friend class GLSLProgramFactory;
 
 		GLSLProgram(const String& source, const String& entryPoint, const String& language, 
-			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes, 
+			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes, 
 			bool isAdjacencyInfoRequired = false);
 
 		/**

+ 1 - 1
CamelotGLRenderer/Source/GLSL/include/CmGLSLProgramFactory.h

@@ -45,7 +45,7 @@ namespace CamelotEngine
 		const String& getLanguage(void) const;
 		/// create an instance of GLSLProgram
         HighLevelGpuProgram* create(const String& source, const String& entryPoint, GpuProgramType gptype, 
-			GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes);
+			GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes);
 		HighLevelGpuProgram* create();
     };
 }

+ 1 - 1
CamelotGLRenderer/Source/GLSL/src/CmGLSLGpuProgram.cpp

@@ -40,7 +40,7 @@ namespace CamelotEngine {
 	UINT32 GLSLGpuProgram::mHullShaderCount = 0;
     //-----------------------------------------------------------------------------
 	GLSLGpuProgram::GLSLGpuProgram(const String& source, const String& entryPoint, const String& language, 
-		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes) 
+		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes) 
 		:GpuProgram(source, entryPoint, language, gptype, profile, includes)
     {
         mSyntaxCode = "glsl";

+ 1 - 1
CamelotGLRenderer/Source/GLSL/src/CmGLSLProgram.cpp

@@ -47,7 +47,7 @@ namespace CamelotEngine
 {
 	//-----------------------------------------------------------------------
 	GLSLProgram::GLSLProgram(const String& source, const String& entryPoint, const String& language, 
-		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes, bool isAdjacencyInfoRequired)
+		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes, bool isAdjacencyInfoRequired)
 		: HighLevelGpuProgram(source, entryPoint, language, gptype, profile, includes, isAdjacencyInfoRequired),
 		mInputOperationType(DOT_TRIANGLE_LIST),
 		mOutputOperationType(DOT_TRIANGLE_LIST), mMaxOutputVertices(3)

+ 1 - 1
CamelotGLRenderer/Source/GLSL/src/CmGLSLProgramFactory.cpp

@@ -39,7 +39,7 @@ namespace CamelotEngine {
     }
     //-----------------------------------------------------------------------
     HighLevelGpuProgram* GLSLProgramFactory::create(const String& source, const String& entryPoint, 
-		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes)
+		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes)
     {
 		GLSLProgram* prog = new GLSLProgram(source, entryPoint, sLanguageName, gptype, profile, includes);
 

+ 1 - 1
CamelotRenderer/Include/CmCgProgram.h

@@ -72,7 +72,7 @@ namespace CamelotEngine {
 		CGprofile mSelectedCgProfile;
 
 		CgProgram(CGcontext context, const String& source, const String& entryPoint, const String& language, 
-			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes, 
+			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes, 
 			bool isAdjacencyInfoRequired = false);
 
         /** Internal load implementation, must be implemented by subclasses.

+ 1 - 1
CamelotRenderer/Include/CmCgProgramFactory.h

@@ -46,7 +46,7 @@ namespace CamelotEngine
 		/// Get the name of the language this factory creates programs for
 		const String& getLanguage(void) const;
         HighLevelGpuProgram* create(const String& source, const String& entryPoint, GpuProgramType gptype, 
-			GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes = nullptr);
+			GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes = nullptr);
 		HighLevelGpuProgram* create();
 		void destroy_internal(HighLevelGpuProgram* prog);
 

+ 1 - 1
CamelotRenderer/Include/CmGpuProgram.h

@@ -148,7 +148,7 @@ namespace CamelotEngine {
 		friend class GpuProgramManager;
 
 		GpuProgram(const String& source, const String& entryPoint, const String& language, 
-			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes, 
+			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes, 
 			bool isAdjacencyInfoRequired = false);
 
         /** Internal method returns whether required capabilities for this program is supported.

+ 3 - 0
CamelotRenderer/Include/CmGpuProgramImportOptions.h

@@ -15,11 +15,13 @@ namespace CamelotEngine
 		void setLanguage(const String& language) { mLanguage = language; }
 		void setProfile(GpuProgramProfile profile) { mProfile = profile; }
 		void setType(GpuProgramType type) { mType = type; }
+		void setIncludes(const vector<GpuProgIncludeHandle>::type& includes) { mIncludes = includes; }
 
 		const String& getEntryPoint() const { return mEntryPoint; }
 		const String& getLanguage() const { return mLanguage; }
 		GpuProgramProfile getProfile() const { return mProfile; }
 		GpuProgramType getType() const { return mType; }
+		const vector<GpuProgIncludeHandle>::type& getIncludes() const { return mIncludes; }
 
 		/************************************************************************/
 		/* 								SERIALIZATION                      		*/
@@ -34,5 +36,6 @@ namespace CamelotEngine
 		String mLanguage;
 		GpuProgramProfile mProfile;
 		GpuProgramType mType;
+		vector<GpuProgIncludeHandle>::type mIncludes;
 	};
 }

+ 7 - 0
CamelotRenderer/Include/CmGpuProgramImportOptionsRTTI.h

@@ -21,6 +21,11 @@ namespace CamelotEngine
 		GpuProgramType& getType(GpuProgramImportOptions* obj) { return obj->mType; }
 		void setType(GpuProgramImportOptions* obj, GpuProgramType& value) { obj->mType = value; }
 
+		GpuProgIncludeHandle& getInclude(GpuProgramImportOptions* obj, UINT32 arrIdx) { return obj->mIncludes[arrIdx]; }
+		void setInclude(GpuProgramImportOptions* obj, UINT32 arrIdx, GpuProgIncludeHandle& value) { obj->mIncludes[arrIdx] = value; }
+		UINT32 getNumIncludes(GpuProgramImportOptions* obj) { return (UINT32)obj->mIncludes.size(); }
+		void setNumIncludes(GpuProgramImportOptions* obj, UINT32 num) { obj->mIncludes.clear(); obj->mIncludes.resize(num); }
+
 	public:
 		GpuProgramImportOptionsRTTI()
 		{
@@ -28,6 +33,8 @@ namespace CamelotEngine
 			addPlainField("mLanguage", 1, &GpuProgramImportOptionsRTTI::getLanguage, &GpuProgramImportOptionsRTTI::setLanguage);
 			addPlainField("mProfile", 2, &GpuProgramImportOptionsRTTI::getProfile, &GpuProgramImportOptionsRTTI::setProfile);
 			addPlainField("mType", 3, &GpuProgramImportOptionsRTTI::getType, &GpuProgramImportOptionsRTTI::setType);
+			addReflectableArrayField("mIncludes", 4, &GpuProgramImportOptionsRTTI::getInclude, &GpuProgramImportOptionsRTTI::getNumIncludes, 
+				&GpuProgramImportOptionsRTTI::setInclude, &GpuProgramImportOptionsRTTI::setNumIncludes);
 		}
 
 		virtual const String& getRTTIName()

+ 2 - 2
CamelotRenderer/Include/CmHighLevelGpuProgram.h

@@ -73,7 +73,7 @@ namespace CamelotEngine {
 
 		/** Constructor, should be used only by factory classes. */
 		HighLevelGpuProgram(const String& source, const String& entryPoint, const String& language, 
-			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes,
+			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes,
 			bool isAdjacencyInfoRequired = false);
 
 		/**
@@ -94,7 +94,7 @@ namespace CamelotEngine {
 		/************************************************************************/
 	public:
 		static HighLevelGpuProgramHandle create(const String& source, const String& entryPoint, 
-			const String& language, GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes = nullptr);
+			const String& language, GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes = nullptr);
     };
 
 	/** @} */

+ 2 - 2
CamelotRenderer/Include/CmHighLevelGpuProgramManager.h

@@ -50,7 +50,7 @@ namespace CamelotEngine {
 		/// Get the name of the language this factory creates programs for
 		virtual const String& getLanguage(void) const = 0;
         virtual HighLevelGpuProgram* create(const String& source, const String& entryPoint, 
-			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes) = 0;
+			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes) = 0;
 		virtual HighLevelGpuProgram* create() = 0;
 	};
 	/** This ResourceManager manages high-level vertex and fragment programs. 
@@ -100,7 +100,7 @@ namespace CamelotEngine {
 		@param gptype The type of program to create
 		*/
 		HighLevelGpuProgramPtr create(const String& source, const String& entryPoint, const String& language, 
-			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes);
+			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes);
 
 		/** Create a new HighLevelGpuProgram. 
 		@par

+ 1 - 1
CamelotRenderer/Source/CmCgProgram.cpp

@@ -139,7 +139,7 @@ namespace CamelotEngine {
 	}
 
 	CgProgram::CgProgram(CGcontext context, const String& source, const String& entryPoint, const String& language, 
-		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes, bool isAdjacencyInfoRequired)
+		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes, bool isAdjacencyInfoRequired)
         : HighLevelGpuProgram(source, entryPoint, language, gptype, profile, includes, isAdjacencyInfoRequired), 
         mCgContext(context), mCgProgram(0), 
         mSelectedCgProfile(CG_PROFILE_UNKNOWN)

+ 1 - 1
CamelotRenderer/Source/CmCgProgramFactory.cpp

@@ -55,7 +55,7 @@ namespace CamelotEngine {
     }
     //-----------------------------------------------------------------------
     HighLevelGpuProgram* CgProgramFactory::create(const String& source, const String& entryPoint, 
-		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes)
+		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes)
     {
 		CgProgram* prog = new CgProgram(mCgContext, source, entryPoint, sLanguageName, gptype, profile, includes);
 

+ 1 - 1
CamelotRenderer/Source/CmGpuProgram.cpp

@@ -47,7 +47,7 @@ namespace CamelotEngine
 {
     //-----------------------------------------------------------------------------
     GpuProgram::GpuProgram(const String& source, const String& entryPoint, const String& language, 
-		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes, bool isAdjacencyInfoRequired) 
+		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes, bool isAdjacencyInfoRequired) 
         :mEntryPoint(entryPoint), mSyntaxCode(language), mType(gptype),
 		mProfile(profile), mNeedsAdjacencyInfo(isAdjacencyInfoRequired)
     {

+ 2 - 1
CamelotRenderer/Source/CmGpuProgramImporter.cpp

@@ -35,8 +35,9 @@ namespace CamelotEngine
 		GpuProgramProfile profile = gpuProgImportOptions->getProfile();
 		String language = gpuProgImportOptions->getLanguage();
 		GpuProgramType gptype = gpuProgImportOptions->getType();
+		vector<GpuProgIncludeHandle>::type includes = gpuProgImportOptions->getIncludes();
 
-		HighLevelGpuProgramHandle gpuProgram = HighLevelGpuProgram::create(shaderSource, entryPoint, language, gptype, profile, nullptr);
+		HighLevelGpuProgramHandle gpuProgram = HighLevelGpuProgram::create(shaderSource, entryPoint, language, gptype, profile, &includes);
 		gpuProgram.waitUntilLoaded();
 
 		return gpuProgram;

+ 2 - 2
CamelotRenderer/Source/CmHighLevelGpuProgram.cpp

@@ -42,7 +42,7 @@ namespace CamelotEngine
 {
     //---------------------------------------------------------------------------
 	HighLevelGpuProgram::HighLevelGpuProgram(const String& source, const String& entryPoint, const String& language, 
-		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes, bool isAdjacencyInfoRequired)
+		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes, bool isAdjacencyInfoRequired)
         : GpuProgram(source, entryPoint, language, gptype, profile, includes, isAdjacencyInfoRequired), 
         mAssemblerProgram(nullptr)
     {
@@ -75,7 +75,7 @@ namespace CamelotEngine
     }
 	//---------------------------------------------------------------------
 	HighLevelGpuProgramHandle HighLevelGpuProgram::create(const String& source, const String& entryPoint, 
-		const String& language, GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes)
+		const String& language, GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes)
 	{
 		HighLevelGpuProgramPtr programPtr = HighLevelGpuProgramManager::instance().create(source, entryPoint, language, gptype, profile, includes);
 

+ 2 - 2
CamelotRenderer/Source/CmHighLevelGpuProgramManager.cpp

@@ -78,7 +78,7 @@ namespace CamelotEngine {
 			return sNullLang;
 		}
 		HighLevelGpuProgram* create(const String& source, const String& entryPoint, 
-			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes)
+			GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes)
 		{
 			return new NullProgram();
 		}
@@ -143,7 +143,7 @@ namespace CamelotEngine {
 	}
     //---------------------------------------------------------------------------
     HighLevelGpuProgramPtr HighLevelGpuProgramManager::create(const String& source, const String& entryPoint, const String& language, 
-		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludePtr>::type* includes)
+		GpuProgramType gptype, GpuProgramProfile profile, const vector<GpuProgIncludeHandle>::type* includes)
     {
 		HighLevelGpuProgramFactory* factory = getFactory(language);
         HighLevelGpuProgramPtr ret = HighLevelGpuProgramPtr(factory->create(source, entryPoint, gptype, profile, includes), &CoreGpuObject::_deleteDelayed);

+ 2 - 2
CamelotRenderer/Source/CmMaterial.cpp

@@ -159,14 +159,14 @@ namespace CamelotEngine
 
 				if(findIter->second->type != iter->second.type)
 				{
-					LOGWRN("Ignoring shader parameter " + iter->first  +". Type doesn't match the one defined in the gpu program. "
+					LOGWRN("Ignoring shader parameter \"" + iter->first  +"\". Type doesn't match the one defined in the gpu program. "
 						+ "Shader defined type: " + toString(iter->second.type) + " - Gpu program defined type: " + toString(findIter->second->type));
 					continue;
 				}
 
 				if(findIter->second->arraySize != iter->second.arraySize)
 				{
-					LOGWRN("Ignoring shader parameter " + iter->first  +". Array size doesn't match the one defined in the gpu program."
+					LOGWRN("Ignoring shader parameter \"" + iter->first  +"\". Array size doesn't match the one defined in the gpu program."
 						+ "Shader defined array size: " + toString(iter->second.arraySize) + " - Gpu program defined array size: " + toString(findIter->second->arraySize));
 					continue;
 				}

+ 6 - 8
CamelotRenderer/TODO.txt

@@ -12,16 +12,14 @@
 >>>>>>>>>>FINAL SPRINT BEFORE EDITOR WORK
 Pass
  - A way to bind buffers to a Pass, while specifying buffer range
- - GpuParams support for buffers, structs
  - Add GL Texture buffers (They're equivalent to DX11 buffers) - http://www.opengl.org/wiki/Buffer_Texture
 
-Shader import:
- - Make sure none of the current shaders in CamelotClient are defined in code anymore
- - Add include files to ImportOptions
-
-Add a better way of determining GLSL cpuMemOffset and block size (seems to be using DX11 padding)
- - I probably need to determine struct sizes before assigning cpuMemOffset
- - I probably also need a preprocessing step to determine array sizes
+GLSL/HLSL
+ - Arrays of objects
+   - I'm assuming there will be a problem when OpenGL optimizes out a certain value
+ - See if I can make HLSL param offsets not fixed? (More like GLSL. It should be possible)
+ - Structs aren't supported in GLSL
+   - I probably need a custom parser for them
 
 Deserialization issues:
  - Currently Reflectable is not allowed to hold a ReflectablePtr