public PreshaderSrc(AsmListing listing, CodeStatementCollection statementCollection)
		{
			statements = new List<CodeStatement>();

			object[] paramsArray = new object[1];
			StringBuilder sb = new StringBuilder();

			foreach (AsmCommand cmd in listing.Commands)
			{
				
				MethodInfo method;
				if (!methodList.TryGetValue(cmd.Target, out method))
				{
					if (cmd.Target == "preshader")
						continue;

					throw new CompileException(string.Format("Error decoding PreShader: Unexpected command '{0}'", cmd.Target));
				}

				string[] args = new string[cmd.OpCount];
				for (int i = 0; i < cmd.OpCount; i++)
				{
					cmd.GetOp(i).ToString(sb);
					args[i] = sb.ToString();
					sb.Length = 0;
				}
				paramsArray[0] = args;

				method.Invoke(this, paramsArray);
			}

			statementCollection.AddRange(this.statements.ToArray());
		}
示例#2
0
        public PreshaderSrc(AsmListing listing, CodeStatementCollection statementCollection)
        {
            statements = new List <CodeStatement>();

            object[]      paramsArray = new object[1];
            StringBuilder sb          = new StringBuilder();

            foreach (AsmCommand cmd in listing.Commands)
            {
                MethodInfo method;
                if (!methodList.TryGetValue(cmd.Target, out method))
                {
                    if (cmd.Target == "preshader")
                    {
                        continue;
                    }

                    throw new CompileException(string.Format("Error decoding PreShader: Unexpected command '{0}'", cmd.Target));
                }

                string[] args = new string[cmd.OpCount];
                for (int i = 0; i < cmd.OpCount; i++)
                {
                    cmd.GetOp(i).ToString(sb);
                    args[i]   = sb.ToString();
                    sb.Length = 0;
                }
                paramsArray[0] = args;

                method.Invoke(this, paramsArray);
            }

            statementCollection.AddRange(this.statements.ToArray());
        }
		public AsmToHlslAsmConverter(AsmListing asmSource, Microsoft.Xna.Framework.TargetPlatform platform, int shaderMaxConstants, int shaderMaxBooleanConstants, bool throwOnError)
		{
            this.platform = platform;

			maxConstant = -1;
			if (shaderMaxConstants != 0)
				maxConstant = shaderMaxConstants;
			maxBoolean = -1;
			if (shaderMaxBooleanConstants != 0)
				maxBoolean = shaderMaxBooleanConstants;
			maxRegister = -1;

			this.samplers = new List<InputOutput>();
			this.inputs = new List<InputOutput>();
			this.outputs = new List<InputOutput>();
			this.assignedConstants = new Dictionary<int, bool>();
			this.localConstants = new Dictionary<int, string>();
			this.localBooleanConstants = new Dictionary<int, string>();
			this.localIntegerConstants = new Dictionary<int, string>();

			for (int i = 0; i < 256; i++)
				assignedConstants.Add(i, false);

			this.source = new StringBuilder();

			this.listing = asmSource;

			if (listing.GetCommandCount() > 0)
			{
				//attempt to decode the shader
				if (DetectProfile())
				{
					List<Command> commands = new List<Command>();
					for (int i = 1; i < listing.GetCommandCount(); i++)
					{
						//extract the commands
						Command cmd = new Command(listing.GetCommand(i));
						if (cmd.name != null)
							commands.Add(cmd);
					}

					List<Command> allCommands = new List<Command>();

					List<Command> newCommands = new List<Command>();
					foreach (Command command in commands)
					{
						newCommands.Clear();
						GenerateCode(command, newCommands);
						allCommands.AddRange(newCommands);
					}
					commands = allCommands;

					bool isAsm = false;

					foreach (Command cmd in commands)
					{
						if (cmd.isAsm != isAsm)
						{
							if (isAsm)
							{
								this.source.Append("};");
								this.source.AppendLine();
							}
							else
							{
								this.source.Append("asm{");
								this.source.AppendLine();
							}
							isAsm = cmd.isAsm;
						}

						this.source.Append(cmd.name);
						for (int i = 0; i < cmd.args.Length; i++)
						{
							this.source.Append(' ');
							if (i != 0)
								this.source.Append(',');
							for (int a = 0; a < cmd.args[i].Length; a++)
								this.source.Append(cmd.args[i][a]);
						}
						this.source.AppendLine();
					}
					if (isAsm)
						this.source.Append("};");
				}
			}

			BuildMethod();

			CompiledShader shader =
				ShaderCompiler.CompileFromSource(
					this.source.ToString(),
					null, null, CompilerOptions.AvoidFlowControl, "Main",
					profile, platform);

			if (throwOnError && !shader.Success)
				Common.ThrowError("An error occured running the Xbox shader HLSL/ASM preprocessor", shader.ErrorsAndWarnings, asmSource.ToString());

			if (!shader.Success)
			{
				//tried the best.. if it failed, ohh well, go back to AssembleFromSource
				//probably used complex flow control?
				string rawAsm = asmSource.ToString();

				shader = ShaderCompiler.AssembleFromSource(rawAsm, null, null, CompilerOptions.None, platform);

				if (!shader.Success)
					Common.ThrowError(shader.ErrorsAndWarnings, rawAsm);
			}

			output = shader.GetShaderCode();
		}
		private bool ExtractAssignmentForExtenionBlock(CodeStatement assign, IShaderDom shader, AsmListing asmListing)
		{
			//special case, blending or instancing assignments need to go in an if block.

			if (asmListing == asm.BlendingShader)
			{
				blendExtensionAssignments.Add(assign);
				return true;
			}

			if (asmListing == asm.InstancingShader)
			{
				instancingExtensionAssignments.Add(assign);
				return true;
			}

			return false;
		}
示例#5
0
        private void CreateVertexInputMethods()
        {
            AsmListing asmVS = this.source.GetAsmTechnique(this.techniqueName, this.platform).VertexShader;

            //create the GetVertexInputCount() and GetVertexInput() methods

            CodeMemberMethod count = new CodeMemberMethod();

            count.Name       = "GetVertexInputCount";
            count.Attributes = MemberAttributes.Family | MemberAttributes.Override;
            count.ReturnType = new CodeTypeReference(typeof(int));

            Comment(count, "Returns the number of vertex inputs used by this shader");
            count.Statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(asmVS.InputCount)));
            classDom.Members.Add(count);

            //inputs are stored in a static array

            //create it...

            int[] arrayValues = new int[asmVS.InputCount * 2];
            for (int i = 0; i < asmVS.InputCount; i++)
            {
                arrayValues[i] = (int)asmVS.GetInput(i).Usage;
                arrayValues[i + asmVS.InputCount] = (int)asmVS.GetInput(i).Index;
            }

            this.vsInputField                = new CodeMemberField(typeof(int[]), "vin");
            this.vsInputField.Attributes     = MemberAttributes.Private | MemberAttributes.Static | MemberAttributes.Final;
            this.vsInputField.InitExpression = ShaderBytes.ToArray(arrayValues, this.directives);

            CodeFieldReferenceExpression vsInputRef = new CodeFieldReferenceExpression(ShaderClassEx, vsInputField.Name);

            //protected internal abstract void GetVertexInput(int index, out VertexElementUsage elementUsage, out int elementIndex);

            CodeMemberMethod getInput = new CodeMemberMethod();

            getInput.Name       = "GetVertexInput";
            getInput.Attributes = MemberAttributes.Family | MemberAttributes.Override;

            CodeParameterDeclarationExpression indexParam = new CodeParameterDeclarationExpression(typeof(int), "i");

            getInput.Parameters.Add(indexParam);

            CodeParameterDeclarationExpression param = new CodeParameterDeclarationExpression(typeof(VertexElementUsage), "usage");

            param.Direction = FieldDirection.Out;
            getInput.Parameters.Add(param);

            param           = new CodeParameterDeclarationExpression(typeof(int), "index");
            param.Direction = FieldDirection.Out;
            getInput.Parameters.Add(param);

            CodeArgumentReferenceExpression indexRef = new CodeArgumentReferenceExpression(indexParam.Name);

            //the element index is stored at 'i + asmVS.InputCount'
            CodeExpression indexArray = new CodeArrayIndexerExpression(vsInputRef,
                                                                       new CodeBinaryOperatorExpression(indexRef, CodeBinaryOperatorType.Add, new CodePrimitiveExpression(asmVS.InputCount)));

            //and the usage must be cast
            CodeExpression usageCast = new CodeCastExpression(typeof(VertexElementUsage), new CodeArrayIndexerExpression(vsInputRef, indexRef));

            getInput.Statements.Add(new CodeAssignStatement(new CodeArgumentReferenceExpression("usage"), usageCast));
            getInput.Statements.Add(new CodeAssignStatement(new CodeArgumentReferenceExpression("index"), indexArray));

            Comment(getInput, "Returns a vertex input used by this shader");

            classDom.Members.Add(getInput);
        }
		private void ProcessShader(string asm, out AsmListing shader, out string comment)
		{
			//format:

			//either,

			/*
			 * //header
			 * preshader
			 * //header
			 * shader
			 * //comment
			 */
			
			//or

			/*
			 * //header
			 * shader
			 * //comment
			 */

			string[] asmLinesSource = asm.Split(new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
			//ignore first and last line (the { and })
			string[] asmLines = new string[Math.Max(0,asmLinesSource.Length - 2)];
			for (int i = 1; i < asmLinesSource.Length-1; i++)
				asmLines[i - 1] = asmLinesSource[i].Trim();

			comment = "";
			if (asmLines.Length > 0)
			{
				comment = asmLines[asmLines.Length - 1];
				if (comment.StartsWith("// "))
					comment = comment.Substring(3);
			}

			bool[] isComment = new bool[asmLines.Length];

			for (int i = 0; i < asmLines.Length - 1; i++)
				isComment[i] = asmLines[i].StartsWith("//");

			//top header
			int headerLength = 0;
			int start = 0;
			for (int i = 1; i < asmLines.Length; i++)
			{
				if (!isComment[i] && asmLines[i].Length != 0)
					break;

				headerLength = i+1;
				start = i+1;
			}

			int firstBlockLength = 0;
			int firstBlockStart = start;
			for (int i = start; i < asmLines.Length; i++)
			{
				firstBlockLength = i - headerLength + 1;
				start = i+1;

				if (isComment[i])
					break;
			}

			int secondHeaderLength = 0;
			int secondHeaderStart = start;
			for (int i = start; i < asmLines.Length; i++)
			{
				if (!isComment[i] && asmLines[i].Length != 0)
					break;

				secondHeaderLength = i - firstBlockLength + 1;
				start = i+1;
			}

			int secondBlockLength = 0;
			int secondBlockStart = start;
			for (int i = start; i < asmLines.Length; i++)
			{
				secondBlockLength = i - secondHeaderLength + 1;
				start = i+1;

				if (isComment[i])
					break;
			}

			if (secondHeaderLength > 0 && 
				secondBlockLength  > 0)
			{
				//preshader is used
//				preshader = new AsmListing(CombineLines(asmLines, firstBlockStart, firstBlockLength), new RegisterSet(CombineLines(asmLines, 1, headerLength)));
//				shader = new AsmListing(CombineLines(asmLines, secondBlockStart, secondBlockLength), new RegisterSet(CombineLines(asmLines, secondHeaderStart, secondHeaderLength)));
				throw new CompileException("Compile Error: Unexpected preshader encountered! Turn back to save yourself!");
			}
			else
			{
				//no preshader
				shader = new AsmListing(CombineLines(asmLines, firstBlockStart, firstBlockLength), new RegisterSet(CombineLines(asmLines, 1, headerLength)));
			}
		}
		private void SetupCommonRegisters()
		{
			Dictionary<string, Register> common = new Dictionary<string, Register>();

			AsmListing[] listings = new AsmListing[] { vsListing, psListing, vsBlendOverride, vsInstancingOverride };

			foreach (AsmListing listing in listings)
			{
				if (listing == null)
					continue;

				for (int i = 0; i < listing.RegisterSet.RegisterCount; i++)
				{
					Register reg = listing.RegisterSet.GetRegister(i);

					if (!common.ContainsKey(reg.Name))
						common.Add(reg.Name, reg);
				}
			}

			Register[] registers = new Register[common.Count];
			int count = 0;

			foreach (Register reg in common.Values)
			{
				registers[count++] = reg;
			}

			this.registers = new RegisterSet(registers);
		}
		private AsmTechnique(string name, string source, TechniqueExtraData defaultValues)
		{
			Tokenizer tokenizer = new Tokenizer(source, false, true, true);
			this.name = name;
			this.defaultValues = defaultValues;

			//parse the asm, and extract the first pass.
			string pass = null;
			string firstPassName = null;
			string blendPass = null, instancingPass = null;

			while (tokenizer.NextToken())
			{
				if (tokenizer.Token.Equals("pass", StringComparison.InvariantCultureIgnoreCase))
				{
					//may have a name next...
					tokenizer.NextToken();
					string token = tokenizer.Token;
					string passName = null;

					if (token != "{")
					{
						//the name is specified
						passName = tokenizer.Token;
						tokenizer.NextToken();
						token = tokenizer.Token;
					}

					//may be a new line
					while (token.Trim().Length == 0)
					{
						tokenizer.NextToken();
						token = tokenizer.Token;
					}

					if (token != "{")
						throw new CompileException("Unexpected token in assembly technique pass declaration, expected '{': " + token);

					if (!tokenizer.ReadBlock())
						throw new CompileException("Unexpected end of string in assembly technique pass declaration");

					bool isAnimated, isInstancing;
					ExtractPassType(passName, out isAnimated, out isInstancing);

					string help = @"
For example:

technique TechniqueName
{
	//default pass:
	pass
	{
		VertexShader = compile vs_2_0 BaseVS();
		PixelShader = compile ps_2_0 BasePS();
	}
	pass Animated
	{
		VertexShader = compile vs_2_0 AnimatedVS();
	}
	pass Instancing
	{
		VertexShader = compile vs_2_0 InstancingVS();
	}
}

Note, the instancing or animation passes may only replace the vertex shader";

					if (pass != null)
					{
						if (blendPass == null && isAnimated)
						{
							blendPass = tokenizer.Token;
						}
						else if (instancingPass == null && isInstancing)
						{
							instancingPass = tokenizer.Token;
						}
						else
							throw new CompileException(@"A shader technique may only define a single Pass, or define a dedicated Animation and/or Instancing pass:"******"A shader technique must define a default pass before defining an instancing or animation pass:"******"Technique '" + name + "' does not define a pass");

			ProcessPass(pass);

			this.vsBlendOverride = ProcessSupplimentaryPass(blendPass);
			this.vsInstancingOverride = ProcessSupplimentaryPass(instancingPass);

			SetupCommonRegisters();

			if (this.vsBlendOverride != null)
				this.vsBlendOverride.RegisterSet.CompactDuplicateRegisters(this.vsListing.RegisterSet, "Animated", this.name);
			if (this.vsInstancingOverride != null)
				this.vsInstancingOverride.RegisterSet.CompactDuplicateRegisters(this.vsListing.RegisterSet, "Instancing", this.name);
		}