Backed out 3 changesets (bug 1459785) for causing https://bugzilla.mozilla.org/show_bug.cgi?id=1464089 a=backout
authorNoemi Erli <nerli@mozilla.com>
Thu, 24 May 2018 18:46:25 +0300
changeset 467844 ff8505d177b9
parent 467843 d99634619b05
child 467845 a6ab60c0ba0c
child 467860 3c31c543e736
child 467892 d70c7ce71813
child 467938 6c9812ad14dc
child 468510 bcd156802d75
push id179
push userfmarier@mozilla.com
push date2018-05-25 23:33 +0000
reviewersbackout
bugs1459785, 1464089
milestone62.0a1
backs out88675b68241a
b7c91a6f1b0a
21af8dc00aa8
Backed out 3 changesets (bug 1459785) for causing https://bugzilla.mozilla.org/show_bug.cgi?id=1464089 a=backout Backed out changeset 88675b68241a (bug 1459785) Backed out changeset b7c91a6f1b0a (bug 1459785) Backed out changeset 21af8dc00aa8 (bug 1459785)
dom/canvas/test/webgl-conf/generated-mochitest.ini
dom/canvas/test/webgl-conf/mochitest-errata.ini
gfx/angle/checkout/include/EGL/eglext_angle.h
gfx/angle/checkout/include/GLSLANG/ShaderLang.h
gfx/angle/checkout/include/GLSLANG/ShaderVars.h
gfx/angle/checkout/include/KHR/khrplatform.h
gfx/angle/checkout/out/gen/angle/id/commit.h
gfx/angle/checkout/src/common/Color.h
gfx/angle/checkout/src/common/FixedVector.h
gfx/angle/checkout/src/common/angleutils.h
gfx/angle/checkout/src/common/bitset_utils.h
gfx/angle/checkout/src/common/mathutil.h
gfx/angle/checkout/src/common/matrix_utils.h
gfx/angle/checkout/src/common/utilities.cpp
gfx/angle/checkout/src/common/utilities.h
gfx/angle/checkout/src/compiler/preprocessor/Tokenizer.cpp
gfx/angle/checkout/src/compiler/preprocessor/Tokenizer.l
gfx/angle/checkout/src/compiler/preprocessor/numeric_lex.h
gfx/angle/checkout/src/compiler/translator/ASTMetadataHLSL.cpp
gfx/angle/checkout/src/compiler/translator/AddAndTrueToLoopCondition.cpp
gfx/angle/checkout/src/compiler/translator/AddAndTrueToLoopCondition.h
gfx/angle/checkout/src/compiler/translator/AddDefaultReturnStatements.cpp
gfx/angle/checkout/src/compiler/translator/AddDefaultReturnStatements.h
gfx/angle/checkout/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
gfx/angle/checkout/src/compiler/translator/ArrayReturnValueToOutParameter.h
gfx/angle/checkout/src/compiler/translator/BaseTypes.h
gfx/angle/checkout/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp
gfx/angle/checkout/src/compiler/translator/BreakVariableAliasingInInnerLoops.h
gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.cpp
gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.h
gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp
gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
gfx/angle/checkout/src/compiler/translator/CallDAG.cpp
gfx/angle/checkout/src/compiler/translator/ClampFragDepth.cpp
gfx/angle/checkout/src/compiler/translator/ClampFragDepth.h
gfx/angle/checkout/src/compiler/translator/ClampPointSize.cpp
gfx/angle/checkout/src/compiler/translator/ClampPointSize.h
gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp
gfx/angle/checkout/src/compiler/translator/CollectVariables.h
gfx/angle/checkout/src/compiler/translator/Compiler.cpp
gfx/angle/checkout/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp
gfx/angle/checkout/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h
gfx/angle/checkout/src/compiler/translator/DeferGlobalInitializers.cpp
gfx/angle/checkout/src/compiler/translator/DeferGlobalInitializers.h
gfx/angle/checkout/src/compiler/translator/EmulateGLFragColorBroadcast.cpp
gfx/angle/checkout/src/compiler/translator/EmulateGLFragColorBroadcast.h
gfx/angle/checkout/src/compiler/translator/EmulatePrecision.cpp
gfx/angle/checkout/src/compiler/translator/EmulatePrecision.h
gfx/angle/checkout/src/compiler/translator/ExpandIntegerPowExpressions.cpp
gfx/angle/checkout/src/compiler/translator/ExpandIntegerPowExpressions.h
gfx/angle/checkout/src/compiler/translator/ExtensionGLSL.h
gfx/angle/checkout/src/compiler/translator/FindMain.cpp
gfx/angle/checkout/src/compiler/translator/FindMain.h
gfx/angle/checkout/src/compiler/translator/FindSymbolNode.cpp
gfx/angle/checkout/src/compiler/translator/FindSymbolNode.h
gfx/angle/checkout/src/compiler/translator/FlagStd140Structs.cpp
gfx/angle/checkout/src/compiler/translator/FoldExpressions.cpp
gfx/angle/checkout/src/compiler/translator/FoldExpressions.h
gfx/angle/checkout/src/compiler/translator/ImmutableString.cpp
gfx/angle/checkout/src/compiler/translator/ImmutableString.h
gfx/angle/checkout/src/compiler/translator/ImmutableStringBuilder.h
gfx/angle/checkout/src/compiler/translator/InitializeVariables.cpp
gfx/angle/checkout/src/compiler/translator/InitializeVariables.h
gfx/angle/checkout/src/compiler/translator/IntermNode.cpp
gfx/angle/checkout/src/compiler/translator/IntermNode.h
gfx/angle/checkout/src/compiler/translator/IntermNodePatternMatcher.cpp
gfx/angle/checkout/src/compiler/translator/IntermNodePatternMatcher.h
gfx/angle/checkout/src/compiler/translator/IntermNode_util.cpp
gfx/angle/checkout/src/compiler/translator/IntermNode_util.h
gfx/angle/checkout/src/compiler/translator/IntermTraverse.cpp
gfx/angle/checkout/src/compiler/translator/IntermTraverse.h
gfx/angle/checkout/src/compiler/translator/IsASTDepthBelowLimit.cpp
gfx/angle/checkout/src/compiler/translator/NodeSearch.h
gfx/angle/checkout/src/compiler/translator/OutputGLSL.cpp
gfx/angle/checkout/src/compiler/translator/OutputGLSLBase.cpp
gfx/angle/checkout/src/compiler/translator/OutputGLSLBase.h
gfx/angle/checkout/src/compiler/translator/OutputHLSL.cpp
gfx/angle/checkout/src/compiler/translator/OutputHLSL.h
gfx/angle/checkout/src/compiler/translator/OutputTree.cpp
gfx/angle/checkout/src/compiler/translator/ParamType.h
gfx/angle/checkout/src/compiler/translator/ParseContext.cpp
gfx/angle/checkout/src/compiler/translator/ParseContext.h
gfx/angle/checkout/src/compiler/translator/ParseContext_autogen.h
gfx/angle/checkout/src/compiler/translator/PruneNoOps.cpp
gfx/angle/checkout/src/compiler/translator/PruneNoOps.h
gfx/angle/checkout/src/compiler/translator/RecordConstantPrecision.cpp
gfx/angle/checkout/src/compiler/translator/RecordConstantPrecision.h
gfx/angle/checkout/src/compiler/translator/RegenerateStructNames.cpp
gfx/angle/checkout/src/compiler/translator/RegenerateStructNames.h
gfx/angle/checkout/src/compiler/translator/RemoveArrayLengthMethod.cpp
gfx/angle/checkout/src/compiler/translator/RemoveArrayLengthMethod.h
gfx/angle/checkout/src/compiler/translator/RemoveDynamicIndexing.cpp
gfx/angle/checkout/src/compiler/translator/RemoveDynamicIndexing.h
gfx/angle/checkout/src/compiler/translator/RemoveEmptySwitchStatements.cpp
gfx/angle/checkout/src/compiler/translator/RemoveEmptySwitchStatements.h
gfx/angle/checkout/src/compiler/translator/RemoveInvariantDeclaration.cpp
gfx/angle/checkout/src/compiler/translator/RemoveInvariantDeclaration.h
gfx/angle/checkout/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp
gfx/angle/checkout/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h
gfx/angle/checkout/src/compiler/translator/RemovePow.cpp
gfx/angle/checkout/src/compiler/translator/RemovePow.h
gfx/angle/checkout/src/compiler/translator/RemoveSwitchFallThrough.cpp
gfx/angle/checkout/src/compiler/translator/RemoveSwitchFallThrough.h
gfx/angle/checkout/src/compiler/translator/RemoveUnreferencedVariables.cpp
gfx/angle/checkout/src/compiler/translator/RemoveUnreferencedVariables.h
gfx/angle/checkout/src/compiler/translator/ReplaceVariable.cpp
gfx/angle/checkout/src/compiler/translator/ReplaceVariable.h
gfx/angle/checkout/src/compiler/translator/RewriteDoWhile.cpp
gfx/angle/checkout/src/compiler/translator/RewriteDoWhile.h
gfx/angle/checkout/src/compiler/translator/RewriteElseBlocks.cpp
gfx/angle/checkout/src/compiler/translator/RewriteElseBlocks.h
gfx/angle/checkout/src/compiler/translator/RewriteTexelFetchOffset.cpp
gfx/angle/checkout/src/compiler/translator/RewriteTexelFetchOffset.h
gfx/angle/checkout/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp
gfx/angle/checkout/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h
gfx/angle/checkout/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp
gfx/angle/checkout/src/compiler/translator/RewriteUnaryMinusOperatorInt.h
gfx/angle/checkout/src/compiler/translator/RunAtTheEndOfShader.cpp
gfx/angle/checkout/src/compiler/translator/RunAtTheEndOfShader.h
gfx/angle/checkout/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp
gfx/angle/checkout/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
gfx/angle/checkout/src/compiler/translator/SeparateArrayConstructorStatements.cpp
gfx/angle/checkout/src/compiler/translator/SeparateArrayConstructorStatements.h
gfx/angle/checkout/src/compiler/translator/SeparateArrayInitialization.cpp
gfx/angle/checkout/src/compiler/translator/SeparateArrayInitialization.h
gfx/angle/checkout/src/compiler/translator/SeparateDeclarations.cpp
gfx/angle/checkout/src/compiler/translator/SeparateDeclarations.h
gfx/angle/checkout/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
gfx/angle/checkout/src/compiler/translator/SeparateExpressionsReturningArrays.h
gfx/angle/checkout/src/compiler/translator/ShaderVars.cpp
gfx/angle/checkout/src/compiler/translator/SimplifyLoopConditions.cpp
gfx/angle/checkout/src/compiler/translator/SimplifyLoopConditions.h
gfx/angle/checkout/src/compiler/translator/SplitSequenceOperator.cpp
gfx/angle/checkout/src/compiler/translator/SplitSequenceOperator.h
gfx/angle/checkout/src/compiler/translator/StaticType.cpp
gfx/angle/checkout/src/compiler/translator/StaticType.h
gfx/angle/checkout/src/compiler/translator/Symbol.cpp
gfx/angle/checkout/src/compiler/translator/Symbol.h
gfx/angle/checkout/src/compiler/translator/SymbolTable.cpp
gfx/angle/checkout/src/compiler/translator/SymbolTable.h
gfx/angle/checkout/src/compiler/translator/SymbolTable_autogen.cpp
gfx/angle/checkout/src/compiler/translator/SymbolTable_autogen.h
gfx/angle/checkout/src/compiler/translator/SymbolUniqueId.cpp
gfx/angle/checkout/src/compiler/translator/SymbolUniqueId.h
gfx/angle/checkout/src/compiler/translator/TranslatorESSL.cpp
gfx/angle/checkout/src/compiler/translator/TranslatorGLSL.cpp
gfx/angle/checkout/src/compiler/translator/TranslatorHLSL.cpp
gfx/angle/checkout/src/compiler/translator/Types.cpp
gfx/angle/checkout/src/compiler/translator/Types.h
gfx/angle/checkout/src/compiler/translator/UnfoldShortCircuitAST.cpp
gfx/angle/checkout/src/compiler/translator/UnfoldShortCircuitAST.h
gfx/angle/checkout/src/compiler/translator/UnfoldShortCircuitToIf.cpp
gfx/angle/checkout/src/compiler/translator/UnfoldShortCircuitToIf.h
gfx/angle/checkout/src/compiler/translator/UseInterfaceBlockFields.cpp
gfx/angle/checkout/src/compiler/translator/UseInterfaceBlockFields.h
gfx/angle/checkout/src/compiler/translator/UtilsHLSL.cpp
gfx/angle/checkout/src/compiler/translator/UtilsHLSL.h
gfx/angle/checkout/src/compiler/translator/ValidateGlobalInitializer.cpp
gfx/angle/checkout/src/compiler/translator/ValidateLimitations.cpp
gfx/angle/checkout/src/compiler/translator/ValidateMaxParameters.cpp
gfx/angle/checkout/src/compiler/translator/ValidateOutputs.cpp
gfx/angle/checkout/src/compiler/translator/ValidateSwitch.cpp
gfx/angle/checkout/src/compiler/translator/ValidateSwitch.h
gfx/angle/checkout/src/compiler/translator/ValidateVaryingLocations.cpp
gfx/angle/checkout/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp
gfx/angle/checkout/src/compiler/translator/VectorizeVectorScalarArithmetic.h
gfx/angle/checkout/src/compiler/translator/VersionGLSL.cpp
gfx/angle/checkout/src/compiler/translator/VersionGLSL.h
gfx/angle/checkout/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp
gfx/angle/checkout/src/compiler/translator/WrapSwitchStatementsInBlocks.h
gfx/angle/checkout/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp
gfx/angle/checkout/src/compiler/translator/glslang.y
gfx/angle/checkout/src/compiler/translator/glslang_tab.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/AddAndTrueToLoopCondition.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/AddAndTrueToLoopCondition.h
gfx/angle/checkout/src/compiler/translator/tree_ops/AddDefaultReturnStatements.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/AddDefaultReturnStatements.h
gfx/angle/checkout/src/compiler/translator/tree_ops/ArrayReturnValueToOutParameter.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/ArrayReturnValueToOutParameter.h
gfx/angle/checkout/src/compiler/translator/tree_ops/BreakVariableAliasingInInnerLoops.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/BreakVariableAliasingInInnerLoops.h
gfx/angle/checkout/src/compiler/translator/tree_ops/ClampFragDepth.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/ClampFragDepth.h
gfx/angle/checkout/src/compiler/translator/tree_ops/ClampPointSize.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/ClampPointSize.h
gfx/angle/checkout/src/compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h
gfx/angle/checkout/src/compiler/translator/tree_ops/DeferGlobalInitializers.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/DeferGlobalInitializers.h
gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateGLFragColorBroadcast.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h
gfx/angle/checkout/src/compiler/translator/tree_ops/EmulatePrecision.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/EmulatePrecision.h
gfx/angle/checkout/src/compiler/translator/tree_ops/ExpandIntegerPowExpressions.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/ExpandIntegerPowExpressions.h
gfx/angle/checkout/src/compiler/translator/tree_ops/FoldExpressions.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/FoldExpressions.h
gfx/angle/checkout/src/compiler/translator/tree_ops/InitializeVariables.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/InitializeVariables.h
gfx/angle/checkout/src/compiler/translator/tree_ops/PruneEmptyCases.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/PruneEmptyCases.h
gfx/angle/checkout/src/compiler/translator/tree_ops/PruneNoOps.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/PruneNoOps.h
gfx/angle/checkout/src/compiler/translator/tree_ops/RecordConstantPrecision.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/RecordConstantPrecision.h
gfx/angle/checkout/src/compiler/translator/tree_ops/RegenerateStructNames.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/RegenerateStructNames.h
gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveArrayLengthMethod.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveArrayLengthMethod.h
gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveDynamicIndexing.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveDynamicIndexing.h
gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveInvariantDeclaration.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveInvariantDeclaration.h
gfx/angle/checkout/src/compiler/translator/tree_ops/RemovePow.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/RemovePow.h
gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveSwitchFallThrough.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveSwitchFallThrough.h
gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveUnreferencedVariables.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveUnreferencedVariables.h
gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteDoWhile.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteDoWhile.h
gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteElseBlocks.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteElseBlocks.h
gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteTexelFetchOffset.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteTexelFetchOffset.h
gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteUnaryMinusOperatorFloat.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteUnaryMinusOperatorFloat.h
gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteUnaryMinusOperatorInt.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteUnaryMinusOperatorInt.h
gfx/angle/checkout/src/compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h
gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateArrayConstructorStatements.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateArrayConstructorStatements.h
gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateArrayInitialization.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateArrayInitialization.h
gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateDeclarations.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateDeclarations.h
gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateExpressionsReturningArrays.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateExpressionsReturningArrays.h
gfx/angle/checkout/src/compiler/translator/tree_ops/SimplifyLoopConditions.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/SimplifyLoopConditions.h
gfx/angle/checkout/src/compiler/translator/tree_ops/SplitSequenceOperator.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/SplitSequenceOperator.h
gfx/angle/checkout/src/compiler/translator/tree_ops/UnfoldShortCircuitAST.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/UnfoldShortCircuitAST.h
gfx/angle/checkout/src/compiler/translator/tree_ops/UnfoldShortCircuitToIf.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/UnfoldShortCircuitToIf.h
gfx/angle/checkout/src/compiler/translator/tree_ops/UseInterfaceBlockFields.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/UseInterfaceBlockFields.h
gfx/angle/checkout/src/compiler/translator/tree_ops/VectorizeVectorScalarArithmetic.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/VectorizeVectorScalarArithmetic.h
gfx/angle/checkout/src/compiler/translator/tree_ops/WrapSwitchStatementsInBlocks.cpp
gfx/angle/checkout/src/compiler/translator/tree_ops/WrapSwitchStatementsInBlocks.h
gfx/angle/checkout/src/compiler/translator/tree_util/BuiltIn_autogen.h
gfx/angle/checkout/src/compiler/translator/tree_util/FindMain.cpp
gfx/angle/checkout/src/compiler/translator/tree_util/FindMain.h
gfx/angle/checkout/src/compiler/translator/tree_util/FindSymbolNode.cpp
gfx/angle/checkout/src/compiler/translator/tree_util/FindSymbolNode.h
gfx/angle/checkout/src/compiler/translator/tree_util/IntermNodePatternMatcher.cpp
gfx/angle/checkout/src/compiler/translator/tree_util/IntermNodePatternMatcher.h
gfx/angle/checkout/src/compiler/translator/tree_util/IntermNode_util.cpp
gfx/angle/checkout/src/compiler/translator/tree_util/IntermNode_util.h
gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp
gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.h
gfx/angle/checkout/src/compiler/translator/tree_util/NodeSearch.h
gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceVariable.cpp
gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceVariable.h
gfx/angle/checkout/src/compiler/translator/tree_util/RunAtTheEndOfShader.cpp
gfx/angle/checkout/src/compiler/translator/tree_util/RunAtTheEndOfShader.h
gfx/angle/checkout/src/libANGLE/BinaryStream.h
gfx/angle/checkout/src/libANGLE/Buffer.cpp
gfx/angle/checkout/src/libANGLE/Buffer.h
gfx/angle/checkout/src/libANGLE/Caps.cpp
gfx/angle/checkout/src/libANGLE/Caps.h
gfx/angle/checkout/src/libANGLE/Compiler.cpp
gfx/angle/checkout/src/libANGLE/Compiler.h
gfx/angle/checkout/src/libANGLE/Context.cpp
gfx/angle/checkout/src/libANGLE/Context.h
gfx/angle/checkout/src/libANGLE/ContextState.cpp
gfx/angle/checkout/src/libANGLE/ContextState.h
gfx/angle/checkout/src/libANGLE/Context_gles_1_0.cpp
gfx/angle/checkout/src/libANGLE/Context_gles_1_0_autogen.h
gfx/angle/checkout/src/libANGLE/Display.cpp
gfx/angle/checkout/src/libANGLE/Error.h
gfx/angle/checkout/src/libANGLE/Error.inl
gfx/angle/checkout/src/libANGLE/ErrorStrings.h
gfx/angle/checkout/src/libANGLE/Framebuffer.cpp
gfx/angle/checkout/src/libANGLE/Framebuffer.h
gfx/angle/checkout/src/libANGLE/FramebufferAttachment.cpp
gfx/angle/checkout/src/libANGLE/FramebufferAttachment.h
gfx/angle/checkout/src/libANGLE/GLES1State.cpp
gfx/angle/checkout/src/libANGLE/GLES1State.h
gfx/angle/checkout/src/libANGLE/HandleAllocator.cpp
gfx/angle/checkout/src/libANGLE/Image.cpp
gfx/angle/checkout/src/libANGLE/ImageIndex.cpp
gfx/angle/checkout/src/libANGLE/ImageIndex.h
gfx/angle/checkout/src/libANGLE/MemoryProgramCache.cpp
gfx/angle/checkout/src/libANGLE/Observer.cpp
gfx/angle/checkout/src/libANGLE/Observer.h
gfx/angle/checkout/src/libANGLE/PackedGLEnums.cpp
gfx/angle/checkout/src/libANGLE/PackedGLEnums.h
gfx/angle/checkout/src/libANGLE/PackedGLEnums_autogen.cpp
gfx/angle/checkout/src/libANGLE/PackedGLEnums_autogen.h
gfx/angle/checkout/src/libANGLE/Program.cpp
gfx/angle/checkout/src/libANGLE/Program.h
gfx/angle/checkout/src/libANGLE/ProgramLinkedResources.cpp
gfx/angle/checkout/src/libANGLE/ProgramLinkedResources.h
gfx/angle/checkout/src/libANGLE/RefCountObject.h
gfx/angle/checkout/src/libANGLE/Renderbuffer.cpp
gfx/angle/checkout/src/libANGLE/ResourceManager.cpp
gfx/angle/checkout/src/libANGLE/ResourceManager.h
gfx/angle/checkout/src/libANGLE/Shader.cpp
gfx/angle/checkout/src/libANGLE/Shader.h
gfx/angle/checkout/src/libANGLE/State.cpp
gfx/angle/checkout/src/libANGLE/State.h
gfx/angle/checkout/src/libANGLE/Stream.cpp
gfx/angle/checkout/src/libANGLE/Surface.cpp
gfx/angle/checkout/src/libANGLE/Texture.cpp
gfx/angle/checkout/src/libANGLE/Texture.h
gfx/angle/checkout/src/libANGLE/TransformFeedback.cpp
gfx/angle/checkout/src/libANGLE/TransformFeedback.h
gfx/angle/checkout/src/libANGLE/Uniform.cpp
gfx/angle/checkout/src/libANGLE/Uniform.h
gfx/angle/checkout/src/libANGLE/VaryingPacking.cpp
gfx/angle/checkout/src/libANGLE/VertexArray.cpp
gfx/angle/checkout/src/libANGLE/VertexArray.h
gfx/angle/checkout/src/libANGLE/VertexAttribute.cpp
gfx/angle/checkout/src/libANGLE/VertexAttribute.h
gfx/angle/checkout/src/libANGLE/angletypes.cpp
gfx/angle/checkout/src/libANGLE/angletypes.h
gfx/angle/checkout/src/libANGLE/entry_points_enum_autogen.h
gfx/angle/checkout/src/libANGLE/es3_copy_conversion_table_autogen.cpp
gfx/angle/checkout/src/libANGLE/format_map_autogen.cpp
gfx/angle/checkout/src/libANGLE/formatutils.cpp
gfx/angle/checkout/src/libANGLE/formatutils.h
gfx/angle/checkout/src/libANGLE/params.cpp
gfx/angle/checkout/src/libANGLE/params.h
gfx/angle/checkout/src/libANGLE/queryconversions.cpp
gfx/angle/checkout/src/libANGLE/queryutils.cpp
gfx/angle/checkout/src/libANGLE/queryutils.h
gfx/angle/checkout/src/libANGLE/renderer/BufferImpl.h
gfx/angle/checkout/src/libANGLE/renderer/Format.h
gfx/angle/checkout/src/libANGLE/renderer/Format_ID_autogen.inl
gfx/angle/checkout/src/libANGLE/renderer/Format_table_autogen.cpp
gfx/angle/checkout/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h
gfx/angle/checkout/src/libANGLE/renderer/FramebufferImpl.h
gfx/angle/checkout/src/libANGLE/renderer/ProgramImpl.h
gfx/angle/checkout/src/libANGLE/renderer/RenderTargetCache.h
gfx/angle/checkout/src/libANGLE/renderer/TextureImpl.cpp
gfx/angle/checkout/src/libANGLE/renderer/TextureImpl.h
gfx/angle/checkout/src/libANGLE/renderer/VertexArrayImpl.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/BufferD3D.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/BufferD3D.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicHLSL.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/EGLImageD3D.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/FramebufferD3D.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/ImageD3D.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/ImageD3D.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/IndexDataManager.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/IndexDataManager.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/ProgramD3D.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/ProgramD3D.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/RenderTargetD3D.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/RendererD3D.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/RendererD3D.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/ShaderD3D.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/TextureD3D.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/TextureD3D.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/TextureStorage.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexBuffer.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexBuffer.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexDataManager.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexDataManager.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Context11.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Image11.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Blit9.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Image9.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h
gfx/angle/checkout/src/libANGLE/renderer/load_functions_table_autogen.cpp
gfx/angle/checkout/src/libANGLE/renderer/renderer_utils.cpp
gfx/angle/checkout/src/libANGLE/renderer/renderer_utils.h
gfx/angle/checkout/src/libANGLE/signal_utils.cpp
gfx/angle/checkout/src/libANGLE/signal_utils.h
gfx/angle/checkout/src/libANGLE/validationEGL.cpp
gfx/angle/checkout/src/libANGLE/validationES.cpp
gfx/angle/checkout/src/libANGLE/validationES.h
gfx/angle/checkout/src/libANGLE/validationES1.cpp
gfx/angle/checkout/src/libANGLE/validationES1.h
gfx/angle/checkout/src/libANGLE/validationES2.cpp
gfx/angle/checkout/src/libANGLE/validationES2.h
gfx/angle/checkout/src/libANGLE/validationES3.cpp
gfx/angle/checkout/src/libANGLE/validationES3.h
gfx/angle/checkout/src/libANGLE/validationES31.cpp
gfx/angle/checkout/src/libANGLE/validationES31.h
gfx/angle/checkout/src/libGLESv2/entry_points_egl.cpp
gfx/angle/checkout/src/libGLESv2/entry_points_gles_1_0_autogen.cpp
gfx/angle/checkout/src/libGLESv2/entry_points_gles_1_0_autogen.h
gfx/angle/checkout/src/libGLESv2/entry_points_gles_2_0_autogen.cpp
gfx/angle/checkout/src/libGLESv2/entry_points_gles_2_0_autogen.h
gfx/angle/checkout/src/libGLESv2/entry_points_gles_2_0_ext.cpp
gfx/angle/checkout/src/libGLESv2/entry_points_gles_3_0_autogen.cpp
gfx/angle/checkout/src/libGLESv2/entry_points_gles_3_1_autogen.cpp
gfx/angle/checkout/src/libGLESv2/entry_points_gles_ext_autogen.cpp
gfx/angle/checkout/src/libGLESv2/entry_points_gles_ext_autogen.h
gfx/angle/checkout/src/libGLESv2/proc_table.h
gfx/angle/checkout/src/third_party/compiler/ArrayBoundsClamper.cpp
gfx/angle/cherries.log
gfx/angle/cherry_picks.txt
gfx/angle/targets/libANGLE/moz.build
gfx/angle/targets/translator/moz.build
gfx/angle/update-angle.py
gfx/angle/vendor_from_git.py
--- a/dom/canvas/test/webgl-conf/generated-mochitest.ini
+++ b/dom/canvas/test/webgl-conf/generated-mochitest.ini
@@ -4952,17 +4952,17 @@ support-files = always-fail.html
                 checkout/test-guidelines.md
                 checkout/webgl-conformance-tests.html
                 iframe-passthrough.css
                 mochi-single.html
 
 [generated/test_..__always-fail.html]
 fail-if = 1
 [generated/test_2_conformance2__attribs__gl-bindAttribLocation-aliasing-inactive.html]
-fail-if = (os != 'win')
+fail-if = 1
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__attribs__gl-vertex-attrib-i-render.html]
 skip-if = (os == 'win') || (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__attribs__gl-vertex-attrib-normalized-int.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__attribs__gl-vertex-attrib.html]
 skip-if = (os == 'win') || (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__attribs__gl-vertexattribipointer-offsets.html]
@@ -5090,18 +5090,20 @@ skip-if = (os == 'android' || os == 'lin
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__shader-with-invalid-characters.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__shader-with-mis-matching-uniform-block.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__short-circuiting-in-loop-condition.html]
 skip-if = (os == 'win' && os_version == '6.1') || (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__switch-case.html]
+fail-if = (os == 'win')
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__texture-offset-non-constant-offset.html]
+fail-if = (os == 'win')
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__texture-offset-out-of-range.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__texture-offset-uniform-texture-coordinate.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__tricky-loop-conditions.html]
 fail-if = (os == 'win')
 skip-if = (os == 'android' || os == 'linux')
@@ -7272,17 +7274,18 @@ skip-if = (os == 'android' || os == 'lin
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__non-existent-varying.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__simultaneous_binding.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__switching-objects.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__too-small-buffers.html]
-skip-if = 1 || (os == 'android' || os == 'linux')
+fail-if = 1
+skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__transform_feedback.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__two-unreferenced-varyings.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__unwritten-output-defaults-to-zero.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__uniforms__dependent-buffer-change.html]
 skip-if = (os == 'android' || os == 'linux')
--- a/dom/canvas/test/webgl-conf/mochitest-errata.ini
+++ b/dom/canvas/test/webgl-conf/mochitest-errata.ini
@@ -84,22 +84,21 @@ skip-if = (os == 'win')
 skip-if = 1
 [generated/test_2_conformance2__rendering__depth-stencil-feedback-loop.html]
 fail-if = 1
 [generated/test_2_conformance2__rendering__instanced-arrays.html]
 fail-if = 1
 [generated/test_2_conformance2__rendering__read-draw-when-missing-image.html]
 fail-if = 1
 [generated/test_2_conformance2__transform_feedback__too-small-buffers.html]
-# ABORT_ON_ERROR
-skip-if = 1
+fail-if = 1
 [generated/test_2_conformance2__uniforms__incompatible-texture-type-for-sampler.html]
 fail-if = 1
 [generated/test_2_conformance2__attribs__gl-bindAttribLocation-aliasing-inactive.html]
-fail-if = (os != 'win')
+fail-if = 1
 
 [generated/test_conformance__rendering__texture-switch-performance.html]
 # Frequent orange on linux+asan, but likely intermittant:
 # Texture switching significantly hurt performance - achieved 77 frames in 2.016 seconds (0.79 times baseline performance)
 skip-if = 1
 [generated/test_2_conformance__rendering__texture-switch-performance.html]
 # Orange on win10+debug
 # Texture switching significantly hurt performance - achieved 3 frames in 2.164
@@ -1165,16 +1164,20 @@ fail-if = (os == 'win')
 [generated/test_2_conformance__rendering__preservedrawingbuffer-leak.html]
 skip-if = (os == 'win')
 [generated/test_conformance__context__context-size-change.html]
 skip-if = (os == 'win')
 [generated/test_conformance__rendering__preservedrawingbuffer-leak.html]
 skip-if = (os == 'win')
 [generated/test_2_conformance2__glsl3__array-initialize-with-same-name-array.html]
 fail-if = (os == 'win')
+[generated/test_2_conformance2__glsl3__switch-case.html]
+fail-if = (os == 'win')
+[generated/test_2_conformance2__glsl3__texture-offset-non-constant-offset.html]
+fail-if = (os == 'win')
 [generated/test_2_conformance__misc__webgl-specific-stencil-settings.html]
 # [gl:0D6DE000] mozilla::gl::GLContext::raw_fDrawArrays: Generated unexpected GL_INVALID_OPERATION error. (0x0502)
 # ERR: gl::ValidateDrawBase(2519): This ANGLE implementation does not support separate front/back stencil writemasks, reference values, or stencil mask values.
 # Hit MOZ_CRASH(Unexpected error with MOZ_GL_DEBUG_ABORT_ON_ERROR. (Run with MOZ_GL_DEBUG_ABORT_ON_ERROR=0 to disable)) at z:/build/build/src/gfx/gl/GLContext.cpp:3030
 skip-if = (os == 'win')
 [generated/test_conformance__misc__webgl-specific-stencil-settings.html]
 skip-if = (os == 'win')
 [generated/test_conformance__textures__misc__tex-video-using-tex-unit-non-zero.html]
--- a/gfx/angle/checkout/include/EGL/eglext_angle.h
+++ b/gfx/angle/checkout/include/EGL/eglext_angle.h
@@ -170,16 +170,11 @@ EGLAPI EGLint EGLAPIENTRY eglProgramCach
 #define EGL_ANGLE_iosurface_client_buffer 1
 #define EGL_IOSURFACE_ANGLE 0x3454
 #define EGL_IOSURFACE_PLANE_ANGLE 0x345A
 #define EGL_TEXTURE_RECTANGLE_ANGLE 0x345B
 #define EGL_TEXTURE_TYPE_ANGLE 0x345C
 #define EGL_TEXTURE_INTERNAL_FORMAT_ANGLE 0x345D
 #endif /* EGL_ANGLE_iosurface_client_buffer */
 
-#ifndef EGL_ANGLE_create_context_extensions_enabled
-#define EGL_ANGLE_create_context_extensions_enabled 1
-#define EGL_EXTENSIONS_ENABLED_ANGLE 0x345F
-#endif /* EGL_ANGLE_create_context_extensions_enabled */
-
 // clang-format on
 
 #endif  // INCLUDE_EGL_EGLEXT_ANGLE_
--- a/gfx/angle/checkout/include/GLSLANG/ShaderLang.h
+++ b/gfx/angle/checkout/include/GLSLANG/ShaderLang.h
@@ -20,17 +20,17 @@
 // and the shading language compiler.
 //
 
 // Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h
 #include "ShaderVars.h"
 
 // Version number for shader translation API.
 // It is incremented every time the API changes.
-#define ANGLE_SH_VERSION 197
+#define ANGLE_SH_VERSION 196
 
 enum ShShaderSpec
 {
     SH_GLES2_SPEC,
     SH_WEBGL_SPEC,
 
     SH_GLES3_SPEC,
     SH_WEBGL2_SPEC,
--- a/gfx/angle/checkout/include/GLSLANG/ShaderVars.h
+++ b/gfx/angle/checkout/include/GLSLANG/ShaderVars.h
@@ -121,22 +121,17 @@ struct ShaderVariable
     // Offset of this variable in parent arrays. In case the parent is an array of arrays, the
     // offset is outerArrayElement * innerArraySize + innerArrayElement.
     // For example, if there's a variable declared as size 3 array of size 4 array of int:
     //   int a[3][4];
     // then the flattenedOffsetInParentArrays of a[2] would be 2.
     // and flattenedOffsetInParentArrays of a[2][1] would be 2*4 + 1 = 9.
     unsigned int flattenedOffsetInParentArrays;
 
-    // Static use means that the variable is accessed somewhere in the shader source.
     bool staticUse;
-    // A variable is active unless the compiler determined that it is not accessed by the shader.
-    // All active variables are statically used, but not all statically used variables are
-    // necessarily active. GLES 3.0.5 section 2.12.6. GLES 3.1 section 7.3.1.
-    bool active;
     std::vector<ShaderVariable> fields;
     std::string structName;
 
   protected:
     bool isSameVariableAtLinkTime(const ShaderVariable &other,
                                   bool matchPrecision,
                                   bool matchName) const;
 
@@ -279,17 +274,16 @@ struct InterfaceBlock
     BlockLayoutType layout;
 
     // Deprecated. Matrix packing should only be queried from individual fields of the block.
     // TODO(oetuaho): Remove this once it is no longer used in Chromium.
     bool isRowMajorLayout;
 
     int binding;
     bool staticUse;
-    bool active;
     BlockType blockType;
     std::vector<InterfaceBlockField> fields;
 };
 
 struct WorkGroupSize
 {
     // Must have a trivial default constructor since it is used in YYSTYPE.
     WorkGroupSize() = default;
--- a/gfx/angle/checkout/include/KHR/khrplatform.h
+++ b/gfx/angle/checkout/include/KHR/khrplatform.h
@@ -1,13 +1,13 @@
 #ifndef __khrplatform_h_
 #define __khrplatform_h_
 
 /*
-** Copyright (c) 2008-2018 The Khronos Group Inc.
+** Copyright (c) 2008-2009 The Khronos Group Inc.
 **
 ** Permission is hereby granted, free of charge, to any person obtaining a
 ** copy of this software and/or associated documentation files (the
 ** "Materials"), to deal in the Materials without restriction, including
 ** without limitation the rights to use, copy, modify, merge, publish,
 ** distribute, sublicense, and/or sell copies of the Materials, and to
 ** permit persons to whom the Materials are furnished to do so, subject to
 ** the following conditions:
@@ -21,26 +21,28 @@
 ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 */
 
 /* Khronos platform-specific types and definitions.
  *
- * The master copy of khrplatform.h is maintained in the Khronos EGL
- * Registry repository at https://github.com/KhronosGroup/EGL-Registry
- * The last semantic modification to khrplatform.h was at commit ID:
- *      67a3e0864c2d75ea5287b9f3d2eb74a745936692
+ * $Revision: 32517 $ on $Date: 2016-03-11 02:41:19 -0800 (Fri, 11 Mar 2016) $
  *
  * Adopters may modify this file to suit their platform. Adopters are
  * encouraged to submit platform specific modifications to the Khronos
  * group so that they can be included in future versions of this file.
- * Please submit changes by filing pull requests or issues on
- * the EGL Registry repository linked above.
+ * Please submit changes by sending them to the public Khronos Bugzilla
+ * (http://khronos.org/bugzilla) by filing a bug against product
+ * "Khronos (general)" component "Registry".
+ *
+ * A predefined template which fills in some of the bug fields can be
+ * reached using http://tinyurl.com/khrplatform-h-bugreport, but you
+ * must create a Bugzilla login first.
  *
  *
  * See the Implementer's Guidelines for information about where this file
  * should be located on your system and for more details of its use:
  *    http://www.khronos.org/registry/implementers_guide.pdf
  *
  * This file should be included as
  *        #include <KHR/khrplatform.h>
@@ -95,17 +97,18 @@
  *-------------------------------------------------------------------------
  * This precedes the return type of the function in the function prototype.
  */
 #if defined(_WIN32) && !defined(__SCITECH_SNAP__)
 #   define KHRONOS_APICALL __declspec(dllimport)
 #elif defined (__SYMBIAN32__)
 #   define KHRONOS_APICALL IMPORT_C
 #elif defined(__ANDROID__)
-#   define KHRONOS_APICALL __attribute__((visibility("default")))
+#   include <sys/cdefs.h>
+#   define KHRONOS_APICALL __attribute__((visibility("default"))) __NDK_FPABI__
 #else
 #   define KHRONOS_APICALL
 #endif
 
 /*-------------------------------------------------------------------------
  * Definition of KHRONOS_APIENTRY
  *-------------------------------------------------------------------------
  * This follows the return type of the function  and precedes the function
@@ -274,9 +277,9 @@ typedef khronos_int64_t        khronos_s
  * comparisons should not be made against KHRONOS_TRUE.
  */
 typedef enum {
     KHRONOS_FALSE = 0,
     KHRONOS_TRUE  = 1,
     KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
 } khronos_boolean_enum_t;
 
-#endif /* __khrplatform_h_ */
+#endif /* __khrplatform_h_ */
\ No newline at end of file
--- a/gfx/angle/checkout/out/gen/angle/id/commit.h
+++ b/gfx/angle/checkout/out/gen/angle/id/commit.h
@@ -1,3 +1,3 @@
-#define ANGLE_COMMIT_HASH "2426b097472f"
+#define ANGLE_COMMIT_HASH "fcbca0e873c3"
 #define ANGLE_COMMIT_HASH_SIZE 12
-#define ANGLE_COMMIT_DATE "2018-05-22 15:14:46 -0700"
+#define ANGLE_COMMIT_DATE "2018-04-20 16:07:35 -0700"
--- a/gfx/angle/checkout/src/common/Color.h
+++ b/gfx/angle/checkout/src/common/Color.h
@@ -10,26 +10,23 @@
 #define COMMON_COLOR_H_
 
 namespace angle
 {
 
 template <typename T>
 struct Color
 {
-    Color();
-    Color(T r, T g, T b, T a);
-
-    const T *data() const { return &red; }
-    T *ptr() { return &red; }
-
     T red;
     T green;
     T blue;
     T alpha;
+
+    Color();
+    Color(T r, T g, T b, T a);
 };
 
 template <typename T>
 bool operator==(const Color<T> &a, const Color<T> &b);
 
 template <typename T>
 bool operator!=(const Color<T> &a, const Color<T> &b);
 
deleted file mode 100644
--- a/gfx/angle/checkout/src/common/FixedVector.h
+++ /dev/null
@@ -1,331 +0,0 @@
-//
-// Copyright 2018 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// FixedVector.h:
-//   A vector class with a maximum size and fixed storage.
-//
-
-#ifndef COMMON_FIXEDVECTOR_H_
-#define COMMON_FIXEDVECTOR_H_
-
-#include "common/debug.h"
-
-#include <algorithm>
-#include <array>
-#include <initializer_list>
-
-namespace angle
-{
-template <class T, size_t N, class Storage = std::array<T, N>>
-class FixedVector final
-{
-  public:
-    using value_type             = typename Storage::value_type;
-    using size_type              = typename Storage::size_type;
-    using reference              = typename Storage::reference;
-    using const_reference        = typename Storage::const_reference;
-    using pointer                = typename Storage::pointer;
-    using const_pointer          = typename Storage::const_pointer;
-    using iterator               = typename Storage::iterator;
-    using const_iterator         = typename Storage::const_iterator;
-    using reverse_iterator       = typename Storage::reverse_iterator;
-    using const_reverse_iterator = typename Storage::const_reverse_iterator;
-
-    FixedVector();
-    FixedVector(size_type count, const value_type &value);
-    FixedVector(size_type count);
-
-    FixedVector(const FixedVector<T, N, Storage> &other);
-    FixedVector(FixedVector<T, N, Storage> &&other);
-    FixedVector(std::initializer_list<value_type> init);
-
-    FixedVector<T, N, Storage> &operator=(const FixedVector<T, N, Storage> &other);
-    FixedVector<T, N, Storage> &operator=(FixedVector<T, N, Storage> &&other);
-    FixedVector<T, N, Storage> &operator=(std::initializer_list<value_type> init);
-
-    ~FixedVector();
-
-    reference at(size_type pos);
-    const_reference at(size_type pos) const;
-
-    reference operator[](size_type pos);
-    const_reference operator[](size_type pos) const;
-
-    pointer data();
-    const_pointer data() const;
-
-    iterator begin();
-    const_iterator begin() const;
-
-    iterator end();
-    const_iterator end() const;
-
-    bool empty() const;
-    size_type size() const;
-    size_type max_size() const;
-
-    void clear();
-
-    void push_back(const value_type &value);
-    void push_back(value_type &&value);
-
-    void pop_back();
-    reference back();
-    const_reference back() const;
-
-    void swap(FixedVector<T, N, Storage> &other);
-
-    void resize(size_type count);
-    void resize(size_type count, const value_type &value);
-
-    bool full() const;
-
-  private:
-    void assign_from_initializer_list(std::initializer_list<value_type> init);
-
-    Storage mStorage;
-    size_type mSize = 0;
-};
-
-template <class T, size_t N, class Storage>
-bool operator==(const FixedVector<T, N, Storage> &a, const FixedVector<T, N, Storage> &b)
-{
-    return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin());
-}
-
-template <class T, size_t N, class Storage>
-bool operator!=(const FixedVector<T, N, Storage> &a, const FixedVector<T, N, Storage> &b)
-{
-    return !(a == b);
-}
-
-template <class T, size_t N, class Storage>
-FixedVector<T, N, Storage>::FixedVector() = default;
-
-template <class T, size_t N, class Storage>
-FixedVector<T, N, Storage>::FixedVector(size_type count, const value_type &value) : mSize(count)
-{
-    ASSERT(count <= N);
-    std::fill(mStorage.begin(), mStorage.begin() + count, value);
-}
-
-template <class T, size_t N, class Storage>
-FixedVector<T, N, Storage>::FixedVector(size_type count) : mSize(count)
-{
-    ASSERT(count <= N);
-}
-
-template <class T, size_t N, class Storage>
-FixedVector<T, N, Storage>::FixedVector(const FixedVector<T, N, Storage> &other) = default;
-
-template <class T, size_t N, class Storage>
-FixedVector<T, N, Storage>::FixedVector(FixedVector<T, N, Storage> &&other) = default;
-
-template <class T, size_t N, class Storage>
-FixedVector<T, N, Storage>::FixedVector(std::initializer_list<value_type> init)
-{
-    ASSERT(init.size() <= N);
-    assign_from_initializer_list(init);
-}
-
-template <class T, size_t N, class Storage>
-FixedVector<T, N, Storage> &FixedVector<T, N, Storage>::operator=(
-    const FixedVector<T, N, Storage> &other) = default;
-
-template <class T, size_t N, class Storage>
-FixedVector<T, N, Storage> &FixedVector<T, N, Storage>::operator=(
-    FixedVector<T, N, Storage> &&other) = default;
-
-template <class T, size_t N, class Storage>
-FixedVector<T, N, Storage> &FixedVector<T, N, Storage>::operator=(
-    std::initializer_list<value_type> init)
-{
-    clear();
-    ASSERT(init.size() <= N);
-    assign_from_initializer_list(init);
-    return this;
-}
-
-template <class T, size_t N, class Storage>
-FixedVector<T, N, Storage>::~FixedVector()
-{
-    clear();
-}
-
-template <class T, size_t N, class Storage>
-typename FixedVector<T, N, Storage>::reference FixedVector<T, N, Storage>::at(size_type pos)
-{
-    ASSERT(pos < N);
-    return mStorage.at(pos);
-}
-
-template <class T, size_t N, class Storage>
-typename FixedVector<T, N, Storage>::const_reference FixedVector<T, N, Storage>::at(
-    size_type pos) const
-{
-    ASSERT(pos < N);
-    return mStorage.at(pos);
-}
-
-template <class T, size_t N, class Storage>
-typename FixedVector<T, N, Storage>::reference FixedVector<T, N, Storage>::operator[](size_type pos)
-{
-    ASSERT(pos < N);
-    return mStorage[pos];
-}
-
-template <class T, size_t N, class Storage>
-typename FixedVector<T, N, Storage>::const_reference FixedVector<T, N, Storage>::operator[](
-    size_type pos) const
-{
-    ASSERT(pos < N);
-    return mStorage[pos];
-}
-
-template <class T, size_t N, class Storage>
-typename FixedVector<T, N, Storage>::const_pointer angle::FixedVector<T, N, Storage>::data() const
-{
-    return mStorage.data();
-}
-
-template <class T, size_t N, class Storage>
-typename FixedVector<T, N, Storage>::pointer angle::FixedVector<T, N, Storage>::data()
-{
-    return mStorage.data();
-}
-
-template <class T, size_t N, class Storage>
-typename FixedVector<T, N, Storage>::iterator FixedVector<T, N, Storage>::begin()
-{
-    return mStorage.begin();
-}
-
-template <class T, size_t N, class Storage>
-typename FixedVector<T, N, Storage>::const_iterator FixedVector<T, N, Storage>::begin() const
-{
-    return mStorage.begin();
-}
-
-template <class T, size_t N, class Storage>
-typename FixedVector<T, N, Storage>::iterator FixedVector<T, N, Storage>::end()
-{
-    return mStorage.begin() + mSize;
-}
-
-template <class T, size_t N, class Storage>
-typename FixedVector<T, N, Storage>::const_iterator FixedVector<T, N, Storage>::end() const
-{
-    return mStorage.begin() + mSize;
-}
-
-template <class T, size_t N, class Storage>
-bool FixedVector<T, N, Storage>::empty() const
-{
-    return mSize == 0;
-}
-
-template <class T, size_t N, class Storage>
-typename FixedVector<T, N, Storage>::size_type FixedVector<T, N, Storage>::size() const
-{
-    return mSize;
-}
-
-template <class T, size_t N, class Storage>
-typename FixedVector<T, N, Storage>::size_type FixedVector<T, N, Storage>::max_size() const
-{
-    return N;
-}
-
-template <class T, size_t N, class Storage>
-void FixedVector<T, N, Storage>::clear()
-{
-    resize(0);
-}
-
-template <class T, size_t N, class Storage>
-void FixedVector<T, N, Storage>::push_back(const value_type &value)
-{
-    ASSERT(mSize < N);
-    mStorage[mSize] = value;
-    mSize++;
-}
-
-template <class T, size_t N, class Storage>
-void FixedVector<T, N, Storage>::push_back(value_type &&value)
-{
-    ASSERT(mSize < N);
-    mStorage[mSize] = std::move(value);
-    mSize++;
-}
-
-template <class T, size_t N, class Storage>
-void FixedVector<T, N, Storage>::pop_back()
-{
-    ASSERT(mSize > 0);
-    mSize--;
-}
-
-template <class T, size_t N, class Storage>
-typename FixedVector<T, N, Storage>::reference FixedVector<T, N, Storage>::back()
-{
-    ASSERT(mSize > 0);
-    return mStorage[mSize - 1];
-}
-
-template <class T, size_t N, class Storage>
-typename FixedVector<T, N, Storage>::const_reference FixedVector<T, N, Storage>::back() const
-{
-    ASSERT(mSize > 0);
-    return mStorage[mSize - 1];
-}
-
-template <class T, size_t N, class Storage>
-void FixedVector<T, N, Storage>::swap(FixedVector<T, N, Storage> &other)
-{
-    std::swap(mSize, other.mSize);
-    std::swap(mStorage, other.mStorage);
-}
-
-template <class T, size_t N, class Storage>
-void FixedVector<T, N, Storage>::resize(size_type count)
-{
-    resize(count, value_type());
-}
-
-template <class T, size_t N, class Storage>
-void FixedVector<T, N, Storage>::resize(size_type count, const value_type &value)
-{
-    ASSERT(count <= N);
-    while (mSize > count)
-    {
-        mSize--;
-        mStorage[mSize] = T();
-    }
-    while (mSize < count)
-    {
-        mStorage[mSize] = value;
-        mSize++;
-    }
-}
-
-template <class T, size_t N, class Storage>
-void FixedVector<T, N, Storage>::assign_from_initializer_list(
-    std::initializer_list<value_type> init)
-{
-    for (auto element : init)
-    {
-        mStorage[mSize] = std::move(element);
-        mSize++;
-    }
-}
-
-template <class T, size_t N, class Storage>
-bool FixedVector<T, N, Storage>::full() const
-{
-    return (mSize == N);
-}
-}  // namespace angle
-
-#endif  // COMMON_FIXEDVECTOR_H_
--- a/gfx/angle/checkout/src/common/angleutils.h
+++ b/gfx/angle/checkout/src/common/angleutils.h
@@ -186,17 +186,16 @@ std::string ToString(const T &value)
     return o.str();
 }
 
 // snprintf is not defined with MSVC prior to to msvc14
 #if defined(_MSC_VER) && _MSC_VER < 1900
 #define snprintf _snprintf
 #endif
 
-#define GL_A1RGB5_ANGLEX 0x6AC5
 #define GL_BGRX8_ANGLEX 0x6ABA
 #define GL_BGR565_ANGLEX 0x6ABB
 #define GL_BGRA4_ANGLEX 0x6ABC
 #define GL_BGR5_A1_ANGLEX 0x6ABD
 #define GL_INT_64_ANGLEX 0x6ABE
 #define GL_UINT_64_ANGLEX 0x6ABF
 #define GL_BGRA8_SRGB_ANGLEX 0x6AC0
 
--- a/gfx/angle/checkout/src/common/bitset_utils.h
+++ b/gfx/angle/checkout/src/common/bitset_utils.h
@@ -35,20 +35,20 @@ class BitSetT final
             mParent->set(mBit, x);
             return *this;
         }
         explicit operator bool() const { return mParent->test(mBit); }
 
       private:
         friend class BitSetT;
 
-        Reference(BitSetT *parent, ParamT bit) : mParent(parent), mBit(bit) {}
+        Reference(BitSetT *parent, std::size_t bit) : mParent(parent), mBit(bit) {}
 
         BitSetT *mParent;
-        ParamT mBit;
+        std::size_t mBit;
     };
 
     class Iterator final
     {
       public:
         Iterator(const BitSetT &bits);
         Iterator &operator++();
 
@@ -59,17 +59,18 @@ class BitSetT final
       private:
         std::size_t getNextBit();
 
         BitSetT mBitsCopy;
         std::size_t mCurrentBit;
     };
 
     BitSetT();
-    constexpr explicit BitSetT(BitsT value);
+    BitSetT(BitsT value);
+    ~BitSetT();
 
     BitSetT(const BitSetT &other);
     BitSetT &operator=(const BitSetT &other);
 
     bool operator==(const BitSetT &other) const;
     bool operator!=(const BitSetT &other) const;
 
     constexpr bool operator[](ParamT pos) const;
@@ -84,20 +85,16 @@ class BitSetT final
 
     constexpr std::size_t size() const { return N; }
 
     BitSetT &operator&=(const BitSetT &other);
     BitSetT &operator|=(const BitSetT &other);
     BitSetT &operator^=(const BitSetT &other);
     BitSetT operator~() const;
 
-    BitSetT &operator&=(BitsT value);
-    BitSetT &operator|=(BitsT value);
-    BitSetT &operator^=(BitsT value);
-
     BitSetT operator<<(std::size_t pos) const;
     BitSetT &operator<<=(std::size_t pos);
     BitSetT operator>>(std::size_t pos) const;
     BitSetT &operator>>=(std::size_t pos);
 
     BitSetT &set();
     BitSetT &set(ParamT pos, bool value = true);
 
@@ -113,21 +110,17 @@ class BitSetT final
     Iterator begin() const { return Iterator(*this); }
     Iterator end() const { return Iterator(BitSetT()); }
 
   private:
     constexpr static BitsT Bit(ParamT x)
     {
         return (static_cast<BitsT>(1) << static_cast<size_t>(x));
     }
-    // Produces a mask of ones up to the "x"th bit.
-    constexpr static BitsT Mask(std::size_t x)
-    {
-        return ((Bit(static_cast<ParamT>(x - 1)) - 1) << 1) + 1;
-    }
+    constexpr static BitsT Mask(std::size_t x) { return ((Bit(x - 1) - 1) << 1) + 1; }
 
     BitsT mBits;
 };
 
 template <size_t N>
 class IterableBitSet : public std::bitset<N>
 {
   public:
@@ -215,17 +208,22 @@ unsigned long IterableBitSet<N>::Iterato
 template <size_t N, typename BitsT, typename ParamT>
 BitSetT<N, BitsT, ParamT>::BitSetT() : mBits(0)
 {
     static_assert(N > 0, "Bitset type cannot support zero bits.");
     static_assert(N <= sizeof(BitsT) * 8, "Bitset type cannot support a size this large.");
 }
 
 template <size_t N, typename BitsT, typename ParamT>
-constexpr BitSetT<N, BitsT, ParamT>::BitSetT(BitsT value) : mBits(value & Mask(N))
+BitSetT<N, BitsT, ParamT>::BitSetT(BitsT value) : mBits(value & Mask(N))
+{
+}
+
+template <size_t N, typename BitsT, typename ParamT>
+BitSetT<N, BitsT, ParamT>::~BitSetT()
 {
 }
 
 template <size_t N, typename BitsT, typename ParamT>
 BitSetT<N, BitsT, ParamT>::BitSetT(const BitSetT &other) : mBits(other.mBits)
 {
 }
 
@@ -310,37 +308,16 @@ BitSetT<N, BitsT, ParamT> &BitSetT<N, Bi
 
 template <size_t N, typename BitsT, typename ParamT>
 BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator~() const
 {
     return BitSetT<N, BitsT, ParamT>(~mBits & Mask(N));
 }
 
 template <size_t N, typename BitsT, typename ParamT>
-BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator&=(BitsT value)
-{
-    mBits &= value;
-    return *this;
-}
-
-template <size_t N, typename BitsT, typename ParamT>
-BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator|=(BitsT value)
-{
-    mBits |= value;
-    return *this;
-}
-
-template <size_t N, typename BitsT, typename ParamT>
-BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator^=(BitsT value)
-{
-    mBits ^= value;
-    return *this;
-}
-
-template <size_t N, typename BitsT, typename ParamT>
 BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator<<(std::size_t pos) const
 {
     return BitSetT<N, BitsT, ParamT>((mBits << pos) & Mask(N));
 }
 
 template <size_t N, typename BitsT, typename ParamT>
 BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator<<=(std::size_t pos)
 {
--- a/gfx/angle/checkout/src/common/mathutil.h
+++ b/gfx/angle/checkout/src/common/mathutil.h
@@ -4,59 +4,57 @@
 // found in the LICENSE file.
 //
 
 // mathutil.h: Math and bit manipulation functions.
 
 #ifndef COMMON_MATHUTIL_H_
 #define COMMON_MATHUTIL_H_
 
+#include <limits>
+#include <algorithm>
 #include <math.h>
+#include <string.h>
 #include <stdint.h>
 #include <stdlib.h>
-#include <string.h>
-#include <algorithm>
-#include <limits>
 
 #include <anglebase/numerics/safe_math.h>
 
 #include "common/debug.h"
 #include "common/platform.h"
 
 namespace angle
 {
 using base::CheckedNumeric;
 using base::IsValueInRangeForNumericType;
 }
 
 namespace gl
 {
 
-const unsigned int Float32One   = 0x3F800000;
+const unsigned int Float32One = 0x3F800000;
 const unsigned short Float16One = 0x3C00;
 
-template <typename T>
+template<typename T>
 inline bool isPow2(T x)
 {
     static_assert(std::is_integral<T>::value, "isPow2 must be called on an integer type.");
     return (x & (x - 1)) == 0 && (x != 0);
 }
 
 inline int log2(int x)
 {
     int r = 0;
-    while ((x >> r) > 1)
-        r++;
+    while ((x >> r) > 1) r++;
     return r;
 }
 
 inline unsigned int ceilPow2(unsigned int x)
 {
-    if (x != 0)
-        x--;
+    if (x != 0) x--;
     x |= x >> 1;
     x |= x >> 2;
     x |= x >> 4;
     x |= x >> 8;
     x |= x >> 16;
     x++;
 
     return x;
@@ -105,29 +103,29 @@ inline unsigned int clampCast(bool value
 }
 
 template <>
 inline int clampCast(bool value)
 {
     return static_cast<int>(value);
 }
 
-template <typename T, typename MIN, typename MAX>
+template<typename T, typename MIN, typename MAX>
 inline T clamp(T x, MIN min, MAX max)
 {
     // Since NaNs fail all comparison tests, a NaN value will default to min
     return x > min ? (x > max ? max : x) : min;
 }
 
 inline float clamp01(float x)
 {
     return clamp(x, 0.0f, 1.0f);
 }
 
-template <const int n>
+template<const int n>
 inline unsigned int unorm(float x)
 {
     const unsigned int max = 0xFFFFFFFF >> (32 - n);
 
     if (x > 1)
     {
         return max;
     }
@@ -139,17 +137,17 @@ inline unsigned int unorm(float x)
     {
         return (unsigned int)(max * x + 0.5f);
     }
 }
 
 inline bool supportsSSE2()
 {
 #if defined(ANGLE_USE_SSE)
-    static bool checked  = false;
+    static bool checked = false;
     static bool supports = false;
 
     if (checked)
     {
         return supports;
     }
 
 #if defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM)
@@ -179,82 +177,79 @@ destType bitCast(const sourceType &sourc
     destType output;
     memcpy(&output, &source, copySize);
     return output;
 }
 
 inline unsigned short float32ToFloat16(float fp32)
 {
     unsigned int fp32i = bitCast<unsigned int>(fp32);
-    unsigned int sign  = (fp32i & 0x80000000) >> 16;
-    unsigned int abs   = fp32i & 0x7FFFFFFF;
+    unsigned int sign = (fp32i & 0x80000000) >> 16;
+    unsigned int abs = fp32i & 0x7FFFFFFF;
 
-    if (abs > 0x47FFEFFF)  // Infinity
+    if(abs > 0x47FFEFFF)   // Infinity
     {
         return static_cast<unsigned short>(sign | 0x7FFF);
     }
-    else if (abs < 0x38800000)  // Denormal
+    else if(abs < 0x38800000)   // Denormal
     {
         unsigned int mantissa = (abs & 0x007FFFFF) | 0x00800000;
-        int e                 = 113 - (abs >> 23);
+        int e = 113 - (abs >> 23);
 
-        if (e < 24)
+        if(e < 24)
         {
             abs = mantissa >> e;
         }
         else
         {
             abs = 0;
         }
 
         return static_cast<unsigned short>(sign | (abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
     }
     else
     {
-        return static_cast<unsigned short>(
-            sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
+        return static_cast<unsigned short>(sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
     }
 }
 
 float float16ToFloat32(unsigned short h);
 
 unsigned int convertRGBFloatsTo999E5(float red, float green, float blue);
 void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float *blue);
 
 inline unsigned short float32ToFloat11(float fp32)
 {
-    const unsigned int float32MantissaMask     = 0x7FFFFF;
-    const unsigned int float32ExponentMask     = 0x7F800000;
-    const unsigned int float32SignMask         = 0x80000000;
-    const unsigned int float32ValueMask        = ~float32SignMask;
+    const unsigned int float32MantissaMask = 0x7FFFFF;
+    const unsigned int float32ExponentMask = 0x7F800000;
+    const unsigned int float32SignMask = 0x80000000;
+    const unsigned int float32ValueMask = ~float32SignMask;
     const unsigned int float32ExponentFirstBit = 23;
-    const unsigned int float32ExponentBias     = 127;
+    const unsigned int float32ExponentBias = 127;
 
-    const unsigned short float11Max          = 0x7BF;
+    const unsigned short float11Max = 0x7BF;
     const unsigned short float11MantissaMask = 0x3F;
     const unsigned short float11ExponentMask = 0x7C0;
-    const unsigned short float11BitMask      = 0x7FF;
-    const unsigned int float11ExponentBias   = 14;
+    const unsigned short float11BitMask = 0x7FF;
+    const unsigned int float11ExponentBias = 14;
 
     const unsigned int float32Maxfloat11 = 0x477E0000;
     const unsigned int float32Minfloat11 = 0x38800000;
 
     const unsigned int float32Bits = bitCast<unsigned int>(fp32);
-    const bool float32Sign         = (float32Bits & float32SignMask) == float32SignMask;
+    const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
 
     unsigned int float32Val = float32Bits & float32ValueMask;
 
     if ((float32Val & float32ExponentMask) == float32ExponentMask)
     {
         // INF or NAN
         if ((float32Val & float32MantissaMask) != 0)
         {
-            return float11ExponentMask |
-                   (((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) &
-                    float11MantissaMask);
+            return float11ExponentMask | (((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) & float11MantissaMask);
         }
         else if (float32Sign)
         {
             // -INF is clamped to 0 since float11 is positive only
             return 0;
         }
         else
         {
@@ -272,62 +267,58 @@ inline unsigned short float32ToFloat11(f
         return float11Max;
     }
     else
     {
         if (float32Val < float32Minfloat11)
         {
             // The number is too small to be represented as a normalized float11
             // Convert it to a denormalized value.
-            const unsigned int shift = (float32ExponentBias - float11ExponentBias) -
-                                       (float32Val >> float32ExponentFirstBit);
-            float32Val =
-                ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
+            const unsigned int shift = (float32ExponentBias - float11ExponentBias) - (float32Val >> float32ExponentFirstBit);
+            float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
         }
         else
         {
             // Rebias the exponent to represent the value as a normalized float11
             float32Val += 0xC8000000;
         }
 
         return ((float32Val + 0xFFFF + ((float32Val >> 17) & 1)) >> 17) & float11BitMask;
     }
 }
 
 inline unsigned short float32ToFloat10(float fp32)
 {
-    const unsigned int float32MantissaMask     = 0x7FFFFF;
-    const unsigned int float32ExponentMask     = 0x7F800000;
-    const unsigned int float32SignMask         = 0x80000000;
-    const unsigned int float32ValueMask        = ~float32SignMask;
+    const unsigned int float32MantissaMask = 0x7FFFFF;
+    const unsigned int float32ExponentMask = 0x7F800000;
+    const unsigned int float32SignMask = 0x80000000;
+    const unsigned int float32ValueMask = ~float32SignMask;
     const unsigned int float32ExponentFirstBit = 23;
-    const unsigned int float32ExponentBias     = 127;
+    const unsigned int float32ExponentBias = 127;
 
-    const unsigned short float10Max          = 0x3DF;
+    const unsigned short float10Max = 0x3DF;
     const unsigned short float10MantissaMask = 0x1F;
     const unsigned short float10ExponentMask = 0x3E0;
-    const unsigned short float10BitMask      = 0x3FF;
-    const unsigned int float10ExponentBias   = 14;
+    const unsigned short float10BitMask = 0x3FF;
+    const unsigned int float10ExponentBias = 14;
 
     const unsigned int float32Maxfloat10 = 0x477C0000;
     const unsigned int float32Minfloat10 = 0x38800000;
 
     const unsigned int float32Bits = bitCast<unsigned int>(fp32);
-    const bool float32Sign         = (float32Bits & float32SignMask) == float32SignMask;
+    const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
 
     unsigned int float32Val = float32Bits & float32ValueMask;
 
     if ((float32Val & float32ExponentMask) == float32ExponentMask)
     {
         // INF or NAN
         if ((float32Val & float32MantissaMask) != 0)
         {
-            return float10ExponentMask |
-                   (((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) &
-                    float10MantissaMask);
+            return float10ExponentMask | (((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) & float10MantissaMask);
         }
         else if (float32Sign)
         {
             // -INF is clamped to 0 since float11 is positive only
             return 0;
         }
         else
         {
@@ -345,20 +336,18 @@ inline unsigned short float32ToFloat10(f
         return float10Max;
     }
     else
     {
         if (float32Val < float32Minfloat10)
         {
             // The number is too small to be represented as a normalized float11
             // Convert it to a denormalized value.
-            const unsigned int shift = (float32ExponentBias - float10ExponentBias) -
-                                       (float32Val >> float32ExponentFirstBit);
-            float32Val =
-                ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
+            const unsigned int shift = (float32ExponentBias - float10ExponentBias) - (float32Val >> float32ExponentFirstBit);
+            float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
         }
         else
         {
             // Rebias the exponent to represent the value as a normalized float11
             float32Val += 0xC8000000;
         }
 
         return ((float32Val + 0x1FFFF + ((float32Val >> 18) & 1)) >> 18) & float10BitMask;
@@ -385,21 +374,22 @@ inline float float11ToFloat32(unsigned s
         {
             // The value is denormalized
             exponent = 1;
 
             do
             {
                 exponent--;
                 mantissa <<= 1;
-            } while ((mantissa & 0x40) == 0);
+            }
+            while ((mantissa & 0x40) == 0);
 
             mantissa = mantissa & 0x3F;
         }
-        else  // The value is zero
+        else // The value is zero
         {
             exponent = static_cast<unsigned short>(-112);
         }
 
         return bitCast<float>(((exponent + 112) << 23) | (mantissa << 17));
     }
 }
 
@@ -423,55 +413,30 @@ inline float float10ToFloat32(unsigned s
         {
             // The value is denormalized
             exponent = 1;
 
             do
             {
                 exponent--;
                 mantissa <<= 1;
-            } while ((mantissa & 0x20) == 0);
+            }
+            while ((mantissa & 0x20) == 0);
 
             mantissa = mantissa & 0x1F;
         }
-        else  // The value is zero
+        else // The value is zero
         {
             exponent = static_cast<unsigned short>(-112);
         }
 
         return bitCast<float>(((exponent + 112) << 23) | (mantissa << 18));
     }
 }
 
-// Convers to and from float and 16.16 fixed point format.
-
-inline float FixedToFloat(uint32_t fixedInput)
-{
-    return static_cast<float>(fixedInput) / 65536.0f;
-}
-
-inline uint32_t FloatToFixed(float floatInput)
-{
-    static constexpr uint32_t kHighest = 32767 * 65536 + 65535;
-    static constexpr uint32_t kLowest  = static_cast<uint32_t>(-32768 * 65536 + 65535);
-
-    if (floatInput > 32767.65535)
-    {
-        return kHighest;
-    }
-    else if (floatInput < -32768.65535)
-    {
-        return kLowest;
-    }
-    else
-    {
-        return static_cast<uint32_t>(floatInput * 65536);
-    }
-}
-
 template <typename T>
 inline float normalizedToFloat(T input)
 {
     static_assert(std::numeric_limits<T>::is_integer, "T must be an integer.");
 
     const float inverseMax = 1.0f / std::numeric_limits<T>::max();
     return input * inverseMax;
 }
@@ -593,26 +558,22 @@ inline float average(float a, float b)
 
 inline unsigned short averageHalfFloat(unsigned short a, unsigned short b)
 {
     return float32ToFloat16((float16ToFloat32(a) + float16ToFloat32(b)) * 0.5f);
 }
 
 inline unsigned int averageFloat11(unsigned int a, unsigned int b)
 {
-    return float32ToFloat11((float11ToFloat32(static_cast<unsigned short>(a)) +
-                             float11ToFloat32(static_cast<unsigned short>(b))) *
-                            0.5f);
+    return float32ToFloat11((float11ToFloat32(static_cast<unsigned short>(a)) + float11ToFloat32(static_cast<unsigned short>(b))) * 0.5f);
 }
 
 inline unsigned int averageFloat10(unsigned int a, unsigned int b)
 {
-    return float32ToFloat10((float10ToFloat32(static_cast<unsigned short>(a)) +
-                             float10ToFloat32(static_cast<unsigned short>(b))) *
-                            0.5f);
+    return float32ToFloat10((float10ToFloat32(static_cast<unsigned short>(a)) + float10ToFloat32(static_cast<unsigned short>(b))) * 0.5f);
 }
 
 template <typename T>
 class Range
 {
   public:
     Range() {}
     Range(T lo, T hi) : mLow(lo), mHigh(hi) {}
@@ -721,60 +682,60 @@ inline float Ldexp(float x, int exp)
 // Then, the results are packed into the returned 32-bit unsigned integer.
 // The first float value will be written to the least significant bits of the output;
 // the last float value will be written to the most significant bits.
 // The conversion of each value to fixed point is done as follows :
 // packSnorm2x16 : round(clamp(c, -1, +1) * 32767.0)
 inline uint32_t packSnorm2x16(float f1, float f2)
 {
     int16_t leastSignificantBits = static_cast<int16_t>(roundf(clamp(f1, -1.0f, 1.0f) * 32767.0f));
-    int16_t mostSignificantBits  = static_cast<int16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
+    int16_t mostSignificantBits = static_cast<int16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
     return static_cast<uint32_t>(mostSignificantBits) << 16 |
            (static_cast<uint32_t>(leastSignificantBits) & 0xFFFF);
 }
 
-// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then,
-// each component is converted to a normalized floating-point value to generate the returned two
-// float values. The first float value will be extracted from the least significant bits of the
-// input; the last float value will be extracted from the most-significant bits. The conversion for
-// unpacked fixed-point value to floating point is done as follows: unpackSnorm2x16 : clamp(f /
-// 32767.0, -1, +1)
+// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then, each
+// component is converted to a normalized floating-point value to generate the returned two float values.
+// The first float value will be extracted from the least significant bits of the input;
+// the last float value will be extracted from the most-significant bits.
+// The conversion for unpacked fixed-point value to floating point is done as follows:
+// unpackSnorm2x16 : clamp(f / 32767.0, -1, +1)
 inline void unpackSnorm2x16(uint32_t u, float *f1, float *f2)
 {
     int16_t leastSignificantBits = static_cast<int16_t>(u & 0xFFFF);
-    int16_t mostSignificantBits  = static_cast<int16_t>(u >> 16);
+    int16_t mostSignificantBits = static_cast<int16_t>(u >> 16);
     *f1 = clamp(static_cast<float>(leastSignificantBits) / 32767.0f, -1.0f, 1.0f);
     *f2 = clamp(static_cast<float>(mostSignificantBits) / 32767.0f, -1.0f, 1.0f);
 }
 
 // First, both normalized floating-point values are converted into 16-bit integer values.
 // Then, the results are packed into the returned 32-bit unsigned integer.
 // The first float value will be written to the least significant bits of the output;
 // the last float value will be written to the most significant bits.
 // The conversion of each value to fixed point is done as follows:
 // packUnorm2x16 : round(clamp(c, 0, +1) * 65535.0)
 inline uint32_t packUnorm2x16(float f1, float f2)
 {
     uint16_t leastSignificantBits = static_cast<uint16_t>(roundf(clamp(f1, 0.0f, 1.0f) * 65535.0f));
-    uint16_t mostSignificantBits  = static_cast<uint16_t>(roundf(clamp(f2, 0.0f, 1.0f) * 65535.0f));
-    return static_cast<uint32_t>(mostSignificantBits) << 16 |
-           static_cast<uint32_t>(leastSignificantBits);
+    uint16_t mostSignificantBits = static_cast<uint16_t>(roundf(clamp(f2, 0.0f, 1.0f) * 65535.0f));
+    return static_cast<uint32_t>(mostSignificantBits) << 16 | static_cast<uint32_t>(leastSignificantBits);
 }
 
-// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then,
-// each component is converted to a normalized floating-point value to generate the returned two
-// float values. The first float value will be extracted from the least significant bits of the
-// input; the last float value will be extracted from the most-significant bits. The conversion for
-// unpacked fixed-point value to floating point is done as follows: unpackUnorm2x16 : f / 65535.0
+// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then, each
+// component is converted to a normalized floating-point value to generate the returned two float values.
+// The first float value will be extracted from the least significant bits of the input;
+// the last float value will be extracted from the most-significant bits.
+// The conversion for unpacked fixed-point value to floating point is done as follows:
+// unpackUnorm2x16 : f / 65535.0
 inline void unpackUnorm2x16(uint32_t u, float *f1, float *f2)
 {
     uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
-    uint16_t mostSignificantBits  = static_cast<uint16_t>(u >> 16);
-    *f1                           = static_cast<float>(leastSignificantBits) / 65535.0f;
-    *f2                           = static_cast<float>(mostSignificantBits) / 65535.0f;
+    uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
+    *f1 = static_cast<float>(leastSignificantBits) / 65535.0f;
+    *f2 = static_cast<float>(mostSignificantBits) / 65535.0f;
 }
 
 // Helper functions intended to be used only here.
 namespace priv
 {
 
 inline uint8_t ToPackedUnorm8(float f)
 {
@@ -855,30 +816,29 @@ inline void UnpackSnorm4x8(uint32_t u, f
 // Returns an unsigned integer obtained by converting the two floating-point values to the 16-bit
 // floating-point representation found in the OpenGL ES Specification, and then packing these
 // two 16-bit integers into a 32-bit unsigned integer.
 // f1: The 16 least-significant bits of the result;
 // f2: The 16 most-significant bits.
 inline uint32_t packHalf2x16(float f1, float f2)
 {
     uint16_t leastSignificantBits = static_cast<uint16_t>(float32ToFloat16(f1));
-    uint16_t mostSignificantBits  = static_cast<uint16_t>(float32ToFloat16(f2));
-    return static_cast<uint32_t>(mostSignificantBits) << 16 |
-           static_cast<uint32_t>(leastSignificantBits);
+    uint16_t mostSignificantBits = static_cast<uint16_t>(float32ToFloat16(f2));
+    return static_cast<uint32_t>(mostSignificantBits) << 16 | static_cast<uint32_t>(leastSignificantBits);
 }
 
-// Returns two floating-point values obtained by unpacking a 32-bit unsigned integer into a pair of
-// 16-bit values, interpreting those values as 16-bit floating-point numbers according to the OpenGL
-// ES Specification, and converting them to 32-bit floating-point values. The first float value is
-// obtained from the 16 least-significant bits of u; the second component is obtained from the 16
-// most-significant bits of u.
+// Returns two floating-point values obtained by unpacking a 32-bit unsigned integer into a pair of 16-bit values,
+// interpreting those values as 16-bit floating-point numbers according to the OpenGL ES Specification,
+// and converting them to 32-bit floating-point values.
+// The first float value is obtained from the 16 least-significant bits of u;
+// the second component is obtained from the 16 most-significant bits of u.
 inline void unpackHalf2x16(uint32_t u, float *f1, float *f2)
 {
     uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
-    uint16_t mostSignificantBits  = static_cast<uint16_t>(u >> 16);
+    uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
 
     *f1 = float16ToFloat32(leastSignificantBits);
     *f2 = float16ToFloat32(mostSignificantBits);
 }
 
 inline uint8_t sRGBToLinear(uint8_t srgbValue)
 {
     float value = srgbValue / 255.0f;
@@ -1039,35 +999,31 @@ int FindMSB(T bits)
     }
     else
     {
         return static_cast<int>(ScanReverse(bits));
     }
 }
 
 // Returns whether the argument is Not a Number.
-// IEEE 754 single precision NaN representation: Exponent(8 bits) - 255, Mantissa(23 bits) -
-// non-zero.
+// IEEE 754 single precision NaN representation: Exponent(8 bits) - 255, Mantissa(23 bits) - non-zero.
 inline bool isNaN(float f)
 {
     // Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
     // Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
-    return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) &&
-           (bitCast<uint32_t>(f) & 0x7fffffu);
+    return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && (bitCast<uint32_t>(f) & 0x7fffffu);
 }
 
 // Returns whether the argument is infinity.
-// IEEE 754 single precision infinity representation: Exponent(8 bits) - 255, Mantissa(23 bits) -
-// zero.
+// IEEE 754 single precision infinity representation: Exponent(8 bits) - 255, Mantissa(23 bits) - zero.
 inline bool isInf(float f)
 {
     // Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
     // Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
-    return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) &&
-           !(bitCast<uint32_t>(f) & 0x7fffffu);
+    return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && !(bitCast<uint32_t>(f) & 0x7fffffu);
 }
 
 namespace priv
 {
 template <unsigned int N, unsigned int R>
 struct iSquareRoot
 {
     static constexpr unsigned int solve()
@@ -1156,30 +1112,31 @@ angle::CheckedNumeric<T> CheckedRoundUp(
 inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor)
 {
     unsigned int divided = value / divisor;
     return (divided + ((value % divisor == 0) ? 0 : 1));
 }
 
 #if defined(_MSC_VER)
 
-#define ANGLE_ROTL(x, y) _rotl(x, y)
-#define ANGLE_ROTR16(x, y) _rotr16(x, y)
+#define ANGLE_ROTL(x,y) _rotl(x,y)
+#define ANGLE_ROTR16(x,y) _rotr16(x,y)
 
 #else
 
 inline uint32_t RotL(uint32_t x, int8_t r)
 {
     return (x << r) | (x >> (32 - r));
 }
 
 inline uint16_t RotR16(uint16_t x, int8_t r)
 {
     return (x >> r) | (x << (16 - r));
 }
 
 #define ANGLE_ROTL(x, y) ::rx::RotL(x, y)
 #define ANGLE_ROTR16(x, y) ::rx::RotR16(x, y)
 
-#endif  // namespace rx
+#endif // namespace rx
+
 }
 
-#endif  // COMMON_MATHUTIL_H_
+#endif   // COMMON_MATHUTIL_H_
--- a/gfx/angle/checkout/src/common/matrix_utils.h
+++ b/gfx/angle/checkout/src/common/matrix_utils.h
@@ -89,38 +89,16 @@ class Matrix
     {
         ASSERT(columns() == m.rows());
         Matrix<T> res  = (*this) * m;
         size_t numElts = res.elements().size();
         mElements.resize(numElts);
         memcpy(mElements.data(), res.data(), numElts * sizeof(float));
     }
 
-    bool operator==(const Matrix<T> &m) const
-    {
-        ASSERT(columns() == m.columns());
-        ASSERT(rows() == m.rows());
-        return mElements == m.elements();
-    }
-
-    bool operator!=(const Matrix<T> &m) const { return !(mElements == m.elements()); }
-
-    bool nearlyEqual(T epsilon, const Matrix<T> &m) const
-    {
-        ASSERT(columns() == m.columns());
-        ASSERT(rows() == m.rows());
-        const auto &otherElts = m.elements();
-        for (size_t i = 0; i < otherElts.size(); i++)
-        {
-            if ((mElements[i] - otherElts[i] > epsilon) && (otherElts[i] - mElements[i] > epsilon))
-                return false;
-        }
-        return true;
-    }
-
     unsigned int size() const
     {
         ASSERT(rows() == columns());
         return rows();
     }
 
     unsigned int rows() const { return mRows; }
 
--- a/gfx/angle/checkout/src/common/utilities.cpp
+++ b/gfx/angle/checkout/src/common/utilities.cpp
@@ -432,16 +432,60 @@ bool IsAtomicCounterType(GLenum type)
 }
 
 bool IsOpaqueType(GLenum type)
 {
     // ESSL 3.10 section 4.1.7 defines opaque types as: samplers, images and atomic counters.
     return IsImageType(type) || IsSamplerType(type) || IsAtomicCounterType(type);
 }
 
+GLenum SamplerTypeToTextureType(GLenum samplerType)
+{
+    switch (samplerType)
+    {
+      case GL_SAMPLER_2D:
+      case GL_INT_SAMPLER_2D:
+      case GL_UNSIGNED_INT_SAMPLER_2D:
+      case GL_SAMPLER_2D_SHADOW:
+        return GL_TEXTURE_2D;
+
+      case GL_SAMPLER_EXTERNAL_OES:
+          return GL_TEXTURE_EXTERNAL_OES;
+
+      case GL_SAMPLER_CUBE:
+      case GL_INT_SAMPLER_CUBE:
+      case GL_UNSIGNED_INT_SAMPLER_CUBE:
+      case GL_SAMPLER_CUBE_SHADOW:
+        return GL_TEXTURE_CUBE_MAP;
+
+      case GL_SAMPLER_2D_ARRAY:
+      case GL_INT_SAMPLER_2D_ARRAY:
+      case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+      case GL_SAMPLER_2D_ARRAY_SHADOW:
+        return GL_TEXTURE_2D_ARRAY;
+
+      case GL_SAMPLER_3D:
+      case GL_INT_SAMPLER_3D:
+      case GL_UNSIGNED_INT_SAMPLER_3D:
+        return GL_TEXTURE_3D;
+
+      case GL_SAMPLER_2D_MULTISAMPLE:
+      case GL_INT_SAMPLER_2D_MULTISAMPLE:
+      case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+          return GL_TEXTURE_2D_MULTISAMPLE;
+
+      case GL_SAMPLER_2D_RECT_ANGLE:
+          return GL_TEXTURE_RECTANGLE_ANGLE;
+
+      default:
+        UNREACHABLE();
+        return 0;
+    }
+}
+
 bool IsMatrixType(GLenum type)
 {
     return VariableRowCount(type) > 1;
 }
 
 GLenum TransposeMatrixType(GLenum type)
 {
     if (!IsMatrixType(type))
@@ -496,16 +540,39 @@ int AllocateFirstFreeBits(unsigned int *
         }
 
         mask <<= 1;
     }
 
     return -1;
 }
 
+static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1, "Unexpected GL cube map enum value.");
+static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2, "Unexpected GL cube map enum value.");
+static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3, "Unexpected GL cube map enum value.");
+static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4, "Unexpected GL cube map enum value.");
+static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5, "Unexpected GL cube map enum value.");
+
+bool IsCubeMapTextureTarget(GLenum target)
+{
+    return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget);
+}
+
+size_t CubeMapTextureTargetToLayerIndex(GLenum target)
+{
+    ASSERT(IsCubeMapTextureTarget(target));
+    return target - static_cast<size_t>(FirstCubeMapTextureTarget);
+}
+
+GLenum LayerIndexToCubeMapTextureTarget(size_t index)
+{
+    ASSERT(index <= (LastCubeMapTextureTarget - FirstCubeMapTextureTarget));
+    return FirstCubeMapTextureTarget + static_cast<GLenum>(index);
+}
+
 IndexRange ComputeIndexRange(GLenum indexType,
                              const GLvoid *indices,
                              size_t count,
                              bool primitiveRestartEnabled)
 {
     switch (indexType)
     {
         case GL_UNSIGNED_BYTE:
@@ -924,16 +991,62 @@ const char *GetGenericErrorMessage(EGLin
             return "Unknown error.";
     }
 }
 
 }  // namespace egl
 
 namespace egl_gl
 {
+GLenum EGLCubeMapTargetToGLCubeMapTarget(EGLenum eglTarget)
+{
+    ASSERT(egl::IsCubeMapTextureTarget(eglTarget));
+    return gl::LayerIndexToCubeMapTextureTarget(egl::CubeMapTextureTargetToLayerIndex(eglTarget));
+}
+
+GLenum EGLImageTargetToGLTextureTarget(EGLenum eglTarget)
+{
+    switch (eglTarget)
+    {
+        case EGL_GL_TEXTURE_2D_KHR:
+            return GL_TEXTURE_2D;
+
+        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
+            return EGLCubeMapTargetToGLCubeMapTarget(eglTarget);
+
+        case EGL_GL_TEXTURE_3D_KHR:
+            return GL_TEXTURE_3D;
+
+        default:
+            UNREACHABLE();
+            return GL_NONE;
+    }
+}
+
+GLenum EGLTextureTargetToGLTextureTarget(EGLenum eglTarget)
+{
+    switch (eglTarget)
+    {
+        case EGL_TEXTURE_2D:
+            return GL_TEXTURE_2D;
+
+        case EGL_TEXTURE_RECTANGLE_ANGLE:
+            return GL_TEXTURE_RECTANGLE_ANGLE;
+
+        default:
+            UNREACHABLE();
+            return GL_NONE;
+    }
+}
+
 GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer)
 {
     return static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));
 }
 }  // namespace egl_gl
 
 namespace gl_egl
 {
--- a/gfx/angle/checkout/src/common/utilities.h
+++ b/gfx/angle/checkout/src/common/utilities.h
@@ -33,26 +33,33 @@ size_t VariableComponentSize(GLenum type
 size_t VariableInternalSize(GLenum type);
 size_t VariableExternalSize(GLenum type);
 int VariableRowCount(GLenum type);
 int VariableColumnCount(GLenum type);
 bool IsSamplerType(GLenum type);
 bool IsImageType(GLenum type);
 bool IsAtomicCounterType(GLenum type);
 bool IsOpaqueType(GLenum type);
+GLenum SamplerTypeToTextureType(GLenum samplerType);
 bool IsMatrixType(GLenum type);
 GLenum TransposeMatrixType(GLenum type);
 int VariableRegisterCount(GLenum type);
 int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix);
 int MatrixComponentCount(GLenum type, bool isRowMajorMatrix);
 int VariableSortOrder(GLenum type);
 GLenum VariableBoolVectorType(GLenum type);
 
 int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize);
 
+static const GLenum FirstCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+static const GLenum LastCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
+bool IsCubeMapTextureTarget(GLenum target);
+size_t CubeMapTextureTargetToLayerIndex(GLenum target);
+GLenum LayerIndexToCubeMapTextureTarget(size_t index);
+
 // Parse the base resource name and array indices. Returns the base name of the resource.
 // If the provided name doesn't index an array, the outSubscripts vector will be empty.
 // If the provided name indexes an array, the outSubscripts vector will contain indices with
 // outermost array indices in the back. If an array index is invalid, GL_INVALID_INDEX is added to
 // outSubscripts.
 std::string ParseResourceName(const std::string &name, std::vector<unsigned int> *outSubscripts);
 
 // Find the child field which matches 'fullName' == var.name + "." + field.name.
@@ -149,16 +156,19 @@ EGLenum LayerIndexToCubeMapTextureTarget
 bool IsTextureTarget(EGLenum target);
 bool IsRenderbufferTarget(EGLenum target);
 
 const char *GetGenericErrorMessage(EGLint error);
 }  // namespace egl
 
 namespace egl_gl
 {
+GLenum EGLCubeMapTargetToGLCubeMapTarget(EGLenum eglTarget);
+GLenum EGLImageTargetToGLTextureTarget(EGLenum eglTarget);
+GLenum EGLTextureTargetToGLTextureTarget(EGLenum eglTarget);
 GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer);
 }
 
 namespace gl_egl
 {
 EGLenum GLComponentTypeToEGLColorComponentType(GLenum glComponentType);
 }  // namespace gl_egl
 
--- a/gfx/angle/checkout/src/compiler/preprocessor/Tokenizer.cpp
+++ b/gfx/angle/checkout/src/compiler/preprocessor/Tokenizer.cpp
@@ -932,17 +932,16 @@ typedef pp::SourceLocation YYLTYPE;
 #define YY_USER_INIT                   \
     do {                               \
         yyfileno = 0;                  \
         yylineno = 1;                  \
         yyextra->leadingSpace = false; \
         yyextra->lineStart = true;     \
     } while(0);
 
-#define YY_NO_INPUT
 #define YY_USER_ACTION                                              \
     do                                                              \
     {                                                               \
         pp::Input* input = &yyextra->input;                         \
         pp::Input::Location* scanLoc = &yyextra->scanLoc;           \
         while ((scanLoc->sIndex < input->count()) &&                \
                (scanLoc->cIndex >= input->length(scanLoc->sIndex))) \
         {                                                           \
--- a/gfx/angle/checkout/src/compiler/preprocessor/Tokenizer.l
+++ b/gfx/angle/checkout/src/compiler/preprocessor/Tokenizer.l
@@ -59,17 +59,16 @@ typedef pp::SourceLocation YYLTYPE;
 #define YY_USER_INIT                   \
     do {                               \
         yyfileno = 0;                  \
         yylineno = 1;                  \
         yyextra->leadingSpace = false; \
         yyextra->lineStart = true;     \
     } while(0);
 
-#define YY_NO_INPUT
 #define YY_USER_ACTION                                              \
     do                                                              \
     {                                                               \
         pp::Input* input = &yyextra->input;                         \
         pp::Input::Location* scanLoc = &yyextra->scanLoc;           \
         while ((scanLoc->sIndex < input->count()) &&                \
                (scanLoc->cIndex >= input->length(scanLoc->sIndex))) \
         {                                                           \
--- a/gfx/angle/checkout/src/compiler/preprocessor/numeric_lex.h
+++ b/gfx/angle/checkout/src/compiler/preprocessor/numeric_lex.h
@@ -43,17 +43,30 @@ bool numeric_lex_int(const std::string &
 
     stream >> (*value);
     return !stream.fail();
 }
 
 template <typename FloatType>
 bool numeric_lex_float(const std::string &str, FloatType *value)
 {
-    // Some platforms have issues with the usage of std::locale and std::stringstream and cause
-    // crashes. Usage of strtod appears to be safe.
-    *value = static_cast<FloatType>(strtod(str.c_str(), nullptr));
-    return errno != ERANGE && std::isfinite(*value);
+// On 64-bit Intel Android, istringstream is broken.  Until this is fixed in
+// a newer NDK, don't use it.  Android doesn't have locale support, so this
+// doesn't have to force the C locale.
+// TODO(thakis): Remove this once this bug has been fixed in the NDK and
+// that NDK has been rolled into chromium.
+#if defined(ANGLE_PLATFORM_ANDROID) && __x86_64__
+    *value = strtod(str.c_str(), nullptr);
+    return errno != ERANGE;
+#else
+    std::istringstream stream(str);
+    // Force "C" locale so that decimal character is always '.', and
+    // not dependent on the current locale.
+    stream.imbue(std::locale::classic());
+
+    stream >> (*value);
+    return !stream.fail() && std::isfinite(*value);
+#endif
 }
 
 }  // namespace pp.
 
 #endif  // COMPILER_PREPROCESSOR_NUMERICLEX_H_
--- a/gfx/angle/checkout/src/compiler/translator/ASTMetadataHLSL.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/ASTMetadataHLSL.cpp
@@ -4,18 +4,18 @@
 // found in the LICENSE file.
 //
 
 // Analysis of the AST needed for HLSL generation
 
 #include "compiler/translator/ASTMetadataHLSL.h"
 
 #include "compiler/translator/CallDAG.h"
+#include "compiler/translator/IntermTraverse.h"
 #include "compiler/translator/SymbolTable.h"
-#include "compiler/translator/tree_util/IntermTraverse.h"
 
 namespace sh
 {
 
 namespace
 {
 
 // Class used to traverse the AST of a function definition, checking if the
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/AddAndTrueToLoopCondition.cpp
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/AddAndTrueToLoopCondition.h"
+
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
+
+namespace
+{
+
+// An AST traverser that rewrites for and while loops by replacing "condition" with
+// "condition && true" to work around condition bug on Intel Mac.
+class AddAndTrueToLoopConditionTraverser : public TIntermTraverser
+{
+  public:
+    AddAndTrueToLoopConditionTraverser() : TIntermTraverser(true, false, false) {}
+
+    bool visitLoop(Visit, TIntermLoop *loop) override
+    {
+        // do-while loop doesn't have this bug.
+        if (loop->getType() != ELoopFor && loop->getType() != ELoopWhile)
+        {
+            return true;
+        }
+
+        // For loop may not have a condition.
+        if (loop->getCondition() == nullptr)
+        {
+            return true;
+        }
+
+        // Constant true.
+        TIntermTyped *trueValue = CreateBoolNode(true);
+
+        // CONDITION && true.
+        TIntermBinary *andOp = new TIntermBinary(EOpLogicalAnd, loop->getCondition(), trueValue);
+        loop->setCondition(andOp);
+
+        return true;
+    }
+};
+
+}  // anonymous namespace
+
+void AddAndTrueToLoopCondition(TIntermNode *root)
+{
+    AddAndTrueToLoopConditionTraverser traverser;
+    root->traverse(&traverser);
+}
+
+}  // namespace sh
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/AddAndTrueToLoopCondition.h
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Rewrite condition in for and while loops to work around driver bug on Intel Mac.
+
+#ifndef COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
+#define COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
+
+class TIntermNode;
+namespace sh
+{
+
+void AddAndTrueToLoopCondition(TIntermNode *root);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/AddDefaultReturnStatements.cpp
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// AddDefaultReturnStatements.cpp: Add default return statements to functions that do not end in a
+//                                 return.
+//
+
+#include "compiler/translator/AddDefaultReturnStatements.h"
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
+
+namespace
+{
+
+bool NeedsReturnStatement(TIntermFunctionDefinition *node, TType *returnType)
+{
+    *returnType = node->getFunctionPrototype()->getType();
+    if (returnType->getBasicType() == EbtVoid)
+    {
+        return false;
+    }
+
+    TIntermBlock *bodyNode    = node->getBody();
+    TIntermBranch *returnNode = bodyNode->getSequence()->back()->getAsBranchNode();
+    if (returnNode != nullptr && returnNode->getFlowOp() == EOpReturn)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+}  // anonymous namespace
+
+void AddDefaultReturnStatements(TIntermBlock *root)
+{
+    TType returnType;
+    for (TIntermNode *node : *root->getSequence())
+    {
+        TIntermFunctionDefinition *definition = node->getAsFunctionDefinition();
+        if (definition != nullptr && NeedsReturnStatement(definition, &returnType))
+        {
+            TIntermBranch *branch = new TIntermBranch(EOpReturn, CreateZeroNode(returnType));
+
+            TIntermBlock *bodyNode = definition->getBody();
+            bodyNode->getSequence()->push_back(branch);
+        }
+    }
+}
+
+}  // namespace sh
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/AddDefaultReturnStatements.h
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// AddDefaultReturnStatements.h: Add default return statements to functions that do not end in a
+//                               return.
+//
+
+#ifndef COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
+#define COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
+
+class TIntermBlock;
+
+namespace sh
+{
+
+void AddDefaultReturnStatements(TIntermBlock *root);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
@@ -0,0 +1,244 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The ArrayReturnValueToOutParameter function changes return values of an array type to out
+// parameters in function definitions, prototypes, and call sites.
+
+#include "compiler/translator/ArrayReturnValueToOutParameter.h"
+
+#include <map>
+
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/StaticType.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+namespace
+{
+
+constexpr const ImmutableString kReturnValueVariableName("angle_return");
+
+void CopyAggregateChildren(TIntermAggregateBase *from, TIntermAggregateBase *to)
+{
+    const TIntermSequence *fromSequence = from->getSequence();
+    for (size_t ii = 0; ii < fromSequence->size(); ++ii)
+    {
+        to->getSequence()->push_back(fromSequence->at(ii));
+    }
+}
+
+class ArrayReturnValueToOutParameterTraverser : private TIntermTraverser
+{
+  public:
+    static void apply(TIntermNode *root, TSymbolTable *symbolTable);
+
+  private:
+    ArrayReturnValueToOutParameterTraverser(TSymbolTable *symbolTable);
+
+    bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
+    bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
+    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+    bool visitBranch(Visit visit, TIntermBranch *node) override;
+    bool visitBinary(Visit visit, TIntermBinary *node) override;
+
+    TIntermAggregate *createReplacementCall(TIntermAggregate *originalCall,
+                                            TIntermTyped *returnValueTarget);
+
+    // Set when traversal is inside a function with array return value.
+    TIntermFunctionDefinition *mFunctionWithArrayReturnValue;
+
+    struct ChangedFunction
+    {
+        const TVariable *returnValueVariable;
+        const TFunction *func;
+    };
+
+    // Map from function symbol ids to the changed function.
+    std::map<int, ChangedFunction> mChangedFunctions;
+};
+
+TIntermAggregate *ArrayReturnValueToOutParameterTraverser::createReplacementCall(
+    TIntermAggregate *originalCall,
+    TIntermTyped *returnValueTarget)
+{
+    TIntermSequence *replacementArguments = new TIntermSequence();
+    TIntermSequence *originalArguments    = originalCall->getSequence();
+    for (auto &arg : *originalArguments)
+    {
+        replacementArguments->push_back(arg);
+    }
+    replacementArguments->push_back(returnValueTarget);
+    ASSERT(originalCall->getFunction());
+    const TSymbolUniqueId &originalId = originalCall->getFunction()->uniqueId();
+    TIntermAggregate *replacementCall = TIntermAggregate::CreateFunctionCall(
+        *mChangedFunctions[originalId.get()].func, replacementArguments);
+    replacementCall->setLine(originalCall->getLine());
+    return replacementCall;
+}
+
+void ArrayReturnValueToOutParameterTraverser::apply(TIntermNode *root, TSymbolTable *symbolTable)
+{
+    ArrayReturnValueToOutParameterTraverser arrayReturnValueToOutParam(symbolTable);
+    root->traverse(&arrayReturnValueToOutParam);
+    arrayReturnValueToOutParam.updateTree();
+}
+
+ArrayReturnValueToOutParameterTraverser::ArrayReturnValueToOutParameterTraverser(
+    TSymbolTable *symbolTable)
+    : TIntermTraverser(true, false, true, symbolTable), mFunctionWithArrayReturnValue(nullptr)
+{
+}
+
+bool ArrayReturnValueToOutParameterTraverser::visitFunctionDefinition(
+    Visit visit,
+    TIntermFunctionDefinition *node)
+{
+    if (node->getFunctionPrototype()->isArray() && visit == PreVisit)
+    {
+        // Replacing the function header is done on visitFunctionPrototype().
+        mFunctionWithArrayReturnValue = node;
+    }
+    if (visit == PostVisit)
+    {
+        mFunctionWithArrayReturnValue = nullptr;
+    }
+    return true;
+}
+
+bool ArrayReturnValueToOutParameterTraverser::visitFunctionPrototype(Visit visit,
+                                                                     TIntermFunctionPrototype *node)
+{
+    if (visit == PreVisit && node->isArray())
+    {
+        // Replace the whole prototype node with another node that has the out parameter
+        // added. Also set the function to return void.
+        const TSymbolUniqueId &functionId = node->getFunction()->uniqueId();
+        if (mChangedFunctions.find(functionId.get()) == mChangedFunctions.end())
+        {
+            TType *returnValueVariableType = new TType(node->getType());
+            returnValueVariableType->setQualifier(EvqOut);
+            ChangedFunction changedFunction;
+            changedFunction.returnValueVariable =
+                new TVariable(mSymbolTable, kReturnValueVariableName, returnValueVariableType,
+                              SymbolType::AngleInternal);
+            TFunction *func = new TFunction(mSymbolTable, node->getFunction()->name(),
+                                            node->getFunction()->symbolType(),
+                                            StaticType::GetBasic<EbtVoid>(), false);
+            for (size_t i = 0; i < node->getFunction()->getParamCount(); ++i)
+            {
+                func->addParameter(node->getFunction()->getParam(i));
+            }
+            func->addParameter(TConstParameter(
+                kReturnValueVariableName, static_cast<const TType *>(returnValueVariableType)));
+            changedFunction.func                = func;
+            mChangedFunctions[functionId.get()] = changedFunction;
+        }
+        TIntermFunctionPrototype *replacement =
+            new TIntermFunctionPrototype(mChangedFunctions[functionId.get()].func);
+        CopyAggregateChildren(node, replacement);
+        replacement->getSequence()->push_back(
+            new TIntermSymbol(mChangedFunctions[functionId.get()].returnValueVariable));
+        replacement->setLine(node->getLine());
+
+        queueReplacement(replacement, OriginalNode::IS_DROPPED);
+    }
+    return false;
+}
+
+bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    ASSERT(!node->isArray() || node->getOp() != EOpCallInternalRawFunction);
+    if (visit == PreVisit && node->isArray() && node->getOp() == EOpCallFunctionInAST)
+    {
+        // Handle call sites where the returned array is not assigned.
+        // Examples where f() is a function returning an array:
+        // 1. f();
+        // 2. another_array == f();
+        // 3. another_function(f());
+        // 4. return f();
+        // Cases 2 to 4 are already converted to simpler cases by
+        // SeparateExpressionsReturningArrays, so we only need to worry about the case where a
+        // function call returning an array forms an expression by itself.
+        TIntermBlock *parentBlock = getParentNode()->getAsBlock();
+        if (parentBlock)
+        {
+            // replace
+            //   f();
+            // with
+            //   type s0[size]; f(s0);
+            TIntermSequence replacements;
+
+            // type s0[size];
+            TIntermDeclaration *returnValueDeclaration = nullptr;
+            TVariable *returnValue = DeclareTempVariable(mSymbolTable, new TType(node->getType()),
+                                                         EvqTemporary, &returnValueDeclaration);
+            replacements.push_back(returnValueDeclaration);
+
+            // f(s0);
+            TIntermSymbol *returnValueSymbol = CreateTempSymbolNode(returnValue);
+            replacements.push_back(createReplacementCall(node, returnValueSymbol));
+            mMultiReplacements.push_back(
+                NodeReplaceWithMultipleEntry(parentBlock, node, replacements));
+        }
+        return false;
+    }
+    return true;
+}
+
+bool ArrayReturnValueToOutParameterTraverser::visitBranch(Visit visit, TIntermBranch *node)
+{
+    if (mFunctionWithArrayReturnValue && node->getFlowOp() == EOpReturn)
+    {
+        // Instead of returning a value, assign to the out parameter and then return.
+        TIntermSequence replacements;
+
+        TIntermTyped *expression = node->getExpression();
+        ASSERT(expression != nullptr);
+        const TSymbolUniqueId &functionId =
+            mFunctionWithArrayReturnValue->getFunction()->uniqueId();
+        ASSERT(mChangedFunctions.find(functionId.get()) != mChangedFunctions.end());
+        TIntermSymbol *returnValueSymbol =
+            new TIntermSymbol(mChangedFunctions[functionId.get()].returnValueVariable);
+        TIntermBinary *replacementAssignment =
+            new TIntermBinary(EOpAssign, returnValueSymbol, expression);
+        replacementAssignment->setLine(expression->getLine());
+        replacements.push_back(replacementAssignment);
+
+        TIntermBranch *replacementBranch = new TIntermBranch(EOpReturn, nullptr);
+        replacementBranch->setLine(node->getLine());
+        replacements.push_back(replacementBranch);
+
+        mMultiReplacements.push_back(
+            NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, replacements));
+    }
+    return false;
+}
+
+bool ArrayReturnValueToOutParameterTraverser::visitBinary(Visit visit, TIntermBinary *node)
+{
+    if (node->getOp() == EOpAssign && node->getLeft()->isArray())
+    {
+        TIntermAggregate *rightAgg = node->getRight()->getAsAggregate();
+        ASSERT(rightAgg == nullptr || rightAgg->getOp() != EOpCallInternalRawFunction);
+        if (rightAgg != nullptr && rightAgg->getOp() == EOpCallFunctionInAST)
+        {
+            TIntermAggregate *replacementCall = createReplacementCall(rightAgg, node->getLeft());
+            queueReplacement(replacementCall, OriginalNode::IS_DROPPED);
+        }
+    }
+    return false;
+}
+
+}  // namespace
+
+void ArrayReturnValueToOutParameter(TIntermNode *root, TSymbolTable *symbolTable)
+{
+    ArrayReturnValueToOutParameterTraverser::apply(root, symbolTable);
+}
+
+}  // namespace sh
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/ArrayReturnValueToOutParameter.h
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The ArrayReturnValueToOutParameter function changes return values of an array type to out
+// parameters in function definitions, prototypes and call sites.
+
+#ifndef COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
+#define COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
+
+namespace sh
+{
+
+class TIntermNode;
+class TSymbolTable;
+
+void ArrayReturnValueToOutParameter(TIntermNode *root, TSymbolTable *symbolTable);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
--- a/gfx/angle/checkout/src/compiler/translator/BaseTypes.h
+++ b/gfx/angle/checkout/src/compiler/translator/BaseTypes.h
@@ -52,22 +52,28 @@ inline const char *getPrecisionString(TP
 //
 enum TBasicType
 {
     EbtVoid,
     EbtFloat,
     EbtInt,
     EbtUInt,
     EbtBool,
-
-    EbtAtomicCounter,
+    EbtGVec4,              // non type: represents vec4, ivec4, and uvec4
+    EbtGenType,            // non type: represents float, vec2, vec3, and vec4
+    EbtGenIType,           // non type: represents int, ivec2, ivec3, and ivec4
+    EbtGenUType,           // non type: represents uint, uvec2, uvec3, and uvec4
+    EbtGenBType,           // non type: represents bool, bvec2, bvec3, and bvec4
+    EbtVec,                // non type: represents vec2, vec3, and vec4
+    EbtIVec,               // non type: represents ivec2, ivec3, and ivec4
+    EbtUVec,               // non type: represents uvec2, uvec3, and uvec4
+    EbtBVec,               // non type: represents bvec2, bvec3, and bvec4
     EbtYuvCscStandardEXT,  // Only valid if EXT_YUV_target exists.
-
     EbtGuardSamplerBegin,  // non type: see implementation of IsSampler()
-    EbtSampler2D = EbtGuardSamplerBegin,
+    EbtSampler2D,
     EbtSampler3D,
     EbtSamplerCube,
     EbtSampler2DArray,
     EbtSamplerExternalOES,       // Only valid if OES_EGL_image_external exists.
     EbtSamplerExternal2DY2YEXT,  // Only valid if GL_EXT_YUV_target exists.
     EbtSampler2DRect,            // Only valid if GL_ARB_texture_rectangle exists.
     EbtSampler2DMS,
     EbtISampler2D,
@@ -78,67 +84,163 @@ enum TBasicType
     EbtUSampler2D,
     EbtUSampler3D,
     EbtUSamplerCube,
     EbtUSampler2DArray,
     EbtUSampler2DMS,
     EbtSampler2DShadow,
     EbtSamplerCubeShadow,
     EbtSampler2DArrayShadow,
-    EbtGuardSamplerEnd = EbtSampler2DArrayShadow,  // non type: see implementation of IsSampler()
+    EbtGuardSamplerEnd,  // non type: see implementation of IsSampler()
+    EbtGSampler2D,       // non type: represents sampler2D, isampler2D, and usampler2D
+    EbtGSampler3D,       // non type: represents sampler3D, isampler3D, and usampler3D
+    EbtGSamplerCube,     // non type: represents samplerCube, isamplerCube, and usamplerCube
+    EbtGSampler2DArray,  // non type: represents sampler2DArray, isampler2DArray, and
+                         // usampler2DArray
+    EbtGSampler2DMS,     // non type: represents sampler2DMS, isampler2DMS, and usampler2DMS
 
     // images
     EbtGuardImageBegin,
-    EbtImage2D = EbtGuardImageBegin,
+    EbtImage2D,
     EbtIImage2D,
     EbtUImage2D,
     EbtImage3D,
     EbtIImage3D,
     EbtUImage3D,
     EbtImage2DArray,
     EbtIImage2DArray,
     EbtUImage2DArray,
     EbtImageCube,
     EbtIImageCube,
     EbtUImageCube,
-    EbtGuardImageEnd = EbtUImageCube,
+    EbtGuardImageEnd,
 
-    EbtLastSimpleType = EbtGuardImageEnd,
+    EbtGuardGImageBegin,
+    EbtGImage2D,       // non type: represents image2D, uimage2D, iimage2D
+    EbtGImage3D,       // non type: represents image3D, uimage3D, iimage3D
+    EbtGImage2DArray,  // non type: represents image2DArray, uimage2DArray, iimage2DArray
+    EbtGImageCube,     // non type: represents imageCube, uimageCube, iimageCube
+    EbtGuardGImageEnd,
 
     EbtStruct,
     EbtInterfaceBlock,
+    EbtAddress,  // should be deprecated??
+
+    EbtAtomicCounter,
 
     // end of list
-    EbtLast = EbtInterfaceBlock
+    EbtLast
 };
 
-constexpr char GetBasicMangledName(TBasicType t)
+constexpr const char *GetBasicMangledName(TBasicType t)
 {
-    if (t > EbtLastSimpleType)
+    switch (t)
     {
-        return '{';
+        case EbtFloat:
+            return "f";
+        case EbtInt:
+            return "i";
+        case EbtUInt:
+            return "u";
+        case EbtBool:
+            return "b";
+        case EbtYuvCscStandardEXT:
+            return "ycs";
+        case EbtSampler2D:
+            return "s2";
+        case EbtSampler3D:
+            return "s3";
+        case EbtSamplerCube:
+            return "sC";
+        case EbtSampler2DArray:
+            return "s2a";
+        case EbtSamplerExternalOES:
+            return "sext";
+        case EbtSamplerExternal2DY2YEXT:
+            return "sext2y2y";
+        case EbtSampler2DRect:
+            return "s2r";
+        case EbtSampler2DMS:
+            return "s2ms";
+        case EbtISampler2D:
+            return "is2";
+        case EbtISampler3D:
+            return "is3";
+        case EbtISamplerCube:
+            return "isC";
+        case EbtISampler2DArray:
+            return "is2a";
+        case EbtISampler2DMS:
+            return "is2ms";
+        case EbtUSampler2D:
+            return "us2";
+        case EbtUSampler3D:
+            return "us3";
+        case EbtUSamplerCube:
+            return "usC";
+        case EbtUSampler2DArray:
+            return "us2a";
+        case EbtUSampler2DMS:
+            return "us2ms";
+        case EbtSampler2DShadow:
+            return "s2s";
+        case EbtSamplerCubeShadow:
+            return "sCs";
+        case EbtSampler2DArrayShadow:
+            return "s2as";
+        case EbtImage2D:
+            return "im2";
+        case EbtIImage2D:
+            return "iim2";
+        case EbtUImage2D:
+            return "uim2";
+        case EbtImage3D:
+            return "im3";
+        case EbtIImage3D:
+            return "iim3";
+        case EbtUImage3D:
+            return "uim3";
+        case EbtImage2DArray:
+            return "im2a";
+        case EbtIImage2DArray:
+            return "iim2a";
+        case EbtUImage2DArray:
+            return "uim2a";
+        case EbtImageCube:
+            return "imc";
+        case EbtIImageCube:
+            return "iimc";
+        case EbtUImageCube:
+            return "uimc";
+        case EbtAtomicCounter:
+            return "ac";
+        case EbtStruct:
+        case EbtInterfaceBlock:
+            return nullptr;
+        default:
+            // EbtVoid, EbtAddress and non types
+            return "";
     }
-    static_assert(EbtLastSimpleType < 52, "We only use alphabetic characters for mangled names");
-    if (t < 26)
-    {
-        return static_cast<char>('A' + t);
-    }
-    return static_cast<char>('a' - 26 + t);
 }
 
 const char *getBasicString(TBasicType t);
 
 inline bool IsSampler(TBasicType type)
 {
-    return type >= EbtGuardSamplerBegin && type <= EbtGuardSamplerEnd;
+    return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd;
 }
 
 inline bool IsImage(TBasicType type)
 {
-    return type >= EbtGuardImageBegin && type <= EbtGuardImageEnd;
+    return type > EbtGuardImageBegin && type < EbtGuardImageEnd;
+}
+
+inline bool IsGImage(TBasicType type)
+{
+    return type > EbtGuardGImageBegin && type < EbtGuardGImageEnd;
 }
 
 inline bool IsAtomicCounter(TBasicType type)
 {
     return type == EbtAtomicCounter;
 }
 
 inline bool IsOpaqueType(TBasicType type)
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp
@@ -0,0 +1,107 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend
+//      may record a variable as aliasing another. Sometimes the alias information gets garbled
+//      so we work around this issue by breaking the aliasing chain in inner loops.
+
+#include "BreakVariableAliasingInInnerLoops.h"
+
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/IntermTraverse.h"
+
+// A HLSL compiler developer gave us more details on the root cause and the workaround needed:
+//     The root problem is that if the HLSL compiler is applying aliasing information even on
+//     incomplete simulations (in this case, a single pass). The bug is triggered by an assignment
+//     that comes from a series of assignments, possibly with swizzled or ternary operators with
+//     known conditionals, where the source is before the loop.
+//     So, a workaround is to add a +0 term to variables the first time they are assigned to in
+//     an inner loop (if they are declared in an outside scope, otherwise there is no need).
+//     This will break the aliasing chain.
+
+// For simplicity here we add a +0 to any assignment that is in at least two nested loops. Because
+// the bug only shows up with swizzles, and ternary assignment, whole array or whole structure
+// assignment don't need a workaround.
+
+namespace sh
+{
+
+namespace
+{
+
+class AliasingBreaker : public TIntermTraverser
+{
+  public:
+    AliasingBreaker() : TIntermTraverser(true, false, true) {}
+
+  protected:
+    bool visitBinary(Visit visit, TIntermBinary *binary)
+    {
+        if (visit != PreVisit)
+        {
+            return false;
+        }
+
+        if (mLoopLevel < 2 || !binary->isAssignment())
+        {
+            return true;
+        }
+
+        TIntermTyped *B = binary->getRight();
+        TType type      = B->getType();
+
+        if (!type.isScalar() && !type.isVector() && !type.isMatrix())
+        {
+            return true;
+        }
+
+        if (type.isArray() || IsSampler(type.getBasicType()))
+        {
+            return true;
+        }
+
+        // We have a scalar / vector / matrix assignment with loop depth 2.
+        // Transform it from
+        //    A = B
+        // to
+        //    A = (B + typeof<B>(0));
+
+        TIntermBinary *bPlusZero = new TIntermBinary(EOpAdd, B, CreateZeroNode(type));
+        bPlusZero->setLine(B->getLine());
+
+        binary->replaceChildNode(B, bPlusZero);
+
+        return true;
+    }
+
+    bool visitLoop(Visit visit, TIntermLoop *loop)
+    {
+        if (visit == PreVisit)
+        {
+            mLoopLevel++;
+        }
+        else
+        {
+            ASSERT(mLoopLevel > 0);
+            mLoopLevel--;
+        }
+
+        return true;
+    }
+
+  private:
+    int mLoopLevel = 0;
+};
+
+}  // anonymous namespace
+
+void BreakVariableAliasingInInnerLoops(TIntermNode *root)
+{
+    AliasingBreaker breaker;
+    root->traverse(&breaker);
+}
+
+}  // namespace sh
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/BreakVariableAliasingInInnerLoops.h
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend
+//      may record a variable as aliasing another. Sometimes the alias information gets garbled
+//      so we work around this issue by breaking the aliasing chain in inner loops.
+
+#ifndef COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
+#define COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
+
+class TIntermNode;
+
+namespace sh
+{
+
+void BreakVariableAliasingInInnerLoops(TIntermNode *root);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
--- a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.cpp
@@ -1,77 +1,174 @@
 //
 // Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
 #include "compiler/translator/BuiltInFunctionEmulator.h"
 #include "angle_gl.h"
+#include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/SymbolTable.h"
 #include "compiler/translator/StaticType.h"
-#include "compiler/translator/Symbol.h"
-#include "compiler/translator/tree_util/IntermTraverse.h"
 
 namespace sh
 {
 
 class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser
 {
   public:
     BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator &emulator)
         : TIntermTraverser(true, false, false), mEmulator(emulator)
     {
     }
 
     bool visitUnary(Visit visit, TIntermUnary *node) override
     {
-        if (node->getFunction())
+        if (visit == PreVisit)
         {
-            bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction());
+            bool needToEmulate =
+                mEmulator.setFunctionCalled(node->getOp(), node->getOperand()->getType());
             if (needToEmulate)
                 node->setUseEmulatedFunction();
         }
         return true;
     }
 
     bool visitAggregate(Visit visit, TIntermAggregate *node) override
     {
-        // Here we handle all the built-in functions mapped to ops, not just the ones that are
-        // currently identified as problematic.
-        if (node->isConstructor() || node->isFunctionCall())
+        if (visit == PreVisit)
         {
-            return true;
+            // Here we handle all the built-in functions mapped to ops, not just the ones that are
+            // currently identified as problematic.
+            if (node->isConstructor() || node->isFunctionCall())
+            {
+                return true;
+            }
+            const TIntermSequence &sequence = *(node->getSequence());
+            bool needToEmulate              = false;
+            // Right now we only handle built-in functions with two to four parameters.
+            if (sequence.size() == 2)
+            {
+                TIntermTyped *param1 = sequence[0]->getAsTyped();
+                TIntermTyped *param2 = sequence[1]->getAsTyped();
+                if (!param1 || !param2)
+                    return true;
+                needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(),
+                                                            param2->getType());
+            }
+            else if (sequence.size() == 3)
+            {
+                TIntermTyped *param1 = sequence[0]->getAsTyped();
+                TIntermTyped *param2 = sequence[1]->getAsTyped();
+                TIntermTyped *param3 = sequence[2]->getAsTyped();
+                if (!param1 || !param2 || !param3)
+                    return true;
+                needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(),
+                                                            param2->getType(), param3->getType());
+            }
+            else if (sequence.size() == 4)
+            {
+                TIntermTyped *param1 = sequence[0]->getAsTyped();
+                TIntermTyped *param2 = sequence[1]->getAsTyped();
+                TIntermTyped *param3 = sequence[2]->getAsTyped();
+                TIntermTyped *param4 = sequence[3]->getAsTyped();
+                if (!param1 || !param2 || !param3 || !param4)
+                    return true;
+                needToEmulate =
+                    mEmulator.setFunctionCalled(node->getOp(), param1->getType(), param2->getType(),
+                                                param3->getType(), param4->getType());
+            }
+            else
+            {
+                return true;
+            }
+
+            if (needToEmulate)
+                node->setUseEmulatedFunction();
         }
-        bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction());
-        if (needToEmulate)
-            node->setUseEmulatedFunction();
         return true;
     }
 
   private:
     BuiltInFunctionEmulator &mEmulator;
 };
 
 BuiltInFunctionEmulator::BuiltInFunctionEmulator()
 {
 }
 
-void BuiltInFunctionEmulator::addEmulatedFunction(const TSymbolUniqueId &uniqueId,
-                                                  const char *emulatedFunctionDefinition)
+FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
+                                                        const TType *param,
+                                                        const char *emulatedFunctionDefinition)
+{
+    FunctionId id(op, param);
+    mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+    return id;
+}
+
+FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
+                                                        const TType *param1,
+                                                        const TType *param2,
+                                                        const char *emulatedFunctionDefinition)
 {
-    mEmulatedFunctions[uniqueId.get()] = std::string(emulatedFunctionDefinition);
+    FunctionId id(op, param1, param2);
+    mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+    return id;
+}
+
+FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
+    const FunctionId &dependency,
+    TOperator op,
+    const TType *param1,
+    const TType *param2,
+    const char *emulatedFunctionDefinition)
+{
+    FunctionId id(op, param1, param2);
+    mEmulatedFunctions[id]    = std::string(emulatedFunctionDefinition);
+    mFunctionDependencies[id] = dependency;
+    return id;
 }
 
-void BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
-    const TSymbolUniqueId &dependency,
-    const TSymbolUniqueId &uniqueId,
+FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
+                                                        const TType *param1,
+                                                        const TType *param2,
+                                                        const TType *param3,
+                                                        const char *emulatedFunctionDefinition)
+{
+    FunctionId id(op, param1, param2, param3);
+    mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+    return id;
+}
+
+FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
+                                                        const TType *param1,
+                                                        const TType *param2,
+                                                        const TType *param3,
+                                                        const TType *param4,
+                                                        const char *emulatedFunctionDefinition)
+{
+    FunctionId id(op, param1, param2, param3, param4);
+    mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+    return id;
+}
+
+FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
+    const FunctionId &dependency,
+    TOperator op,
+    const TType *param1,
+    const TType *param2,
+    const TType *param3,
+    const TType *param4,
     const char *emulatedFunctionDefinition)
 {
-    mEmulatedFunctions[uniqueId.get()]    = std::string(emulatedFunctionDefinition);
-    mFunctionDependencies[uniqueId.get()] = dependency.get();
+    FunctionId id(op, param1, param2, param3, param4);
+    mEmulatedFunctions[id]    = std::string(emulatedFunctionDefinition);
+    mFunctionDependencies[id] = dependency;
+    return id;
 }
 
 bool BuiltInFunctionEmulator::isOutputEmpty() const
 {
     return (mFunctions.size() == 0);
 }
 
 void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const
@@ -80,61 +177,86 @@ void BuiltInFunctionEmulator::outputEmul
     {
         const char *body = findEmulatedFunction(function);
         ASSERT(body);
         out << body;
         out << "\n\n";
     }
 }
 
-const char *BuiltInFunctionEmulator::findEmulatedFunction(int uniqueId) const
+bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, const TType &param)
+{
+    return setFunctionCalled(FunctionId(op, &param));
+}
+
+bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
+                                                const TType &param1,
+                                                const TType &param2)
+{
+    return setFunctionCalled(FunctionId(op, &param1, &param2));
+}
+
+bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
+                                                const TType &param1,
+                                                const TType &param2,
+                                                const TType &param3)
+{
+    return setFunctionCalled(FunctionId(op, &param1, &param2, &param3));
+}
+
+bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
+                                                const TType &param1,
+                                                const TType &param2,
+                                                const TType &param3,
+                                                const TType &param4)
+{
+    return setFunctionCalled(FunctionId(op, &param1, &param2, &param3, &param4));
+}
+
+const char *BuiltInFunctionEmulator::findEmulatedFunction(const FunctionId &functionId) const
 {
     for (const auto &queryFunction : mQueryFunctions)
     {
-        const char *result = queryFunction(uniqueId);
+        const char *result = queryFunction(functionId);
         if (result)
         {
             return result;
         }
     }
 
-    const auto &result = mEmulatedFunctions.find(uniqueId);
+    const auto &result = mEmulatedFunctions.find(functionId);
     if (result != mEmulatedFunctions.end())
     {
         return result->second.c_str();
     }
 
     return nullptr;
 }
 
-bool BuiltInFunctionEmulator::setFunctionCalled(const TFunction *function)
+bool BuiltInFunctionEmulator::setFunctionCalled(const FunctionId &functionId)
 {
-    ASSERT(function != nullptr);
-    return setFunctionCalled(function->uniqueId().get());
-}
-
-bool BuiltInFunctionEmulator::setFunctionCalled(int uniqueId)
-{
-    if (!findEmulatedFunction(uniqueId))
+    if (!findEmulatedFunction(functionId))
     {
         return false;
     }
 
     for (size_t i = 0; i < mFunctions.size(); ++i)
     {
-        if (mFunctions[i] == uniqueId)
+        if (mFunctions[i] == functionId)
             return true;
     }
     // If the function depends on another, mark the dependency as called.
-    auto dependency = mFunctionDependencies.find(uniqueId);
+    auto dependency = mFunctionDependencies.find(functionId);
     if (dependency != mFunctionDependencies.end())
     {
         setFunctionCalled((*dependency).second);
     }
-    mFunctions.push_back(uniqueId);
+    // Copy the functionId if it needs to be stored, to make sure that the TType pointers inside
+    // remain valid and constant.
+    mFunctions.push_back(functionId.getCopy());
     return true;
 }
 
 void BuiltInFunctionEmulator::markBuiltInFunctionsForEmulation(TIntermNode *root)
 {
     ASSERT(root);
 
     if (mEmulatedFunctions.empty() && mQueryFunctions.empty())
@@ -157,9 +279,81 @@ void BuiltInFunctionEmulator::addFunctio
 
 // static
 void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name)
 {
     ASSERT(name[strlen(name) - 1] != '(');
     out << name << "_emu";
 }
 
+FunctionId::FunctionId()
+    : mOp(EOpNull),
+      mParam1(StaticType::GetBasic<EbtVoid>()),
+      mParam2(StaticType::GetBasic<EbtVoid>()),
+      mParam3(StaticType::GetBasic<EbtVoid>()),
+      mParam4(StaticType::GetBasic<EbtVoid>())
+{
+}
+
+FunctionId::FunctionId(TOperator op, const TType *param)
+    : mOp(op),
+      mParam1(param),
+      mParam2(StaticType::GetBasic<EbtVoid>()),
+      mParam3(StaticType::GetBasic<EbtVoid>()),
+      mParam4(StaticType::GetBasic<EbtVoid>())
+{
+}
+
+FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2)
+    : mOp(op),
+      mParam1(param1),
+      mParam2(param2),
+      mParam3(StaticType::GetBasic<EbtVoid>()),
+      mParam4(StaticType::GetBasic<EbtVoid>())
+{
+}
+
+FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3)
+    : mOp(op),
+      mParam1(param1),
+      mParam2(param2),
+      mParam3(param3),
+      mParam4(StaticType::GetBasic<EbtVoid>())
+{
+}
+
+FunctionId::FunctionId(TOperator op,
+                       const TType *param1,
+                       const TType *param2,
+                       const TType *param3,
+                       const TType *param4)
+    : mOp(op), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(param4)
+{
+}
+
+bool FunctionId::operator==(const FunctionId &other) const
+{
+    return (mOp == other.mOp && *mParam1 == *other.mParam1 && *mParam2 == *other.mParam2 &&
+            *mParam3 == *other.mParam3 && *mParam4 == *other.mParam4);
+}
+
+bool FunctionId::operator<(const FunctionId &other) const
+{
+    if (mOp != other.mOp)
+        return mOp < other.mOp;
+    if (*mParam1 != *other.mParam1)
+        return *mParam1 < *other.mParam1;
+    if (*mParam2 != *other.mParam2)
+        return *mParam2 < *other.mParam2;
+    if (*mParam3 != *other.mParam3)
+        return *mParam3 < *other.mParam3;
+    if (*mParam4 != *other.mParam4)
+        return *mParam4 < *other.mParam4;
+    return false;  // all fields are equal
+}
+
+FunctionId FunctionId::getCopy() const
+{
+    return FunctionId(mOp, new TType(*mParam1), new TType(*mParam2), new TType(*mParam3),
+                      new TType(*mParam4));
+}
+
 }  // namespace sh
--- a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.h
+++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.h
@@ -3,25 +3,92 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
 #ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
 #define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
 
 #include "compiler/translator/InfoSink.h"
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/ParamType.h"
 
 namespace sh
 {
 
-class TIntermNode;
-class TFunction;
-class TSymbolUniqueId;
+struct MiniFunctionId
+{
+    constexpr MiniFunctionId(TOperator op         = EOpNull,
+                             ParamType paramType1 = ParamType::Void,
+                             ParamType paramType2 = ParamType::Void,
+                             ParamType paramType3 = ParamType::Void,
+                             ParamType paramType4 = ParamType::Void)
+        : op(op),
+          paramType1(paramType1),
+          paramType2(paramType2),
+          paramType3(paramType3),
+          paramType4(paramType4)
+    {
+    }
+
+    TOperator op;
+    ParamType paramType1;
+    ParamType paramType2;
+    ParamType paramType3;
+    ParamType paramType4;
+};
+
+class FunctionId final
+{
+  public:
+    FunctionId();
+    FunctionId(TOperator op, const TType *param);
+    FunctionId(TOperator op, const TType *param1, const TType *param2);
+    FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3);
+    FunctionId(TOperator op,
+               const TType *param1,
+               const TType *param2,
+               const TType *param3,
+               const TType *param4);
 
-using BuiltinQueryFunc = const char *(int);
+    FunctionId(const FunctionId &) = default;
+    FunctionId &operator=(const FunctionId &) = default;
+
+    bool operator==(const FunctionId &other) const;
+    bool operator<(const FunctionId &other) const;
+
+    FunctionId getCopy() const;
+
+  private:
+    friend bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId);
+    TOperator mOp;
+
+    // The memory that these TType objects use is freed by PoolAllocator. The
+    // BuiltInFunctionEmulator's lifetime can extend until after the memory pool is freed, but
+    // that's not an issue since this class never destructs these objects.
+    const TType *mParam1;
+    const TType *mParam2;
+    const TType *mParam3;
+    const TType *mParam4;
+};
+
+inline bool operator==(ParamType paramType, const TType *type)
+{
+    return SameParamType(paramType, type->getBasicType(), type->getNominalSize(),
+                         type->getSecondarySize());
+}
+
+inline bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId)
+{
+    return miniId.op == functionId.mOp && miniId.paramType1 == functionId.mParam1 &&
+           miniId.paramType2 == functionId.mParam2 && miniId.paramType3 == functionId.mParam3 &&
+           miniId.paramType4 == functionId.mParam4;
+}
+
+using BuiltinQueryFunc = const char *(const FunctionId &);
 
 //
 // This class decides which built-in functions need to be replaced with the emulated ones. It can be
 // used to work around driver bugs or implement functions that are not natively implemented on a
 // specific platform.
 //
 class BuiltInFunctionEmulator
 {
@@ -36,45 +103,81 @@ class BuiltInFunctionEmulator
     static void WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name);
 
     bool isOutputEmpty() const;
 
     // Output function emulation definition. This should be before any other shader source.
     void outputEmulatedFunctions(TInfoSinkBase &out) const;
 
     // Add functions that need to be emulated.
-    void addEmulatedFunction(const TSymbolUniqueId &uniqueId,
-                             const char *emulatedFunctionDefinition);
+    FunctionId addEmulatedFunction(TOperator op,
+                                   const TType *param,
+                                   const char *emulatedFunctionDefinition);
+    FunctionId addEmulatedFunction(TOperator op,
+                                   const TType *param1,
+                                   const TType *param2,
+                                   const char *emulatedFunctionDefinition);
+    FunctionId addEmulatedFunction(TOperator op,
+                                   const TType *param1,
+                                   const TType *param2,
+                                   const TType *param3,
+                                   const char *emulatedFunctionDefinition);
+    FunctionId addEmulatedFunction(TOperator op,
+                                   const TType *param1,
+                                   const TType *param2,
+                                   const TType *param3,
+                                   const TType *param4,
+                                   const char *emulatedFunctionDefinition);
 
-    void addEmulatedFunctionWithDependency(const TSymbolUniqueId &dependency,
-                                           const TSymbolUniqueId &uniqueId,
-                                           const char *emulatedFunctionDefinition);
+    FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
+                                                 TOperator op,
+                                                 const TType *param1,
+                                                 const TType *param2,
+                                                 const char *emulatedFunctionDefinition);
+    FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
+                                                 TOperator op,
+                                                 const TType *param1,
+                                                 const TType *param2,
+                                                 const TType *param3,
+                                                 const TType *param4,
+                                                 const char *emulatedFunctionDefinition);
 
     void addFunctionMap(BuiltinQueryFunc queryFunc);
 
   private:
     class BuiltInFunctionEmulationMarker;
 
     // Records that a function is called by the shader and might need to be emulated. If the
     // function is not in mEmulatedFunctions, this becomes a no-op. Returns true if the function
     // call needs to be replaced with an emulated one.
-    bool setFunctionCalled(const TFunction *function);
-    bool setFunctionCalled(int uniqueId);
+    bool setFunctionCalled(TOperator op, const TType &param);
+    bool setFunctionCalled(TOperator op, const TType &param1, const TType &param2);
+    bool setFunctionCalled(TOperator op,
+                           const TType &param1,
+                           const TType &param2,
+                           const TType &param3);
+    bool setFunctionCalled(TOperator op,
+                           const TType &param1,
+                           const TType &param2,
+                           const TType &param3,
+                           const TType &param4);
 
-    const char *findEmulatedFunction(int uniqueId) const;
+    bool setFunctionCalled(const FunctionId &functionId);
 
-    // Map from function unique id to emulated function definition
-    std::map<int, std::string> mEmulatedFunctions;
+    const char *findEmulatedFunction(const FunctionId &functionId) const;
+
+    // Map from function id to emulated function definition
+    std::map<FunctionId, std::string> mEmulatedFunctions;
 
     // Map from dependent functions to their dependencies. This structure allows each function to
     // have at most one dependency.
-    std::map<int, int> mFunctionDependencies;
+    std::map<FunctionId, FunctionId> mFunctionDependencies;
 
     // Called function ids
-    std::vector<int> mFunctions;
+    std::vector<FunctionId> mFunctions;
 
     // Constexpr function tables.
     std::vector<BuiltinQueryFunc *> mQueryFunctions;
 };
 
 }  // namespace sh
 
 #endif  // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
--- a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp
@@ -2,159 +2,178 @@
 // Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
 #include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
 #include "angle_gl.h"
 #include "compiler/translator/BuiltInFunctionEmulator.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/StaticType.h"
 #include "compiler/translator/VersionGLSL.h"
-#include "compiler/translator/tree_util/BuiltIn_autogen.h"
 
 namespace sh
 {
 
 void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
                                                       sh::GLenum shaderType)
 {
     if (shaderType == GL_VERTEX_SHADER)
     {
-        emu->addEmulatedFunction(BuiltInId::abs_Int1, "int abs_emu(int x) { return x * sign(x); }");
+        const TType *int1 = StaticType::GetBasic<EbtInt>();
+        emu->addEmulatedFunction(EOpAbs, int1, "int abs_emu(int x) { return x * sign(x); }");
     }
 }
 
 void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
                                                         int targetGLSLVersion)
 {
     // isnan() is supported since GLSL 1.3.
     if (targetGLSLVersion < GLSL_VERSION_130)
         return;
 
+    const TType *float1 = StaticType::GetBasic<EbtFloat>();
+    const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
+    const TType *float3 = StaticType::GetBasic<EbtFloat, 3>();
+    const TType *float4 = StaticType::GetBasic<EbtFloat, 4>();
+
     // !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false.
     emu->addEmulatedFunction(
-        BuiltInId::isnan_Float1,
+        EOpIsnan, float1,
         "bool isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }");
     emu->addEmulatedFunction(
-        BuiltInId::isnan_Float2,
+        EOpIsnan, float2,
         "bvec2 isnan_emu(vec2 x)\n"
         "{\n"
         "    bvec2 isnan;\n"
         "    for (int i = 0; i < 2; i++)\n"
         "    {\n"
         "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
         "    }\n"
         "    return isnan;\n"
         "}\n");
     emu->addEmulatedFunction(
-        BuiltInId::isnan_Float3,
+        EOpIsnan, float3,
         "bvec3 isnan_emu(vec3 x)\n"
         "{\n"
         "    bvec3 isnan;\n"
         "    for (int i = 0; i < 3; i++)\n"
         "    {\n"
         "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
         "    }\n"
         "    return isnan;\n"
         "}\n");
     emu->addEmulatedFunction(
-        BuiltInId::isnan_Float4,
+        EOpIsnan, float4,
         "bvec4 isnan_emu(vec4 x)\n"
         "{\n"
         "    bvec4 isnan;\n"
         "    for (int i = 0; i < 4; i++)\n"
         "    {\n"
         "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
         "    }\n"
         "    return isnan;\n"
         "}\n");
 }
 
 void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu)
 {
-    emu->addEmulatedFunction(BuiltInId::atan_Float1_Float1,
-                             "emu_precision float atan_emu(emu_precision float y, emu_precision "
-                             "float x)\n"
-                             "{\n"
-                             "    if (x > 0.0) return atan(y / x);\n"
-                             "    else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n"
-                             "    else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n"
-                             "    else return 1.57079632 * sign(y);\n"
-                             "}\n");
-    static const std::array<TSymbolUniqueId, 4> ids = {
-        BuiltInId::atan_Float1_Float1, BuiltInId::atan_Float2_Float2, BuiltInId::atan_Float3_Float3,
-        BuiltInId::atan_Float4_Float4,
+    const TType *float1 = StaticType::GetBasic<EbtFloat>();
+    auto floatFuncId    = emu->addEmulatedFunction(
+        EOpAtan, float1, float1,
+        "emu_precision float atan_emu(emu_precision float y, emu_precision "
+        "float x)\n"
+        "{\n"
+        "    if (x > 0.0) return atan(y / x);\n"
+        "    else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n"
+        "    else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n"
+        "    else return 1.57079632 * sign(y);\n"
+        "}\n");
+    static const std::array<const TType *, 5> floatVecs = {
+        nullptr,
+        nullptr,
+        StaticType::GetBasic<EbtFloat, 2>(),
+        StaticType::GetBasic<EbtFloat, 3>(),
+        StaticType::GetBasic<EbtFloat, 4>(),
     };
     for (int dim = 2; dim <= 4; ++dim)
     {
+        const TType *floatVec = floatVecs[dim];
         std::stringstream ss;
         ss << "emu_precision vec" << dim << " atan_emu(emu_precision vec" << dim
            << " y, emu_precision vec" << dim << " x)\n"
            << "{\n"
               "    return vec"
            << dim << "(";
         for (int i = 0; i < dim; ++i)
         {
             ss << "atan_emu(y[" << i << "], x[" << i << "])";
             if (i < dim - 1)
             {
                 ss << ", ";
             }
         }
         ss << ");\n"
               "}\n";
-        emu->addEmulatedFunctionWithDependency(BuiltInId::atan_Float1_Float1, ids[dim - 1],
+        emu->addEmulatedFunctionWithDependency(floatFuncId, EOpAtan, floatVec, floatVec,
                                                ss.str().c_str());
     }
 }
 
 // Emulate built-in functions missing from GLSL 1.30 and higher
 void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu,
                                                         sh::GLenum shaderType,
                                                         int targetGLSLVersion)
 {
     // Emulate packUnorm2x16 and unpackUnorm2x16 (GLSL 4.10)
     if (targetGLSLVersion < GLSL_VERSION_410)
     {
+        const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
+        const TType *uint1  = StaticType::GetBasic<EbtUInt>();
+
         // clang-format off
-        emu->addEmulatedFunction(BuiltInId::packUnorm2x16_Float2,
+        emu->addEmulatedFunction(EOpPackUnorm2x16, float2,
             "uint packUnorm2x16_emu(vec2 v)\n"
             "{\n"
             "    int x = int(round(clamp(v.x, 0.0, 1.0) * 65535.0));\n"
             "    int y = int(round(clamp(v.y, 0.0, 1.0) * 65535.0));\n"
             "    return uint((y << 16) | (x & 0xFFFF));\n"
             "}\n");
 
-        emu->addEmulatedFunction(BuiltInId::unpackUnorm2x16_UInt1,
+        emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1,
             "vec2 unpackUnorm2x16_emu(uint u)\n"
             "{\n"
             "    float x = float(u & 0xFFFFu) / 65535.0;\n"
             "    float y = float(u >> 16) / 65535.0;\n"
             "    return vec2(x, y);\n"
             "}\n");
         // clang-format on
     }
 
     // Emulate packSnorm2x16, packHalf2x16, unpackSnorm2x16, and unpackHalf2x16 (GLSL 4.20)
     // by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30).
     if (targetGLSLVersion >= GLSL_VERSION_330 && targetGLSLVersion < GLSL_VERSION_420)
     {
+        const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
+        const TType *uint1  = StaticType::GetBasic<EbtUInt>();
+
         // clang-format off
-        emu->addEmulatedFunction(BuiltInId::packSnorm2x16_Float2,
+        emu->addEmulatedFunction(EOpPackSnorm2x16, float2,
             "uint packSnorm2x16_emu(vec2 v)\n"
             "{\n"
             "    #if defined(GL_ARB_shading_language_packing)\n"
             "        return packSnorm2x16(v);\n"
             "    #else\n"
             "        int x = int(round(clamp(v.x, -1.0, 1.0) * 32767.0));\n"
             "        int y = int(round(clamp(v.y, -1.0, 1.0) * 32767.0));\n"
             "        return uint((y << 16) | (x & 0xFFFF));\n"
             "    #endif\n"
             "}\n");
-        emu->addEmulatedFunction(BuiltInId::unpackSnorm2x16_UInt1,
+        emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
             "#if !defined(GL_ARB_shading_language_packing)\n"
             "    float fromSnorm(uint x)\n"
             "    {\n"
             "        int xi = (int(x) & 0x7FFF) - (int(x) & 0x8000);\n"
             "        return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
             "    }\n"
             "#endif\n"
             "\n"
@@ -165,17 +184,17 @@ void InitBuiltInFunctionEmulatorForGLSLM
             "    #else\n"
             "        uint y = (u >> 16);\n"
             "        uint x = u;\n"
             "        return vec2(fromSnorm(x), fromSnorm(y));\n"
             "    #endif\n"
             "}\n");
         // Functions uint f32tof16(float val) and float f16tof32(uint val) are
         // based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL".
-        emu->addEmulatedFunction(BuiltInId::packHalf2x16_Float2,
+        emu->addEmulatedFunction(EOpPackHalf2x16, float2,
             "#if !defined(GL_ARB_shading_language_packing)\n"
             "    uint f32tof16(float val)\n"
             "    {\n"
             "        uint f32 = floatBitsToUint(val);\n"
             "        uint f16 = 0u;\n"
             "        uint sign = (f32 >> 16) & 0x8000u;\n"
             "        int exponent = int((f32 >> 23) & 0xFFu) - 127;\n"
             "        uint mantissa = f32 & 0x007FFFFFu;\n"
@@ -212,17 +231,17 @@ void InitBuiltInFunctionEmulatorForGLSLM
             "    #if defined(GL_ARB_shading_language_packing)\n"
             "        return packHalf2x16(v);\n"
             "    #else\n"
             "        uint x = f32tof16(v.x);\n"
             "        uint y = f32tof16(v.y);\n"
             "        return (y << 16) | x;\n"
             "    #endif\n"
             "}\n");
-        emu->addEmulatedFunction(BuiltInId::unpackHalf2x16_UInt1,
+        emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1,
             "#if !defined(GL_ARB_shading_language_packing)\n"
             "    float f16tof32(uint val)\n"
             "    {\n"
             "        uint sign = (val & 0x8000u) << 16;\n"
             "        int exponent = int((val & 0x7C00u) >> 10);\n"
             "        uint mantissa = val & 0x03FFu;\n"
             "        float f32 = 0.0;\n"
             "        if(exponent == 0)\n"
--- a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
@@ -1,131 +1,142 @@
 //
 // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
-#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
 #include "angle_gl.h"
 #include "compiler/translator/BuiltInFunctionEmulator.h"
+#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
+#include "compiler/translator/SymbolTable.h"
 #include "compiler/translator/VersionGLSL.h"
-#include "compiler/translator/tree_util/BuiltIn_autogen.h"
 
 namespace sh
 {
 
 // Defined in emulated_builtin_functions_hlsl_autogen.cpp.
-const char *FindHLSLFunction(int uniqueId);
+const char *FindHLSLFunction(const FunctionId &functionID);
 
 void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu,
                                                         int targetGLSLVersion)
 {
     if (targetGLSLVersion < GLSL_VERSION_130)
         return;
 
-    emu->addEmulatedFunction(BuiltInId::isnan_Float1,
+    TType *float1 = new TType(EbtFloat);
+    TType *float2 = new TType(EbtFloat, 2);
+    TType *float3 = new TType(EbtFloat, 3);
+    TType *float4 = new TType(EbtFloat, 4);
+
+    emu->addEmulatedFunction(EOpIsnan, float1,
                              "bool isnan_emu(float x)\n"
                              "{\n"
                              "    return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n"
                              "}\n"
                              "\n");
 
     emu->addEmulatedFunction(
-        BuiltInId::isnan_Float2,
+        EOpIsnan, float2,
         "bool2 isnan_emu(float2 x)\n"
         "{\n"
         "    bool2 isnan;\n"
         "    for (int i = 0; i < 2; i++)\n"
         "    {\n"
         "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
         "    }\n"
         "    return isnan;\n"
         "}\n");
 
     emu->addEmulatedFunction(
-        BuiltInId::isnan_Float3,
+        EOpIsnan, float3,
         "bool3 isnan_emu(float3 x)\n"
         "{\n"
         "    bool3 isnan;\n"
         "    for (int i = 0; i < 3; i++)\n"
         "    {\n"
         "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
         "    }\n"
         "    return isnan;\n"
         "}\n");
 
     emu->addEmulatedFunction(
-        BuiltInId::isnan_Float4,
+        EOpIsnan, float4,
         "bool4 isnan_emu(float4 x)\n"
         "{\n"
         "    bool4 isnan;\n"
         "    for (int i = 0; i < 4; i++)\n"
         "    {\n"
         "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
         "    }\n"
         "    return isnan;\n"
         "}\n");
 }
 
 void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
 {
+    TType *int1   = new TType(EbtInt);
+    TType *int2   = new TType(EbtInt, 2);
+    TType *int3   = new TType(EbtInt, 3);
+    TType *int4   = new TType(EbtInt, 4);
+    TType *uint1  = new TType(EbtUInt);
+    TType *uint2  = new TType(EbtUInt, 2);
+    TType *uint3  = new TType(EbtUInt, 3);
+    TType *uint4  = new TType(EbtUInt, 4);
+
     emu->addFunctionMap(FindHLSLFunction);
 
     // (a + b2^16) * (c + d2^16) = ac + (ad + bc) * 2^16 + bd * 2^32
     // Also note that below, a * d + ((a * c) >> 16) is guaranteed not to overflow, because:
     // a <= 0xffff, d <= 0xffff, ((a * c) >> 16) <= 0xffff and 0xffff * 0xffff + 0xffff = 0xffff0000
-    emu->addEmulatedFunction(BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
-                             "void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n"
-                             "{\n"
-                             "    lsb = x * y;\n"
-                             "    uint a = (x & 0xffffu);\n"
-                             "    uint b = (x >> 16);\n"
-                             "    uint c = (y & 0xffffu);\n"
-                             "    uint d = (y >> 16);\n"
-                             "    uint ad = a * d + ((a * c) >> 16);\n"
-                             "    uint bc = b * c;\n"
-                             "    uint carry = uint(ad > (0xffffffffu - bc));\n"
-                             "    msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n"
-                             "}\n");
+    FunctionId umulExtendedUint1 = emu->addEmulatedFunction(
+        EOpUmulExtended, uint1, uint1, uint1, uint1,
+        "void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n"
+        "{\n"
+        "    lsb = x * y;\n"
+        "    uint a = (x & 0xffffu);\n"
+        "    uint b = (x >> 16);\n"
+        "    uint c = (y & 0xffffu);\n"
+        "    uint d = (y >> 16);\n"
+        "    uint ad = a * d + ((a * c) >> 16);\n"
+        "    uint bc = b * c;\n"
+        "    uint carry = uint(ad > (0xffffffffu - bc));\n"
+        "    msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n"
+        "}\n");
     emu->addEmulatedFunctionWithDependency(
-        BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
-        BuiltInId::umulExtended_UInt2_UInt2_UInt2_UInt2,
+        umulExtendedUint1, EOpUmulExtended, uint2, uint2, uint2, uint2,
         "void umulExtended_emu(uint2 x, uint2 y, out uint2 msb, out uint2 lsb)\n"
         "{\n"
         "    umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
         "    umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
         "}\n");
     emu->addEmulatedFunctionWithDependency(
-        BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
-        BuiltInId::umulExtended_UInt3_UInt3_UInt3_UInt3,
+        umulExtendedUint1, EOpUmulExtended, uint3, uint3, uint3, uint3,
         "void umulExtended_emu(uint3 x, uint3 y, out uint3 msb, out uint3 lsb)\n"
         "{\n"
         "    umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
         "    umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
         "    umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
         "}\n");
     emu->addEmulatedFunctionWithDependency(
-        BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
-        BuiltInId::umulExtended_UInt4_UInt4_UInt4_UInt4,
+        umulExtendedUint1, EOpUmulExtended, uint4, uint4, uint4, uint4,
         "void umulExtended_emu(uint4 x, uint4 y, out uint4 msb, out uint4 lsb)\n"
         "{\n"
         "    umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
         "    umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
         "    umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
         "    umulExtended_emu(x.w, y.w, msb.w, lsb.w);\n"
         "}\n");
 
     // The imul emulation does two's complement negation on the lsb and msb manually in case the
     // result needs to be negative.
     // TODO(oetuaho): Note that this code doesn't take one edge case into account, where x or y is
     // -2^31. abs(-2^31) is undefined.
-    emu->addEmulatedFunctionWithDependency(
-        BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
-        BuiltInId::imulExtended_Int1_Int1_Int1_Int1,
+    FunctionId imulExtendedInt1 = emu->addEmulatedFunctionWithDependency(
+        umulExtendedUint1, EOpImulExtended, int1, int1, int1, int1,
         "void imulExtended_emu(int x, int y, out int msb, out int lsb)\n"
         "{\n"
         "    uint unsignedMsb;\n"
         "    uint unsignedLsb;\n"
         "    bool negative = (x < 0) != (y < 0);\n"
         "    umulExtended_emu(uint(abs(x)), uint(abs(y)), unsignedMsb, unsignedLsb);\n"
         "    lsb = asint(unsignedLsb);\n"
         "    msb = asint(unsignedMsb);\n"
@@ -140,32 +151,32 @@ void InitBuiltInFunctionEmulatorForHLSL(
         "        }\n"
         "        else\n"
         "        {\n"
         "            lsb += 1;\n"
         "        }\n"
         "    }\n"
         "}\n");
     emu->addEmulatedFunctionWithDependency(
-        BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int2_Int2_Int2_Int2,
+        imulExtendedInt1, EOpImulExtended, int2, int2, int2, int2,
         "void imulExtended_emu(int2 x, int2 y, out int2 msb, out int2 lsb)\n"
         "{\n"
         "    imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
         "    imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
         "}\n");
     emu->addEmulatedFunctionWithDependency(
-        BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int3_Int3_Int3_Int3,
+        imulExtendedInt1, EOpImulExtended, int3, int3, int3, int3,
         "void imulExtended_emu(int3 x, int3 y, out int3 msb, out int3 lsb)\n"
         "{\n"
         "    imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
         "    imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
         "    imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
         "}\n");
     emu->addEmulatedFunctionWithDependency(
-        BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int4_Int4_Int4_Int4,
+        imulExtendedInt1, EOpImulExtended, int4, int4, int4, int4,
         "void imulExtended_emu(int4 x, int4 y, out int4 msb, out int4 lsb)\n"
         "{\n"
         "    imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
         "    imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
         "    imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
         "    imulExtended_emu(x.w, y.w, msb.w, lsb.w);\n"
         "}\n");
 }
--- a/gfx/angle/checkout/src/compiler/translator/CallDAG.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/CallDAG.cpp
@@ -6,18 +6,18 @@
 
 // CallDAG.h: Implements a call graph DAG of functions to be re-used accross
 // analyses, allows to efficiently traverse the functions in topological
 // order.
 
 #include "compiler/translator/CallDAG.h"
 
 #include "compiler/translator/Diagnostics.h"
+#include "compiler/translator/IntermTraverse.h"
 #include "compiler/translator/SymbolTable.h"
-#include "compiler/translator/tree_util/IntermTraverse.h"
 
 namespace sh
 {
 
 // The CallDAGCreator does all the processing required to create the CallDAG
 // structure so that the latter contains only the necessary variables.
 class CallDAG::CallDAGCreator : public TIntermTraverser
 {
@@ -111,23 +111,26 @@ class CallDAG::CallDAGCreator : public T
         mCurrentFunction->name           = node->getFunction()->name();
         mCurrentFunction->definitionNode = node;
 
         node->getBody()->traverse(this);
         mCurrentFunction = nullptr;
         return false;
     }
 
-    void visitFunctionPrototype(TIntermFunctionPrototype *node) override
+    bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override
     {
         ASSERT(mCurrentFunction == nullptr);
 
         // Function declaration, create an empty record.
         auto &record = mFunctions[node->getFunction()->uniqueId().get()];
         record.name  = node->getFunction()->name();
+
+        // No need to traverse the parameters.
+        return false;
     }
 
     // Track functions called from another function.
     bool visitAggregate(Visit visit, TIntermAggregate *node) override
     {
         if (node->getOp() == EOpCallFunctionInAST)
         {
             // Function call, add the callees
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/ClampFragDepth.cpp
@@ -0,0 +1,54 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ClampFragDepth.cpp: Limit the value that is written to gl_FragDepth to the range [0.0, 1.0].
+// The clamping is run at the very end of shader execution, and is only performed if the shader
+// statically accesses gl_FragDepth.
+//
+
+#include "compiler/translator/ClampFragDepth.h"
+
+#include "compiler/translator/FindSymbolNode.h"
+#include "compiler/translator/ImmutableString.h"
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/RunAtTheEndOfShader.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+void ClampFragDepth(TIntermBlock *root, TSymbolTable *symbolTable)
+{
+    // Only clamp gl_FragDepth if it's used in the shader.
+    if (!FindSymbolNode(root, ImmutableString("gl_FragDepth")))
+    {
+        return;
+    }
+
+    TIntermSymbol *fragDepthNode =
+        ReferenceBuiltInVariable(ImmutableString("gl_FragDepth"), *symbolTable, 300);
+
+    TIntermTyped *minFragDepthNode = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
+
+    TConstantUnion *maxFragDepthConstant = new TConstantUnion();
+    maxFragDepthConstant->setFConst(1.0);
+    TIntermConstantUnion *maxFragDepthNode =
+        new TIntermConstantUnion(maxFragDepthConstant, TType(EbtFloat, EbpHigh, EvqConst));
+
+    // clamp(gl_FragDepth, 0.0, 1.0)
+    TIntermSequence *clampArguments = new TIntermSequence();
+    clampArguments->push_back(fragDepthNode->deepCopy());
+    clampArguments->push_back(minFragDepthNode);
+    clampArguments->push_back(maxFragDepthNode);
+    TIntermTyped *clampedFragDepth =
+        CreateBuiltInFunctionCallNode("clamp", clampArguments, *symbolTable, 100);
+
+    // gl_FragDepth = clamp(gl_FragDepth, 0.0, 1.0)
+    TIntermBinary *assignFragDepth = new TIntermBinary(EOpAssign, fragDepthNode, clampedFragDepth);
+
+    RunAtTheEndOfShader(root, assignFragDepth, symbolTable);
+}
+
+}  // namespace sh
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/ClampFragDepth.h
@@ -0,0 +1,24 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ClampFragDepth.h: Limit the value that is written to gl_FragDepth to the range [0.0, 1.0].
+// The clamping is run at the very end of shader execution, and is only performed if the shader
+// statically accesses gl_FragDepth.
+//
+
+#ifndef COMPILER_TRANSLATOR_CLAMPFRAGDEPTH_H_
+#define COMPILER_TRANSLATOR_CLAMPFRAGDEPTH_H_
+
+namespace sh
+{
+
+class TIntermBlock;
+class TSymbolTable;
+
+void ClampFragDepth(TIntermBlock *root, TSymbolTable *symbolTable);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_CLAMPFRAGDEPTH_H_
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/ClampPointSize.cpp
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ClampPointSize.cpp: Limit the value that is written to gl_PointSize.
+//
+
+#include "compiler/translator/ClampPointSize.h"
+
+#include "compiler/translator/FindSymbolNode.h"
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/RunAtTheEndOfShader.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+void ClampPointSize(TIntermBlock *root, float maxPointSize, TSymbolTable *symbolTable)
+{
+    // Only clamp gl_PointSize if it's used in the shader.
+    if (!FindSymbolNode(root, ImmutableString("gl_PointSize")))
+    {
+        return;
+    }
+
+    TIntermSymbol *pointSizeNode =
+        ReferenceBuiltInVariable(ImmutableString("gl_PointSize"), *symbolTable, 100);
+
+    TConstantUnion *maxPointSizeConstant = new TConstantUnion();
+    maxPointSizeConstant->setFConst(maxPointSize);
+    TIntermConstantUnion *maxPointSizeNode =
+        new TIntermConstantUnion(maxPointSizeConstant, TType(EbtFloat, EbpHigh, EvqConst));
+
+    // min(gl_PointSize, maxPointSize)
+    TIntermSequence *minArguments = new TIntermSequence();
+    minArguments->push_back(pointSizeNode->deepCopy());
+    minArguments->push_back(maxPointSizeNode);
+    TIntermTyped *clampedPointSize =
+        CreateBuiltInFunctionCallNode("min", minArguments, *symbolTable, 100);
+
+    // gl_PointSize = min(gl_PointSize, maxPointSize)
+    TIntermBinary *assignPointSize = new TIntermBinary(EOpAssign, pointSizeNode, clampedPointSize);
+
+    RunAtTheEndOfShader(root, assignPointSize, symbolTable);
+}
+
+}  // namespace sh
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/ClampPointSize.h
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ClampPointSize.h: Limit the value that is written to gl_PointSize.
+//
+
+#ifndef COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_
+#define COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_
+
+namespace sh
+{
+
+class TIntermBlock;
+class TSymbolTable;
+
+void ClampPointSize(TIntermBlock *root, float maxPointSize, TSymbolTable *symbolTable);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_
--- a/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp
@@ -5,18 +5,18 @@
 //
 // CollectVariables.cpp: Collect lists of shader interface variables based on the AST.
 
 #include "compiler/translator/CollectVariables.h"
 
 #include "angle_gl.h"
 #include "common/utilities.h"
 #include "compiler/translator/HashNames.h"
+#include "compiler/translator/IntermTraverse.h"
 #include "compiler/translator/SymbolTable.h"
-#include "compiler/translator/tree_util/IntermTraverse.h"
 #include "compiler/translator/util.h"
 
 namespace sh
 {
 
 namespace
 {
 
@@ -63,46 +63,44 @@ VarT *FindVariable(const ImmutableString
     {
         if (name == (*infoList)[ii].name)
             return &((*infoList)[ii]);
     }
 
     return nullptr;
 }
 
-// Note that this shouldn't be called for interface blocks - active information is collected for
+// Note that this shouldn't be called for interface blocks - static use information is collected for
 // individual fields in case of interface blocks.
-void MarkActive(ShaderVariable *variable)
+void MarkStaticallyUsed(ShaderVariable *variable)
 {
-    if (!variable->active)
+    if (!variable->staticUse)
     {
         if (variable->isStruct())
         {
             // Conservatively assume all fields are statically used as well.
             for (auto &field : variable->fields)
             {
-                MarkActive(&field);
+                MarkStaticallyUsed(&field);
             }
         }
-        ASSERT(variable->staticUse);
-        variable->active    = true;
+        variable->staticUse = true;
     }
 }
 
 ShaderVariable *FindVariableInInterfaceBlock(const ImmutableString &name,
                                              const TInterfaceBlock *interfaceBlock,
                                              std::vector<InterfaceBlock> *infoList)
 {
     ASSERT(interfaceBlock);
     InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), infoList);
     ASSERT(namedBlock);
 
     // Set static use on the parent interface block here
     namedBlock->staticUse = true;
-    namedBlock->active    = true;
     return FindVariable(name, &namedBlock->fields);
 }
 
 // Traverses the intermediate tree to collect all attributes, uniforms, varyings, fragment outputs,
 // and interface blocks.
 class CollectVariablesTraverser : public TIntermTraverser
 {
   public:
@@ -111,53 +109,50 @@ class CollectVariablesTraverser : public
                               std::vector<Uniform> *uniforms,
                               std::vector<Varying> *inputVaryings,
                               std::vector<Varying> *outputVaryings,
                               std::vector<InterfaceBlock> *uniformBlocks,
                               std::vector<InterfaceBlock> *shaderStorageBlocks,
                               std::vector<InterfaceBlock> *inBlocks,
                               ShHashFunction64 hashFunction,
                               TSymbolTable *symbolTable,
+                              int shaderVersion,
                               GLenum shaderType,
                               const TExtensionBehavior &extensionBehavior);
 
-    bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
     void visitSymbol(TIntermSymbol *symbol) override;
     bool visitDeclaration(Visit, TIntermDeclaration *node) override;
     bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
 
   private:
     std::string getMappedName(const TSymbol *symbol) const;
 
-    void setFieldOrVariableProperties(const TType &type,
-                                      bool staticUse,
-                                      ShaderVariable *variableOut) const;
+    void setFieldOrVariableProperties(const TType &type, ShaderVariable *variableOut) const;
     void setFieldProperties(const TType &type,
                             const ImmutableString &name,
-                            bool staticUse,
                             ShaderVariable *variableOut) const;
     void setCommonVariableProperties(const TType &type,
                                      const TVariable &variable,
                                      ShaderVariable *variableOut) const;
 
     Attribute recordAttribute(const TIntermSymbol &variable) const;
     OutputVariable recordOutputVariable(const TIntermSymbol &variable) const;
     Varying recordVarying(const TIntermSymbol &variable) const;
     void recordInterfaceBlock(const char *instanceName,
                               const TType &interfaceBlockType,
                               InterfaceBlock *interfaceBlock) const;
     Uniform recordUniform(const TIntermSymbol &variable) const;
 
-    void setBuiltInInfoFromSymbol(const TVariable &variable, ShaderVariable *info);
+    void setBuiltInInfoFromSymbolTable(const ImmutableString &name, ShaderVariable *info);
 
-    void recordBuiltInVaryingUsed(const TVariable &variable,
+    void recordBuiltInVaryingUsed(const ImmutableString &name,
                                   bool *addedFlag,
                                   std::vector<Varying> *varyings);
-    void recordBuiltInFragmentOutputUsed(const TVariable &variable, bool *addedFlag);
-    void recordBuiltInAttributeUsed(const TVariable &variable, bool *addedFlag);
+    void recordBuiltInFragmentOutputUsed(const ImmutableString &name, bool *addedFlag);
+    void recordBuiltInAttributeUsed(const ImmutableString &name, bool *addedFlag);
     InterfaceBlock *recordGLInUsed(const TType &glInType);
     InterfaceBlock *findNamedInterfaceBlock(const ImmutableString &name) const;
 
     std::vector<Attribute> *mAttribs;
     std::vector<OutputVariable> *mOutputVariables;
     std::vector<Uniform> *mUniforms;
     std::vector<Varying> *mInputVaryings;
     std::vector<Varying> *mOutputVaryings;
@@ -196,31 +191,33 @@ class CollectVariablesTraverser : public
     bool mInvocationIDAdded;
 
     // Geometry Shader and Fragment Shader builtins
     bool mPrimitiveIDAdded;
     bool mLayerAdded;
 
     ShHashFunction64 mHashFunction;
 
+    int mShaderVersion;
     GLenum mShaderType;
     const TExtensionBehavior &mExtensionBehavior;
 };
 
 CollectVariablesTraverser::CollectVariablesTraverser(
     std::vector<sh::Attribute> *attribs,
     std::vector<sh::OutputVariable> *outputVariables,
     std::vector<sh::Uniform> *uniforms,
     std::vector<sh::Varying> *inputVaryings,
     std::vector<sh::Varying> *outputVaryings,
     std::vector<sh::InterfaceBlock> *uniformBlocks,
     std::vector<sh::InterfaceBlock> *shaderStorageBlocks,
     std::vector<sh::InterfaceBlock> *inBlocks,
     ShHashFunction64 hashFunction,
     TSymbolTable *symbolTable,
+    int shaderVersion,
     GLenum shaderType,
     const TExtensionBehavior &extensionBehavior)
     : TIntermTraverser(true, false, false, symbolTable),
       mAttribs(attribs),
       mOutputVariables(outputVariables),
       mUniforms(uniforms),
       mInputVaryings(inputVaryings),
       mOutputVaryings(outputVaryings),
@@ -243,116 +240,112 @@ CollectVariablesTraverser::CollectVariab
       mSecondaryFragColorEXTAdded(false),
       mSecondaryFragDataEXTAdded(false),
       mPerVertexInAdded(false),
       mPrimitiveIDInAdded(false),
       mInvocationIDAdded(false),
       mPrimitiveIDAdded(false),
       mLayerAdded(false),
       mHashFunction(hashFunction),
+      mShaderVersion(shaderVersion),
       mShaderType(shaderType),
       mExtensionBehavior(extensionBehavior)
 {
 }
 
 std::string CollectVariablesTraverser::getMappedName(const TSymbol *symbol) const
 {
     return HashName(symbol, mHashFunction, nullptr).data();
 }
 
-void CollectVariablesTraverser::setBuiltInInfoFromSymbol(const TVariable &variable,
-                                                         ShaderVariable *info)
+void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const ImmutableString &name,
+                                                              ShaderVariable *info)
 {
-    const TType &type = variable.getType();
+    const TVariable *symbolTableVar =
+        reinterpret_cast<const TVariable *>(mSymbolTable->findBuiltIn(name, mShaderVersion));
+    ASSERT(symbolTableVar);
+    const TType &type = symbolTableVar->getType();
 
-    info->name       = variable.name().data();
-    info->mappedName = variable.name().data();
+    info->name       = name.data();
+    info->mappedName = name.data();
     info->type       = GLVariableType(type);
     info->precision = GLVariablePrecision(type);
     if (auto *arraySizes = type.getArraySizes())
     {
         info->arraySizes.assign(arraySizes->begin(), arraySizes->end());
     }
 }
 
-void CollectVariablesTraverser::recordBuiltInVaryingUsed(const TVariable &variable,
+void CollectVariablesTraverser::recordBuiltInVaryingUsed(const ImmutableString &name,
                                                          bool *addedFlag,
                                                          std::vector<Varying> *varyings)
 {
     ASSERT(varyings);
     if (!(*addedFlag))
     {
         Varying info;
-        setBuiltInInfoFromSymbol(variable, &info);
+        setBuiltInInfoFromSymbolTable(name, &info);
         info.staticUse   = true;
-        info.active      = true;
-        info.isInvariant = mSymbolTable->isVaryingInvariant(variable.name());
+        info.isInvariant = mSymbolTable->isVaryingInvariant(name);
         varyings->push_back(info);
         (*addedFlag) = true;
     }
 }
 
-void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const TVariable &variable,
+void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const ImmutableString &name,
                                                                 bool *addedFlag)
 {
     if (!(*addedFlag))
     {
         OutputVariable info;
-        setBuiltInInfoFromSymbol(variable, &info);
+        setBuiltInInfoFromSymbolTable(name, &info);
         info.staticUse = true;
-        info.active    = true;
         mOutputVariables->push_back(info);
         (*addedFlag) = true;
     }
 }
 
-void CollectVariablesTraverser::recordBuiltInAttributeUsed(const TVariable &variable,
+void CollectVariablesTraverser::recordBuiltInAttributeUsed(const ImmutableString &name,
                                                            bool *addedFlag)
 {
     if (!(*addedFlag))
     {
         Attribute info;
-        setBuiltInInfoFromSymbol(variable, &info);
+        setBuiltInInfoFromSymbolTable(name, &info);
         info.staticUse = true;
-        info.active    = true;
         info.location  = -1;
         mAttribs->push_back(info);
         (*addedFlag) = true;
     }
 }
 
 InterfaceBlock *CollectVariablesTraverser::recordGLInUsed(const TType &glInType)
 {
     if (!mPerVertexInAdded)
     {
         ASSERT(glInType.getQualifier() == EvqPerVertexIn);
         InterfaceBlock info;
         recordInterfaceBlock("gl_in", glInType, &info);
+        info.staticUse = true;
 
         mPerVertexInAdded = true;
         mInBlocks->push_back(info);
         return &mInBlocks->back();
     }
     else
     {
         return FindVariable(ImmutableString("gl_PerVertex"), mInBlocks);
     }
 }
 
-bool CollectVariablesTraverser::visitInvariantDeclaration(Visit visit,
-                                                          TIntermInvariantDeclaration *node)
-{
-    // We should not mark variables as active just based on an invariant declaration, so we don't
-    // traverse the symbols declared invariant.
-    return false;
-}
-
-// We want to check whether a uniform/varying is active because we need to skip updating inactive
-// ones. We also only count the active ones in packing computing. Also, gl_FragCoord, gl_PointCoord,
-// and gl_FrontFacing count toward varying counting if they are active in a fragment shader.
+// We want to check whether a uniform/varying is statically used
+// because we only count the used ones in packing computing.
+// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
+// toward varying counting if they are statically used in a fragment
+// shader.
 void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
 {
     ASSERT(symbol != nullptr);
 
     if (symbol->variable().symbolType() == SymbolType::AngleInternal ||
         symbol->variable().symbolType() == SymbolType::Empty)
     {
         // Internal variables or nameless variables are not collected.
@@ -387,41 +380,37 @@ void CollectVariablesTraverser::visitSym
         {
             Uniform info;
             const char kName[] = "gl_DepthRange";
             info.name          = kName;
             info.mappedName    = kName;
             info.type          = GL_NONE;
             info.precision     = GL_NONE;
             info.staticUse     = true;
-            info.active        = true;
 
             ShaderVariable nearInfo(GL_FLOAT);
             const char kNearName[] = "near";
             nearInfo.name          = kNearName;
             nearInfo.mappedName    = kNearName;
             nearInfo.precision     = GL_HIGH_FLOAT;
             nearInfo.staticUse     = true;
-            nearInfo.active        = true;
 
             ShaderVariable farInfo(GL_FLOAT);
             const char kFarName[] = "far";
             farInfo.name          = kFarName;
             farInfo.mappedName    = kFarName;
             farInfo.precision     = GL_HIGH_FLOAT;
             farInfo.staticUse     = true;
-            farInfo.active        = true;
 
             ShaderVariable diffInfo(GL_FLOAT);
             const char kDiffName[] = "diff";
             diffInfo.name          = kDiffName;
             diffInfo.mappedName    = kDiffName;
             diffInfo.precision     = GL_HIGH_FLOAT;
             diffInfo.staticUse     = true;
-            diffInfo.active        = true;
 
             info.fields.push_back(nearInfo);
             info.fields.push_back(farInfo);
             info.fields.push_back(diffInfo);
 
             mUniforms->push_back(info);
             mDepthRangeAdded = true;
         }
@@ -456,126 +445,148 @@ void CollectVariablesTraverser::visitSym
             case EvqBuffer:
             {
                 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
                 var =
                     FindVariableInInterfaceBlock(symbolName, interfaceBlock, mShaderStorageBlocks);
             }
             break;
             case EvqFragCoord:
-                recordBuiltInVaryingUsed(symbol->variable(), &mFragCoordAdded, mInputVaryings);
+                recordBuiltInVaryingUsed(ImmutableString("gl_FragCoord"), &mFragCoordAdded,
+                                         mInputVaryings);
                 return;
             case EvqFrontFacing:
-                recordBuiltInVaryingUsed(symbol->variable(), &mFrontFacingAdded, mInputVaryings);
+                recordBuiltInVaryingUsed(ImmutableString("gl_FrontFacing"), &mFrontFacingAdded,
+                                         mInputVaryings);
                 return;
             case EvqPointCoord:
-                recordBuiltInVaryingUsed(symbol->variable(), &mPointCoordAdded, mInputVaryings);
+                recordBuiltInVaryingUsed(ImmutableString("gl_PointCoord"), &mPointCoordAdded,
+                                         mInputVaryings);
                 return;
             case EvqInstanceID:
                 // Whenever the SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW option is set,
                 // gl_InstanceID is added inside expressions to initialize ViewID_OVR and
-                // InstanceID. Note that gl_InstanceID is not added to the symbol table for ESSL1
-                // shaders.
-                recordBuiltInAttributeUsed(symbol->variable(), &mInstanceIDAdded);
+                // InstanceID. gl_InstanceID is not added to the symbol table for ESSL1 shaders
+                // which makes it necessary to populate the type information explicitly instead of
+                // extracting it from the symbol table.
+                if (!mInstanceIDAdded)
+                {
+                    Attribute info;
+                    const char kName[] = "gl_InstanceID";
+                    info.name          = kName;
+                    info.mappedName    = kName;
+                    info.type          = GL_INT;
+                    info.precision     = GL_HIGH_INT;  // Defined by spec.
+                    info.staticUse     = true;
+                    info.location      = -1;
+                    mAttribs->push_back(info);
+                    mInstanceIDAdded = true;
+                }
                 return;
             case EvqVertexID:
-                recordBuiltInAttributeUsed(symbol->variable(), &mVertexIDAdded);
+                recordBuiltInAttributeUsed(ImmutableString("gl_VertexID"), &mVertexIDAdded);
                 return;
             case EvqPosition:
-                recordBuiltInVaryingUsed(symbol->variable(), &mPositionAdded, mOutputVaryings);
+                recordBuiltInVaryingUsed(ImmutableString("gl_Position"), &mPositionAdded,
+                                         mOutputVaryings);
                 return;
             case EvqPointSize:
-                recordBuiltInVaryingUsed(symbol->variable(), &mPointSizeAdded, mOutputVaryings);
+                recordBuiltInVaryingUsed(ImmutableString("gl_PointSize"), &mPointSizeAdded,
+                                         mOutputVaryings);
                 return;
             case EvqLastFragData:
-                recordBuiltInVaryingUsed(symbol->variable(), &mLastFragDataAdded, mInputVaryings);
+                recordBuiltInVaryingUsed(ImmutableString("gl_LastFragData"), &mLastFragDataAdded,
+                                         mInputVaryings);
                 return;
             case EvqFragColor:
-                recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragColorAdded);
+                recordBuiltInFragmentOutputUsed(ImmutableString("gl_FragColor"), &mFragColorAdded);
                 return;
             case EvqFragData:
                 if (!mFragDataAdded)
                 {
                     OutputVariable info;
-                    setBuiltInInfoFromSymbol(symbol->variable(), &info);
+                    setBuiltInInfoFromSymbolTable(ImmutableString("gl_FragData"), &info);
                     if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
                     {
                         ASSERT(info.arraySizes.size() == 1u);
                         info.arraySizes.back() = 1u;
                     }
                     info.staticUse = true;
-                    info.active    = true;
                     mOutputVariables->push_back(info);
                     mFragDataAdded = true;
                 }
                 return;
             case EvqFragDepthEXT:
-                recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragDepthEXTAdded);
+                recordBuiltInFragmentOutputUsed(ImmutableString("gl_FragDepthEXT"),
+                                                &mFragDepthEXTAdded);
                 return;
             case EvqFragDepth:
-                recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragDepthAdded);
+                recordBuiltInFragmentOutputUsed(ImmutableString("gl_FragDepth"), &mFragDepthAdded);
                 return;
             case EvqSecondaryFragColorEXT:
-                recordBuiltInFragmentOutputUsed(symbol->variable(), &mSecondaryFragColorEXTAdded);
+                recordBuiltInFragmentOutputUsed(ImmutableString("gl_SecondaryFragColorEXT"),
+                                                &mSecondaryFragColorEXTAdded);
                 return;
             case EvqSecondaryFragDataEXT:
-                recordBuiltInFragmentOutputUsed(symbol->variable(), &mSecondaryFragDataEXTAdded);
+                recordBuiltInFragmentOutputUsed(ImmutableString("gl_SecondaryFragDataEXT"),
+                                                &mSecondaryFragDataEXTAdded);
                 return;
             case EvqInvocationID:
-                recordBuiltInVaryingUsed(symbol->variable(), &mInvocationIDAdded, mInputVaryings);
+                recordBuiltInVaryingUsed(ImmutableString("gl_InvocationID"), &mInvocationIDAdded,
+                                         mInputVaryings);
                 break;
             case EvqPrimitiveIDIn:
-                recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDInAdded, mInputVaryings);
+                recordBuiltInVaryingUsed(ImmutableString("gl_PrimitiveIDIn"), &mPrimitiveIDInAdded,
+                                         mInputVaryings);
                 break;
             case EvqPrimitiveID:
                 if (mShaderType == GL_GEOMETRY_SHADER_EXT)
                 {
-                    recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDAdded,
+                    recordBuiltInVaryingUsed(ImmutableString("gl_PrimitiveID"), &mPrimitiveIDAdded,
                                              mOutputVaryings);
                 }
                 else
                 {
                     ASSERT(mShaderType == GL_FRAGMENT_SHADER);
-                    recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDAdded,
+                    recordBuiltInVaryingUsed(ImmutableString("gl_PrimitiveID"), &mPrimitiveIDAdded,
                                              mInputVaryings);
                 }
                 break;
             case EvqLayer:
                 if (mShaderType == GL_GEOMETRY_SHADER_EXT)
                 {
-                    recordBuiltInVaryingUsed(symbol->variable(), &mLayerAdded, mOutputVaryings);
+                    recordBuiltInVaryingUsed(ImmutableString("gl_Layer"), &mLayerAdded,
+                                             mOutputVaryings);
                 }
                 else if (mShaderType == GL_FRAGMENT_SHADER)
                 {
-                    recordBuiltInVaryingUsed(symbol->variable(), &mLayerAdded, mInputVaryings);
+                    recordBuiltInVaryingUsed(ImmutableString("gl_Layer"), &mLayerAdded,
+                                             mInputVaryings);
                 }
                 else
                 {
                     ASSERT(mShaderType == GL_VERTEX_SHADER &&
                            IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview));
                 }
                 break;
             default:
                 break;
         }
     }
     if (var)
     {
-        MarkActive(var);
+        MarkStaticallyUsed(var);
     }
 }
 
 void CollectVariablesTraverser::setFieldOrVariableProperties(const TType &type,
-                                                             bool staticUse,
                                                              ShaderVariable *variableOut) const
 {
     ASSERT(variableOut);
 
-    variableOut->staticUse = staticUse;
-
     const TStructure *structure = type.getStruct();
     if (!structure)
     {
         variableOut->type      = GLVariableType(type);
         variableOut->precision = GLVariablePrecision(type);
     }
     else
     {
@@ -588,45 +599,43 @@ void CollectVariablesTraverser::setField
 
         const TFieldList &fields = structure->fields();
 
         for (const TField *field : fields)
         {
             // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
             // ShaderVariable objects.
             ShaderVariable fieldVariable;
-            setFieldProperties(*field->type(), field->name(), staticUse, &fieldVariable);
+            setFieldProperties(*field->type(), field->name(), &fieldVariable);
             variableOut->fields.push_back(fieldVariable);
         }
     }
     if (auto *arraySizes = type.getArraySizes())
     {
         variableOut->arraySizes.assign(arraySizes->begin(), arraySizes->end());
     }
 }
 
 void CollectVariablesTraverser::setFieldProperties(const TType &type,
                                                    const ImmutableString &name,
-                                                   bool staticUse,
                                                    ShaderVariable *variableOut) const
 {
     ASSERT(variableOut);
-    setFieldOrVariableProperties(type, staticUse, variableOut);
+    setFieldOrVariableProperties(type, variableOut);
     variableOut->name.assign(name.data(), name.length());
     variableOut->mappedName = HashName(name, mHashFunction, nullptr).data();
 }
 
 void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
                                                             const TVariable &variable,
                                                             ShaderVariable *variableOut) const
 {
     ASSERT(variableOut);
 
-    variableOut->staticUse = mSymbolTable->isStaticallyUsed(variable);
-    setFieldOrVariableProperties(type, variableOut->staticUse, variableOut);
+    setFieldOrVariableProperties(type, variableOut);
     ASSERT(variable.symbolType() != SymbolType::Empty);
     variableOut->name.assign(variable.name().data(), variable.name().length());
     variableOut->mappedName = getMappedName(&variable);
 }
 
 Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const
 {
     const TType &type = variable.getType();
@@ -692,73 +701,41 @@ void CollectVariablesTraverser::recordIn
     const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock();
     ASSERT(blockType);
 
     interfaceBlock->name       = blockType->name().data();
     interfaceBlock->mappedName = getMappedName(blockType);
     if (instanceName != nullptr)
     {
         interfaceBlock->instanceName = instanceName;
-        const TSymbol *blockSymbol   = nullptr;
-        if (strncmp(instanceName, "gl_in", 5u) == 0)
-        {
-            blockSymbol = mSymbolTable->getGlInVariableWithArraySize();
-        }
-        else
-        {
-            blockSymbol = mSymbolTable->findGlobal(ImmutableString(instanceName));
-        }
-        ASSERT(blockSymbol && blockSymbol->isVariable());
-        interfaceBlock->staticUse =
-            mSymbolTable->isStaticallyUsed(*static_cast<const TVariable *>(blockSymbol));
     }
     ASSERT(!interfaceBlockType.isArrayOfArrays());  // Disallowed by GLSL ES 3.10 section 4.3.9
     interfaceBlock->arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getOutermostArraySize() : 0;
 
     interfaceBlock->blockType = GetBlockType(interfaceBlockType.getQualifier());
     if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM ||
         interfaceBlock->blockType == BlockType::BLOCK_BUFFER)
     {
         // TODO(oetuaho): Remove setting isRowMajorLayout.
         interfaceBlock->isRowMajorLayout = false;
         interfaceBlock->binding          = blockType->blockBinding();
         interfaceBlock->layout           = GetBlockLayoutType(blockType->blockStorage());
     }
 
     // Gather field information
-    bool anyFieldStaticallyUsed = false;
     for (const TField *field : blockType->fields())
     {
         const TType &fieldType = *field->type();
 
-        bool staticUse = false;
-        if (instanceName == nullptr)
-        {
-            // Static use of individual fields has been recorded, since they are present in the
-            // symbol table as variables.
-            const TSymbol *fieldSymbol = mSymbolTable->findGlobal(field->name());
-            ASSERT(fieldSymbol && fieldSymbol->isVariable());
-            staticUse =
-                mSymbolTable->isStaticallyUsed(*static_cast<const TVariable *>(fieldSymbol));
-            if (staticUse)
-            {
-                anyFieldStaticallyUsed = true;
-            }
-        }
-
         InterfaceBlockField fieldVariable;
-        setFieldProperties(fieldType, field->name(), staticUse, &fieldVariable);
+        setFieldProperties(fieldType, field->name(), &fieldVariable);
         fieldVariable.isRowMajorLayout =
             (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
         interfaceBlock->fields.push_back(fieldVariable);
     }
-    if (anyFieldStaticallyUsed)
-    {
-        interfaceBlock->staticUse = true;
-    }
 }
 
 Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const
 {
     Uniform uniform;
     setCommonVariableProperties(variable.getType(), variable.variable(), &uniform);
     uniform.binding  = variable.getType().getLayoutQualifier().binding;
     uniform.location = variable.getType().getLayoutQualifier().location;
@@ -866,17 +843,17 @@ InterfaceBlock *CollectVariablesTraverse
     }
     return namedBlock;
 }
 
 bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode)
 {
     if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
     {
-        // NOTE: we do not determine static use / activeness for individual blocks of an array.
+        // NOTE: we do not determine static use for individual blocks of an array
         TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
         ASSERT(blockNode);
 
         TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
         ASSERT(constantUnion);
 
         InterfaceBlock *namedBlock = nullptr;
 
@@ -900,25 +877,20 @@ bool CollectVariablesTraverser::visitBin
         }
 
         const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
         if (!namedBlock)
         {
             namedBlock = findNamedInterfaceBlock(interfaceBlock->name());
         }
         ASSERT(namedBlock);
-        ASSERT(namedBlock->staticUse);
-        namedBlock->active      = true;
+        namedBlock->staticUse   = true;
         unsigned int fieldIndex = static_cast<unsigned int>(constantUnion->getIConst(0));
         ASSERT(fieldIndex < namedBlock->fields.size());
-        // TODO(oetuaho): Would be nicer to record static use of fields of named interface blocks
-        // more accurately at parse time - now we only mark the fields statically used if they are
-        // active. http://anglebug.com/2440
         namedBlock->fields[fieldIndex].staticUse = true;
-        namedBlock->fields[fieldIndex].active    = true;
 
         if (traverseIndexExpression)
         {
             ASSERT(interfaceIndexingNode);
             interfaceIndexingNode->getRight()->traverse(this);
         }
         return false;
     }
@@ -934,18 +906,20 @@ void CollectVariables(TIntermBlock *root
                       std::vector<Uniform> *uniforms,
                       std::vector<Varying> *inputVaryings,
                       std::vector<Varying> *outputVaryings,
                       std::vector<InterfaceBlock> *uniformBlocks,
                       std::vector<InterfaceBlock> *shaderStorageBlocks,
                       std::vector<InterfaceBlock> *inBlocks,
                       ShHashFunction64 hashFunction,
                       TSymbolTable *symbolTable,
+                      int shaderVersion,
                       GLenum shaderType,
                       const TExtensionBehavior &extensionBehavior)
 {
     CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings,
                                       outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks,
-                                      hashFunction, symbolTable, shaderType, extensionBehavior);
+                                      hashFunction, symbolTable, shaderVersion, shaderType,
+                                      extensionBehavior);
     root->traverse(&collect);
 }
 
 }  // namespace sh
--- a/gfx/angle/checkout/src/compiler/translator/CollectVariables.h
+++ b/gfx/angle/checkout/src/compiler/translator/CollectVariables.h
@@ -24,13 +24,14 @@ void CollectVariables(TIntermBlock *root
                       std::vector<Uniform> *uniforms,
                       std::vector<Varying> *inputVaryings,
                       std::vector<Varying> *outputVaryings,
                       std::vector<InterfaceBlock> *uniformBlocks,
                       std::vector<InterfaceBlock> *shaderStorageBlocks,
                       std::vector<InterfaceBlock> *inBlocks,
                       ShHashFunction64 hashFunction,
                       TSymbolTable *symbolTable,
+                      int shaderVersion,
                       GLenum shaderType,
                       const TExtensionBehavior &extensionBehavior);
 }
 
 #endif  // COMPILER_TRANSLATOR_COLLECTVARIABLES_H_
--- a/gfx/angle/checkout/src/compiler/translator/Compiler.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/Compiler.cpp
@@ -5,53 +5,53 @@
 //
 
 #include "compiler/translator/Compiler.h"
 
 #include <sstream>
 
 #include "angle_gl.h"
 #include "common/utilities.h"
+#include "compiler/translator/AddAndTrueToLoopCondition.h"
 #include "compiler/translator/CallDAG.h"
+#include "compiler/translator/ClampFragDepth.h"
+#include "compiler/translator/ClampPointSize.h"
 #include "compiler/translator/CollectVariables.h"
+#include "compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h"
+#include "compiler/translator/DeferGlobalInitializers.h"
+#include "compiler/translator/EmulateGLFragColorBroadcast.h"
+#include "compiler/translator/EmulatePrecision.h"
+#include "compiler/translator/FoldExpressions.h"
 #include "compiler/translator/Initialize.h"
+#include "compiler/translator/InitializeVariables.h"
+#include "compiler/translator/IntermNodePatternMatcher.h"
 #include "compiler/translator/IsASTDepthBelowLimit.h"
 #include "compiler/translator/OutputTree.h"
 #include "compiler/translator/ParseContext.h"
+#include "compiler/translator/PruneNoOps.h"
+#include "compiler/translator/RegenerateStructNames.h"
+#include "compiler/translator/RemoveArrayLengthMethod.h"
+#include "compiler/translator/RemoveEmptySwitchStatements.h"
+#include "compiler/translator/RemoveInvariantDeclaration.h"
+#include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h"
+#include "compiler/translator/RemovePow.h"
+#include "compiler/translator/RemoveUnreferencedVariables.h"
+#include "compiler/translator/RewriteDoWhile.h"
+#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
+#include "compiler/translator/SeparateDeclarations.h"
+#include "compiler/translator/SimplifyLoopConditions.h"
+#include "compiler/translator/SplitSequenceOperator.h"
+#include "compiler/translator/UnfoldShortCircuitAST.h"
+#include "compiler/translator/UseInterfaceBlockFields.h"
 #include "compiler/translator/ValidateLimitations.h"
 #include "compiler/translator/ValidateMaxParameters.h"
 #include "compiler/translator/ValidateOutputs.h"
 #include "compiler/translator/ValidateVaryingLocations.h"
 #include "compiler/translator/VariablePacker.h"
-#include "compiler/translator/tree_ops/AddAndTrueToLoopCondition.h"
-#include "compiler/translator/tree_ops/ClampFragDepth.h"
-#include "compiler/translator/tree_ops/ClampPointSize.h"
-#include "compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h"
-#include "compiler/translator/tree_ops/DeferGlobalInitializers.h"
-#include "compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h"
-#include "compiler/translator/tree_ops/EmulatePrecision.h"
-#include "compiler/translator/tree_ops/FoldExpressions.h"
-#include "compiler/translator/tree_ops/InitializeVariables.h"
-#include "compiler/translator/tree_ops/PruneEmptyCases.h"
-#include "compiler/translator/tree_ops/PruneNoOps.h"
-#include "compiler/translator/tree_ops/RegenerateStructNames.h"
-#include "compiler/translator/tree_ops/RemoveArrayLengthMethod.h"
-#include "compiler/translator/tree_ops/RemoveInvariantDeclaration.h"
-#include "compiler/translator/tree_ops/RemovePow.h"
-#include "compiler/translator/tree_ops/RemoveUnreferencedVariables.h"
-#include "compiler/translator/tree_ops/RewriteDoWhile.h"
-#include "compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h"
-#include "compiler/translator/tree_ops/SeparateDeclarations.h"
-#include "compiler/translator/tree_ops/SimplifyLoopConditions.h"
-#include "compiler/translator/tree_ops/SplitSequenceOperator.h"
-#include "compiler/translator/tree_ops/UnfoldShortCircuitAST.h"
-#include "compiler/translator/tree_ops/UseInterfaceBlockFields.h"
-#include "compiler/translator/tree_ops/VectorizeVectorScalarArithmetic.h"
-#include "compiler/translator/tree_util/BuiltIn_autogen.h"
-#include "compiler/translator/tree_util/IntermNodePatternMatcher.h"
+#include "compiler/translator/VectorizeVectorScalarArithmetic.h"
 #include "compiler/translator/util.h"
 #include "third_party/compiler/ArrayBoundsClamper.h"
 
 namespace sh
 {
 
 namespace
 {
@@ -188,22 +188,22 @@ class TScopedPoolAllocator
     TPoolAllocator *mAllocator;
 };
 
 class TScopedSymbolTableLevel
 {
   public:
     TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table)
     {
-        ASSERT(mTable->isEmpty());
+        ASSERT(mTable->atBuiltInLevel());
         mTable->push();
     }
     ~TScopedSymbolTableLevel()
     {
-        while (!mTable->isEmpty())
+        while (!mTable->atBuiltInLevel())
             mTable->pop();
     }
 
   private:
     TSymbolTable *mTable;
 };
 
 int MapSpecToShaderVersion(ShShaderSpec spec)
@@ -220,61 +220,16 @@ int MapSpecToShaderVersion(ShShaderSpec 
         case SH_WEBGL3_SPEC:
             return 310;
         default:
             UNREACHABLE();
             return 0;
     }
 }
 
-bool ValidateFragColorAndFragData(GLenum shaderType,
-                                  int shaderVersion,
-                                  const TSymbolTable &symbolTable,
-                                  TDiagnostics *diagnostics)
-{
-    if (shaderVersion > 100 || shaderType != GL_FRAGMENT_SHADER)
-    {
-        return true;
-    }
-
-    bool usesFragColor = false;
-    bool usesFragData  = false;
-    // This validation is a bit stricter than the spec - it's only an error to write to
-    // both FragData and FragColor. But because it's better not to have reads from undefined
-    // variables, we always return an error if they are both referenced, rather than only if they
-    // are written.
-    if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_FragColor()) ||
-        symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()))
-    {
-        usesFragColor = true;
-    }
-    // Extension variables may not always be initialized (saves some time at symbol table init).
-    bool secondaryFragDataUsed =
-        symbolTable.gl_SecondaryFragDataEXT() != nullptr &&
-        symbolTable.isStaticallyUsed(*symbolTable.gl_SecondaryFragDataEXT());
-    if (symbolTable.isStaticallyUsed(*symbolTable.gl_FragData()) || secondaryFragDataUsed)
-    {
-        usesFragData = true;
-    }
-    if (usesFragColor && usesFragData)
-    {
-        const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
-        if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()) ||
-            secondaryFragDataUsed)
-        {
-            errorMessage =
-                "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
-                " and (gl_FragColor, gl_SecondaryFragColorEXT)";
-        }
-        diagnostics->globalError(errorMessage);
-        return false;
-    }
-    return true;
-}
-
 }  // namespace
 
 TShHandleBase::TShHandleBase()
 {
     allocator.push();
     SetGlobalPoolAllocator(&allocator);
 }
 
@@ -491,36 +446,41 @@ bool TCompiler::checkAndSimplifyAST(TInt
     }
 
     if (shouldRunLoopAndIndexingValidation(compileOptions) &&
         !ValidateLimitations(root, shaderType, &symbolTable, &mDiagnostics))
     {
         return false;
     }
 
-    if (!ValidateFragColorAndFragData(shaderType, shaderVersion, symbolTable, &mDiagnostics))
-    {
-        return false;
-    }
-
     // Fold expressions that could not be folded before validation that was done as a part of
     // parsing.
     FoldExpressions(root, &mDiagnostics);
     // Folding should only be able to generate warnings.
     ASSERT(mDiagnostics.numErrors() == 0);
 
     // We prune no-ops to work around driver bugs and to keep AST processing and output simple.
     // The following kinds of no-ops are pruned:
     //   1. Empty declarations "int;".
     //   2. Literal statements: "1.0;". The ESSL output doesn't define a default precision
     //      for float, so float literal statements would end up with no precision which is
     //      invalid ESSL.
     // After this empty declarations are not allowed in the AST.
     PruneNoOps(root, &symbolTable);
 
+    // In case the last case inside a switch statement is a certain type of no-op, GLSL
+    // compilers in drivers may not accept it. In this case we clean up the dead code from the
+    // end of switch statements. This is also required because PruneNoOps may have left switch
+    // statements that only contained an empty declaration inside the final case in an invalid
+    // state. Relies on that PruneNoOps has already been run.
+    RemoveNoOpCasesFromEndOfSwitchStatements(root, &symbolTable);
+
+    // Remove empty switch statements - this makes output simpler.
+    RemoveEmptySwitchStatements(root);
+
     // Create the function DAG and check there is no recursion
     if (!initCallDag(root))
     {
         return false;
     }
 
     if ((compileOptions & SH_LIMIT_CALL_STACK_DEPTH) && !checkCallDepth())
     {
@@ -583,17 +543,17 @@ bool TCompiler::checkAndSimplifyAST(TInt
 
     if (compileOptions & SH_UNFOLD_SHORT_CIRCUIT)
     {
         UnfoldShortCircuitAST(root);
     }
 
     if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT)
     {
-        RemovePow(root, &symbolTable);
+        RemovePow(root);
     }
 
     if (compileOptions & SH_REGENERATE_STRUCT_NAMES)
     {
         RegenerateStructNames gen(&symbolTable);
         root->traverse(&gen);
     }
 
@@ -623,24 +583,16 @@ bool TCompiler::checkAndSimplifyAST(TInt
 
     SplitSequenceOperator(root, IntermNodePatternMatcher::kArrayLengthMethod | simplifyScalarized,
                           &getSymbolTable());
 
     RemoveArrayLengthMethod(root);
 
     RemoveUnreferencedVariables(root, &symbolTable);
 
-    // In case the last case inside a switch statement is a certain type of no-op, GLSL compilers in
-    // drivers may not accept it. In this case we clean up the dead code from the end of switch
-    // statements. This is also required because PruneNoOps or RemoveUnreferencedVariables may have
-    // left switch statements that only contained an empty declaration inside the final case in an
-    // invalid state. Relies on that PruneNoOps and RemoveUnreferencedVariables have already been
-    // run.
-    PruneEmptyCases(root);
-
     // Built-in function emulation needs to happen after validateLimitations pass.
     // TODO(jmadill): Remove global pool allocator.
     GetGlobalPoolAllocator()->lock();
     initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions);
     GetGlobalPoolAllocator()->unlock();
     builtInFunctionEmulator.markBuiltInFunctionsForEmulation(root);
 
     if (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)
@@ -648,17 +600,17 @@ bool TCompiler::checkAndSimplifyAST(TInt
         ScalarizeVecAndMatConstructorArgs(root, shaderType, fragmentPrecisionHigh, &symbolTable);
     }
 
     if (shouldCollectVariables(compileOptions))
     {
         ASSERT(!variablesCollected);
         CollectVariables(root, &attributes, &outputVariables, &uniforms, &inputVaryings,
                          &outputVaryings, &uniformBlocks, &shaderStorageBlocks, &inBlocks,
-                         hashFunction, &symbolTable, shaderType, extensionBehavior);
+                         hashFunction, &symbolTable, shaderVersion, shaderType, extensionBehavior);
         collectInterfaceBlocks();
         variablesCollected = true;
         if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)
         {
             useAllMembersInUnusedStandardAndSharedBlocks(root);
         }
         if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
         {
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp
@@ -0,0 +1,210 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Applies the necessary AST transformations to support multiview rendering through instancing.
+// Check the header file For more information.
+//
+
+#include "compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h"
+
+#include "compiler/translator/FindMain.h"
+#include "compiler/translator/InitializeVariables.h"
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/ReplaceVariable.h"
+#include "compiler/translator/StaticType.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
+
+namespace
+{
+
+constexpr const ImmutableString kGlLayerString("gl_Layer");
+constexpr const ImmutableString kGlViewportIndexString("gl_ViewportIndex");
+constexpr const ImmutableString kGlViewIdOVRString("gl_ViewID_OVR");
+constexpr const ImmutableString kGlInstanceIdString("gl_InstanceID");
+constexpr const ImmutableString kViewIDVariableName("ViewID_OVR");
+constexpr const ImmutableString kInstanceIDVariableName("InstanceID");
+constexpr const ImmutableString kMultiviewBaseViewLayerIndexVariableName(
+    "multiviewBaseViewLayerIndex");
+
+TIntermSymbol *CreateGLInstanceIDSymbol(const TSymbolTable &symbolTable)
+{
+    return ReferenceBuiltInVariable(kGlInstanceIdString, symbolTable, 300);
+}
+
+// Adds the InstanceID and ViewID_OVR initializers to the end of the initializers' sequence.
+void InitializeViewIDAndInstanceID(const TVariable *viewID,
+                                   const TVariable *instanceID,
+                                   unsigned numberOfViews,
+                                   const TSymbolTable &symbolTable,
+                                   TIntermSequence *initializers)
+{
+    // Create an unsigned numberOfViews node.
+    TConstantUnion *numberOfViewsUnsignedConstant = new TConstantUnion();
+    numberOfViewsUnsignedConstant->setUConst(numberOfViews);
+    TIntermConstantUnion *numberOfViewsUint =
+        new TIntermConstantUnion(numberOfViewsUnsignedConstant, TType(EbtUInt, EbpHigh, EvqConst));
+
+    // Create a uint(gl_InstanceID) node.
+    TIntermSequence *glInstanceIDSymbolCastArguments = new TIntermSequence();
+    glInstanceIDSymbolCastArguments->push_back(CreateGLInstanceIDSymbol(symbolTable));
+    TIntermAggregate *glInstanceIDAsUint = TIntermAggregate::CreateConstructor(
+        TType(EbtUInt, EbpHigh, EvqTemporary), glInstanceIDSymbolCastArguments);
+
+    // Create a uint(gl_InstanceID) / numberOfViews node.
+    TIntermBinary *normalizedInstanceID =
+        new TIntermBinary(EOpDiv, glInstanceIDAsUint, numberOfViewsUint);
+
+    // Create an int(uint(gl_InstanceID) / numberOfViews) node.
+    TIntermSequence *normalizedInstanceIDCastArguments = new TIntermSequence();
+    normalizedInstanceIDCastArguments->push_back(normalizedInstanceID);
+    TIntermAggregate *normalizedInstanceIDAsInt = TIntermAggregate::CreateConstructor(
+        TType(EbtInt, EbpHigh, EvqTemporary), normalizedInstanceIDCastArguments);
+
+    // Create an InstanceID = int(uint(gl_InstanceID) / numberOfViews) node.
+    TIntermBinary *instanceIDInitializer =
+        new TIntermBinary(EOpAssign, new TIntermSymbol(instanceID), normalizedInstanceIDAsInt);
+    initializers->push_back(instanceIDInitializer);
+
+    // Create a uint(gl_InstanceID) % numberOfViews node.
+    TIntermBinary *normalizedViewID =
+        new TIntermBinary(EOpIMod, glInstanceIDAsUint->deepCopy(), numberOfViewsUint->deepCopy());
+
+    // Create a ViewID_OVR = uint(gl_InstanceID) % numberOfViews node.
+    TIntermBinary *viewIDInitializer =
+        new TIntermBinary(EOpAssign, new TIntermSymbol(viewID), normalizedViewID);
+    initializers->push_back(viewIDInitializer);
+}
+
+void DeclareGlobalVariable(TIntermBlock *root, const TVariable *variable)
+{
+    TIntermDeclaration *declaration = new TIntermDeclaration();
+    declaration->appendDeclarator(new TIntermSymbol(variable));
+
+    TIntermSequence *globalSequence = root->getSequence();
+    globalSequence->insert(globalSequence->begin(), declaration);
+}
+
+// Adds a branch to write int(ViewID_OVR) to either gl_ViewportIndex or gl_Layer. The branch is
+// added to the end of the initializers' sequence.
+void SelectViewIndexInVertexShader(const TVariable *viewID,
+                                   const TVariable *multiviewBaseViewLayerIndex,
+                                   TIntermSequence *initializers,
+                                   const TSymbolTable &symbolTable)
+{
+    // Create an int(ViewID_OVR) node.
+    TIntermSequence *viewIDSymbolCastArguments = new TIntermSequence();
+    viewIDSymbolCastArguments->push_back(new TIntermSymbol(viewID));
+    TIntermAggregate *viewIDAsInt = TIntermAggregate::CreateConstructor(
+        TType(EbtInt, EbpHigh, EvqTemporary), viewIDSymbolCastArguments);
+
+    // Create a gl_ViewportIndex node.
+    TIntermSymbol *viewportIndexSymbol =
+        ReferenceBuiltInVariable(kGlViewportIndexString, symbolTable, 0);
+
+    // Create a { gl_ViewportIndex = int(ViewID_OVR) } node.
+    TIntermBlock *viewportIndexInitializerInBlock = new TIntermBlock();
+    viewportIndexInitializerInBlock->appendStatement(
+        new TIntermBinary(EOpAssign, viewportIndexSymbol, viewIDAsInt));
+
+    // Create a gl_Layer node.
+    TIntermSymbol *layerSymbol = ReferenceBuiltInVariable(kGlLayerString, symbolTable, 0);
+
+    // Create an int(ViewID_OVR) + multiviewBaseViewLayerIndex node
+    TIntermBinary *sumOfViewIDAndBaseViewIndex = new TIntermBinary(
+        EOpAdd, viewIDAsInt->deepCopy(), new TIntermSymbol(multiviewBaseViewLayerIndex));
+
+    // Create a { gl_Layer = int(ViewID_OVR) + multiviewBaseViewLayerIndex } node.
+    TIntermBlock *layerInitializerInBlock = new TIntermBlock();
+    layerInitializerInBlock->appendStatement(
+        new TIntermBinary(EOpAssign, layerSymbol, sumOfViewIDAndBaseViewIndex));
+
+    // Create a node to compare whether the base view index uniform is less than zero.
+    TIntermBinary *multiviewBaseViewLayerIndexZeroComparison =
+        new TIntermBinary(EOpLessThan, new TIntermSymbol(multiviewBaseViewLayerIndex),
+                          CreateZeroNode(TType(EbtInt, EbpHigh, EvqConst)));
+
+    // Create an if-else statement to select the code path.
+    TIntermIfElse *multiviewBranch =
+        new TIntermIfElse(multiviewBaseViewLayerIndexZeroComparison,
+                          viewportIndexInitializerInBlock, layerInitializerInBlock);
+
+    initializers->push_back(multiviewBranch);
+}
+
+}  // namespace
+
+void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
+                                                 unsigned numberOfViews,
+                                                 GLenum shaderType,
+                                                 ShCompileOptions compileOptions,
+                                                 ShShaderOutput shaderOutput,
+                                                 TSymbolTable *symbolTable)
+{
+    ASSERT(shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER);
+
+    TQualifier viewIDQualifier  = (shaderType == GL_VERTEX_SHADER) ? EvqFlatOut : EvqFlatIn;
+    const TVariable *viewID =
+        new TVariable(symbolTable, kViewIDVariableName,
+                      new TType(EbtUInt, EbpHigh, viewIDQualifier), SymbolType::AngleInternal);
+
+    DeclareGlobalVariable(root, viewID);
+    ReplaceVariable(
+        root,
+        static_cast<const TVariable *>(symbolTable->findBuiltIn(kGlViewIdOVRString, 300, true)),
+        viewID);
+    if (shaderType == GL_VERTEX_SHADER)
+    {
+        // Replacing gl_InstanceID with InstanceID should happen before adding the initializers of
+        // InstanceID and ViewID.
+        const TType *instanceIDVariableType   = StaticType::Get<EbtInt, EbpHigh, EvqGlobal, 1, 1>();
+        const TVariable *instanceID =
+            new TVariable(symbolTable, kInstanceIDVariableName, instanceIDVariableType,
+                          SymbolType::AngleInternal);
+        DeclareGlobalVariable(root, instanceID);
+        ReplaceVariable(root,
+                        static_cast<const TVariable *>(
+                            symbolTable->findBuiltIn(kGlInstanceIdString, 300, true)),
+                        instanceID);
+
+        TIntermSequence *initializers = new TIntermSequence();
+        InitializeViewIDAndInstanceID(viewID, instanceID, numberOfViews, *symbolTable,
+                                      initializers);
+
+        // The AST transformation which adds the expression to select the viewport index should
+        // be done only for the GLSL and ESSL output.
+        const bool selectView = (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u;
+        // Assert that if the view is selected in the vertex shader, then the output is
+        // either GLSL or ESSL.
+        ASSERT(!selectView || IsOutputGLSL(shaderOutput) || IsOutputESSL(shaderOutput));
+        if (selectView)
+        {
+            // Add a uniform to switch between side-by-side and layered rendering.
+            const TType *baseLayerIndexVariableType =
+                StaticType::Get<EbtInt, EbpHigh, EvqUniform, 1, 1>();
+            const TVariable *multiviewBaseViewLayerIndex =
+                new TVariable(symbolTable, kMultiviewBaseViewLayerIndexVariableName,
+                              baseLayerIndexVariableType, SymbolType::AngleInternal);
+            DeclareGlobalVariable(root, multiviewBaseViewLayerIndex);
+
+            // Setting a value to gl_ViewportIndex or gl_Layer should happen after ViewID_OVR's
+            // initialization.
+            SelectViewIndexInVertexShader(viewID, multiviewBaseViewLayerIndex, initializers,
+                                          *symbolTable);
+        }
+
+        // Insert initializers at the beginning of main().
+        TIntermBlock *initializersBlock = new TIntermBlock();
+        initializersBlock->getSequence()->swap(*initializers);
+        TIntermBlock *mainBody = FindMainBody(root);
+        mainBody->getSequence()->insert(mainBody->getSequence()->begin(), initializersBlock);
+    }
+}
+
+}  // namespace sh
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Regardless of the shader type, the following AST transformations are applied:
+// - Add declaration of View_ID_OVR.
+// - Replace every occurrence of gl_ViewID_OVR with ViewID_OVR, mark ViewID_OVR as internal and
+// declare it as a flat varying.
+//
+// If the shader type is a vertex shader, the following AST transformations are applied:
+// - Replace every occurrence of gl_InstanceID with InstanceID, mark InstanceID as internal and set
+// its qualifier to EvqTemporary.
+// - Add initializers of ViewID_OVR and InstanceID to the beginning of the body of main. The pass
+// should be executed before any variables get collected so that usage of gl_InstanceID is recorded.
+// - If the output is ESSL or GLSL and the SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is
+// enabled, the expression
+// "if (multiviewBaseViewLayerIndex < 0) {
+//      gl_ViewportIndex = int(ViewID_OVR);
+//  } else {
+//      gl_Layer = int(ViewID_OVR) + multiviewBaseViewLayerIndex;
+//  }"
+// is added after ViewID and InstanceID are initialized. Also, MultiviewRenderPath is added as a
+// uniform.
+//
+
+#ifndef COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
+#define COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
+
+#include "GLSLANG/ShaderLang.h"
+#include "angle_gl.h"
+
+namespace sh
+{
+
+class TIntermBlock;
+class TSymbolTable;
+
+void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
+                                                 unsigned numberOfViews,
+                                                 GLenum shaderType,
+                                                 ShCompileOptions compileOptions,
+                                                 ShShaderOutput shaderOutput,
+                                                 TSymbolTable *symbolTable);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/DeferGlobalInitializers.cpp
@@ -0,0 +1,167 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DeferGlobalInitializers is an AST traverser that moves global initializers into a separate
+// function that is called in the beginning of main(). This enables initialization of globals with
+// uniforms or non-constant globals, as allowed by the WebGL spec. Some initializers referencing
+// non-constants may need to be unfolded into if statements in HLSL - this kind of steps should be
+// done after DeferGlobalInitializers is run. Note that it's important that the function definition
+// is at the end of the shader, as some globals may be declared after main().
+//
+// It can also initialize all uninitialized globals.
+//
+
+#include "compiler/translator/DeferGlobalInitializers.h"
+
+#include <vector>
+
+#include "compiler/translator/FindMain.h"
+#include "compiler/translator/InitializeVariables.h"
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/ReplaceVariable.h"
+#include "compiler/translator/StaticType.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+namespace
+{
+
+constexpr const ImmutableString kInitGlobalsString("initGlobals");
+
+void GetDeferredInitializers(TIntermDeclaration *declaration,
+                             bool initializeUninitializedGlobals,
+                             bool canUseLoopsToInitialize,
+                             bool highPrecisionSupported,
+                             TIntermSequence *deferredInitializersOut,
+                             std::vector<const TVariable *> *variablesToReplaceOut,
+                             TSymbolTable *symbolTable)
+{
+    // SeparateDeclarations should have already been run.
+    ASSERT(declaration->getSequence()->size() == 1);
+
+    TIntermNode *declarator = declaration->getSequence()->back();
+    TIntermBinary *init     = declarator->getAsBinaryNode();
+    if (init)
+    {
+        TIntermSymbol *symbolNode = init->getLeft()->getAsSymbolNode();
+        ASSERT(symbolNode);
+        TIntermTyped *expression = init->getRight();
+
+        if (expression->getQualifier() != EvqConst || !expression->hasConstantValue())
+        {
+            // For variables which are not constant, defer their real initialization until
+            // after we initialize uniforms.
+            // Deferral is done also in any cases where the variable can not be converted to a
+            // constant union, since otherwise there's a chance that HLSL output will generate extra
+            // statements from the initializer expression.
+
+            // Change const global to a regular global if its initialization is deferred.
+            // This can happen if ANGLE has not been able to fold the constant expression used
+            // as an initializer.
+            ASSERT(symbolNode->getQualifier() == EvqConst ||
+                   symbolNode->getQualifier() == EvqGlobal);
+            if (symbolNode->getQualifier() == EvqConst)
+            {
+                variablesToReplaceOut->push_back(&symbolNode->variable());
+            }
+
+            TIntermBinary *deferredInit =
+                new TIntermBinary(EOpAssign, symbolNode->deepCopy(), init->getRight());
+            deferredInitializersOut->push_back(deferredInit);
+
+            // Remove the initializer from the global scope and just declare the global instead.
+            declaration->replaceChildNode(init, symbolNode);
+        }
+    }
+    else if (initializeUninitializedGlobals)
+    {
+        TIntermSymbol *symbolNode = declarator->getAsSymbolNode();
+        ASSERT(symbolNode);
+
+        // Ignore ANGLE internal variables and nameless declarations.
+        if (symbolNode->variable().symbolType() == SymbolType::AngleInternal ||
+            symbolNode->variable().symbolType() == SymbolType::Empty)
+            return;
+
+        if (symbolNode->getQualifier() == EvqGlobal)
+        {
+            TIntermSequence *initCode = CreateInitCode(symbolNode, canUseLoopsToInitialize,
+                                                       highPrecisionSupported, symbolTable);
+            deferredInitializersOut->insert(deferredInitializersOut->end(), initCode->begin(),
+                                            initCode->end());
+        }
+    }
+}
+
+void InsertInitCallToMain(TIntermBlock *root,
+                          TIntermSequence *deferredInitializers,
+                          TSymbolTable *symbolTable)
+{
+    TIntermBlock *initGlobalsBlock = new TIntermBlock();
+    initGlobalsBlock->getSequence()->swap(*deferredInitializers);
+
+    TFunction *initGlobalsFunction =
+        new TFunction(symbolTable, kInitGlobalsString, SymbolType::AngleInternal,
+                      StaticType::GetBasic<EbtVoid>(), false);
+
+    TIntermFunctionPrototype *initGlobalsFunctionPrototype =
+        CreateInternalFunctionPrototypeNode(*initGlobalsFunction);
+    root->getSequence()->insert(root->getSequence()->begin(), initGlobalsFunctionPrototype);
+    TIntermFunctionDefinition *initGlobalsFunctionDefinition =
+        CreateInternalFunctionDefinitionNode(*initGlobalsFunction, initGlobalsBlock);
+    root->appendStatement(initGlobalsFunctionDefinition);
+
+    TIntermAggregate *initGlobalsCall =
+        TIntermAggregate::CreateFunctionCall(*initGlobalsFunction, new TIntermSequence());
+
+    TIntermBlock *mainBody = FindMainBody(root);
+    mainBody->getSequence()->insert(mainBody->getSequence()->begin(), initGlobalsCall);
+}
+
+}  // namespace
+
+void DeferGlobalInitializers(TIntermBlock *root,
+                             bool initializeUninitializedGlobals,
+                             bool canUseLoopsToInitialize,
+                             bool highPrecisionSupported,
+                             TSymbolTable *symbolTable)
+{
+    TIntermSequence *deferredInitializers = new TIntermSequence();
+    std::vector<const TVariable *> variablesToReplace;
+
+    // Loop over all global statements and process the declarations. This is simpler than using a
+    // traverser.
+    for (TIntermNode *statement : *root->getSequence())
+    {
+        TIntermDeclaration *declaration = statement->getAsDeclarationNode();
+        if (declaration)
+        {
+            GetDeferredInitializers(declaration, initializeUninitializedGlobals,
+                                    canUseLoopsToInitialize, highPrecisionSupported,
+                                    deferredInitializers, &variablesToReplace, symbolTable);
+        }
+    }
+
+    // Add the function with initialization and the call to that.
+    if (!deferredInitializers->empty())
+    {
+        InsertInitCallToMain(root, deferredInitializers, symbolTable);
+    }
+
+    // Replace constant variables with non-constant global variables.
+    for (const TVariable *var : variablesToReplace)
+    {
+        TType *replacementType = new TType(var->getType());
+        replacementType->setQualifier(EvqGlobal);
+        TVariable *replacement =
+            new TVariable(symbolTable, var->name(), replacementType, var->symbolType());
+        ReplaceVariable(root, var, replacement);
+    }
+}
+
+}  // namespace sh
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/DeferGlobalInitializers.h
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DeferGlobalInitializers is an AST traverser that moves global initializers into a separate
+// function that is called in the beginning of main(). This enables initialization of globals with
+// uniforms or non-constant globals, as allowed by the WebGL spec. Some initializers referencing
+// non-constants may need to be unfolded into if statements in HLSL - this kind of steps should be
+// done after DeferGlobalInitializers is run. Note that it's important that the function definition
+// is at the end of the shader, as some globals may be declared after main().
+//
+// It can also initialize all uninitialized globals.
+//
+
+#ifndef COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_
+#define COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_
+
+namespace sh
+{
+
+class TIntermBlock;
+class TSymbolTable;
+
+void DeferGlobalInitializers(TIntermBlock *root,
+                             bool initializeUninitializedGlobals,
+                             bool canUseLoopsToInitialize,
+                             bool highPrecisionSupported,
+                             TSymbolTable *symbolTable);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/EmulateGLFragColorBroadcast.cpp
@@ -0,0 +1,132 @@
+//
+// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// gl_FragColor needs to broadcast to all color buffers in ES2 if
+// GL_EXT_draw_buffers is explicitly enabled in a fragment shader.
+//
+// We emulate this by replacing all gl_FragColor with gl_FragData[0], and in the end
+// of main() function, assigning gl_FragData[1], ..., gl_FragData[maxDrawBuffers-1]
+// with gl_FragData[0].
+//
+
+#include "compiler/translator/EmulateGLFragColorBroadcast.h"
+
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/RunAtTheEndOfShader.h"
+#include "compiler/translator/Symbol.h"
+
+namespace sh
+{
+
+namespace
+{
+
+constexpr const ImmutableString kGlFragDataString("gl_FragData");
+
+class GLFragColorBroadcastTraverser : public TIntermTraverser
+{
+  public:
+    GLFragColorBroadcastTraverser(int maxDrawBuffers, TSymbolTable *symbolTable, int shaderVersion)
+        : TIntermTraverser(true, false, false, symbolTable),
+          mGLFragColorUsed(false),
+          mMaxDrawBuffers(maxDrawBuffers),
+          mShaderVersion(shaderVersion)
+    {
+    }
+
+    void broadcastGLFragColor(TIntermBlock *root);
+
+    bool isGLFragColorUsed() const { return mGLFragColorUsed; }
+
+  protected:
+    void visitSymbol(TIntermSymbol *node) override;
+
+    TIntermBinary *constructGLFragDataNode(int index) const;
+    TIntermBinary *constructGLFragDataAssignNode(int index) const;
+
+  private:
+    bool mGLFragColorUsed;
+    int mMaxDrawBuffers;
+    const int mShaderVersion;
+};
+
+TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataNode(int index) const
+{
+    TIntermSymbol *symbol =
+        ReferenceBuiltInVariable(kGlFragDataString, *mSymbolTable, mShaderVersion);
+    TIntermTyped *indexNode = CreateIndexNode(index);
+
+    TIntermBinary *binary = new TIntermBinary(EOpIndexDirect, symbol, indexNode);
+    return binary;
+}
+
+TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataAssignNode(int index) const
+{
+    TIntermTyped *fragDataIndex = constructGLFragDataNode(index);
+    TIntermTyped *fragDataZero  = constructGLFragDataNode(0);
+
+    return new TIntermBinary(EOpAssign, fragDataIndex, fragDataZero);
+}
+
+void GLFragColorBroadcastTraverser::visitSymbol(TIntermSymbol *node)
+{
+    if (node->variable().symbolType() == SymbolType::BuiltIn && node->getName() == "gl_FragColor")
+    {
+        queueReplacement(constructGLFragDataNode(0), OriginalNode::IS_DROPPED);
+        mGLFragColorUsed = true;
+    }
+}
+
+void GLFragColorBroadcastTraverser::broadcastGLFragColor(TIntermBlock *root)
+{
+    ASSERT(mMaxDrawBuffers > 1);
+    if (!mGLFragColorUsed)
+    {
+        return;
+    }
+
+    TIntermBlock *broadcastBlock = new TIntermBlock();
+    // Now insert statements
+    //   gl_FragData[1] = gl_FragData[0];
+    //   ...
+    //   gl_FragData[maxDrawBuffers - 1] = gl_FragData[0];
+    for (int colorIndex = 1; colorIndex < mMaxDrawBuffers; ++colorIndex)
+    {
+        broadcastBlock->appendStatement(constructGLFragDataAssignNode(colorIndex));
+    }
+    RunAtTheEndOfShader(root, broadcastBlock, mSymbolTable);
+}
+
+}  // namespace anonymous
+
+void EmulateGLFragColorBroadcast(TIntermBlock *root,
+                                 int maxDrawBuffers,
+                                 std::vector<sh::OutputVariable> *outputVariables,
+                                 TSymbolTable *symbolTable,
+                                 int shaderVersion)
+{
+    ASSERT(maxDrawBuffers > 1);
+    GLFragColorBroadcastTraverser traverser(maxDrawBuffers, symbolTable, shaderVersion);
+    root->traverse(&traverser);
+    if (traverser.isGLFragColorUsed())
+    {
+        traverser.updateTree();
+        traverser.broadcastGLFragColor(root);
+        for (auto &var : *outputVariables)
+        {
+            if (var.name == "gl_FragColor")
+            {
+                // TODO(zmo): Find a way to keep the original variable information.
+                var.name       = "gl_FragData";
+                var.mappedName = "gl_FragData";
+                var.arraySizes.push_back(maxDrawBuffers);
+                ASSERT(var.arraySizes.size() == 1u);
+            }
+        }
+    }
+}
+
+}  // namespace sh
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/EmulateGLFragColorBroadcast.h
@@ -0,0 +1,31 @@
+//
+// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Emulate gl_FragColor broadcast behaviors in ES2 where
+// GL_EXT_draw_buffers is explicitly enabled in a fragment shader.
+//
+
+#ifndef COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_
+#define COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_
+
+#include <vector>
+
+namespace sh
+{
+struct OutputVariable;
+class TIntermBlock;
+class TSymbolTable;
+
+// Replace all gl_FragColor with gl_FragData[0], and in the end of main() function,
+// assign gl_FragData[1] ... gl_FragData[maxDrawBuffers - 1] with gl_FragData[0].
+// If gl_FragColor is in outputVariables, it is replaced by gl_FragData.
+void EmulateGLFragColorBroadcast(TIntermBlock *root,
+                                 int maxDrawBuffers,
+                                 std::vector<OutputVariable> *outputVariables,
+                                 TSymbolTable *symbolTable,
+                                 int shaderVersion);
+}
+
+#endif  // COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/EmulatePrecision.cpp
@@ -0,0 +1,779 @@
+//
+// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/EmulatePrecision.h"
+
+#include "compiler/translator/FunctionLookup.h"
+
+#include <memory>
+
+namespace sh
+{
+
+namespace
+{
+
+constexpr const ImmutableString kParamXName("x");
+constexpr const ImmutableString kParamYName("y");
+constexpr const ImmutableString kAngleFrmString("angle_frm");
+constexpr const ImmutableString kAngleFrlString("angle_frl");
+
+class RoundingHelperWriter : angle::NonCopyable
+{
+  public:
+    static RoundingHelperWriter *createHelperWriter(const ShShaderOutput outputLanguage);
+
+    void writeCommonRoundingHelpers(TInfoSinkBase &sink, const int shaderVersion);
+    void writeCompoundAssignmentHelper(TInfoSinkBase &sink,
+                                       const char *lType,
+                                       const char *rType,
+                                       const char *opStr,
+                                       const char *opNameStr);
+
+    virtual ~RoundingHelperWriter() {}
+
+  protected:
+    RoundingHelperWriter(const ShShaderOutput outputLanguage) : mOutputLanguage(outputLanguage) {}
+    RoundingHelperWriter() = delete;
+
+    const ShShaderOutput mOutputLanguage;
+
+  private:
+    virtual std::string getTypeString(const char *glslType)     = 0;
+    virtual void writeFloatRoundingHelpers(TInfoSinkBase &sink) = 0;
+    virtual void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) = 0;
+    virtual void writeMatrixRoundingHelper(TInfoSinkBase &sink,
+                                           const unsigned int columns,
+                                           const unsigned int rows,
+                                           const char *functionName) = 0;
+};
+
+class RoundingHelperWriterGLSL : public RoundingHelperWriter
+{
+  public:
+    RoundingHelperWriterGLSL(const ShShaderOutput outputLanguage)
+        : RoundingHelperWriter(outputLanguage)
+    {
+    }
+
+  private:
+    std::string getTypeString(const char *glslType) override;
+    void writeFloatRoundingHelpers(TInfoSinkBase &sink) override;
+    void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) override;
+    void writeMatrixRoundingHelper(TInfoSinkBase &sink,
+                                   const unsigned int columns,
+                                   const unsigned int rows,
+                                   const char *functionName) override;
+};
+
+class RoundingHelperWriterESSL : public RoundingHelperWriterGLSL
+{
+  public:
+    RoundingHelperWriterESSL(const ShShaderOutput outputLanguage)
+        : RoundingHelperWriterGLSL(outputLanguage)
+    {
+    }
+
+  private:
+    std::string getTypeString(const char *glslType) override;
+};
+
+class RoundingHelperWriterHLSL : public RoundingHelperWriter
+{
+  public:
+    RoundingHelperWriterHLSL(const ShShaderOutput outputLanguage)
+        : RoundingHelperWriter(outputLanguage)
+    {
+    }
+
+  private:
+    std::string getTypeString(const char *glslType) override;
+    void writeFloatRoundingHelpers(TInfoSinkBase &sink) override;
+    void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) override;
+    void writeMatrixRoundingHelper(TInfoSinkBase &sink,
+                                   const unsigned int columns,
+                                   const unsigned int rows,
+                                   const char *functionName) override;
+};
+
+RoundingHelperWriter *RoundingHelperWriter::createHelperWriter(const ShShaderOutput outputLanguage)
+{
+    ASSERT(EmulatePrecision::SupportedInLanguage(outputLanguage));
+    switch (outputLanguage)
+    {
+        case SH_HLSL_4_1_OUTPUT:
+            return new RoundingHelperWriterHLSL(outputLanguage);
+        case SH_ESSL_OUTPUT:
+            return new RoundingHelperWriterESSL(outputLanguage);
+        default:
+            return new RoundingHelperWriterGLSL(outputLanguage);
+    }
+}
+
+void RoundingHelperWriter::writeCommonRoundingHelpers(TInfoSinkBase &sink, const int shaderVersion)
+{
+    // Write the angle_frm functions that round floating point numbers to
+    // half precision, and angle_frl functions that round them to minimum lowp
+    // precision.
+
+    writeFloatRoundingHelpers(sink);
+    writeVectorRoundingHelpers(sink, 2);
+    writeVectorRoundingHelpers(sink, 3);
+    writeVectorRoundingHelpers(sink, 4);
+    if (shaderVersion > 100)
+    {
+        for (unsigned int columns = 2; columns <= 4; ++columns)
+        {
+            for (unsigned int rows = 2; rows <= 4; ++rows)
+            {
+                writeMatrixRoundingHelper(sink, columns, rows, "angle_frm");
+                writeMatrixRoundingHelper(sink, columns, rows, "angle_frl");
+            }
+        }
+    }
+    else
+    {
+        for (unsigned int size = 2; size <= 4; ++size)
+        {
+            writeMatrixRoundingHelper(sink, size, size, "angle_frm");
+            writeMatrixRoundingHelper(sink, size, size, "angle_frl");
+        }
+    }
+}
+
+void RoundingHelperWriter::writeCompoundAssignmentHelper(TInfoSinkBase &sink,
+                                                         const char *lType,
+                                                         const char *rType,
+                                                         const char *opStr,
+                                                         const char *opNameStr)
+{
+    std::string lTypeStr = getTypeString(lType);
+    std::string rTypeStr = getTypeString(rType);
+
+    // Note that y should be passed through angle_frm at the function call site,
+    // but x can't be passed through angle_frm there since it is an inout parameter.
+    // So only pass x and the result through angle_frm here.
+    // clang-format off
+    sink <<
+        lTypeStr << " angle_compound_" << opNameStr << "_frm(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
+        "    x = angle_frm(angle_frm(x) " << opStr << " y);\n"
+        "    return x;\n"
+        "}\n";
+    sink <<
+        lTypeStr << " angle_compound_" << opNameStr << "_frl(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
+        "    x = angle_frl(angle_frl(x) " << opStr << " y);\n"
+        "    return x;\n"
+        "}\n";
+    // clang-format on
+}
+
+std::string RoundingHelperWriterGLSL::getTypeString(const char *glslType)
+{
+    return glslType;
+}
+
+std::string RoundingHelperWriterESSL::getTypeString(const char *glslType)
+{
+    std::stringstream typeStrStr;
+    typeStrStr << "highp " << glslType;
+    return typeStrStr.str();
+}
+
+void RoundingHelperWriterGLSL::writeFloatRoundingHelpers(TInfoSinkBase &sink)
+{
+    // Unoptimized version of angle_frm for single floats:
+    //
+    // int webgl_maxNormalExponent(in int exponentBits)
+    // {
+    //     int possibleExponents = int(exp2(float(exponentBits)));
+    //     int exponentBias = possibleExponents / 2 - 1;
+    //     int allExponentBitsOne = possibleExponents - 1;
+    //     return (allExponentBitsOne - 1) - exponentBias;
+    // }
+    //
+    // float angle_frm(in float x)
+    // {
+    //     int mantissaBits = 10;
+    //     int exponentBits = 5;
+    //     float possibleMantissas = exp2(float(mantissaBits));
+    //     float mantissaMax = 2.0 - 1.0 / possibleMantissas;
+    //     int maxNE = webgl_maxNormalExponent(exponentBits);
+    //     float max = exp2(float(maxNE)) * mantissaMax;
+    //     if (x > max)
+    //     {
+    //         return max;
+    //     }
+    //     if (x < -max)
+    //     {
+    //         return -max;
+    //     }
+    //     float exponent = floor(log2(abs(x)));
+    //     if (abs(x) == 0.0 || exponent < -float(maxNE))
+    //     {
+    //         return 0.0 * sign(x)
+    //     }
+    //     x = x * exp2(-(exponent - float(mantissaBits)));
+    //     x = sign(x) * floor(abs(x));
+    //     return x * exp2(exponent - float(mantissaBits));
+    // }
+
+    // All numbers with a magnitude less than 2^-15 are subnormal, and are
+    // flushed to zero.
+
+    // Note the constant numbers below:
+    // a) 65504 is the maximum possible mantissa (1.1111111111 in binary) times
+    //    2^15, the maximum normal exponent.
+    // b) 10.0 is the number of mantissa bits.
+    // c) -25.0 is the minimum normal half-float exponent -15.0 minus the number
+    //    of mantissa bits.
+    // d) + 1e-30 is to make sure the argument of log2() won't be zero. It can
+    //    only affect the result of log2 on x where abs(x) < 1e-22. Since these
+    //    numbers will be flushed to zero either way (2^-15 is the smallest
+    //    normal positive number), this does not introduce any error.
+
+    std::string floatType = getTypeString("float");
+
+    // clang-format off
+    sink <<
+        floatType << " angle_frm(in " << floatType << " x) {\n"
+        "    x = clamp(x, -65504.0, 65504.0);\n"
+        "    " << floatType << " exponent = floor(log2(abs(x) + 1e-30)) - 10.0;\n"
+        "    bool isNonZero = (exponent >= -25.0);\n"
+        "    x = x * exp2(-exponent);\n"
+        "    x = sign(x) * floor(abs(x));\n"
+        "    return x * exp2(exponent) * float(isNonZero);\n"
+        "}\n";
+
+    sink <<
+        floatType << " angle_frl(in " << floatType << " x) {\n"
+        "    x = clamp(x, -2.0, 2.0);\n"
+        "    x = x * 256.0;\n"
+        "    x = sign(x) * floor(abs(x));\n"
+        "    return x * 0.00390625;\n"
+        "}\n";
+    // clang-format on
+}
+
+void RoundingHelperWriterGLSL::writeVectorRoundingHelpers(TInfoSinkBase &sink,
+                                                          const unsigned int size)
+{
+    std::stringstream vecTypeStrStr;
+    vecTypeStrStr << "vec" << size;
+    std::string vecType = getTypeString(vecTypeStrStr.str().c_str());
+
+    // clang-format off
+    sink <<
+        vecType << " angle_frm(in " << vecType << " v) {\n"
+        "    v = clamp(v, -65504.0, 65504.0);\n"
+        "    " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n"
+        "    bvec" << size << " isNonZero = greaterThanEqual(exponent, vec" << size << "(-25.0));\n"
+        "    v = v * exp2(-exponent);\n"
+        "    v = sign(v) * floor(abs(v));\n"
+        "    return v * exp2(exponent) * vec" << size << "(isNonZero);\n"
+        "}\n";
+
+    sink <<
+        vecType << " angle_frl(in " << vecType << " v) {\n"
+        "    v = clamp(v, -2.0, 2.0);\n"
+        "    v = v * 256.0;\n"
+        "    v = sign(v) * floor(abs(v));\n"
+        "    return v * 0.00390625;\n"
+        "}\n";
+    // clang-format on
+}
+
+void RoundingHelperWriterGLSL::writeMatrixRoundingHelper(TInfoSinkBase &sink,
+                                                         const unsigned int columns,
+                                                         const unsigned int rows,
+                                                         const char *functionName)
+{
+    std::stringstream matTypeStrStr;
+    matTypeStrStr << "mat" << columns;
+    if (rows != columns)
+    {
+        matTypeStrStr << "x" << rows;
+    }
+    std::string matType = getTypeString(matTypeStrStr.str().c_str());
+
+    sink << matType << " " << functionName << "(in " << matType << " m) {\n"
+         << "    " << matType << " rounded;\n";
+
+    for (unsigned int i = 0; i < columns; ++i)
+    {
+        sink << "    rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n";
+    }
+
+    sink << "    return rounded;\n"
+            "}\n";
+}
+
+static const char *GetHLSLTypeStr(const char *floatTypeStr)
+{
+    if (strcmp(floatTypeStr, "float") == 0)
+    {
+        return "float";
+    }
+    if (strcmp(floatTypeStr, "vec2") == 0)
+    {
+        return "float2";
+    }
+    if (strcmp(floatTypeStr, "vec3") == 0)
+    {
+        return "float3";
+    }
+    if (strcmp(floatTypeStr, "vec4") == 0)
+    {
+        return "float4";
+    }
+    if (strcmp(floatTypeStr, "mat2") == 0)
+    {
+        return "float2x2";
+    }
+    if (strcmp(floatTypeStr, "mat3") == 0)
+    {
+        return "float3x3";
+    }
+    if (strcmp(floatTypeStr, "mat4") == 0)
+    {
+        return "float4x4";
+    }
+    if (strcmp(floatTypeStr, "mat2x3") == 0)
+    {
+        return "float2x3";
+    }
+    if (strcmp(floatTypeStr, "mat2x4") == 0)
+    {
+        return "float2x4";
+    }
+    if (strcmp(floatTypeStr, "mat3x2") == 0)
+    {
+        return "float3x2";
+    }
+    if (strcmp(floatTypeStr, "mat3x4") == 0)
+    {
+        return "float3x4";
+    }
+    if (strcmp(floatTypeStr, "mat4x2") == 0)
+    {
+        return "float4x2";
+    }
+    if (strcmp(floatTypeStr, "mat4x3") == 0)
+    {
+        return "float4x3";
+    }
+    UNREACHABLE();
+    return nullptr;
+}
+
+std::string RoundingHelperWriterHLSL::getTypeString(const char *glslType)
+{
+    return GetHLSLTypeStr(glslType);
+}
+
+void RoundingHelperWriterHLSL::writeFloatRoundingHelpers(TInfoSinkBase &sink)
+{
+    // In HLSL scalars are the same as 1-vectors.
+    writeVectorRoundingHelpers(sink, 1);
+}
+
+void RoundingHelperWriterHLSL::writeVectorRoundingHelpers(TInfoSinkBase &sink,
+                                                          const unsigned int size)
+{
+    std::stringstream vecTypeStrStr;
+    vecTypeStrStr << "float" << size;
+    std::string vecType = vecTypeStrStr.str();
+
+    // clang-format off
+    sink <<
+        vecType << " angle_frm(" << vecType << " v) {\n"
+        "    v = clamp(v, -65504.0, 65504.0);\n"
+        "    " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n"
+        "    bool" << size << " isNonZero = exponent < -25.0;\n"
+        "    v = v * exp2(-exponent);\n"
+        "    v = sign(v) * floor(abs(v));\n"
+        "    return v * exp2(exponent) * (float" << size << ")(isNonZero);\n"
+        "}\n";
+
+    sink <<
+        vecType << " angle_frl(" << vecType << " v) {\n"
+        "    v = clamp(v, -2.0, 2.0);\n"
+        "    v = v * 256.0;\n"
+        "    v = sign(v) * floor(abs(v));\n"
+        "    return v * 0.00390625;\n"
+        "}\n";
+    // clang-format on
+}