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