Преглед на файлове

All shaders are loaded from files
Added includes to GpuProgramImportOptions

Marko Pintera преди 13 години
родител
ревизия
89658aa9eb
променени са 32 файла, в които са добавени 173 реда и са изтрити 155 реда
  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