using System;
using System.IO;
using System.Linq;
using SharpDX.Direct3D9;
namespace Blacklight.SharpDX9.ShaderBuilder
{
///
/// Compiles a D3D9 effect file to the effect binary the device loads, at build time, so no launch pays for it.
///
public static class Program
{
///
/// Resolves an #include by looking in each directory in turn.
///
public class DirectoryIncludeHandler : SharpDX.D3DCompiler.Include
{
private readonly string[] directories;
public DirectoryIncludeHandler(params string[] directories)
{
this.directories = directories;
}
public IDisposable Shadow { get; set; }
public Stream Open(SharpDX.D3DCompiler.IncludeType type, string fileName, Stream parentStream)
{
foreach (string directory in directories)
{
string path = Path.Combine(directory, fileName);
if (File.Exists(path))
{
return File.OpenRead(path);
}
}
throw new FileNotFoundException(
$"The shader includes {fileName}, which isn't in any of: {string.Join(", ", directories)}.");
}
public void Close(Stream stream)
{
stream.Dispose();
}
public void Dispose()
{
Shadow?.Dispose();
}
}
///
/// Returns the effect binary for the effect file at `sourcePath`, finding its includes in `includeDirectories`.
///
public static byte[] Compile(string sourcePath, params string[] includeDirectories)
{
string directory = Path.GetDirectoryName(Path.GetFullPath(sourcePath));
string preprocessed;
using (var includes = new DirectoryIncludeHandler(new[] { directory }.Concat(includeDirectories).ToArray()))
{
preprocessed = SharpDX.D3DCompiler.ShaderBytecode.Preprocess(
File.ReadAllText(sourcePath), null, includes, out string _);
}
var compiler = EffectCompiler.FromMemory(
new System.Text.UTF8Encoding().GetBytes(preprocessed), ShaderFlags.None);
using (var effect = compiler.CompileEffect(ShaderFlags.None))
{
var returnMe = new byte[effect.Length];
effect.Read(returnMe, 0, returnMe.Length);
return returnMe;
}
}
public static int Main(string[] args)
{
if (args.Length < 2)
{
Console.Error.WriteLine("Usage: ShaderBuilder