forked from AcademySoftwareFoundation/MaterialX
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ShaderStage.h
370 lines (280 loc) · 11.6 KB
/
ShaderStage.h
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
//
// TM & (c) 2017 Lucasfilm Entertainment Company Ltd. and Lucasfilm Ltd.
// All rights reserved. See LICENSE.txt for license.
//
#ifndef MATERIALX_SHADERSTAGE_H
#define MATERIALX_SHADERSTAGE_H
/// @file
/// Class related to holding information for shader stages
#include <MaterialXGenShader/Export.h>
#include <MaterialXGenShader/GenOptions.h>
#include <MaterialXGenShader/ShaderGraph.h>
#include <MaterialXGenShader/Syntax.h>
#include <MaterialXFormat/File.h>
#include <MaterialXCore/Node.h>
#include <sstream>
// Macro for begin/end of statements to be picked up by a given shader stage.
// For shaders that are multi-stage all code generation statements adding code
// to the shader should be wrapped inside such begin/end stating its target.
#define BEGIN_SHADER_STAGE(stage, name) if (stage.getName() == name) {
#define END_SHADER_STAGE(stage, name) }
MATERIALX_NAMESPACE_BEGIN
namespace Stage
{
/// Identifier for pixel stage.
/// This is the main stage used by all shader targets.
/// For single stage shader targets this is the one
/// and only stage.
/// Shader targets with multiple stages can add additional
/// stage identifiers to the Stage namespace.
extern MX_GENSHADER_API const string PIXEL;
}
class VariableBlock;
/// Shared pointer to a VariableBlock
using VariableBlockPtr = std::shared_ptr<VariableBlock>;
/// Shared pointer to a map between string identifiers and VariableBlocks
using VariableBlockMap = std::unordered_map<string, VariableBlockPtr>;
/// A standard function predicate taking an ShaderPort pointer and returning a boolean.
using ShaderPortPredicate = std::function<bool(ShaderPort*)>;
/// @class VariableBlock
/// A block of variables in a shader stage
class MX_GENSHADER_API VariableBlock
{
public:
VariableBlock(const string& name, const string& instance) :
_name(name),
_instance(instance)
{}
/// Get the name of this block.
const string& getName() const { return _name; }
/// Set the name of this block.
void setName(const string& name) { _name = name; }
/// Get the instance name of this block.
const string& getInstance() const { return _instance; }
/// Set the instance name of this block.
void setInstance(const string& instance) { _instance = instance; }
/// Return true if the block has no variables.
bool empty() const { return _variableOrder.empty(); }
/// Return the number of variables in this block.
size_t size() const { return _variableOrder.size(); }
/// Return a variable by index.
ShaderPort* operator[](size_t index) { return _variableOrder[index]; }
/// Return a variable by index.
const ShaderPort* operator[](size_t index) const { return _variableOrder[index]; }
/// Return a const reference to our variable order vector.
const vector<ShaderPort*>& getVariableOrder() const { return _variableOrder; }
/// Return a variable by name. Throws exception if
/// no variable is found by the given name.
ShaderPort* operator[](const string& name);
/// Return a variable by name. Throws exception if
/// no variable is found by the given name.
const ShaderPort* operator[](const string& name) const;
/// Return a variable by name. Returns nullptr if
/// no variable is found by the given name.
ShaderPort* find(const string& name);
/// Return a variable by name. Returns nullptr if
/// no variable is found by the given name.
const ShaderPort* find(const string& name) const;
/// Find a port based on a predicate
ShaderPort* find(const ShaderPortPredicate& predicate);
/// Add a new shader port to this block.
ShaderPort* add(const TypeDesc* type, const string& name, ValuePtr value = nullptr);
/// Add an existing shader port to this block.
void add(ShaderPortPtr port);
private:
string _name;
string _instance;
std::unordered_map<string, ShaderPortPtr> _variableMap;
vector<ShaderPort*> _variableOrder;
};
/// @class ShaderStage
/// A shader stage, containing the state and
/// resulting source code for the stage.
class MX_GENSHADER_API ShaderStage
{
public:
using FunctionCallId = std::pair<const ShaderNode*, int>;
struct Scope
{
Syntax::Punctuation punctuation;
std::set<FunctionCallId> functions;
Scope(Syntax::Punctuation p) : punctuation(p) {}
};
public:
/// Contructor.
ShaderStage(const string& name, ConstSyntaxPtr syntax);
/// Return the stage name.
const string& getName() const { return _name; }
/// Return the stage function name.
const string& getFunctionName() const { return _functionName; }
/// Set the stage source code.
void setSourceCode(const string& code) { _code = code; }
/// Return the stage source code.
const string& getSourceCode() const { return _code; }
/// Create a new uniform variable block.
VariableBlockPtr createUniformBlock(const string& name, const string& instance = EMPTY_STRING);
/// Create a new input variable block.
VariableBlockPtr createInputBlock(const string& name, const string& instance = EMPTY_STRING);
/// Create a new output variable block.
VariableBlockPtr createOutputBlock(const string& name, const string& instance = EMPTY_STRING);
/// Return the uniform variable block with given name.
VariableBlock& getUniformBlock(const string& name);
/// Return the uniform variable block with given name.
const VariableBlock& getUniformBlock(const string& name) const;
/// Return the input variable block with given name.
VariableBlock& getInputBlock(const string& name);
/// Return the input variable block with given name.
const VariableBlock& getInputBlock(const string& name) const;
/// Return the output variable block with given name.
VariableBlock& getOutputBlock(const string& name);
/// Return the output variable block with given name.
const VariableBlock& getOutputBlock(const string& name) const;
/// Return the constant variable block.
VariableBlock& getConstantBlock();
/// Return the constant variable block.
const VariableBlock& getConstantBlock() const;
/// Return a map of all uniform blocks.
const VariableBlockMap& getUniformBlocks() const
{
return _uniforms;
}
/// Return a map of all input blocks.
const VariableBlockMap& getInputBlocks() const
{
return _inputs;
}
/// Return a map of all output blocks.
const VariableBlockMap& getOutputBlocks() const
{
return _outputs;
}
/// Return a set of all include files
const StringSet& getIncludes() const
{
return _includes;
}
/// Return a set of all source dependencies
const StringSet& getSourceDependencies() const
{
return _sourceDependencies;
}
/// Start a new scope using the given bracket type.
void beginScope(Syntax::Punctuation punc = Syntax::CURLY_BRACKETS);
/// End the current scope.
void endScope(bool semicolon = false, bool newline = true);
/// Start a new line.
void beginLine();
/// End the current line.
void endLine(bool semicolon = true);
/// Add a newline character.
void newLine();
/// Add a string.
void addString(const string& str);
/// Add a single line of code, optionally appending a semicolon.
void addLine(const string& str, bool semicolon = true);
/// Add a single line code comment.
void addComment(const string& str);
/// Add a block of code.
void addBlock(const string& str, const FilePath& sourceFilename, GenContext& context);
/// Add the contents of an include file if not already present.
void addInclude(const FilePath& includeFilename, const FilePath& sourceFilename, GenContext& context);
/// Add a source file dependency for dependency tracking purposes
void addSourceDependency(const FilePath& file);
/// Add a value.
template<typename T>
void addValue(const T& value)
{
StringStream str;
str << value;
_code += str.str();
}
/// Add the function definition for a node's implementation.
void addFunctionDefinition(const ShaderNode& node, GenContext& context);
/// Add the function call for the given node.
void addFunctionCall(const ShaderNode& node, GenContext& context);
/// Return true if the function for the given node has been emitted in the current scope.
bool isEmitted(const ShaderNode& node, GenContext& context) const;
/// Set stage function name.
void setFunctionName(const string& functionName)
{
_functionName = functionName;
}
private:
/// Name of the stage
const string _name;
/// Name of the stage main function
string _functionName;
/// Syntax for the type of shader to generate.
ConstSyntaxPtr _syntax;
/// Current indentation level.
int _indentations;
/// Current scope.
vector<Scope> _scopes;
/// Set of include files that has been included.
StringSet _includes;
/// Set of source file dependencies from source code nodes
StringSet _sourceDependencies;
/// Set of hash ID's for functions that has been defined.
std::set<size_t> _definedFunctions;
/// Block holding constant variables for this stage.
VariableBlock _constants;
/// Map of blocks holding uniform variables for this stage.
VariableBlockMap _uniforms;
/// Map of blocks holding input variables for this stage.
VariableBlockMap _inputs;
/// Map of blocks holding output variables for this stage.
VariableBlockMap _outputs;
/// Resulting source code for this stage.
string _code;
friend class ShaderGenerator;
};
/// Shared pointer to a ShaderStage
using ShaderStagePtr = std::shared_ptr<ShaderStage>;
/// Utility function for adding a new shader port to a uniform block.
inline ShaderPort* addStageUniform(const string& block,
const TypeDesc* type,
const string& name,
ShaderStage& stage)
{
VariableBlock& uniforms = stage.getUniformBlock(block);
return uniforms.add(type, name);
}
/// Utility function for adding a new shader port to an input block.
inline ShaderPort* addStageInput(const string& block,
const TypeDesc* type,
const string& name,
ShaderStage& stage)
{
VariableBlock& inputs = stage.getInputBlock(block);
return inputs.add(type, name);
}
/// Utility function for adding a new shader port to an output block.
inline ShaderPort* addStageOutput(const string& block,
const TypeDesc* type,
const string& name,
ShaderStage& stage)
{
VariableBlock& outputs = stage.getOutputBlock(block);
return outputs.add(type, name);
}
/// Utility function for adding a connector block between stages.
inline void addStageConnectorBlock(const string& block,
const string& instance,
ShaderStage& from,
ShaderStage& to)
{
from.createOutputBlock(block, instance);
to.createInputBlock(block, instance);
}
/// Utility function for adding a variable to a stage connector block.
inline void addStageConnector(const string& block,
const TypeDesc* type,
const string& name,
ShaderStage& from,
ShaderStage& to)
{
addStageOutput(block, type, name, from);
addStageInput(block, type, name, to);
}
MATERIALX_NAMESPACE_END
#endif