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