1 //
2 // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 #ifndef COMPILER_TRANSLATOR_OUTPUTHLSL_H_
8 #define COMPILER_TRANSLATOR_OUTPUTHLSL_H_
9 
10 #include <list>
11 #include <map>
12 #include <stack>
13 
14 #include "angle_gl.h"
15 #include "compiler/translator/ASTMetadataHLSL.h"
16 #include "compiler/translator/Compiler.h"
17 #include "compiler/translator/FlagStd140Structs.h"
18 #include "compiler/translator/IntermTraverse.h"
19 
20 class BuiltInFunctionEmulator;
21 
22 namespace sh
23 {
24 class StructureHLSL;
25 class TextureFunctionHLSL;
26 class TSymbolTable;
27 class ImageFunctionHLSL;
28 class UnfoldShortCircuit;
29 class UniformHLSL;
30 
31 typedef std::map<TString, TIntermSymbol *> ReferencedSymbols;
32 
33 class OutputHLSL : public TIntermTraverser
34 {
35   public:
36     OutputHLSL(sh::GLenum shaderType,
37                int shaderVersion,
38                const TExtensionBehavior &extensionBehavior,
39                const char *sourcePath,
40                ShShaderOutput outputType,
41                int numRenderTargets,
42                const std::vector<Uniform> &uniforms,
43                ShCompileOptions compileOptions,
44                TSymbolTable *symbolTable,
45                PerformanceDiagnostics *perfDiagnostics);
46 
47     ~OutputHLSL();
48 
49     void output(TIntermNode *treeRoot, TInfoSinkBase &objSink);
50 
51     const std::map<std::string, unsigned int> &getUniformBlockRegisterMap() const;
52     const std::map<std::string, unsigned int> &getUniformRegisterMap() const;
53 
54     static TString initializer(const TType &type);
55 
getInfoSink()56     TInfoSinkBase &getInfoSink()
57     {
58         ASSERT(!mInfoSinkStack.empty());
59         return *mInfoSinkStack.top();
60     }
61 
62     static bool canWriteAsHLSLLiteral(TIntermTyped *expression);
63 
64   protected:
65     void header(TInfoSinkBase &out,
66                 const std::vector<MappedStruct> &std140Structs,
67                 const BuiltInFunctionEmulator *builtInFunctionEmulator) const;
68 
69     void writeFloat(TInfoSinkBase &out, float f);
70     void writeSingleConstant(TInfoSinkBase &out, const TConstantUnion *const constUnion);
71     const TConstantUnion *writeConstantUnionArray(TInfoSinkBase &out,
72                                                   const TConstantUnion *const constUnion,
73                                                   const size_t size);
74 
75     // Visit AST nodes and output their code to the body stream
76     void visitSymbol(TIntermSymbol *) override;
77     void visitRaw(TIntermRaw *) override;
78     void visitConstantUnion(TIntermConstantUnion *) override;
79     bool visitSwizzle(Visit visit, TIntermSwizzle *node) override;
80     bool visitBinary(Visit visit, TIntermBinary *) override;
81     bool visitUnary(Visit visit, TIntermUnary *) override;
82     bool visitTernary(Visit visit, TIntermTernary *) override;
83     bool visitIfElse(Visit visit, TIntermIfElse *) override;
84     bool visitSwitch(Visit visit, TIntermSwitch *) override;
85     bool visitCase(Visit visit, TIntermCase *) override;
86     bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
87     bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
88     bool visitAggregate(Visit visit, TIntermAggregate *) override;
89     bool visitBlock(Visit visit, TIntermBlock *node) override;
90     bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
91     bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
92     bool visitLoop(Visit visit, TIntermLoop *) override;
93     bool visitBranch(Visit visit, TIntermBranch *) override;
94 
95     bool handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node);
96 
97     // Emit one of three strings depending on traverse phase. Called with literal strings so using
98     // const char* instead of TString.
99     void outputTriplet(TInfoSinkBase &out,
100                        Visit visit,
101                        const char *preString,
102                        const char *inString,
103                        const char *postString);
104     void outputLineDirective(TInfoSinkBase &out, int line);
105     TString argumentString(const TIntermSymbol *symbol);
106 
107     void outputConstructor(TInfoSinkBase &out, Visit visit, TIntermAggregate *node);
108     const TConstantUnion *writeConstantUnion(TInfoSinkBase &out,
109                                              const TType &type,
110                                              const TConstantUnion *constUnion);
111 
112     void outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out);
113     void outputAssign(Visit visit, const TType &type, TInfoSinkBase &out);
114 
115     void writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, TOperator op);
116 
117     // Returns true if it found a 'same symbol' initializer (initializer that references the
118     // variable it's initting)
119     bool writeSameSymbolInitializer(TInfoSinkBase &out,
120                                     TIntermSymbol *symbolNode,
121                                     TIntermTyped *expression);
122     // Returns true if variable initializer could be written using literal {} notation.
123     bool writeConstantInitialization(TInfoSinkBase &out,
124                                      TIntermSymbol *symbolNode,
125                                      TIntermTyped *expression);
126 
127     void writeIfElse(TInfoSinkBase &out, TIntermIfElse *node);
128 
129     // Returns the function name
130     TString addStructEqualityFunction(const TStructure &structure);
131     TString addArrayEqualityFunction(const TType &type);
132     TString addArrayAssignmentFunction(const TType &type);
133     TString addArrayConstructIntoFunction(const TType &type);
134 
135     // Ensures if the type is a struct, the struct is defined
136     void ensureStructDefined(const TType &type);
137 
138     sh::GLenum mShaderType;
139     int mShaderVersion;
140     const TExtensionBehavior &mExtensionBehavior;
141     const char *mSourcePath;
142     const ShShaderOutput mOutputType;
143     ShCompileOptions mCompileOptions;
144 
145     bool mInsideFunction;
146 
147     // Output streams
148     TInfoSinkBase mHeader;
149     TInfoSinkBase mBody;
150     TInfoSinkBase mFooter;
151 
152     // A stack is useful when we want to traverse in the header, or in helper functions, but not
153     // always write to the body. Instead use an InfoSink stack to keep our current state intact.
154     // TODO (jmadill): Just passing an InfoSink in function parameters would be simpler.
155     std::stack<TInfoSinkBase *> mInfoSinkStack;
156 
157     ReferencedSymbols mReferencedUniforms;
158     ReferencedSymbols mReferencedUniformBlocks;
159     ReferencedSymbols mReferencedAttributes;
160     ReferencedSymbols mReferencedVaryings;
161     ReferencedSymbols mReferencedOutputVariables;
162 
163     StructureHLSL *mStructureHLSL;
164     UniformHLSL *mUniformHLSL;
165     TextureFunctionHLSL *mTextureFunctionHLSL;
166     ImageFunctionHLSL *mImageFunctionHLSL;
167 
168     // Parameters determining what goes in the header output
169     bool mUsesFragColor;
170     bool mUsesFragData;
171     bool mUsesDepthRange;
172     bool mUsesFragCoord;
173     bool mUsesPointCoord;
174     bool mUsesFrontFacing;
175     bool mUsesPointSize;
176     bool mUsesInstanceID;
177     bool mHasMultiviewExtensionEnabled;
178     bool mUsesViewID;
179     bool mUsesVertexID;
180     bool mUsesFragDepth;
181     bool mUsesNumWorkGroups;
182     bool mUsesWorkGroupID;
183     bool mUsesLocalInvocationID;
184     bool mUsesGlobalInvocationID;
185     bool mUsesLocalInvocationIndex;
186     bool mUsesXor;
187     bool mUsesDiscardRewriting;
188     bool mUsesNestedBreak;
189     bool mRequiresIEEEStrictCompiling;
190 
191     int mNumRenderTargets;
192 
193     int mUniqueIndex;  // For creating unique names
194 
195     CallDAG mCallDag;
196     MetadataList mASTMetadataList;
197     ASTMetadataHLSL *mCurrentFunctionMetadata;
198     bool mOutputLod0Function;
199     bool mInsideDiscontinuousLoop;
200     int mNestedLoopDepth;
201 
202     TIntermSymbol *mExcessiveLoopIndex;
203 
204     TString structInitializerString(int indent, const TType &type, const TString &name) const;
205 
206     struct HelperFunction
207     {
208         TString functionName;
209         TString functionDefinition;
210 
~HelperFunctionHelperFunction211         virtual ~HelperFunction() {}
212     };
213 
214     // A list of all equality comparison functions. It's important to preserve the order at
215     // which we add the functions, since nested structures call each other recursively, and
216     // structure equality functions may need to call array equality functions and vice versa.
217     // The ownership of the pointers is maintained by the type-specific arrays.
218     std::vector<HelperFunction *> mEqualityFunctions;
219 
220     struct StructEqualityFunction : public HelperFunction
221     {
222         const TStructure *structure;
223     };
224     std::vector<StructEqualityFunction *> mStructEqualityFunctions;
225 
226     struct ArrayHelperFunction : public HelperFunction
227     {
228         TType type;
229     };
230     std::vector<ArrayHelperFunction *> mArrayEqualityFunctions;
231 
232     std::vector<ArrayHelperFunction> mArrayAssignmentFunctions;
233 
234     // The construct-into functions are functions that fill an N-element array passed as an out
235     // parameter with the other N parameters of the function. This is used to work around that
236     // arrays can't be return values in HLSL.
237     std::vector<ArrayHelperFunction> mArrayConstructIntoFunctions;
238 
239     PerformanceDiagnostics *mPerfDiagnostics;
240 
241   private:
242     TString generateStructMapping(const std::vector<MappedStruct> &std140Structs) const;
243     TString samplerNamePrefixFromStruct(TIntermTyped *node);
244     bool ancestorEvaluatesToSamplerInStruct();
245 };
246 }
247 
248 #endif  // COMPILER_TRANSLATOR_OUTPUTHLSL_H_
249