forked from MonoGame/MonoGame
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathShaderInfo.cs
131 lines (107 loc) · 4.27 KB
/
ShaderInfo.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
using System;
using System.Collections.Generic;
using System.IO;
namespace TwoMGFX
{
public class ShaderInfo
{
public string FilePath { get; private set; }
public string FileContent { get; private set; }
public ShaderProfile Profile { get; private set; }
public string OutputFilePath { get; private set; }
public bool Debug { get; private set; }
public List<TechniqueInfo> Techniques = new List<TechniqueInfo>();
public Dictionary<string, SamplerStateInfo> SamplerStates = new Dictionary<string, SamplerStateInfo>();
public List<string> Dependencies { get; private set; }
public List<string> AdditionalOutputFiles { get; private set; }
static public ShaderInfo FromFile(string path, Options options, IEffectCompilerOutput output)
{
var effectSource = File.ReadAllText(path);
return FromString(effectSource, path, options, output);
}
static public ShaderInfo FromString(string effectSource, string filePath, Options options, IEffectCompilerOutput output)
{
var macros = new Dictionary<string, string>();
macros.Add("MGFX", "1");
// Under the DX11 profile we pass a few more macros.
if (options.Profile == ShaderProfile.DirectX_11)
{
macros.Add("HLSL", "1");
macros.Add("SM4", "1");
}
else if (options.Profile == ShaderProfile.OpenGL)
{
macros.Add("GLSL", "1");
macros.Add("OPENGL", "1");
}
else if (options.Profile == ShaderProfile.PlayStation4)
{
throw new NotSupportedException("PlayStation 4 support isn't available in this build.");
}
// If we're building shaders for debug set that flag too.
if (options.Debug)
macros.Add("DEBUG", "1");
if (!string.IsNullOrEmpty(options.Defines))
{
var defines = options.Defines.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var define in defines)
macros.Add(define, "1");
}
// Use the D3DCompiler to pre-process the file resolving
// all #includes and macros.... this even works for GLSL.
string newFile;
var fullPath = Path.GetFullPath(filePath);
var dependencies = new List<string>();
newFile = Preprocessor.Preprocess(effectSource, fullPath, macros, dependencies, output);
// Parse the resulting file for techniques and passes.
var tree = new Parser(new Scanner()).Parse(newFile, fullPath);
if (tree.Errors.Count > 0)
{
var errors = String.Empty;
foreach (var error in tree.Errors)
errors += string.Format("{0}({1},{2}) : {3}\r\n", error.File, error.Line, error.Column, error.Message);
throw new Exception(errors);
}
// Evaluate the results of the parse tree.
var result = tree.Eval() as ShaderInfo;
result.Dependencies = dependencies;
result.FilePath = fullPath;
result.FileContent = newFile;
if (!string.IsNullOrEmpty(options.OutputFile))
result.OutputFilePath = Path.GetFullPath(options.OutputFile);
result.AdditionalOutputFiles = new List<string>();
// Remove empty techniques.
for (var i=0; i < result.Techniques.Count; i++)
{
var tech = result.Techniques[i];
if (tech.Passes.Count <= 0)
{
result.Techniques.RemoveAt(i);
i--;
}
}
// We must have at least one technique.
if (result.Techniques.Count <= 0)
throw new Exception("The effect must contain at least one technique and pass!");
// Finally remove the techniques from the file.
//
// TODO: Do we really need to do this, or will the HLSL
// compiler just ignore it as we compile shaders?
//
/*
var extra = 2;
var offset = 0;
foreach (var tech in result.Techniques)
{
// Remove the technique from the file.
newFile = newFile.Remove(tech.startPos + offset, tech.length + extra);
offset -= tech.length + extra;
techniques.Add(tech);
}
*/
result.Profile = options.Profile;
result.Debug = options.Debug;
return result;
}
}
}