internal static void Do(Option option) { if (!option.IsValid) { DisplayUsage(); return; } RunPreprocess(option); RunFxc(option); char* bytecode = (char*)System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(option.ByteCodedFile); var dir = Path.GetDirectoryName(option.Input); var tmp = DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss") + ".txt"; tmp = Path.Combine(dir, tmp); DebugWriteLine("{0}", tmp); char* output = (char*)System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(tmp); bool result = izanagi.tool.MojoShaderProxy.Parse((sbyte*)bytecode, (sbyte*)output); DebugWriteLine("{0}", result ? "Succeeded" : "Failed"); if (!result) { throw new Exception("Failed parsing shader by MojoShader!!"); } else { DebugWriteLine("Export to [{0}]", option.Output); Dictionary<string, string> samplerNameDefs = new Dictionary<string, string>(); AnalyzeSamplerName(tmp, samplerNameDefs); // GLSLにプリプロセスを行う #if true var preprocessed = tmp + ".pp"; RunPreprocess( new Option() { Input = tmp, PreprocessedFile = preprocessed, }); File.Delete(tmp); tmp = preprocessed; #endif // 後処理を行う int count = 0; using (var sr = new StreamReader(tmp, Encoding.ASCII)) { using (var sw = new StreamWriter(option.Output, false, Encoding.ASCII)) { if (option.IsExportAsStringTable) { sw.WriteLine("const char* " + option.Entry + " = {"); } while (sr.Peek() >= 0) { var line = sr.ReadLine(); if (count == 0) { if (option.glType == GLType.GLES2) { // 先頭に浮動小数の精度を定義する WriteLine(option, sw, "precision highp float;"); WriteLine(option, sw, ""); } } else { sw.WriteLine(); Write(option, sw, line); // サンプラの元の名前をコメントとして挿入する if (line.Contains("uniform sampler")) { sw.WriteLine(); foreach (var pair in samplerNameDefs) { var comment = string.Format("// original name:{0}/{1}", pair.Key, pair.Value); WriteLine(option, sw, comment); } // すべてを挿入したのでクリアする samplerNameDefs.Clear(); } } count++; } if (option.IsExportAsStringTable) { sw.WriteLine("};"); } } } } File.Delete(tmp); }
static void Main(string[] args) { try { var option = new Option(args); if (option.IsAnaylizeMode) { int index = Analyzer.GetSamplerIndex(option.Input, option.Entry); Console.WriteLine(index); } else { Compiler.Do(option); } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } }
static void WriteLine(Option option, StreamWriter sw, string line) { string output = line; if (option.IsExportAsStringTable) { output = string.Format("\"{0}\\n\"", line); sw.WriteLine(output); } else { sw.Write(output + "\n"); } }
/// <summary> /// Preproc.exe を実行 /// </summary> /// <param name="option"></param> /// <param name="enableLineDirectives"></param> static void RunPreprocess( Option option, bool enableLineDirectives = true) { var process = new Process(); process.StartInfo = PrepareProcessPreproc(option, enableLineDirectives); DebugWriteLine("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); process.Start(); process.WaitForExit(); }
/// <summary> /// fxc.exe を実行 /// </summary> /// <param name="option"></param> static void RunFxc(Option option) { var process = new Process(); process.StartInfo = PrepareProcessFxc(option); DebugWriteLine("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); process.Start(); process.WaitForExit(); var output = process.StandardError.ReadToEnd(); Console.WriteLine(output); }
/// <summary> /// Preproc.exe のプロセスを実行するための準備 /// </summary> /// <param name="option"></param> /// <param name="enableLineDirectives"></param> /// <returns>Preproc.exe のプロセス開始情報</returns> static ProcessStartInfo PrepareProcessPreproc( Option option, bool enableLineDirectives) { // NOTE // Preproc.exe は実行ファイルと同じパスにあること var asm = Assembly.GetEntryAssembly(); string path = asm.Location; var preproc = Path.GetDirectoryName(path); preproc = Path.Combine(preproc, "Preproc.exe"); if (!File.Exists(preproc)) { // TODO throw new Exception(); } string args = ""; if (!string.IsNullOrEmpty(option.Includes)) { args += " -I" + " " + option.Includes; } if (!string.IsNullOrEmpty(option.Defines)) { args += " -D" + " " + option.Defines; } if (!enableLineDirectives) { args += " " + "-EP"; } args += " " + option.Input; args += " " + option.PreprocessedFile; ProcessStartInfo info = new ProcessStartInfo(); info.FileName = preproc; info.Arguments = args; info.CreateNoWindow = true; info.RedirectStandardOutput = true; info.RedirectStandardError = false; info.UseShellExecute = false; return info; }
/// <summary> /// fxc.exe のプロセスを実行するための準備 /// </summary> /// <param name="option"></param> /// <returns>fxc.exe のプロセス開始情報</returns> static ProcessStartInfo PrepareProcessFxc(Option option) { // DXSDKのディレクトリのパスを環境変数より取得 var dxDir = System.Environment.GetEnvironmentVariable("DXSDK_DIR"); if (string.IsNullOrEmpty(dxDir)) { throw new Exception("No DXSDK."); } ProcessStartInfo info = new ProcessStartInfo(); // fxc.exe のパス info.FileName = Path.Combine(dxDir, @"Utilities\bin\x64", "fxc.exe"); info.Arguments = "/nologo"; info.Arguments += " " + "/Fo" + " " + option.ByteCodedFile; info.Arguments += " " + "/E" + " " + option.Entry; info.Arguments += " " + "/T" + " " + option.Profile; info.Arguments += " " + option.PreprocessedFile; info.CreateNoWindow = true; info.RedirectStandardOutput = true; info.RedirectStandardError = true; info.UseShellExecute = false; return info; }