SND\AstrorEnales_cp bf14329432 - Implemented BasicEffect.fx for Dx10, Dx11 and Metro
- Started to work on a Sample to demonstrate all the BasicEffect possibilities
2012-09-09 14:31:03 +00:00

301 lines
7.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using HLSLParser;
// This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license.
// For details see: http://anxframework.codeplex.com/license
namespace DX11MetroShaderGenerator
{
public class MetroCodeGenerator
{
#region Private
private EffectFile sourceEffect;
private string resultSourceCode;
private Dictionary<string, CompiledPass[]> compiledTechniques;
#endregion
#region Public
public byte[] ResultByteCode
{
get;
private set;
}
#endregion
#region Constructor
public MetroCodeGenerator(string sourceCode)
{
Parser parser = Parser.LoadFromSource(sourceCode);
parser.Parse();
sourceEffect = parser.Effect;
BuildSourceCode();
compiledTechniques = new Dictionary<string, CompiledPass[]>();
CompileTechniques();
ExportToByteCode();
}
#endregion
#region BuildSourceCode
private void BuildSourceCode()
{
resultSourceCode = "";
foreach (var typeDef in sourceEffect.TypeDefs)
{
resultSourceCode += typeDef.ToString() + "\n";
}
foreach (var variable in sourceEffect.Variables)
{
resultSourceCode += variable.ToString() + "\n";
}
foreach (var sampler in sourceEffect.Samplers)
{
resultSourceCode += sampler.ToString() + "\n";
}
foreach (var structure in sourceEffect.Structures)
{
resultSourceCode += structure.ToString() + "\n";
}
foreach (var buffer in sourceEffect.Buffers)
{
resultSourceCode += buffer.ToString() + "\n";
}
foreach (var method in sourceEffect.Methods)
{
resultSourceCode += method.ToString() + "\n";
}
}
#endregion
#region CompileTechniques
private void CompileTechniques()
{
foreach (Technique technique in sourceEffect.Techniques)
{
CompiledPass[] passes = new CompiledPass[technique.Passes.Count];
compiledTechniques.Add(technique.Name, passes);
int passIndex = 0;
foreach (Pass pass in technique.Passes)
{
passes[passIndex] = CompilePass(pass);
}
}
}
#endregion
#region CompilePass
private CompiledPass CompilePass(Pass pass)
{
byte[] vertexCode = CompileShader(pass.VertexShaderProfile, pass.VertexShader);
byte[] pixelCode = CompileShader(pass.PixelShaderProfile, pass.PixelShader);
return new CompiledPass(pass.Name, vertexCode, pixelCode);
}
#endregion
#region CompileShader
private byte[] CompileShader(string profile, string entryPoint)
{
int indexOfOpenParenthesis = entryPoint.IndexOf('(');
entryPoint = entryPoint.Substring(0, indexOfOpenParenthesis);
return ExecuteCompiler(resultSourceCode, profile, entryPoint);
}
#endregion
#region ExportToByteCode
private void ExportToByteCode()
{
using (MemoryStream stream = new MemoryStream())
{
BinaryWriter writer = new BinaryWriter(stream);
ExportVariables(writer);
ExportStructures(writer);
ExportTechniques(writer);
ResultByteCode = stream.ToArray();
}
}
#endregion
#region ExportVariables
private void ExportVariables(BinaryWriter writer)
{
writer.Write(sourceEffect.Variables.Count);
foreach (Variable variable in sourceEffect.Variables)
{
writer.Write(variable.Type);
writer.Write(variable.Name);
writer.Write(variable.ArraySize);
writer.Write((byte)variable.Dimensions.Length);
for (int dimIndex = 0; dimIndex < variable.Dimensions.Length; dimIndex++)
{
writer.Write((byte)variable.Dimensions[dimIndex]);
}
}
}
#endregion
#region ExportStructures
private void ExportStructures(BinaryWriter writer)
{
writer.Write(sourceEffect.Structures.Count);
foreach (Structure structure in sourceEffect.Structures)
{
writer.Write(structure.Name);
writer.Write(structure.Variables.Count);
foreach (Variable variable in structure.Variables)
{
writer.Write(variable.Type);
writer.Write(variable.Name);
string semantic = variable.Semantic != null ? variable.Semantic : "";
writer.Write(semantic);
}
}
}
#endregion
#region ExportTechniques
private void ExportTechniques(BinaryWriter writer)
{
writer.Write(compiledTechniques.Count);
foreach (string key in compiledTechniques.Keys)
{
CompiledPass[] passes = compiledTechniques[key];
writer.Write(key);
writer.Write(passes.Length);
foreach (CompiledPass pass in passes)
{
writer.Write(pass.Name);
writer.Write(pass.VertexShaderCode.Length);
writer.Write(pass.VertexShaderCode);
writer.Write(pass.PixelShaderCode.Length);
writer.Write(pass.PixelShaderCode);
}
}
}
#endregion
#region ExecuteCompiler
private byte[] ExecuteCompiler(string source, string profile, string entryPoint)
{
string tempSourcePath = Path.GetTempFileName() + ".fx";
string tempDestPath = Path.GetTempFileName() + "_" + profile + ".fxo";
File.WriteAllText(tempSourcePath, source);
Process process = new Process();
process.StartInfo.FileName = GetCompilerFilepath();
process.StartInfo.Arguments = "/E" + entryPoint + " /T" + profile +
"_level_9_1 \"" + tempSourcePath + "\" /Fo" + tempDestPath;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
string output = "";
DataReceivedEventHandler logHandler =
delegate(object sender, DataReceivedEventArgs e)
{
if (String.IsNullOrEmpty(e.Data) == false)
{
output += e.Data + "\n";
}
};
process.OutputDataReceived += logHandler;
process.ErrorDataReceived += logHandler;
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
process.WaitForExit();
if (File.Exists(tempSourcePath))
{
File.Delete(tempSourcePath);
}
if (File.Exists(tempDestPath))
{
byte[] result = File.ReadAllBytes(tempDestPath);
File.Delete(tempDestPath);
return result;
}
return new byte[0];
}
#endregion
#region GetCompilerFilepath
private string GetCompilerFilepath()
{
string fxcToolPath = "";
string subDir = Environment.Is64BitOperatingSystem ? "x64" : "x86";
string sdkPath = Environment.GetEnvironmentVariable("DXSDK_DIR");
if (String.IsNullOrEmpty(sdkPath) == false)
{
fxcToolPath = Path.Combine(sdkPath, @"Utilities\bin\", subDir);
}
else
{
fxcToolPath = GetExistingPathFrom(new string[]
{
// Win8 paths
@"C:\Program Files (x86)\Windows Kits\8.0\bin\" + subDir + "\\",
@"C:\Program Files\Windows Kits\8.0\bin\" + subDir + "\\",
// Win7 paths
@"C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Utilities\bin\" +
subDir + "\\",
@"C:\Program Files\Microsoft DirectX SDK (June 2010)\Utilities\bin\" +
subDir + "\\",
});
if (String.IsNullOrEmpty(fxcToolPath))
{
throw new Exception(
"Unable to find the DirectX SDK! Make sure to install it.");
}
}
fxcToolPath = Path.Combine(fxcToolPath, "fxc.exe");
if (File.Exists(fxcToolPath) == false)
{
throw new Exception(
"Unable to compile shaders, cause the fxc.exe doesn't exist!");
}
return fxcToolPath;
}
#endregion
#region GetExistingPathFrom
private string GetExistingPathFrom(string[] possiblePaths)
{
foreach (string path in possiblePaths)
{
if (Directory.Exists(path))
{
return path;
}
}
return null;
}
#endregion
}
}