1 //
2 // Copyright (c) 2002-2013 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_COMPILER_H_
8 #define COMPILER_TRANSLATOR_COMPILER_H_
9 
10 //
11 // Machine independent part of the compiler private objects
12 // sent as ShHandle to the driver.
13 //
14 // This should not be included by driver code.
15 //
16 
17 #include <GLSLANG/ShaderVars.h>
18 
19 #include "compiler/translator/BuiltInFunctionEmulator.h"
20 #include "compiler/translator/CallDAG.h"
21 #include "compiler/translator/Diagnostics.h"
22 #include "compiler/translator/ExtensionBehavior.h"
23 #include "compiler/translator/HashNames.h"
24 #include "compiler/translator/InfoSink.h"
25 #include "compiler/translator/Pragma.h"
26 #include "compiler/translator/SymbolTable.h"
27 #include "third_party/compiler/ArrayBoundsClamper.h"
28 
29 namespace sh
30 {
31 
32 class TCompiler;
33 class TParseContext;
34 #ifdef ANGLE_ENABLE_HLSL
35 class TranslatorHLSL;
36 #endif  // ANGLE_ENABLE_HLSL
37 
38 //
39 // Helper function to identify specs that are based on the WebGL spec.
40 //
41 bool IsWebGLBasedSpec(ShShaderSpec spec);
42 
43 //
44 // Helper function to check if the shader type is GLSL.
45 //
46 bool IsGLSL130OrNewer(ShShaderOutput output);
47 bool IsGLSL420OrNewer(ShShaderOutput output);
48 bool IsGLSL410OrOlder(ShShaderOutput output);
49 
50 //
51 // Helper function to check if the invariant qualifier can be removed.
52 //
53 bool RemoveInvariant(sh::GLenum shaderType,
54                      int shaderVersion,
55                      ShShaderOutput outputType,
56                      ShCompileOptions compileOptions);
57 
58 //
59 // The base class used to back handles returned to the driver.
60 //
61 class TShHandleBase
62 {
63   public:
64     TShHandleBase();
65     virtual ~TShHandleBase();
getAsCompiler()66     virtual TCompiler *getAsCompiler() { return 0; }
67 #ifdef ANGLE_ENABLE_HLSL
getAsTranslatorHLSL()68     virtual TranslatorHLSL *getAsTranslatorHLSL() { return 0; }
69 #endif  // ANGLE_ENABLE_HLSL
70 
71   protected:
72     // Memory allocator. Allocates and tracks memory required by the compiler.
73     // Deallocates all memory when compiler is destructed.
74     TPoolAllocator allocator;
75 };
76 
77 //
78 // The base class for the machine dependent compiler to derive from
79 // for managing object code from the compile.
80 //
81 class TCompiler : public TShHandleBase
82 {
83   public:
84     TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
85     ~TCompiler() override;
getAsCompiler()86     TCompiler *getAsCompiler() override { return this; }
87 
88     bool Init(const ShBuiltInResources &resources);
89 
90     // compileTreeForTesting should be used only when tests require access to
91     // the AST. Users of this function need to manually manage the global pool
92     // allocator. Returns nullptr whenever there are compilation errors.
93     TIntermBlock *compileTreeForTesting(const char *const shaderStrings[],
94                                         size_t numStrings,
95                                         ShCompileOptions compileOptions);
96 
97     bool compile(const char *const shaderStrings[],
98                  size_t numStrings,
99                  ShCompileOptions compileOptions);
100 
101     // Get results of the last compilation.
getShaderVersion()102     int getShaderVersion() const { return shaderVersion; }
getInfoSink()103     TInfoSink &getInfoSink() { return infoSink; }
104 
isComputeShaderLocalSizeDeclared()105     bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; }
getComputeShaderLocalSize()106     const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; }
getNumViews()107     int getNumViews() const { return mNumViews; }
108 
109     // Clears the results from the previous compilation.
110     void clearResults();
111 
getAttributes()112     const std::vector<sh::Attribute> &getAttributes() const { return attributes; }
getOutputVariables()113     const std::vector<sh::OutputVariable> &getOutputVariables() const { return outputVariables; }
getUniforms()114     const std::vector<sh::Uniform> &getUniforms() const { return uniforms; }
getInputVaryings()115     const std::vector<sh::Varying> &getInputVaryings() const { return inputVaryings; }
getOutputVaryings()116     const std::vector<sh::Varying> &getOutputVaryings() const { return outputVaryings; }
getInterfaceBlocks()117     const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return interfaceBlocks; }
getUniformBlocks()118     const std::vector<sh::InterfaceBlock> &getUniformBlocks() const { return uniformBlocks; }
getShaderStorageBlocks()119     const std::vector<sh::InterfaceBlock> &getShaderStorageBlocks() const
120     {
121         return shaderStorageBlocks;
122     }
getInBlocks()123     const std::vector<sh::InterfaceBlock> &getInBlocks() const { return inBlocks; }
124 
getHashFunction()125     ShHashFunction64 getHashFunction() const { return hashFunction; }
getNameMap()126     NameMap &getNameMap() { return nameMap; }
getSymbolTable()127     TSymbolTable &getSymbolTable() { return symbolTable; }
getShaderSpec()128     ShShaderSpec getShaderSpec() const { return shaderSpec; }
getOutputType()129     ShShaderOutput getOutputType() const { return outputType; }
getBuiltInResourcesString()130     const std::string &getBuiltInResourcesString() const { return builtInResourcesString; }
131 
132     bool shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const;
133 
134     // Get the resources set by InitBuiltInSymbolTable
135     const ShBuiltInResources &getResources() const;
136 
getGeometryShaderMaxVertices()137     int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; }
getGeometryShaderInvocations()138     int getGeometryShaderInvocations() const { return mGeometryShaderInvocations; }
getGeometryShaderInputPrimitiveType()139     TLayoutPrimitiveType getGeometryShaderInputPrimitiveType() const
140     {
141         return mGeometryShaderInputPrimitiveType;
142     }
getGeometryShaderOutputPrimitiveType()143     TLayoutPrimitiveType getGeometryShaderOutputPrimitiveType() const
144     {
145         return mGeometryShaderOutputPrimitiveType;
146     }
147 
getShaderType()148     sh::GLenum getShaderType() const { return shaderType; }
149 
150   protected:
151     // Initialize symbol-table with built-in symbols.
152     bool InitBuiltInSymbolTable(const ShBuiltInResources &resources);
153     // Compute the string representation of the built-in resources
154     void setResourceString();
155     // Return false if the call depth is exceeded.
156     bool checkCallDepth();
157     // Add emulated functions to the built-in function emulator.
initBuiltInFunctionEmulator(BuiltInFunctionEmulator * emu,ShCompileOptions compileOptions)158     virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
159                                              ShCompileOptions compileOptions){};
160     // Translate to object code. May generate performance warnings through the diagnostics.
161     virtual void translate(TIntermBlock *root,
162                            ShCompileOptions compileOptions,
163                            PerformanceDiagnostics *perfDiagnostics) = 0;
164     // Insert statements to reference all members in unused uniform blocks with standard and shared
165     // layout. This is to work around a Mac driver that treats unused standard/shared
166     // uniform blocks as inactive.
167     void useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root);
168     // Insert statements to initialize output variables in the beginning of main().
169     // This is to avoid undefined behaviors.
170     void initializeOutputVariables(TIntermBlock *root);
171     // Insert gl_Position = vec4(0,0,0,0) to the beginning of main().
172     // It is to work around a Linux driver bug where missing this causes compile failure
173     // while spec says it is allowed.
174     // This function should only be applied to vertex shaders.
175     void initializeGLPosition(TIntermBlock *root);
176     // Return true if the maximum expression complexity is below the limit.
177     bool limitExpressionComplexity(TIntermBlock *root);
178     // Get built-in extensions with default behavior.
179     const TExtensionBehavior &getExtensionBehavior() const;
180     const char *getSourcePath() const;
getPragma()181     const TPragma &getPragma() const { return mPragma; }
182     void writePragma(ShCompileOptions compileOptions);
183     // Relies on collectVariables having been called.
184     bool isVaryingDefined(const char *varyingName);
185 
186     const ArrayBoundsClamper &getArrayBoundsClamper() const;
187     ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const;
188     const BuiltInFunctionEmulator &getBuiltInFunctionEmulator() const;
189 
190     virtual bool shouldFlattenPragmaStdglInvariantAll() = 0;
191     virtual bool shouldCollectVariables(ShCompileOptions compileOptions);
192 
193     bool wereVariablesCollected() const;
194     std::vector<sh::Attribute> attributes;
195     std::vector<sh::OutputVariable> outputVariables;
196     std::vector<sh::Uniform> uniforms;
197     std::vector<sh::Varying> inputVaryings;
198     std::vector<sh::Varying> outputVaryings;
199     std::vector<sh::InterfaceBlock> interfaceBlocks;
200     std::vector<sh::InterfaceBlock> uniformBlocks;
201     std::vector<sh::InterfaceBlock> shaderStorageBlocks;
202     std::vector<sh::InterfaceBlock> inBlocks;
203 
204   private:
205     // Creates the function call DAG for further analysis, returning false if there is a recursion
206     bool initCallDag(TIntermNode *root);
207     // Return false if "main" doesn't exist
208     bool tagUsedFunctions();
209     void internalTagUsedFunction(size_t index);
210 
211     void initSamplerDefaultPrecision(TBasicType samplerType);
212 
213     void collectInterfaceBlocks();
214 
215     bool variablesCollected;
216 
217     bool mGLPositionInitialized;
218 
219     // Removes unused function declarations and prototypes from the AST
220     class UnusedPredicate;
221     void pruneUnusedFunctions(TIntermBlock *root);
222 
223     TIntermBlock *compileTreeImpl(const char *const shaderStrings[],
224                                   size_t numStrings,
225                                   const ShCompileOptions compileOptions);
226 
227     // Fetches and stores shader metadata that is not stored within the AST itself, such as shader
228     // version.
229     void setASTMetadata(const TParseContext &parseContext);
230 
231     // Does checks that need to be run after parsing is complete and returns true if they pass.
232     bool checkAndSimplifyAST(TIntermBlock *root,
233                              const TParseContext &parseContext,
234                              ShCompileOptions compileOptions);
235 
236     sh::GLenum shaderType;
237     ShShaderSpec shaderSpec;
238     ShShaderOutput outputType;
239 
240     struct FunctionMetadata
241     {
FunctionMetadataFunctionMetadata242         FunctionMetadata() : used(false) {}
243         bool used;
244     };
245 
246     CallDAG mCallDag;
247     std::vector<FunctionMetadata> functionMetadata;
248 
249     int maxUniformVectors;
250     int maxExpressionComplexity;
251     int maxCallStackDepth;
252     int maxFunctionParameters;
253 
254     ShBuiltInResources compileResources;
255     std::string builtInResourcesString;
256 
257     // Built-in symbol table for the given language, spec, and resources.
258     // It is preserved from compile-to-compile.
259     TSymbolTable symbolTable;
260     // Built-in extensions with default behavior.
261     TExtensionBehavior extensionBehavior;
262     bool fragmentPrecisionHigh;
263 
264     ArrayBoundsClamper arrayBoundsClamper;
265     ShArrayIndexClampingStrategy clampingStrategy;
266     BuiltInFunctionEmulator builtInFunctionEmulator;
267 
268     // Results of compilation.
269     int shaderVersion;
270     TInfoSink infoSink;       // Output sink.
271     TDiagnostics mDiagnostics;
272     const char *mSourcePath;  // Path of source file or NULL
273 
274     // compute shader local group size
275     bool mComputeShaderLocalSizeDeclared;
276     sh::WorkGroupSize mComputeShaderLocalSize;
277 
278     // GL_OVR_multiview num_views.
279     int mNumViews;
280 
281     // geometry shader parameters.
282     int mGeometryShaderMaxVertices;
283     int mGeometryShaderInvocations;
284     TLayoutPrimitiveType mGeometryShaderInputPrimitiveType;
285     TLayoutPrimitiveType mGeometryShaderOutputPrimitiveType;
286 
287     // name hashing.
288     ShHashFunction64 hashFunction;
289     NameMap nameMap;
290 
291     TPragma mPragma;
292 };
293 
294 //
295 // This is the interface between the machine independent code
296 // and the machine dependent code.
297 //
298 // The machine dependent code should derive from the classes
299 // above. Then Construct*() and Delete*() will create and
300 // destroy the machine dependent objects, which contain the
301 // above machine independent information.
302 //
303 TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
304 void DeleteCompiler(TCompiler *);
305 
306 }  // namespace sh
307 
308 #endif  // COMPILER_TRANSLATOR_COMPILER_H_
309