2012-08-22 10:34:39 +00:00
|
|
|
|
#region Using Statements
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
namespace ANX.Framework.Content.Pipeline.Processors
|
|
|
|
|
{
|
|
|
|
|
public class HLSLCompiler : IComparable<HLSLCompiler>, IEquatable<HLSLCompiler>
|
|
|
|
|
{
|
|
|
|
|
private string executable;
|
|
|
|
|
private string version;
|
|
|
|
|
private string helpOutput;
|
|
|
|
|
private string[] profiles;
|
|
|
|
|
|
|
|
|
|
public HLSLCompiler(string executable)
|
|
|
|
|
{
|
|
|
|
|
if (!String.IsNullOrEmpty(executable) && File.Exists(executable))
|
|
|
|
|
{
|
|
|
|
|
this.executable = executable;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentNullException("executable", "fxc.exe does not exist");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string Version
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (String.IsNullOrEmpty(version))
|
|
|
|
|
{
|
|
|
|
|
version = CompilerVersion;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return version;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IEnumerable<string> SupportedProfiles
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (profiles == null || profiles.Length <= 0)
|
|
|
|
|
{
|
|
|
|
|
const string profileStart = @"(cs|ds|fx|ps|hs|gs|vs|tx)(_)(\S+)\s?";
|
|
|
|
|
|
|
|
|
|
Regex pattern = new Regex(profileStart, RegexOptions.Singleline | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
|
|
|
|
|
MatchCollection m = pattern.Matches(CompilerHelpOutput);
|
|
|
|
|
|
|
|
|
|
HashSet<String> tempProfiles = new HashSet<string>();
|
|
|
|
|
foreach (Match profileMatch in m)
|
|
|
|
|
{
|
|
|
|
|
tempProfiles.Add(profileMatch.Value.Trim());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
profiles = tempProfiles.ToArray<String>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return profiles;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public byte[] Compile(string source, EffectProcessorDebugMode debugMode, string targetProfile)
|
|
|
|
|
{
|
|
|
|
|
string tempInputFile = CreateTemporaryShaderFile(source);
|
|
|
|
|
string tempOutputFile = Path.GetTempFileName();
|
|
|
|
|
byte[] byteCode;
|
|
|
|
|
|
|
|
|
|
ProcessStartInfo startInfo = new ProcessStartInfo
|
|
|
|
|
{
|
|
|
|
|
FileName = executable,
|
2012-11-14 14:35:58 +00:00
|
|
|
|
Arguments = String.Format("{0} {1} {2} {3}", "/Fo " + tempOutputFile, GetCompilerTargetProfile(targetProfile), GetCompilerDebugFlags(debugMode, targetProfile), tempInputFile),
|
2012-08-22 10:34:39 +00:00
|
|
|
|
UseShellExecute = false,
|
|
|
|
|
RedirectStandardOutput = true,
|
|
|
|
|
CreateNoWindow = true
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using (var proc = Process.Start(startInfo))
|
|
|
|
|
{
|
|
|
|
|
helpOutput = proc.StandardOutput.ReadToEnd();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byteCode = File.ReadAllBytes(tempOutputFile);
|
|
|
|
|
|
|
|
|
|
if (File.Exists(tempInputFile))
|
|
|
|
|
{
|
|
|
|
|
File.Delete(tempInputFile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (File.Exists(tempOutputFile))
|
|
|
|
|
{
|
|
|
|
|
File.Delete(tempOutputFile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return byteCode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int CompareTo(HLSLCompiler other)
|
|
|
|
|
{
|
|
|
|
|
return Version.CompareTo(other.Version);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool Equals(HLSLCompiler other)
|
|
|
|
|
{
|
|
|
|
|
return String.Equals(Version, other.Version, StringComparison.InvariantCultureIgnoreCase);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override int GetHashCode()
|
|
|
|
|
{
|
|
|
|
|
return Version.GetHashCode();
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-14 14:35:58 +00:00
|
|
|
|
private string GetCompilerDebugFlags(EffectProcessorDebugMode debugMode, string targetProfile)
|
2012-08-22 10:34:39 +00:00
|
|
|
|
{
|
|
|
|
|
if ((debugMode == EffectProcessorDebugMode.Auto && System.Diagnostics.Debugger.IsAttached) || debugMode == EffectProcessorDebugMode.Debug)
|
|
|
|
|
{
|
2012-08-27 12:19:52 +00:00
|
|
|
|
return "/Od /Op";
|
2012-08-22 10:34:39 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2012-11-14 14:35:58 +00:00
|
|
|
|
if (targetProfile == "fx_5_0")
|
|
|
|
|
{
|
|
|
|
|
return "/O3";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return "/O3 /Qstrip_debug";
|
|
|
|
|
}
|
2012-08-22 10:34:39 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string GetCompilerTargetProfile(string targetProfile)
|
|
|
|
|
{
|
|
|
|
|
foreach (string profile in SupportedProfiles)
|
|
|
|
|
{
|
|
|
|
|
if (string.Equals(profile, targetProfile, StringComparison.InvariantCultureIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
return String.Format("/T {0}", targetProfile);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw new Exception(String.Format("fxc.exe version {0} does not support profile {1}", CompilerVersion, targetProfile));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string CreateTemporaryShaderFile(string shaderSourceCode)
|
|
|
|
|
{
|
|
|
|
|
string file = Path.GetTempFileName();
|
|
|
|
|
File.WriteAllText(file, shaderSourceCode);
|
|
|
|
|
return file;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string CompilerHelpOutput
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(helpOutput))
|
|
|
|
|
{
|
|
|
|
|
ProcessStartInfo startInfo = new ProcessStartInfo
|
|
|
|
|
{
|
|
|
|
|
FileName = executable,
|
|
|
|
|
Arguments = @"/help",
|
|
|
|
|
UseShellExecute = false,
|
|
|
|
|
RedirectStandardOutput = true,
|
|
|
|
|
CreateNoWindow = true
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using (var proc = Process.Start(startInfo))
|
|
|
|
|
{
|
|
|
|
|
helpOutput = proc.StandardOutput.ReadToEnd();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return helpOutput;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string CompilerVersion
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
Regex pattern = new Regex(@"\d+(\.\d+)+");
|
|
|
|
|
Match m = pattern.Match(CompilerHelpOutput);
|
|
|
|
|
if (m.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
return m.Value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|