private string ProcessTechniqueVS(SourceShader shader, HlslTechnique technique, AsmTechnique asmTechnique, ShaderExtension extension, Platform platform)
		{
			HlslMethod vs = shader.GetMethod(technique.VertexShaderMethodName, platform);
			HlslMethod ps = shader.GetMethod(technique.PixelShaderMethodName, platform);

			if (vs == null) throw new CompileException(string.Format("Unabled to find declaration for vertex shader method '{0}'", technique.VertexShaderMethodName));
			if (ps == null) throw new CompileException(string.Format("Unabled to find declaration for pixel shader method '{0}'", technique.PixelShaderMethodName));

			string nameAppend = "_" + Guid.NewGuid().ToString("N") + "_" + extension.ToString();
			string blendName = "__blend_weights__GEN";
			string indicesName = "__blend_indices__GEN";

			//generated merged matrices
			StringBuilder matrixGen = new StringBuilder();
			foreach (var remap in matrixRemap.Values)
			{
				if (remap.BaseName != null) // this will be null for the world matrix
				{
					//find the matching register in the technique
					string matrixType;
					string matrixExpansion = GetMatrixRankExpansion(remap.Name, asmTechnique, out matrixType);

					if (extension == ShaderExtension.Instancing)
						matrixGen.AppendFormat("\tfloat4x4 {0} = float4x4(({4})mul({1},{2}){3});", remap.RemapTo, worldMatrixName, remap.BaseName, matrixExpansion, matrixType);
					if (extension == ShaderExtension.Blending)
						matrixGen.AppendFormat("\tfloat4x4 {0} = float4x4(({4})mul({1},{2}){3});", remap.RemapTo, worldMatrixName, remap.Name, matrixExpansion, matrixType);
					matrixGen.AppendLine();
				}
			}


			//create the method signatures
			footer.AppendLine();
			bool multiArg = false;
			StringBuilder argList = new StringBuilder();
			int argIndex = -1;
			bool transposeWorldMatrix = false;

			foreach (var element in vs.HlslShader.Elements)
			{
				if (element.Statement == vs.Name)
				{
					footer.Append(vs.Name);
					footer.Append(nameAppend);
				}
				else
				{
					if (element.Statement == "(" || element.Statement == ",")
						argIndex = 0;
					else
					{
						argIndex++;
						if (element.Statement == "out" ||
							element.Statement == "in" ||
							element.Statement == "inout" ||
							element.Statement == "uniform" ||
							element.Statement == "const")
							argIndex--;
						if (argIndex != -1 && argIndex == 2)
						{
							if (argList.Length > 0)
								argList.Append(", ");
							argList.Append(element.Statement);
						}
					}

					if (element.Statement == ")")
					{
						argIndex = -1;

						if (methodNames.TryGetValue(vs.Name, out multiArg) && multiArg)
							footer.Append(", ");

						if (extension == ShaderExtension.Instancing)
						{
							footer.Append("float4x4 " + worldMatrixName + "_transpose : POSITION12");
							transposeWorldMatrix = true;
						}
						if (extension == ShaderExtension.Blending)
						{
							footer.AppendFormat("float4 {0} : BLENDWEIGHT, int4 {1} : BLENDINDICES", blendName, indicesName);
						}
					}

					footer.Append(element);
					footer.Append(' ');
				}
			}
			footer.AppendLine();
			footer.AppendLine("{");

			if (transposeWorldMatrix)
			{
				footer.AppendLine("\tfloat4x4 " + worldMatrixName + " = transpose(" + worldMatrixName + "_transpose);");
			}

			if (extension == ShaderExtension.Blending)
			{
				string calculation =
@"	float4x4 {3}
		= transpose(float4x4(
			{0}[{1}.x * 3 + 0] * {2}.x + {0}[{1}.y * 3 + 0] * {2}.y + {0}[{1}.z * 3 + 0] * {2}.z + {0}[{1}.w * 3 + 0] * {2}.w,
			{0}[{1}.x * 3 + 1] * {2}.x + {0}[{1}.y * 3 + 1] * {2}.y + {0}[{1}.z * 3 + 1] * {2}.z + {0}[{1}.w * 3 + 1] * {2}.w,
			{0}[{1}.x * 3 + 2] * {2}.x + {0}[{1}.y * 3 + 2] * {2}.y + {0}[{1}.z * 3 + 2] * {2}.z + {0}[{1}.w * 3 + 2] * {2}.w,
			float4(0,0,0,1)));";

				footer.AppendFormat(calculation, blendMatricesName, indicesName, blendName, worldMatrixName);
				footer.AppendLine();
			}
			
			footer.Append(matrixGen);
			
			footer.AppendFormat("\t{4}{0}({1}{2}{3});", ToInternalMethodName(vs.Name, extension), methodCallAppend, multiArg ? ", " : "", argList, vs.HasReturnValue ? "return " : "");

			footer.AppendLine();
			footer.AppendLine("}");

			return vs.Name + nameAppend;
		}
		void TranslateMatrices(HlslStructure.ShaderStatement[] elements, int callDepth, ShaderExtension extension)
		{
			bool isInstancing = extension == ShaderExtension.Instancing;
			List<int> skipFinalRemappingIndices = new List<int>();

			int processingMul = 0, depth = 0, arg = 0;
			int argStart = 0, argEnd = 0;
			int remapArg = -1;
			int remapIndex = 0;
			MatrixMapping remapping = new MatrixMapping();

			Stack<int> mulStart = new Stack<int>();
			Stack<int> mulDepth = new Stack<int>();
			Stack<int> mulArg = new Stack<int>();
			Stack<int> mulArgStart = new Stack<int>();
			Stack<int> mulArgEnd = new Stack<int>();
			Stack<int> mulRemap = new Stack<int>();
			Stack<int> mulRemapIdx = new Stack<int>();
			Stack<MatrixMapping> mulRemapping = new Stack<MatrixMapping>();

			for (int i = 0; i < elements.Length; i++)
			{
				string line = elements[i].Statement;

				if (line == "mul")
				{
					processingMul++;
					mulStart.Push(i);
					mulDepth.Push(depth);
					mulArg.Push(arg);
					mulArgEnd.Push(argEnd);
					mulArgStart.Push(argStart);
					mulRemap.Push(remapArg);
					mulRemapping.Push(remapping);
					mulRemapIdx.Push(remapIndex);

					depth = 0;
					arg = 0;
					argStart = 0;
					argEnd = 0;
					remapArg = -1;
					remapIndex = 0;
					remapping = new MatrixMapping();
				}

				MatrixMapping mapping;
				if (processingMul > 0 && depth == 1 && matrixRemap.TryGetValue(line, out mapping) && (mapping.BaseName != null || !isInstancing))
				{
					remapArg = arg;
					remapping = mapping;
					remapIndex = i;
				}

				if (processingMul > 0 && line == "(")
				{
					if (depth == 0)
						argStart = i;
					depth++;
				}

				if (processingMul > 0 && depth == 1 && line == ",")
				{
					if (depth == 1)
						argEnd = i;
					arg++;
				}

				if (processingMul > 0 && line == ")")
				{
					depth--;
					if (depth == 0)
					{
						string baseMatrix = remapping.Name;
						if (isInstancing)
							baseMatrix = remapping.BaseName;

						string prefix = "";
						int startPrefix = -1;
						if (remapArg == 1)
							startPrefix = argEnd;
						if (remapArg == 0)
							startPrefix = argStart;

						if (remapIndex > startPrefix && startPrefix != -1)
						{
							for (int p = startPrefix + 1; p < remapIndex; p++)
								prefix += elements[p].Statement + " ";
						}

						//right, see if the args need modifying.
						if (remapArg == 1)
						{
							//a known remapping matrix was used.
							var element = elements[remapIndex];
							elements[remapIndex] = new HlslStructure.ShaderStatement(baseMatrix, element.Line);

							element = elements[argStart];
							elements[argStart] = new HlslStructure.ShaderStatement("(mul(", element.Line);

							element = elements[argEnd];
							elements[argEnd] = new HlslStructure.ShaderStatement("," + prefix + worldMatrixName + "),", element.Line);

							if (!isInstancing)
								skipFinalRemappingIndices.Add(remapIndex);
						}

						if (remapArg == 0) // transpose
						{
							//a known remapping matrix was used.
							var element = elements[remapIndex];
							elements[remapIndex] = new HlslStructure.ShaderStatement(baseMatrix, element.Line);

							element = elements[argEnd];
							elements[argEnd] = new HlslStructure.ShaderStatement(",mul(" + prefix + worldMatrixName + ",", element.Line);

							element = elements[i];
							elements[i] = new HlslStructure.ShaderStatement("))", element.Line);

							if (!isInstancing)
								skipFinalRemappingIndices.Add(remapIndex);
						}


						processingMul--;
						mulStart.Pop();
						depth = mulDepth.Pop();
						arg = mulArg.Pop();
						argEnd = mulArgEnd.Pop();
						argStart = mulArgStart.Pop();
						remapArg = mulRemap.Pop();
						remapping = mulRemapping.Pop();
						remapIndex = mulRemapIdx.Pop();
					}
				}
			}

			//find unremapped matrices
			if (callDepth > 0)
			{
				for (int i = 0; i < elements.Length; i++)
				{
					//it is intended that this matrix reference is not modified.
					if (!isInstancing && skipFinalRemappingIndices.Contains(i))
						continue;

					MatrixMapping mapping;
					if (matrixRemap.TryGetValue(elements[i].Statement, out mapping))
						elements[i] = new HlslStructure.ShaderStatement(mapping.RemapTo, elements[i].Line);
				}
			}
		}
		void TranslateMethodNames(HlslStructure.ShaderStatement[] elements, int callDepth, ShaderExtension extension)
		{
			for (int i = 0; i < elements.Length; i++)
			{
				string methodName = elements[i].Statement;

				bool multArg;
				if (methodNames.TryGetValue(methodName, out multArg))
				{
					BuildMethod(methodName, extension);

					//find the method start
					for (int n = i+1; n < elements.Length; n++)
					{
						if (elements[n] == "(")
						{
							string argAppend = multArg ? ", " : "";
							//append the method signatures
							if (callDepth == 0)
								elements[n] = new HlslStructure.ShaderStatement("(" + this.methodSignatureAppend + argAppend, elements[n].Line);
							else
								elements[n] = new HlslStructure.ShaderStatement("(" + this.methodCallAppend + argAppend, elements[n].Line);

							elements[i] = new HlslStructure.ShaderStatement(ToInternalMethodName(methodName,extension), elements[i].Line);
							break;
						}
					}
				}
			}
		}
		void BuildMethod(string methodName, ShaderExtension extension)
		{
			if (methodBuilt.ContainsKey(methodName) == false)
				return;
			if (methodBuilt[methodName])
				return;

			StringBuilder sb = new StringBuilder();

			foreach (var method in methodList)
			{
				if (method.Name == methodName)
				{
					methodBuilt[methodName] = true;
					method.HlslShader.ToString(sb, 0, this, null, false, false);
				}
			}

			this.builtShader.Append(sb);
		}
		private void BuildTechniqueMethod(SourceShader shader, ShaderExtension extension)
		{
			methodExtractionExtension = extension;

			foreach (var method in methodList)
			{
				if (methodBuilt.ContainsKey(method.Name) == false)
					methodBuilt.Add(method.Name, false);
			}

			foreach (var tech in shader.GetAllTechniques())
			{
				BuildMethod(tech.VertexShaderMethodName, extension);
			}

			methodBuilt.Clear();

			UnwindBackup(shader.HlslShader);
		}
		static string ToInternalMethodName(string name, ShaderExtension extension)
		{
			return string.Format("__{0}__{1}_GENCALL", name, extension);
		}