private void SetupCommonRegisters() { Dictionary <string, Register> common = new Dictionary <string, Register>(); AsmListing[] listings = new AsmListing[] { vsListing, psListing, vsPreshaderListing, psPreshaderListing }; 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 void ProcessShader(string asm, out AsmListing shader, out AsmListing preshader, out string comment) { preshader = null; //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))); } else { //no preshader shader = new AsmListing(CombineLines(asmLines, firstBlockStart, firstBlockLength), new RegisterSet(CombineLines(asmLines, 1, headerLength))); } }
public AsmToHlslAsmConverter(AsmListing asmSource, Microsoft.Xna.Framework.TargetPlatform platform, int shaderMaxConstants, int shaderMaxBooleanConstants, bool throwOnError) { 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(); }