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