private static string GetTechniqueInvoke(TokenRename rename, StringBuilder sb, HlslMethod method, IEnumerator<string> argsEnum)
		{
			string methodCall = rename.TranslateMethodName(method.Name);

			StringBuilder call = new StringBuilder();

			call.Append(methodCall);
			call.Append("(");

			while (argsEnum.MoveNext())
			{
				call.Append(argsEnum.Current);
			}
			call.Append(")");

			return call.ToString();
		}
		private static void ExtractMethodBody(TokenRename rename, StringBuilder sb, HlslMethod method, string prefix)
		{
			method.HlslShader.ToString(sb, 0, rename, prefix, true, false);
		}
		private static void ExtractMethodBodies(StringBuilder sb, TokenRename rename)
		{
			StringBuilder methodBody = new StringBuilder();
			for (int i = 0; i < rename.methodList.Count; i++)
			{
				ExtractMethodBody(rename, methodBody, rename.methodList[i], null);
				sb.Insert(0, methodBody);
				methodBody.Length = 0;
			}
		}
		private static void MapRegistersToRenamer(TokenRename rename, RegisterSet set, string extension)
		{
			foreach (Register reg in set)
			{
				if (reg.Category == RegisterCategory.Sampler)
					rename.samplerRemapping.Add(reg.Name, string.Format("_" + extension + "_s{0}", reg.Index));
				else
				{
					if (reg.ArraySize > 0)
						rename.arrayRemapping.Add(reg.Name, TranslateRegisterName(reg.Name, extension));
					else
						rename.registerRemapping.Add(reg.Name, TranslateRegisterName(reg.Name, extension));
				}
			}
		}
		public static byte[] Generate(SourceShader source, HlslTechnique technique, Platform platform)
		{

		//	ShaderExtensionGenerator exGen = new ShaderExtensionGenerator(source, platform);

			TokenRename vsRename, psRename;
			TokenRename vsBlendRename, vsInstanceRename;

			vsRename = new TokenRename(source, platform, "VS");
			psRename = new TokenRename(source, platform, "PS");

			vsBlendRename = new TokenRename(source, platform, "VS_B");
			vsInstanceRename = new TokenRename(source, platform, "VS_I");

			HlslMethod methodVS = source.GetMethod(technique.VertexShaderMethodName, platform);
			HlslMethod methodPS = source.GetMethod(technique.PixelShaderMethodName, platform);
			
			HlslMethod methodBlending = source.GetMethod(technique.BlendingShaderMethodName, platform);
			HlslMethod methodInstancing = source.GetMethod(technique.InstancingShaderMethodName, platform);

			if (methodPS == null || methodVS == null)
				return null;

			string vsPrefix, psPrefix;

			AsmTechnique asmTechnique = source.GetAsmTechnique(technique.Name, platform);
			vsPrefix = BuildMapping(asmTechnique, "vs", asmTechnique.VertexShader.RegisterSet);
			psPrefix = BuildMapping(asmTechnique, "ps", asmTechnique.PixelShader.RegisterSet);

			string blendingPrefix = null, instancingPrefix = null;
			if (asmTechnique.BlendingShader != null)
				blendingPrefix = BuildMapping(asmTechnique, "vsb", asmTechnique.BlendingShader.RegisterSet);
			if (asmTechnique.InstancingShader != null)
				instancingPrefix = BuildMapping(asmTechnique, "vsi", asmTechnique.InstancingShader.RegisterSet);

			//build the method bodies for the technique

			//process through all the methods used.
			vsRename.methodList.Add(methodVS);
			psRename.methodList.Add(methodPS);

			if (methodBlending != null) vsBlendRename.methodList.Add(methodBlending);
			if (methodInstancing != null) vsInstanceRename.methodList.Add(methodInstancing);

			//setup remapping for registers used
			MapRegistersToRenamer(vsRename, asmTechnique.VertexShader.RegisterSet, "vs");
			MapRegistersToRenamer(psRename, asmTechnique.PixelShader.RegisterSet, "ps");

			if (asmTechnique.BlendingShader != null)
			{
				MapRegistersToRenamer(vsBlendRename, asmTechnique.VertexShader.RegisterSet, "vs");
				MapRegistersToRenamer(vsBlendRename, asmTechnique.BlendingShader.RegisterSet, "vsb");
			}
			if (asmTechnique.InstancingShader != null)
			{
				MapRegistersToRenamer(vsInstanceRename, asmTechnique.VertexShader.RegisterSet, "vs");
				MapRegistersToRenamer(vsInstanceRename, asmTechnique.InstancingShader.RegisterSet, "vsi");
			}

			//finally, parse all the registers used by the Effect. Dump them in as 'unused'
			RegisterSet decompiledEffectRegisters = source.GetDecompiledEffect(platform).EffectRegisters;

			string unusedSamplerName = "__unused_sampler";
			string unusedFloatName = "__unused_";
			string unusedMatrixName = "__unused4x4_";
			string unusedArrayName = "__unused_array";

			foreach (Register reg in decompiledEffectRegisters)
			{
				if (reg.Name == null || reg.Category == RegisterCategory.Texture)
					continue;
				if (reg.Category == RegisterCategory.Sampler)
				{
					vsRename.unusedRemapping.Add(reg.Name, unusedSamplerName);
					psRename.unusedRemapping.Add(reg.Name, unusedSamplerName);
					vsBlendRename.unusedRemapping.Add(reg.Name, unusedSamplerName);
					vsInstanceRename.unusedRemapping.Add(reg.Name, unusedSamplerName);
				}
				else
				{
					vsRename.unusedRemapping.Add(reg.Name, reg.ArraySize > 0 ? unusedArrayName : (reg.Size > 1 ? unusedMatrixName : unusedFloatName));
					psRename.unusedRemapping.Add(reg.Name, reg.ArraySize > 0 ? unusedArrayName : (reg.Size > 1 ? unusedMatrixName : unusedFloatName));
					vsBlendRename.unusedRemapping.Add(reg.Name, reg.ArraySize > 0 ? unusedArrayName : (reg.Size > 1 ? unusedMatrixName : unusedFloatName));
					vsInstanceRename.unusedRemapping.Add(reg.Name, reg.ArraySize > 0 ? unusedArrayName : (reg.Size > 1 ? unusedMatrixName : unusedFloatName));
				}
			}
			//will write booleans down if the values are used.
			vsRename.unusedAccessed = new Dictionary<string, bool>();
			psRename.unusedAccessed = vsRename.unusedAccessed;
			vsBlendRename.unusedAccessed = vsRename.unusedAccessed;
			vsInstanceRename.unusedAccessed = vsRename.unusedAccessed;


			//note, the method list will be added to as new methods are needed by the base method.
			StringBuilder sb = new StringBuilder();

			//extract PS methods
			ExtractMethodBodies(sb, psRename);

			//extract VS methods
			ExtractMethodBodies(sb, vsRename);

			ExtractMethodBodies(sb, vsBlendRename);
			ExtractMethodBodies(sb, vsInstanceRename);

			string techniqueVsName = GetTechniqueInvoke(vsRename, sb, methodVS, technique.VertexShaderArgs);
			string techniquePsName = GetTechniqueInvoke(psRename, sb, methodPS, technique.PixelShaderArgs);

			string techniqueBlendingName = null, techniqueInstancingName = null;

			if (asmTechnique.BlendingShader != null)
				techniqueBlendingName = GetTechniqueInvoke(vsBlendRename, sb, methodBlending, technique.BlendingShaderArgs);
			if (asmTechnique.InstancingShader != null)
				techniqueInstancingName = GetTechniqueInvoke(vsInstanceRename, sb, methodInstancing, technique.InstancingShaderArgs);

			StringBuilder constants = new StringBuilder();

			//work out if any unused values were touched...
			//if so, add them.
			bool addUnusedSampler = false;
			bool addUnusedFloat = false;

			foreach (KeyValuePair<string,bool> item in vsRename.unusedAccessed)
			{
				if (item.Value)
				{
					//something has been used unexpectadly.
					Register reg;
					if (decompiledEffectRegisters.TryGetRegister(item.Key,out reg))
					{
						if (reg.Category == RegisterCategory.Sampler)
							addUnusedSampler = true;
						else
							addUnusedFloat = true;
					}
				}
			}
			if (addUnusedSampler)
				constants.AppendLine("sampler " + unusedSamplerName + ";");
			if (addUnusedFloat)
			{
				constants.AppendLine("const static float4 " + unusedFloatName + " = 0;");
				constants.AppendLine("const static float4x4 " + unusedMatrixName + " = 0;");
				constants.AppendLine("#define " + unusedArrayName + "(__INDEX__) " + unusedFloatName);
			}


			//setup the VS/PS constants
			asmTechnique.ConstructTechniqueConstants(constants, true);

			constants.Append(vsPrefix);
			constants.Append(psPrefix);
			if (blendingPrefix != null) constants.Append(blendingPrefix);
			if (instancingPrefix != null) constants.Append(instancingPrefix);

			constants.AppendLine(ExtractFixedDeclarations(source.HlslShader));

			//finally, build the technique delcaration
			string techniqueStructure =
@"{2}
{3}
technique Shader
{0}
	pass
	{0}
		VertexShader = compile {4} {5};
		PixelShader  = compile {6} {7};
	{1}
{8}{9}{1}";

			string extensionPass =
@"	pass {2}
	{0}
		VertexShader = compile {3} {4};
		PixelShader  = compile {5} {6};
	{1}
";
			string blendExtension = "", instanceExtension = "";

			if (asmTechnique.BlendingShader != null)
			{
				blendExtension = string.Format(extensionPass, "{", "}", "Blending", technique.GetVertexShaderVersion(platform), techniqueBlendingName, technique.GetPixelShaderVersion(platform), techniquePsName);
			}
			if (asmTechnique.InstancingShader != null)
			{
				instanceExtension = string.Format(extensionPass, "{", "}", "Instancing", "vs_3_0", techniqueInstancingName, "ps_3_0", techniquePsName);
			}

			string techniqueSource = string.Format(techniqueStructure, "{", "}", constants, sb,
				technique.GetVertexShaderVersion(platform), techniqueVsName,
				technique.GetPixelShaderVersion(platform), techniquePsName,
				blendExtension,instanceExtension);

			var types = typeof(EffectCompiler).Assembly.GetType("Xen.Graphics.ShaderSystem.EffectCompiler");
			var method = types.GetMethod("CompileEffect");

			CompileEffect effect = Delegate.CreateDelegate(typeof(CompileEffect), types.GetMethod("CompileEffect")) as CompileEffect;

			string compileErrors;
			byte[] compiledEffect = EffectCompiler.CompileEffect(techniqueSource, source.FileName, platform == Platform.Xbox, out compileErrors);

			if (compileErrors != null)
			{
				string[] errors = SanitizeConversionErrorMessage(compileErrors, techniqueSource, source.ShaderSource, source);

				if (source.ManualExtensions == false)
				{
					string errorsLine = "";
					foreach (var error in errors)
						errorsLine += error + Environment.NewLine;

					//error occured in generated code!
					ShaderExtensionGenerator.ThrowGeneratorError(errorsLine.Trim(), source.FileName);
				}
				else
				{
					string header = "XenFX Platform Technique Extraction Failed:";

					if (errors == null)
						Common.ThrowError(header, compileErrors);
					else
						Common.ThrowError(header, errors);
				}
			}

			return compiledEffect;
		}