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_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 "common/PackedEnums.h" 20 #include "compiler/translator/BuiltInFunctionEmulator.h" 21 #include "compiler/translator/CallDAG.h" 22 #include "compiler/translator/Diagnostics.h" 23 #include "compiler/translator/ExtensionBehavior.h" 24 #include "compiler/translator/HashNames.h" 25 #include "compiler/translator/InfoSink.h" 26 #include "compiler/translator/Pragma.h" 27 #include "compiler/translator/SymbolTable.h" 28 #include "compiler/translator/ValidateAST.h" 29 30 namespace sh 31 { 32 33 class TCompiler; 34 class TParseContext; 35 #ifdef ANGLE_ENABLE_HLSL 36 class TranslatorHLSL; 37 #endif // ANGLE_ENABLE_HLSL 38 #ifdef ANGLE_ENABLE_METAL 39 class TranslatorMSL; 40 #endif // ANGLE_ENABLE_METAL 41 42 using MetadataFlagBits = angle::PackedEnumBitSet<sh::MetadataFlags, uint32_t>; 43 using SpecConstUsageBits = angle::PackedEnumBitSet<vk::SpecConstUsage, uint32_t>; 44 45 // 46 // Helper function to check if the shader type is GLSL. 47 // 48 bool IsGLSL130OrNewer(ShShaderOutput output); 49 bool IsGLSL420OrNewer(ShShaderOutput output); 50 bool IsGLSL410OrOlder(ShShaderOutput output); 51 52 // 53 // Helper function to check if the invariant qualifier can be removed. 54 // 55 bool RemoveInvariant(sh::GLenum shaderType, 56 int shaderVersion, 57 ShShaderOutput outputType, 58 const ShCompileOptions &compileOptions); 59 60 // 61 // The base class used to back handles returned to the driver. 62 // 63 class TShHandleBase 64 { 65 public: 66 TShHandleBase(); 67 virtual ~TShHandleBase(); getAsCompiler()68 virtual TCompiler *getAsCompiler() { return nullptr; } 69 #ifdef ANGLE_ENABLE_HLSL getAsTranslatorHLSL()70 virtual TranslatorHLSL *getAsTranslatorHLSL() { return nullptr; } 71 #endif // ANGLE_ENABLE_HLSL 72 #ifdef ANGLE_ENABLE_METAL getAsTranslatorMSL()73 virtual TranslatorMSL *getAsTranslatorMSL() { return nullptr; } 74 #endif // ANGLE_ENABLE_METAL 75 76 protected: 77 // Memory allocator. Allocates and tracks memory required by the compiler. 78 // Deallocates all memory when compiler is destructed. 79 angle::PoolAllocator allocator; 80 }; 81 82 struct TFunctionMetadata 83 { 84 bool used = false; 85 }; 86 87 // 88 // The base class for the machine dependent compiler to derive from 89 // for managing object code from the compile. 90 // 91 class TCompiler : public TShHandleBase 92 { 93 public: 94 TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); 95 ~TCompiler() override; getAsCompiler()96 TCompiler *getAsCompiler() override { return this; } 97 98 bool Init(const ShBuiltInResources &resources); 99 100 // compileTreeForTesting should be used only when tests require access to 101 // the AST. Users of this function need to manually manage the global pool 102 // allocator. Returns nullptr whenever there are compilation errors. 103 TIntermBlock *compileTreeForTesting(const char *const shaderStrings[], 104 size_t numStrings, 105 const ShCompileOptions &compileOptions); 106 107 bool compile(const char *const shaderStrings[], 108 size_t numStrings, 109 const ShCompileOptions &compileOptions); 110 111 // Get results of the last compilation. getShaderVersion()112 int getShaderVersion() const { return mShaderVersion; } getInfoSink()113 TInfoSink &getInfoSink() { return mInfoSink; } 114 specifyEarlyFragmentTests()115 bool specifyEarlyFragmentTests() { return mEarlyFragmentTestsSpecified = true; } isEarlyFragmentTestsSpecified()116 bool isEarlyFragmentTestsSpecified() const { return mEarlyFragmentTestsSpecified; } getMetadataFlags()117 MetadataFlagBits getMetadataFlags() const { return mMetadataFlags; } getSpecConstUsageBits()118 SpecConstUsageBits getSpecConstUsageBits() const { return mSpecConstUsageBits; } 119 isComputeShaderLocalSizeDeclared()120 bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; } getComputeShaderLocalSize()121 const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; } getNumViews()122 int getNumViews() const { return mNumViews; } 123 124 // Clears the results from the previous compilation. 125 void clearResults(); 126 getAttributes()127 const std::vector<sh::ShaderVariable> &getAttributes() const { return mAttributes; } getOutputVariables()128 const std::vector<sh::ShaderVariable> &getOutputVariables() const { return mOutputVariables; } getUniforms()129 const std::vector<sh::ShaderVariable> &getUniforms() const { return mUniforms; } getInputVaryings()130 const std::vector<sh::ShaderVariable> &getInputVaryings() const { return mInputVaryings; } getOutputVaryings()131 const std::vector<sh::ShaderVariable> &getOutputVaryings() const { return mOutputVaryings; } getInterfaceBlocks()132 const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return mInterfaceBlocks; } getUniformBlocks()133 const std::vector<sh::InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; } getShaderStorageBlocks()134 const std::vector<sh::InterfaceBlock> &getShaderStorageBlocks() const 135 { 136 return mShaderStorageBlocks; 137 } 138 getHashFunction()139 ShHashFunction64 getHashFunction() const { return mResources.HashFunction; } getNameMap()140 NameMap &getNameMap() { return mNameMap; } getSymbolTable()141 TSymbolTable &getSymbolTable() { return mSymbolTable; } getShaderSpec()142 ShShaderSpec getShaderSpec() const { return mShaderSpec; } getOutputType()143 ShShaderOutput getOutputType() const { return mOutputType; } getBuiltInResources()144 const ShBuiltInResources &getBuiltInResources() const { return mResources; } getBuiltInResourcesString()145 const std::string &getBuiltInResourcesString() const { return mBuiltInResourcesString; } 146 147 bool isHighPrecisionSupported() const; 148 149 bool shouldRunLoopAndIndexingValidation(const ShCompileOptions &compileOptions) const; 150 bool shouldLimitTypeSizes() const; 151 152 // Get the resources set by InitBuiltInSymbolTable 153 const ShBuiltInResources &getResources() const; 154 getPragma()155 const TPragma &getPragma() const { return mPragma; } 156 getGeometryShaderMaxVertices()157 int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; } getGeometryShaderInvocations()158 int getGeometryShaderInvocations() const { return mGeometryShaderInvocations; } getGeometryShaderInputPrimitiveType()159 TLayoutPrimitiveType getGeometryShaderInputPrimitiveType() const 160 { 161 return mGeometryShaderInputPrimitiveType; 162 } getGeometryShaderOutputPrimitiveType()163 TLayoutPrimitiveType getGeometryShaderOutputPrimitiveType() const 164 { 165 return mGeometryShaderOutputPrimitiveType; 166 } 167 168 unsigned int getStructSize(const ShaderVariable &var) const; 169 getTessControlShaderOutputVertices()170 int getTessControlShaderOutputVertices() const { return mTessControlShaderOutputVertices; } getTessEvaluationShaderInputPrimitiveType()171 TLayoutTessEvaluationType getTessEvaluationShaderInputPrimitiveType() const 172 { 173 return mTessEvaluationShaderInputPrimitiveType; 174 } getTessEvaluationShaderInputVertexSpacingType()175 TLayoutTessEvaluationType getTessEvaluationShaderInputVertexSpacingType() const 176 { 177 return mTessEvaluationShaderInputVertexSpacingType; 178 } getTessEvaluationShaderInputOrderingType()179 TLayoutTessEvaluationType getTessEvaluationShaderInputOrderingType() const 180 { 181 return mTessEvaluationShaderInputOrderingType; 182 } getTessEvaluationShaderInputPointType()183 TLayoutTessEvaluationType getTessEvaluationShaderInputPointType() const 184 { 185 return mTessEvaluationShaderInputPointType; 186 } 187 hasAnyPreciseType()188 bool hasAnyPreciseType() const { return mHasAnyPreciseType; } 189 getAdvancedBlendEquations()190 AdvancedBlendEquations getAdvancedBlendEquations() const { return mAdvancedBlendEquations; } 191 hasPixelLocalStorageUniforms()192 bool hasPixelLocalStorageUniforms() const { return mHasPixelLocalStorageUniforms; } 193 getPixelLocalStorageType()194 ShPixelLocalStorageType getPixelLocalStorageType() const { return mCompileOptions.pls.type; } 195 196 unsigned int getSharedMemorySize() const; 197 getShaderType()198 sh::GLenum getShaderType() const { return mShaderType; } 199 200 // Generate a self-contained binary representation of the shader. 201 bool getShaderBinary(const ShHandle compilerHandle, 202 const char *const shaderStrings[], 203 size_t numStrings, 204 const ShCompileOptions &compileOptions, 205 ShaderBinaryBlob *const binaryOut); 206 207 // Validate the AST and produce errors if it is inconsistent. 208 bool validateAST(TIntermNode *root); 209 // Some transformations may need to temporarily disable validation until they are complete. A 210 // set of disable/enable helpers are used for this purpose. 211 bool disableValidateFunctionCall(); 212 void restoreValidateFunctionCall(bool enable); 213 bool disableValidateVariableReferences(); 214 void restoreValidateVariableReferences(bool enable); 215 // When the AST is post-processed (such as to determine precise-ness of intermediate nodes), 216 // it's expected to no longer transform. 217 void enableValidateNoMoreTransformations(); 218 areClipDistanceOrCullDistanceUsed()219 bool areClipDistanceOrCullDistanceUsed() const 220 { 221 return mClipDistanceSize > 0 || mCullDistanceSize > 0; 222 } 223 getClipDistanceArraySize()224 uint8_t getClipDistanceArraySize() const { return mClipDistanceSize; } 225 getCullDistanceArraySize()226 uint8_t getCullDistanceArraySize() const { return mCullDistanceSize; } 227 usesDerivatives()228 bool usesDerivatives() const { return mUsesDerivatives; } 229 supportsAttributeAliasing()230 bool supportsAttributeAliasing() const 231 { 232 return mShaderVersion == 100 && !IsWebGLBasedSpec(mShaderSpec); 233 } 234 235 protected: 236 // Add emulated functions to the built-in function emulator. initBuiltInFunctionEmulator(BuiltInFunctionEmulator * emu,const ShCompileOptions & compileOptions)237 virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, 238 const ShCompileOptions &compileOptions) 239 {} 240 // Translate to object code. May generate performance warnings through the diagnostics. 241 [[nodiscard]] virtual bool translate(TIntermBlock *root, 242 const ShCompileOptions &compileOptions, 243 PerformanceDiagnostics *perfDiagnostics) = 0; 244 // Get built-in extensions with default behavior. 245 const TExtensionBehavior &getExtensionBehavior() const; 246 const char *getSourcePath() const; 247 // Relies on collectVariables having been called. 248 bool isVaryingDefined(const char *varyingName); 249 250 const BuiltInFunctionEmulator &getBuiltInFunctionEmulator() const; 251 252 virtual bool shouldFlattenPragmaStdglInvariantAll() = 0; 253 254 std::vector<sh::ShaderVariable> mAttributes; 255 std::vector<sh::ShaderVariable> mOutputVariables; 256 std::vector<sh::ShaderVariable> mUniforms; 257 std::vector<sh::ShaderVariable> mInputVaryings; 258 std::vector<sh::ShaderVariable> mOutputVaryings; 259 std::vector<sh::ShaderVariable> mSharedVariables; 260 std::vector<sh::InterfaceBlock> mInterfaceBlocks; 261 std::vector<sh::InterfaceBlock> mUniformBlocks; 262 std::vector<sh::InterfaceBlock> mShaderStorageBlocks; 263 264 // Track what should be validated given passes currently applied. 265 ValidateASTOptions mValidateASTOptions; 266 267 MetadataFlagBits mMetadataFlags; 268 269 // Specialization constant usage bits 270 SpecConstUsageBits mSpecConstUsageBits; 271 272 private: 273 // Initialize symbol-table with built-in symbols. 274 bool initBuiltInSymbolTable(const ShBuiltInResources &resources); 275 // Compute the string representation of the built-in resources 276 void setResourceString(); 277 // Return false if the call depth is exceeded. 278 bool checkCallDepth(); 279 // Insert statements to reference all members in unused uniform blocks with standard and shared 280 // layout. This is to work around a Mac driver that treats unused standard/shared 281 // uniform blocks as inactive. 282 [[nodiscard]] bool useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root); 283 // Insert statements to initialize output variables in the beginning of main(). 284 // This is to avoid undefined behaviors. 285 [[nodiscard]] bool initializeOutputVariables(TIntermBlock *root); 286 // Insert gl_Position = vec4(0,0,0,0) to the beginning of main(). 287 // It is to work around a Linux driver bug where missing this causes compile failure 288 // while spec says it is allowed. 289 // This function should only be applied to vertex shaders. 290 [[nodiscard]] bool initializeGLPosition(TIntermBlock *root); 291 // Return true if the maximum expression complexity is below the limit. 292 bool limitExpressionComplexity(TIntermBlock *root); 293 // Creates the function call DAG for further analysis, returning false if there is a recursion 294 bool initCallDag(TIntermNode *root); 295 // Return false if "main" doesn't exist 296 bool tagUsedFunctions(); 297 void internalTagUsedFunction(size_t index); 298 299 void collectInterfaceBlocks(); 300 301 bool mVariablesCollected; 302 303 bool mGLPositionInitialized; 304 305 // Removes unused function declarations and prototypes from the AST 306 bool pruneUnusedFunctions(TIntermBlock *root); 307 308 TIntermBlock *compileTreeImpl(const char *const shaderStrings[], 309 size_t numStrings, 310 const ShCompileOptions &compileOptions); 311 312 // Fetches and stores shader metadata that is not stored within the AST itself, such as shader 313 // version. 314 void setASTMetadata(const TParseContext &parseContext); 315 316 // Check if shader version meets the requirement. 317 bool checkShaderVersion(TParseContext *parseContext); 318 319 // Does checks that need to be run after parsing is complete and returns true if they pass. 320 bool checkAndSimplifyAST(TIntermBlock *root, 321 const TParseContext &parseContext, 322 const ShCompileOptions &compileOptions); 323 324 bool postParseChecks(const TParseContext &parseContext); 325 326 sh::GLenum mShaderType; 327 ShShaderSpec mShaderSpec; 328 ShShaderOutput mOutputType; 329 330 CallDAG mCallDag; 331 std::vector<TFunctionMetadata> mFunctionMetadata; 332 333 ShBuiltInResources mResources; 334 std::string mBuiltInResourcesString; 335 336 // Built-in symbol table for the given language, spec, and resources. 337 // It is preserved from compile-to-compile. 338 TSymbolTable mSymbolTable; 339 // Built-in extensions with default behavior. 340 TExtensionBehavior mExtensionBehavior; 341 342 BuiltInFunctionEmulator mBuiltInFunctionEmulator; 343 344 // Results of compilation. 345 int mShaderVersion; 346 TInfoSink mInfoSink; // Output sink. 347 TDiagnostics mDiagnostics; 348 const char *mSourcePath; // Path of source file or NULL 349 350 // Fragment shader early fragment tests 351 bool mEarlyFragmentTestsSpecified; 352 353 // compute shader local group size 354 bool mComputeShaderLocalSizeDeclared; 355 sh::WorkGroupSize mComputeShaderLocalSize; 356 357 // GL_OVR_multiview num_views. 358 int mNumViews; 359 360 // Track gl_ClipDistance / gl_CullDistance usage. 361 uint8_t mClipDistanceSize; 362 uint8_t mCullDistanceSize; 363 364 // geometry shader parameters. 365 int mGeometryShaderMaxVertices; 366 int mGeometryShaderInvocations; 367 TLayoutPrimitiveType mGeometryShaderInputPrimitiveType; 368 TLayoutPrimitiveType mGeometryShaderOutputPrimitiveType; 369 370 // tesssellation shader parameters 371 int mTessControlShaderOutputVertices; 372 TLayoutTessEvaluationType mTessEvaluationShaderInputPrimitiveType; 373 TLayoutTessEvaluationType mTessEvaluationShaderInputVertexSpacingType; 374 TLayoutTessEvaluationType mTessEvaluationShaderInputOrderingType; 375 TLayoutTessEvaluationType mTessEvaluationShaderInputPointType; 376 377 bool mHasAnyPreciseType; 378 379 // advanced blend equation parameters 380 AdvancedBlendEquations mAdvancedBlendEquations; 381 382 // ANGLE_shader_pixel_local_storage. 383 bool mHasPixelLocalStorageUniforms; 384 385 // Fragment shader uses screen-space derivatives 386 bool mUsesDerivatives; 387 388 // name hashing. 389 NameMap mNameMap; 390 391 TPragma mPragma; 392 393 ShCompileOptions mCompileOptions; 394 }; 395 396 // 397 // This is the interface between the machine independent code 398 // and the machine dependent code. 399 // 400 // The machine dependent code should derive from the classes 401 // above. Then Construct*() and Delete*() will create and 402 // destroy the machine dependent objects, which contain the 403 // above machine independent information. 404 // 405 TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); 406 void DeleteCompiler(TCompiler *); 407 408 struct ShaderDumpHeader 409 { 410 uint32_t type; 411 uint32_t spec; 412 uint32_t output; 413 uint8_t basicCompileOptions[32]; 414 uint8_t metalCompileOptions[32]; 415 uint8_t plsCompileOptions[32]; 416 uint8_t padding[20]; 417 }; 418 static_assert(sizeof(ShaderDumpHeader) == 128); 419 420 } // namespace sh 421 422 #endif // COMPILER_TRANSLATOR_COMPILER_H_ 423