Adding new extension GL_OVR_multiview

GL_OVR_multiview functions exactly the same as GL_OVR_multiview2.
All GL_OVR_multiview2 tests now also repeat the same test using GL_OVR_multiview

Bug: angleproject:3341
Change-Id: I7e5294fb6bbf7692535174a15da6a42e1b5fc4e2
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1575904
Commit-Queue: Rafael Cintron <rafael.cintron@microsoft.com>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/compiler/translator/CollectVariables.cpp b/src/compiler/translator/CollectVariables.cpp
index cbaaf83..813eb13 100644
--- a/src/compiler/translator/CollectVariables.cpp
+++ b/src/compiler/translator/CollectVariables.cpp
@@ -554,7 +554,8 @@
                 else
                 {
                     ASSERT(mShaderType == GL_VERTEX_SHADER &&
-                           IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview2));
+                           (IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview2) ||
+                            IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview)));
                 }
                 break;
             default:
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index b987d18..5dfe9da 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -565,7 +565,8 @@
     }
 
     if ((compileOptions & SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW) &&
-        parseContext.isExtensionEnabled(TExtension::OVR_multiview2) &&
+        (parseContext.isExtensionEnabled(TExtension::OVR_multiview2) ||
+         parseContext.isExtensionEnabled(TExtension::OVR_multiview)) &&
         getShaderType() != GL_COMPUTE_SHADER)
     {
         DeclareAndInitBuiltinsForInstancedMultiview(root, mNumViews, mShaderType, compileOptions,
@@ -975,6 +976,7 @@
         << ":NV_shader_framebuffer_fetch:" << mResources.NV_shader_framebuffer_fetch
         << ":ARM_shader_framebuffer_fetch:" << mResources.ARM_shader_framebuffer_fetch
         << ":OVR_multiview2:" << mResources.OVR_multiview2
+        << ":OVR_multiview:" << mResources.OVR_multiview
         << ":EXT_YUV_target:" << mResources.EXT_YUV_target
         << ":EXT_geometry_shader:" << mResources.EXT_geometry_shader
         << ":MaxVertexOutputVectors:" << mResources.MaxVertexOutputVectors
diff --git a/src/compiler/translator/ExtensionBehavior.cpp b/src/compiler/translator/ExtensionBehavior.cpp
index e602819..c903ff8 100644
--- a/src/compiler/translator/ExtensionBehavior.cpp
+++ b/src/compiler/translator/ExtensionBehavior.cpp
@@ -29,6 +29,7 @@
     OP(OES_EGL_image_external_essl3)             \
     OP(OES_standard_derivatives)                 \
     OP(OES_texture_storage_multisample_2d_array) \
+    OP(OVR_multiview)                            \
     OP(OVR_multiview2)                           \
     OP(ANGLE_multi_draw)
 
diff --git a/src/compiler/translator/ExtensionBehavior.h b/src/compiler/translator/ExtensionBehavior.h
index 161cc66..9c55f8f 100644
--- a/src/compiler/translator/ExtensionBehavior.h
+++ b/src/compiler/translator/ExtensionBehavior.h
@@ -34,6 +34,7 @@
     OES_EGL_image_external_essl3,
     OES_standard_derivatives,
     OES_texture_storage_multisample_2d_array,
+    OVR_multiview,
     OVR_multiview2,
     ANGLE_multi_draw,
 };
diff --git a/src/compiler/translator/Initialize.cpp b/src/compiler/translator/Initialize.cpp
index aec19c9..99ae558 100644
--- a/src/compiler/translator/Initialize.cpp
+++ b/src/compiler/translator/Initialize.cpp
@@ -61,6 +61,10 @@
     {
         extBehavior[TExtension::ARM_shader_framebuffer_fetch] = EBhUndefined;
     }
+    if (resources.OVR_multiview)
+    {
+        extBehavior[TExtension::OVR_multiview] = EBhUndefined;
+    }
     if (resources.OVR_multiview2)
     {
         extBehavior[TExtension::OVR_multiview2] = EBhUndefined;
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index d7257eb..cc24ec6 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -264,6 +264,7 @@
     mUsesPointSize   = false;
     mUsesInstanceID  = false;
     mHasMultiviewExtensionEnabled =
+        IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview) ||
         IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview2);
     mUsesViewID                  = false;
     mUsesVertexID                = false;
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 588488a..19d0fda 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -219,6 +219,12 @@
 
 TParseContext::~TParseContext() {}
 
+bool TParseContext::anyMultiviewExtensionAvailable()
+{
+    return isExtensionEnabled(TExtension::OVR_multiview) ||
+           isExtensionEnabled(TExtension::OVR_multiview2);
+}
+
 bool TParseContext::parseVectorFields(const TSourceLoc &line,
                                       const ImmutableString &compString,
                                       int vecSize,
@@ -1345,8 +1351,7 @@
 
     // If multiview extension is enabled, "in" qualifier is allowed in the vertex shader in previous
     // parsing steps. So it needs to be checked here.
-    if (isExtensionEnabled(TExtension::OVR_multiview2) && mShaderVersion < 300 &&
-        qualifier == EvqVertexIn)
+    if (anyMultiviewExtensionAvailable() && mShaderVersion < 300 && qualifier == EvqVertexIn)
     {
         error(location, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
     }
@@ -3104,8 +3109,7 @@
             return;
         }
     }
-    else if (isExtensionEnabled(TExtension::OVR_multiview2) &&
-             typeQualifier.qualifier == EvqVertexIn)
+    else if (anyMultiviewExtensionAvailable() && typeQualifier.qualifier == EvqVertexIn)
     {
         // This error is only specified in WebGL, but tightens unspecified behavior in the native
         // specification.
@@ -4533,7 +4537,9 @@
     }
     else if (qualifierType == "num_views" && mShaderType == GL_VERTEX_SHADER)
     {
-        if (checkCanUseExtension(qualifierTypeLine, TExtension::OVR_multiview2))
+        if (checkCanUseOneOfExtensions(
+                qualifierTypeLine, std::array<TExtension, 2u>{
+                                       {TExtension::OVR_multiview, TExtension::OVR_multiview2}}))
         {
             parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
         }
@@ -4595,7 +4601,7 @@
     {
         case GL_VERTEX_SHADER:
         {
-            if (mShaderVersion < 300 && !isExtensionEnabled(TExtension::OVR_multiview2))
+            if (mShaderVersion < 300 && !anyMultiviewExtensionAvailable())
             {
                 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
             }
diff --git a/src/compiler/translator/ParseContext.h b/src/compiler/translator/ParseContext.h
index b82816e..b5bf8ae 100644
--- a/src/compiler/translator/ParseContext.h
+++ b/src/compiler/translator/ParseContext.h
@@ -42,6 +42,7 @@
                   const ShBuiltInResources &resources);
     ~TParseContext();
 
+    bool anyMultiviewExtensionAvailable();
     const angle::pp::Preprocessor &getPreprocessor() const { return mPreprocessor; }
     angle::pp::Preprocessor &getPreprocessor() { return mPreprocessor; }
     void *getScanner() const { return mScanner; }
diff --git a/src/compiler/translator/ShaderLang.cpp b/src/compiler/translator/ShaderLang.cpp
index a79c506..78f33de 100644
--- a/src/compiler/translator/ShaderLang.cpp
+++ b/src/compiler/translator/ShaderLang.cpp
@@ -199,6 +199,7 @@
     resources->EXT_shader_framebuffer_fetch             = 0;
     resources->NV_shader_framebuffer_fetch              = 0;
     resources->ARM_shader_framebuffer_fetch             = 0;
+    resources->OVR_multiview                            = 0;
     resources->OVR_multiview2                           = 0;
     resources->EXT_YUV_target                           = 0;
     resources->EXT_geometry_shader                      = 0;
diff --git a/src/compiler/translator/SymbolTable_autogen.cpp b/src/compiler/translator/SymbolTable_autogen.cpp
index da96962..756bf7b 100644
--- a/src/compiler/translator/SymbolTable_autogen.cpp
+++ b/src/compiler/translator/SymbolTable_autogen.cpp
@@ -1603,13 +1603,13 @@
     BuiltInId::gl_ViewID_OVR,
     BuiltInName::gl_ViewID_OVR,
     SymbolType::BuiltIn,
-    TExtension::OVR_multiview2,
+    TExtension::UNDEFINED,
     StaticType::Get<EbtUInt, EbpHigh, EvqViewIDOVR, 1, 1>());
 constexpr const TVariable kVar_gl_ViewID_OVRESSL1(
     BuiltInId::gl_ViewID_OVRESSL1,
     BuiltInName::gl_ViewID_OVR,
     SymbolType::BuiltIn,
-    TExtension::OVR_multiview2,
+    TExtension::UNDEFINED,
     StaticType::Get<EbtInt, EbpHigh, EvqViewIDOVR, 1, 1>());
 constexpr const TVariable kVar_gl_ViewportIndex(
     BuiltInId::gl_ViewportIndex,
@@ -16806,7 +16806,8 @@
                 }
             }
         }
-        if (mResources.OVR_multiview2 && mShaderType != GL_COMPUTE_SHADER)
+        if ((mResources.OVR_multiview || mResources.OVR_multiview2) &&
+            mShaderType != GL_COMPUTE_SHADER)
         {
             switch (nameHash)
             {
@@ -17296,7 +17297,8 @@
                 }
             }
         }
-        if (mResources.OVR_multiview2 && mShaderType != GL_COMPUTE_SHADER)
+        if ((mResources.OVR_multiview || mResources.OVR_multiview2) &&
+            mShaderType != GL_COMPUTE_SHADER)
         {
             switch (nameHash)
             {
diff --git a/src/compiler/translator/TranslatorESSL.cpp b/src/compiler/translator/TranslatorESSL.cpp
index 786a291..d67cf17 100644
--- a/src/compiler/translator/TranslatorESSL.cpp
+++ b/src/compiler/translator/TranslatorESSL.cpp
@@ -132,7 +132,8 @@
     {
         if (iter->second != EBhUndefined)
         {
-            const bool isMultiview = (iter->first == TExtension::OVR_multiview2);
+            const bool isMultiview = (iter->first == TExtension::OVR_multiview) ||
+                                     (iter->first == TExtension::OVR_multiview2);
             if (getResources().NV_shader_framebuffer_fetch &&
                 iter->first == TExtension::EXT_shader_framebuffer_fetch)
             {
diff --git a/src/compiler/translator/TranslatorGLSL.cpp b/src/compiler/translator/TranslatorGLSL.cpp
index 4bd8f54..5752f95 100644
--- a/src/compiler/translator/TranslatorGLSL.cpp
+++ b/src/compiler/translator/TranslatorGLSL.cpp
@@ -277,7 +277,8 @@
             }
         }
 
-        const bool isMultiview = (iter.first == TExtension::OVR_multiview2);
+        const bool isMultiview =
+            (iter.first == TExtension::OVR_multiview) || (iter.first == TExtension::OVR_multiview2);
         if (isMultiview && getShaderType() == GL_VERTEX_SHADER &&
             (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u)
         {
diff --git a/src/compiler/translator/builtin_symbols_hash_autogen.txt b/src/compiler/translator/builtin_symbols_hash_autogen.txt
index 46fc273..5b0be6c 100644
--- a/src/compiler/translator/builtin_symbols_hash_autogen.txt
+++ b/src/compiler/translator/builtin_symbols_hash_autogen.txt
@@ -1 +1 @@
-defc05f112e255400323d95b3610cfeb
\ No newline at end of file
+6edf8fb36322aa738e34a1ef287a4d33
\ No newline at end of file
diff --git a/src/compiler/translator/builtin_variables.json b/src/compiler/translator/builtin_variables.json
index f9461b4..078b7d5 100644
--- a/src/compiler/translator/builtin_variables.json
+++ b/src/compiler/translator/builtin_variables.json
@@ -856,13 +856,12 @@
         }
     },
     "Multiview":{
-        "condition":"mResources.OVR_multiview2 && shaderType != GL_COMPUTE_SHADER",
+        "condition":"(mResources.OVR_multiview||mResources.OVR_multiview2) && shaderType != GL_COMPUTE_SHADER",
         "subgroups":{
             "ESSL3":{
                 "variables":{
                     "gl_ViewID_OVR":{
                         "level":"ESSL3_BUILTINS",
-                        "extension":"OVR_multiview2",
                         "type":{
                             "basic":"UInt",
                             "precision":"High",
@@ -876,7 +875,6 @@
                     "gl_ViewID_OVR":{
                         "suffix":"ESSL1",
                         "level":"ESSL1_BUILTINS",
-                        "extension":"OVR_multiview2",
                         "type":{
                             "basic":"Int",
                             "precision":"High",
diff --git a/src/compiler/translator/glslang.l b/src/compiler/translator/glslang.l
index 8af29a8..5c82a12 100644
--- a/src/compiler/translator/glslang.l
+++ b/src/compiler/translator/glslang.l
@@ -82,7 +82,6 @@
 static int ES2_reserved_ES3_keyword(TParseContext *context, int token);
 static int ES2_keyword_ES3_reserved(TParseContext *context, int token);
 static int ES2_ident_ES3_keyword(TParseContext *context, int token);
-static int ES2_ident_ES3_keyword_multiview_keyword(TParseContext *context, int token);
 static int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token);
 static int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token);
 static int ES2_and_ES3_ident_ES3_1_keyword(TParseContext *context, int token);
@@ -213,7 +212,7 @@
 
 "struct"       { return STRUCT; }
 
-"layout"  { return ES2_ident_ES3_keyword_multiview_keyword(context, LAYOUT); }
+"layout"  { return ES2_ident_ES3_keyword(context, LAYOUT); }
 
 "yuvCscStandardEXT"    { return ES3_extension_keyword_else_ident(context, TExtension::EXT_YUV_target, YUVCSCSTANDARDEXT); }
 "itu_601"              { return yuvcscstandardext_constant(context); }
@@ -523,22 +522,6 @@
     return token;
 }
 
-int ES2_ident_ES3_keyword_multiview_keyword(TParseContext *context, int token)
-{
-    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
-    yyscan_t yyscanner = (yyscan_t) context->getScanner();
-
-    // not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name
-    // except when multiview extension is enabled
-    if (context->getShaderVersion() < 300 && !context->isExtensionEnabled(TExtension::OVR_multiview))
-    {
-        yylval->lex.string = AllocatePoolCharArray(yytext, yyleng);
-        return check_type(yyscanner);
-    }
-
-    return token;
-}
-
 int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token)
 {
     yyscan_t yyscanner = (yyscan_t) context->getScanner();
diff --git a/src/compiler/translator/glslang.y b/src/compiler/translator/glslang.y
index fb38828..6a7da3d 100644
--- a/src/compiler/translator/glslang.y
+++ b/src/compiler/translator/glslang.y
@@ -136,8 +136,8 @@
     }  \
 } while (0)
 
-#define ES2_ONLY(S, L) {  \
-    if (context->getShaderVersion() != 100) do {  \
+#define ES2_ONLY(S, L) do {  \
+    if (context->getShaderVersion() != 100) {  \
         context->error(L, " supported in GLSL ES 1.00 only", S);  \
     }  \
 } while (0)
@@ -148,12 +148,6 @@
     }  \
 } while (0)
 
-#define ES3_OR_NEWER_OR_MULTIVIEW(TOKEN, LINE, REASON) do {  \
-    if (context->getShaderVersion() < 300 && !context->isExtensionEnabled(TExtension::OVR_multiview)) {  \
-        context->error(LINE, REASON " supported in GLSL ES 3.00 and above only", TOKEN);  \
-    }  \
-} while (0)
-
 #define ES3_1_ONLY(TOKEN, LINE, REASON) do {  \
     if (context->getShaderVersion() != 310) {  \
         context->error(LINE, REASON " supported in GLSL ES 3.10 only", TOKEN);  \
@@ -897,7 +891,7 @@
 
 layout_qualifier
     : LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN {
-        ES3_OR_NEWER_OR_MULTIVIEW("layout", @1, "qualifier");
+        ES3_OR_NEWER("layout", @1, "qualifier");
         $$ = $3;
     }
     ;
diff --git a/src/compiler/translator/glslang_lex.cpp b/src/compiler/translator/glslang_lex.cpp
index 2bf0ab3..638c1d3 100644
--- a/src/compiler/translator/glslang_lex.cpp
+++ b/src/compiler/translator/glslang_lex.cpp
@@ -1221,7 +1221,6 @@
 static int ES2_reserved_ES3_keyword(TParseContext *context, int token);
 static int ES2_keyword_ES3_reserved(TParseContext *context, int token);
 static int ES2_ident_ES3_keyword(TParseContext *context, int token);
-static int ES2_ident_ES3_keyword_multiview_keyword(TParseContext *context, int token);
 static int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token);
 static int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token);
 static int ES2_and_ES3_ident_ES3_1_keyword(TParseContext *context, int token);
@@ -2047,7 +2046,7 @@
 	YY_BREAK
 case 87:
 YY_RULE_SETUP
-{ return ES2_ident_ES3_keyword_multiview_keyword(context, LAYOUT); }
+{ return ES2_ident_ES3_keyword(context, LAYOUT); }
 	YY_BREAK
 case 88:
 YY_RULE_SETUP
@@ -3888,22 +3887,6 @@
     return token;
 }
 
-int ES2_ident_ES3_keyword_multiview_keyword(TParseContext *context, int token)
-{
-    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
-    yyscan_t yyscanner = (yyscan_t) context->getScanner();
-
-    // not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name
-    // except when multiview extension is enabled
-    if (context->getShaderVersion() < 300 && !context->isExtensionEnabled(TExtension::OVR_multiview2))
-    {
-        yylval->lex.string = AllocatePoolCharArray(yytext, yyleng);
-        return check_type(yyscanner);
-    }
-
-    return token;
-}
-
 int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token)
 {
     yyscan_t yyscanner = (yyscan_t) context->getScanner();
@@ -4109,4 +4092,3 @@
     return 0;
 }
 
- 
\ No newline at end of file
diff --git a/src/compiler/translator/glslang_tab.cpp b/src/compiler/translator/glslang_tab.cpp
index e092656..bf4efe8 100644
--- a/src/compiler/translator/glslang_tab.cpp
+++ b/src/compiler/translator/glslang_tab.cpp
@@ -738,37 +738,37 @@
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   253,   253,   254,   257,   264,   267,   272,   277,   282,
-     287,   296,   302,   305,   308,   311,   314,   317,   323,   330,
-     336,   339,   347,   350,   356,   359,   365,   369,   376,   384,
-     387,   390,   396,   399,   402,   405,   412,   413,   414,   415,
-     423,   424,   427,   430,   437,   438,   441,   447,   448,   452,
-     459,   460,   463,   466,   469,   475,   476,   479,   485,   486,
-     493,   494,   501,   502,   509,   510,   516,   517,   523,   524,
-     530,   531,   537,   538,   544,   545,   546,   547,   551,   552,
-     553,   557,   561,   565,   569,   576,   579,   585,   592,   599,
-     602,   605,   609,   613,   617,   621,   625,   632,   639,   642,
-     649,   657,   674,   684,   687,   693,   697,   701,   705,   712,
-     719,   722,   726,   730,   735,   742,   746,   750,   754,   759,
-     766,   770,   776,   779,   785,   789,   796,   802,   806,   810,
-     813,   816,   825,   830,   834,   837,   840,   843,   846,   850,
-     853,   857,   860,   863,   866,   869,   872,   879,   886,   889,
-     892,   898,   905,   908,   914,   917,   920,   923,   929,   932,
-     939,   944,   951,   956,   967,   970,   973,   976,   979,   982,
-     986,   990,   994,   998,  1002,  1006,  1010,  1014,  1018,  1022,
-    1026,  1030,  1034,  1038,  1042,  1046,  1050,  1054,  1058,  1062,
-    1066,  1073,  1076,  1079,  1082,  1085,  1088,  1091,  1094,  1097,
-    1100,  1103,  1106,  1109,  1112,  1115,  1118,  1121,  1124,  1127,
-    1130,  1133,  1136,  1146,  1153,  1160,  1163,  1166,  1169,  1172,
-    1175,  1178,  1181,  1184,  1187,  1190,  1193,  1196,  1199,  1202,
-    1210,  1210,  1213,  1213,  1219,  1222,  1228,  1231,  1238,  1242,
-    1248,  1251,  1257,  1261,  1265,  1266,  1272,  1273,  1274,  1275,
-    1276,  1277,  1278,  1282,  1286,  1286,  1286,  1293,  1294,  1298,
-    1298,  1299,  1299,  1304,  1308,  1315,  1319,  1326,  1327,  1331,
-    1337,  1341,  1350,  1350,  1357,  1360,  1366,  1370,  1376,  1376,
-    1381,  1381,  1385,  1385,  1393,  1396,  1402,  1405,  1411,  1415,
-    1422,  1425,  1428,  1431,  1434,  1442,  1448,  1454,  1457,  1463,
-    1463
+       0,   248,   248,   249,   252,   259,   262,   267,   272,   277,
+     282,   291,   297,   300,   303,   306,   309,   312,   318,   325,
+     331,   334,   342,   345,   351,   354,   360,   364,   371,   379,
+     382,   385,   391,   394,   397,   400,   407,   408,   409,   410,
+     418,   419,   422,   425,   432,   433,   436,   442,   443,   447,
+     454,   455,   458,   461,   464,   470,   471,   474,   480,   481,
+     488,   489,   496,   497,   504,   505,   511,   512,   518,   519,
+     525,   526,   532,   533,   539,   540,   541,   542,   546,   547,
+     548,   552,   556,   560,   564,   571,   574,   580,   587,   594,
+     597,   600,   604,   608,   612,   616,   620,   627,   634,   637,
+     644,   652,   669,   679,   682,   688,   692,   696,   700,   707,
+     714,   717,   721,   725,   730,   737,   741,   745,   749,   754,
+     761,   765,   771,   774,   780,   784,   791,   797,   801,   805,
+     808,   811,   820,   825,   829,   832,   835,   838,   841,   845,
+     848,   852,   855,   858,   861,   864,   867,   874,   881,   884,
+     887,   893,   900,   903,   909,   912,   915,   918,   924,   927,
+     934,   939,   946,   951,   962,   965,   968,   971,   974,   977,
+     981,   985,   989,   993,   997,  1001,  1005,  1009,  1013,  1017,
+    1021,  1025,  1029,  1033,  1037,  1041,  1045,  1049,  1053,  1057,
+    1061,  1068,  1071,  1074,  1077,  1080,  1083,  1086,  1089,  1092,
+    1095,  1098,  1101,  1104,  1107,  1110,  1113,  1116,  1119,  1122,
+    1125,  1128,  1131,  1141,  1148,  1155,  1158,  1161,  1164,  1167,
+    1170,  1173,  1176,  1179,  1182,  1185,  1188,  1191,  1194,  1197,
+    1205,  1205,  1208,  1208,  1214,  1217,  1223,  1226,  1233,  1237,
+    1243,  1246,  1252,  1256,  1260,  1261,  1267,  1268,  1269,  1270,
+    1271,  1272,  1273,  1277,  1281,  1281,  1281,  1288,  1289,  1293,
+    1293,  1294,  1294,  1299,  1303,  1310,  1314,  1321,  1322,  1326,
+    1332,  1336,  1345,  1345,  1352,  1355,  1361,  1365,  1371,  1371,
+    1376,  1376,  1380,  1380,  1388,  1391,  1397,  1400,  1406,  1410,
+    1417,  1420,  1423,  1426,  1429,  1437,  1443,  1449,  1452,  1458,
+    1458
 };
 #endif
 
@@ -3735,7 +3735,7 @@
   case 151:
 
     {
-       ES3_OR_NEWER("layout", (yylsp[-3]), "qualifier");
+        ES3_OR_NEWER("layout", (yylsp[-3]), "qualifier");
         (yyval.interm.layoutQualifier) = (yyvsp[-1].interm.layoutQualifier);
     }
 
@@ -5199,4 +5199,3 @@
 int glslang_parse(TParseContext* context) {
     return yyparse(context, context->getScanner());
 }
- 
\ No newline at end of file
diff --git a/src/compiler/translator/glslang_tab.h b/src/compiler/translator/glslang_tab.h
index e05076f..5ffee8a 100644
--- a/src/compiler/translator/glslang_tab.h
+++ b/src/compiler/translator/glslang_tab.h
@@ -43,6 +43,7 @@
 
 #define YYLTYPE TSourceLoc
 #define YYLTYPE_IS_DECLARED 1
+#define YYLTYPE_IS_TRIVIAL 1
 
 /* Token type.  */
 #ifndef YYTOKENTYPE
diff --git a/src/libANGLE/Caps.cpp b/src/libANGLE/Caps.cpp
index a116cd9..e7b0b96 100644
--- a/src/libANGLE/Caps.cpp
+++ b/src/libANGLE/Caps.cpp
@@ -197,8 +197,9 @@
       standardDerivatives(false),
       shaderTextureLOD(false),
       fragDepth(false),
-      multiview2(false),
+      multiview(false),
       maxViews(1u),
+      multiview2(false),
       textureUsage(false),
       translatedShaderSource(false),
       fboRenderMipmap(false),
@@ -865,6 +866,7 @@
         map["GL_OES_standard_derivatives"] = enableableExtension(&Extensions::standardDerivatives);
         map["GL_EXT_shader_texture_lod"] = enableableExtension(&Extensions::shaderTextureLOD);
         map["GL_EXT_frag_depth"] = enableableExtension(&Extensions::fragDepth);
+        map["GL_OVR_multiview"] = enableableExtension(&Extensions::multiview);
         map["GL_OVR_multiview2"] = enableableExtension(&Extensions::multiview2);
         map["GL_ANGLE_texture_usage"] = enableableExtension(&Extensions::textureUsage);
         map["GL_ANGLE_translated_shader_source"] = esOnlyExtension(&Extensions::translatedShaderSource);
diff --git a/src/libANGLE/Caps.h b/src/libANGLE/Caps.h
index fe9bc46..08311de 100644
--- a/src/libANGLE/Caps.h
+++ b/src/libANGLE/Caps.h
@@ -302,9 +302,12 @@
     // GL_EXT_frag_depth
     bool fragDepth;
 
+    // OVR_multiview
+    bool multiview;
+    GLuint maxViews;
+
     // OVR_multiview2
     bool multiview2;
-    GLuint maxViews;
 
     // GL_ANGLE_texture_usage
     bool textureUsage;
diff --git a/src/libANGLE/Compiler.cpp b/src/libANGLE/Compiler.cpp
index 22bc470..9d0106d 100644
--- a/src/libANGLE/Compiler.cpp
+++ b/src/libANGLE/Compiler.cpp
@@ -92,6 +92,9 @@
     mResources.FragmentPrecisionHigh = 1;
     mResources.EXT_frag_depth        = extensions.fragDepth;
 
+    // OVR_multiview state
+    mResources.OVR_multiview = extensions.multiview;
+
     // OVR_multiview2 state
     mResources.OVR_multiview2 = extensions.multiview2;
     mResources.MaxViewsOVR    = extensions.maxViews;
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index 6036492..47c2105 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -3140,6 +3140,7 @@
         supportedExtensions.colorBufferFloat      = false;
         supportedExtensions.eglImageExternalEssl3 = false;
         supportedExtensions.textureNorm16         = false;
+        supportedExtensions.multiview             = false;
         supportedExtensions.multiview2            = false;
         supportedExtensions.maxViews              = 1u;
         supportedExtensions.copyTexture3d         = false;
@@ -7690,7 +7691,7 @@
         return true;
     }
 
-    if (getExtensions().multiview2 && pname == GL_MAX_VIEWS_OVR)
+    if ((getExtensions().multiview2 || getExtensions().multiview) && pname == GL_MAX_VIEWS_OVR)
     {
         *type      = GL_INT;
         *numParams = 1;
diff --git a/src/libANGLE/renderer/d3d/ShaderD3D.cpp b/src/libANGLE/renderer/d3d/ShaderD3D.cpp
index 26cc821..13dbe87 100644
--- a/src/libANGLE/renderer/d3d/ShaderD3D.cpp
+++ b/src/libANGLE/renderer/d3d/ShaderD3D.cpp
@@ -122,7 +122,7 @@
     {
         mAdditionalOptions |= SH_FORCE_ATOMIC_VALUE_RESOLUTION;
     }
-    if (extensions.multiview2)
+    if (extensions.multiview || extensions.multiview2)
     {
         mAdditionalOptions |= SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW;
     }
@@ -271,15 +271,15 @@
         const std::string &translatedSource = mData.getTranslatedSource();
 
         mUsesMultipleRenderTargets = translatedSource.find("GL_USES_MRT") != std::string::npos;
-        mUsesFragColor   = translatedSource.find("GL_USES_FRAG_COLOR") != std::string::npos;
-        mUsesFragData    = translatedSource.find("GL_USES_FRAG_DATA") != std::string::npos;
+        mUsesFragColor      = translatedSource.find("GL_USES_FRAG_COLOR") != std::string::npos;
+        mUsesFragData       = translatedSource.find("GL_USES_FRAG_DATA") != std::string::npos;
         mUsesSecondaryColor = translatedSource.find("GL_USES_SECONDARY_COLOR") != std::string::npos;
-        mUsesFragCoord   = translatedSource.find("GL_USES_FRAG_COORD") != std::string::npos;
-        mUsesFrontFacing = translatedSource.find("GL_USES_FRONT_FACING") != std::string::npos;
-        mUsesPointSize   = translatedSource.find("GL_USES_POINT_SIZE") != std::string::npos;
-        mUsesPointCoord  = translatedSource.find("GL_USES_POINT_COORD") != std::string::npos;
-        mUsesDepthRange  = translatedSource.find("GL_USES_DEPTH_RANGE") != std::string::npos;
-        mUsesFragDepth   = translatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos;
+        mUsesFragCoord      = translatedSource.find("GL_USES_FRAG_COORD") != std::string::npos;
+        mUsesFrontFacing    = translatedSource.find("GL_USES_FRONT_FACING") != std::string::npos;
+        mUsesPointSize      = translatedSource.find("GL_USES_POINT_SIZE") != std::string::npos;
+        mUsesPointCoord     = translatedSource.find("GL_USES_POINT_COORD") != std::string::npos;
+        mUsesDepthRange     = translatedSource.find("GL_USES_DEPTH_RANGE") != std::string::npos;
+        mUsesFragDepth      = translatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos;
         mHasANGLEMultiviewEnabled =
             translatedSource.find("GL_ANGLE_MULTIVIEW_ENABLED") != std::string::npos;
         mUsesVertexID = translatedSource.find("GL_USES_VERTEX_ID") != std::string::npos;
diff --git a/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
index 835bdb2..56df36f 100644
--- a/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
@@ -1866,7 +1866,7 @@
 
     mShaderConstants.init(caps);
 
-    mIsMultiviewEnabled = extensions.multiview2;
+    mIsMultiviewEnabled = extensions.multiview || extensions.multiview2;
 
     ANGLE_TRY(mVertexDataManager.initialize(context));
 
diff --git a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
index e88b906..8fbb77a 100644
--- a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
@@ -334,6 +334,9 @@
     {
         mAppliedNumViewsToDivisor = numViews;
         mAttribsToTranslate.set();
+        // mDynamicAttribsMask may have already been set (updateVertexAttribStorage
+        // We don't want to override DYNAMIC attribs as they will be handled separately.
+        mAttribsToTranslate = mAttribsToTranslate ^ mDynamicAttribsMask;
     }
 }
 
diff --git a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
index fa20c72..1f8ab91 100644
--- a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -1619,8 +1619,9 @@
     extensions->standardDerivatives    = GetDerivativeInstructionSupport(featureLevel);
     extensions->shaderTextureLOD       = GetShaderTextureLODSupport(featureLevel);
     extensions->fragDepth              = true;
+    extensions->multiview              = IsMultiviewSupported(featureLevel);
     extensions->multiview2             = IsMultiviewSupported(featureLevel);
-    if (extensions->multiview2)
+    if (extensions->multiview || extensions->multiview2)
     {
         extensions->maxViews =
             std::min(static_cast<GLuint>(gl::IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS),
@@ -1643,12 +1644,12 @@
     extensions->copyTexture                      = true;
     extensions->copyCompressedTexture            = true;
     extensions->textureStorageMultisample2DArray = true;
-    extensions->multiviewMultisample =
-        (extensions->multiview2 && extensions->textureStorageMultisample2DArray);
-    extensions->copyTexture3d      = true;
-    extensions->textureBorderClamp = true;
-    extensions->textureMultisample = true;
-    extensions->provokingVertex    = true;
+    extensions->multiviewMultisample     = ((extensions->multiview || extensions->multiview2) &&
+                                        extensions->textureStorageMultisample2DArray);
+    extensions->copyTexture3d            = true;
+    extensions->textureBorderClamp       = true;
+    extensions->textureMultisample       = true;
+    extensions->provokingVertex          = true;
     extensions->blendFuncExtended        = true;
     extensions->maxDualSourceDrawBuffers = 1;
 
diff --git a/src/libANGLE/renderer/gl/StateManagerGL.cpp b/src/libANGLE/renderer/gl/StateManagerGL.cpp
index ff9727d..4da46ee 100644
--- a/src/libANGLE/renderer/gl/StateManagerGL.cpp
+++ b/src/libANGLE/renderer/gl/StateManagerGL.cpp
@@ -126,7 +126,7 @@
       mPathStencilFunc(GL_ALWAYS),
       mPathStencilRef(0),
       mPathStencilMask(std::numeric_limits<GLuint>::max()),
-      mIsMultiviewEnabled(extensions.multiview2),
+      mIsMultiviewEnabled(extensions.multiview || extensions.multiview2),
       mProvokingVertex(GL_LAST_VERTEX_CONVENTION),
       mLocalDirtyBits()
 {
diff --git a/src/libANGLE/renderer/gl/renderergl_utils.cpp b/src/libANGLE/renderer/gl/renderergl_utils.cpp
index 7752832..030f264 100644
--- a/src/libANGLE/renderer/gl/renderergl_utils.cpp
+++ b/src/libANGLE/renderer/gl/renderergl_utils.cpp
@@ -1108,6 +1108,7 @@
 
     if (functions->hasGLExtension("GL_NV_viewport_array2"))
     {
+        extensions->multiview  = true;
         extensions->multiview2 = true;
         // GL_MAX_ARRAY_TEXTURE_LAYERS is guaranteed to be at least 256.
         const int maxLayers = QuerySingleGLInt(functions, GL_MAX_ARRAY_TEXTURE_LAYERS);
@@ -1204,8 +1205,8 @@
     extensions->textureStorageMultisample2DArray =
         functions->isAtLeastGL(gl::Version(4, 2)) || functions->isAtLeastGLES(gl::Version(3, 2));
 
-    extensions->multiviewMultisample =
-        extensions->textureStorageMultisample2DArray && extensions->multiview2;
+    extensions->multiviewMultisample = extensions->textureStorageMultisample2DArray &&
+                                       (extensions->multiview || extensions->multiview2);
 
     extensions->textureMultisample = functions->isAtLeastGL(gl::Version(3, 2)) ||
                                      functions->hasGLExtension("GL_ARB_texture_multisample");
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index 54c54a8..9b62d1f 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -2699,7 +2699,7 @@
             return kTextureTypeConflict;
         }
 
-        if (extensions.multiview2)
+        if (extensions.multiview || extensions.multiview2)
         {
             const int programNumViews     = program->usesMultiview() ? program->getNumViews() : 1;
             const int framebufferNumViews = framebuffer->getNumViews();
@@ -3860,7 +3860,8 @@
 
         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR:
         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR:
-            if (clientVersion < 3 || !context->getExtensions().multiview2)
+            if (clientVersion < 3 ||
+                !(context->getExtensions().multiview || context->getExtensions().multiview2))
             {
                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
                 return false;
diff --git a/src/libANGLE/validationES2.cpp b/src/libANGLE/validationES2.cpp
index c4e05e1..248a511 100644
--- a/src/libANGLE/validationES2.cpp
+++ b/src/libANGLE/validationES2.cpp
@@ -2689,7 +2689,7 @@
         }
     }
 
-    if (extensions.multiview2 && extensions.disjointTimerQuery)
+    if ((extensions.multiview || extensions.multiview2) && extensions.disjointTimerQuery)
     {
         const State &state       = context->getState();
         Framebuffer *framebuffer = state.getDrawFramebuffer();
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp
index 1acb578..5d555a1 100644
--- a/src/libANGLE/validationES3.cpp
+++ b/src/libANGLE/validationES3.cpp
@@ -36,7 +36,7 @@
                                                   GLint level,
                                                   GLsizei numViews)
 {
-    if (!context->getExtensions().multiview2)
+    if (!(context->getExtensions().multiview || context->getExtensions().multiview2))
     {
         context->validationError(GL_INVALID_OPERATION, kMultiviewNotAvailable);
         return false;
diff --git a/src/libGLESv2/proc_table_data.json b/src/libGLESv2/proc_table_data.json
index 3976915..2489731 100644
--- a/src/libGLESv2/proc_table_data.json
+++ b/src/libGLESv2/proc_table_data.json
@@ -578,6 +578,10 @@
       "glMultiDrawElementsInstancedANGLE"
     ],
 
+    "GL_OVR_multiview": [
+        "glFramebufferTextureMultiviewOVR"
+    ],
+
     "GL_OVR_multiview2": [
         "glFramebufferTextureMultiviewOVR"
     ],
diff --git a/src/tests/angle_perftests.gni b/src/tests/angle_perftests.gni
index c63b02c..c969c23 100644
--- a/src/tests/angle_perftests.gni
+++ b/src/tests/angle_perftests.gni
@@ -32,6 +32,10 @@
   "perf_tests/glmark2Benchmark.cpp",
   "perf_tests/third_party/perf/perf_test.cc",
   "perf_tests/third_party/perf/perf_test.h",
+  "test_utils/ANGLETest.cpp",
+  "test_utils/ANGLETest.h",
+  "test_utils/MultiviewTest.cpp",
+  "test_utils/MultiviewTest.h",
   "test_utils/angle_test_configs.cpp",
   "test_utils/angle_test_configs.h",
   "test_utils/angle_test_instantiate.cpp",
diff --git a/src/tests/angle_unittests.gni b/src/tests/angle_unittests.gni
index 15847eb..fa132e9 100644
--- a/src/tests/angle_unittests.gni
+++ b/src/tests/angle_unittests.gni
@@ -100,6 +100,7 @@
   "../tests/compiler_tests/UnfoldShortCircuitAST_test.cpp",
   "../tests/compiler_tests/VariablePacker_test.cpp",
   "../tests/compiler_tests/VectorizeVectorScalarArithmetic_test.cpp",
+  "../tests/compiler_tests/OVR_multiview_test.cpp",
   "../tests/compiler_tests/OVR_multiview2_test.cpp",
   "../tests/compiler_tests/WorkGroupSize_test.cpp",
   "../tests/test_expectations/GPUTestExpectationsParser_unittest.cpp",
diff --git a/src/tests/compiler_tests/OVR_multiview2_test.cpp b/src/tests/compiler_tests/OVR_multiview2_test.cpp
index b294a2f..2ac541e 100644
--- a/src/tests/compiler_tests/OVR_multiview2_test.cpp
+++ b/src/tests/compiler_tests/OVR_multiview2_test.cpp
@@ -3,7 +3,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// WEBGL_multiview_test.cpp:
+// OVR_multiview2_test.cpp:
 //   Test that shaders with gl_ViewID_OVR are validated correctly.
 //
 
@@ -87,10 +87,10 @@
     TQualifier mSymbolQualifier;
 };
 
-class OVRMultiviewVertexShaderTest : public ShaderCompileTreeTest
+class OVRMultiview2VertexShaderTest : public ShaderCompileTreeTest
 {
   public:
-    OVRMultiviewVertexShaderTest() {}
+    OVRMultiview2VertexShaderTest() {}
 
   protected:
     ::GLenum getShaderType() const override { return GL_VERTEX_SHADER; }
@@ -102,10 +102,10 @@
     }
 };
 
-class OVRMultiviewFragmentShaderTest : public ShaderCompileTreeTest
+class OVRMultiview2FragmentShaderTest : public ShaderCompileTreeTest
 {
   public:
-    OVRMultiviewFragmentShaderTest() {}
+    OVRMultiview2FragmentShaderTest() {}
 
   protected:
     ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
@@ -117,10 +117,10 @@
     }
 };
 
-class OVRMultiviewOutputCodeTest : public MatchOutputCodeTest
+class OVRMultiview2OutputCodeTest : public MatchOutputCodeTest
 {
   public:
-    OVRMultiviewOutputCodeTest(sh::GLenum shaderType)
+    OVRMultiview2OutputCodeTest(sh::GLenum shaderType)
         : MatchOutputCodeTest(shaderType, 0, SH_ESSL_OUTPUT)
     {
         addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT);
@@ -151,22 +151,22 @@
     }
 };
 
-class OVRMultiviewVertexShaderOutputCodeTest : public OVRMultiviewOutputCodeTest
+class OVRMultiview2VertexShaderOutputCodeTest : public OVRMultiview2OutputCodeTest
 {
   public:
-    OVRMultiviewVertexShaderOutputCodeTest() : OVRMultiviewOutputCodeTest(GL_VERTEX_SHADER) {}
+    OVRMultiview2VertexShaderOutputCodeTest() : OVRMultiview2OutputCodeTest(GL_VERTEX_SHADER) {}
 };
 
-class OVRMultiviewFragmentShaderOutputCodeTest : public OVRMultiviewOutputCodeTest
+class OVRMultiview2FragmentShaderOutputCodeTest : public OVRMultiview2OutputCodeTest
 {
   public:
-    OVRMultiviewFragmentShaderOutputCodeTest() : OVRMultiviewOutputCodeTest(GL_FRAGMENT_SHADER) {}
+    OVRMultiview2FragmentShaderOutputCodeTest() : OVRMultiview2OutputCodeTest(GL_FRAGMENT_SHADER) {}
 };
 
-class OVRMultiviewComputeShaderOutputCodeTest : public OVRMultiviewOutputCodeTest
+class OVRMultiview2ComputeShaderOutputCodeTest : public OVRMultiview2OutputCodeTest
 {
   public:
-    OVRMultiviewComputeShaderOutputCodeTest() : OVRMultiviewOutputCodeTest(GL_COMPUTE_SHADER) {}
+    OVRMultiview2ComputeShaderOutputCodeTest() : OVRMultiview2OutputCodeTest(GL_COMPUTE_SHADER) {}
 };
 
 void VariableOccursNTimes(TIntermBlock *root,
@@ -189,7 +189,7 @@
 
 // Unsupported GL_OVR_multiview extension directive (GL_OVR_multiview2 spec only exposes
 // GL_OVR_multiview2).
-TEST_F(OVRMultiviewVertexShaderTest, InvalidMultiview2)
+TEST_F(OVRMultiview2VertexShaderTest, InvalidMultiview2)
 {
     const std::string &shaderString =
         "#version 300 es\n"
@@ -207,7 +207,7 @@
 }
 
 // Invalid combination of non-matching num_views declarations.
-TEST_F(OVRMultiviewVertexShaderTest, InvalidNumViewsMismatch)
+TEST_F(OVRMultiview2VertexShaderTest, InvalidNumViewsMismatch)
 {
     const std::string &shaderString =
         "#version 300 es\n"
@@ -226,7 +226,7 @@
 }
 
 // Invalid value zero for num_views.
-TEST_F(OVRMultiviewVertexShaderTest, InvalidNumViewsZero)
+TEST_F(OVRMultiview2VertexShaderTest, InvalidNumViewsZero)
 {
     const std::string &shaderString =
         "#version 300 es\n"
@@ -244,7 +244,7 @@
 }
 
 // Too large value for num_views.
-TEST_F(OVRMultiviewVertexShaderTest, InvalidNumViewsGreaterThanMax)
+TEST_F(OVRMultiview2VertexShaderTest, InvalidNumViewsGreaterThanMax)
 {
     const std::string &shaderString =
         "#version 300 es\n"
@@ -262,7 +262,7 @@
 }
 
 // Valid use of gl_ViewID_OVR.
-TEST_F(OVRMultiviewVertexShaderTest, ViewIDUsed)
+TEST_F(OVRMultiview2VertexShaderTest, ViewIDUsed)
 {
     const std::string &shaderString =
         "#version 300 es\n"
@@ -292,7 +292,7 @@
 }
 
 // Read gl_FragCoord in a OVR_multiview2 fragment shader.
-TEST_F(OVRMultiviewFragmentShaderTest, ReadOfFragCoord)
+TEST_F(OVRMultiview2FragmentShaderTest, ReadOfFragCoord)
 {
     const std::string &shaderString =
         "#version 300 es\n"
@@ -310,7 +310,7 @@
 }
 
 // Read gl_ViewID_OVR in an OVR_multiview2 fragment shader.
-TEST_F(OVRMultiviewFragmentShaderTest, ReadOfViewID)
+TEST_F(OVRMultiview2FragmentShaderTest, ReadOfViewID)
 {
     const std::string &shaderString =
         "#version 300 es\n"
@@ -328,7 +328,7 @@
 }
 
 // Correct use of GL_OVR_multiview2 macro.
-TEST_F(OVRMultiviewVertexShaderTest, UseOfExtensionMacro)
+TEST_F(OVRMultiview2VertexShaderTest, UseOfExtensionMacro)
 {
     const std::string &shaderString =
         "#version 300 es\n"
@@ -347,7 +347,7 @@
 }
 
 // Test that gl_ViewID_OVR can't be used as an l-value.
-TEST_F(OVRMultiviewVertexShaderTest, ViewIdAsLValue)
+TEST_F(OVRMultiview2VertexShaderTest, ViewIdAsLValue)
 {
     const std::string &shaderString =
         "#version 300 es\n"
@@ -369,7 +369,7 @@
 }
 
 // Test that compiling an ESSL 1.00 shader with multiview support fails.
-TEST_F(OVRMultiviewVertexShaderTest, ESSL1Shader)
+TEST_F(OVRMultiview2VertexShaderTest, ESSL1Shader)
 {
     const std::string &shaderString =
         "#extension GL_OVR_multiview2 : require\n"
@@ -392,7 +392,7 @@
 }
 
 // Test that compiling an ESSL 1.00 shader with an unsupported global layout qualifier fails.
-TEST_F(OVRMultiviewVertexShaderTest, ESSL1ShaderUnsupportedGlobalLayoutQualifier)
+TEST_F(OVRMultiview2VertexShaderTest, ESSL1ShaderUnsupportedGlobalLayoutQualifier)
 {
     const std::string &shaderString =
         "#extension GL_OVR_multiview2 : require\n"
@@ -416,7 +416,7 @@
 }
 
 // Test that compiling an ESSL 1.00 vertex shader with an unsupported input storage qualifier fails.
-TEST_F(OVRMultiviewVertexShaderTest, ESSL1ShaderUnsupportedInputStorageQualifier)
+TEST_F(OVRMultiview2VertexShaderTest, ESSL1ShaderUnsupportedInputStorageQualifier)
 {
     const std::string &shaderString =
         "#extension GL_OVR_multiview2 : require\n"
@@ -441,7 +441,7 @@
 
 // Test that compiling an ESSL 1.00 fragment shader with an unsupported input storage qualifier
 // fails.
-TEST_F(OVRMultiviewFragmentShaderTest, ESSL1ShaderUnsupportedInStorageQualifier)
+TEST_F(OVRMultiview2FragmentShaderTest, ESSL1ShaderUnsupportedInStorageQualifier)
 {
     const std::string &shaderString =
         "#extension GL_OVR_multiview2 : require\n"
@@ -468,7 +468,7 @@
 // twice: once to initialize ViewID_OVR and once for InstanceID. The number of occurrences of
 // InstanceID in the AST should be the sum of two and the number of occurrences of gl_InstanceID
 // before any renaming.
-TEST_F(OVRMultiviewVertexShaderTest, GLInstanceIDIsRenamed)
+TEST_F(OVRMultiview2VertexShaderTest, GLInstanceIDIsRenamed)
 {
     const std::string &shaderString =
         "#version 300 es\n"
@@ -504,7 +504,7 @@
 // Test that gl_ViewID_OVR gets correctly replaced by ViewID_OVR. gl_ViewID_OVR should not be found
 // by either name or qualifier. The number of occurrences of ViewID_OVR in the AST should be the sum
 // of two and the number of occurrences of gl_ViewID_OVR before any renaming.
-TEST_F(OVRMultiviewVertexShaderTest, GLViewIDIsRenamed)
+TEST_F(OVRMultiview2VertexShaderTest, GLViewIDIsRenamed)
 {
     const std::string &shaderString =
         "#version 300 es\n"
@@ -536,7 +536,7 @@
 
 // The test checks that ViewID_OVR and InstanceID have the correct initializers based on the
 // number of views.
-TEST_F(OVRMultiviewVertexShaderOutputCodeTest, ViewIDAndInstanceIDHaveCorrectValues)
+TEST_F(OVRMultiview2VertexShaderOutputCodeTest, ViewIDAndInstanceIDHaveCorrectValues)
 {
     const std::string &shaderString =
         "#version 300 es\n"
@@ -564,7 +564,7 @@
 
 // The test checks that the directive enabling GL_OVR_multiview2 is not outputted if the extension
 // is emulated.
-TEST_F(OVRMultiviewVertexShaderOutputCodeTest, StrippedOVRMultiviewDirective)
+TEST_F(OVRMultiview2VertexShaderOutputCodeTest, StrippedOVRMultiviewDirective)
 {
     const std::string &shaderString =
         "#version 300 es\n"
@@ -585,7 +585,7 @@
 }
 
 // Test that ViewID_OVR is declared as a flat input variable in an ESSL 3.00 fragment shader.
-TEST_F(OVRMultiviewFragmentShaderTest, ViewIDDeclaredAsFlatInput)
+TEST_F(OVRMultiview2FragmentShaderTest, ViewIDDeclaredAsFlatInput)
 {
     const std::string &shaderString =
         "#version 300 es\n"
@@ -599,7 +599,7 @@
 }
 
 // Test that ViewID_OVR is declared as a flat output variable in an ESSL 1.00 vertex shader.
-TEST_F(OVRMultiviewVertexShaderTest, ViewIDDeclaredAsFlatOutput)
+TEST_F(OVRMultiview2VertexShaderTest, ViewIDDeclaredAsFlatOutput)
 {
     const std::string &shaderString =
         "#extension GL_OVR_multiview2 : require\n"
@@ -613,7 +613,7 @@
 
 // The test checks that the GL_NV_viewport_array2 extension is emitted in a vertex shader if the
 // SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set.
-TEST_F(OVRMultiviewVertexShaderOutputCodeTest, ViewportArray2IsEmitted)
+TEST_F(OVRMultiview2VertexShaderOutputCodeTest, ViewportArray2IsEmitted)
 {
     const std::string &shaderString =
         "#version 300 es\n"
@@ -630,7 +630,7 @@
 // The test checks that the GL_NV_viewport_array2 extension is not emitted in a vertex shader if the
 // OVR_multiview2 extension is not requested in the shader source even if the
 // SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set.
-TEST_F(OVRMultiviewVertexShaderOutputCodeTest, ViewportArray2IsNotEmitted)
+TEST_F(OVRMultiview2VertexShaderOutputCodeTest, ViewportArray2IsNotEmitted)
 {
     const std::string &shaderString =
         "#version 300 es\n"
@@ -645,7 +645,7 @@
 
 // The test checks that the GL_NV_viewport_array2 extension is not emitted in a fragment shader if
 // the SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set.
-TEST_F(OVRMultiviewFragmentShaderOutputCodeTest, ViewportArray2IsNotEmitted)
+TEST_F(OVRMultiview2FragmentShaderOutputCodeTest, ViewportArray2IsNotEmitted)
 {
     const std::string &shaderString =
         "#version 300 es\n"
@@ -661,7 +661,7 @@
 
 // The test checks that the GL_NV_viewport_array2 extension is not emitted in a compute shader if
 // the SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set.
-TEST_F(OVRMultiviewComputeShaderOutputCodeTest, ViewportArray2IsNotEmitted)
+TEST_F(OVRMultiview2ComputeShaderOutputCodeTest, ViewportArray2IsNotEmitted)
 {
     const std::string &shaderString =
         R"(#version 310 es
@@ -677,7 +677,7 @@
 
 // The test checks that the viewport index is selected after the initialization of ViewID_OVR for
 // GLSL and ESSL ouputs.
-TEST_F(OVRMultiviewVertexShaderOutputCodeTest, GlViewportIndexIsSet)
+TEST_F(OVRMultiview2VertexShaderOutputCodeTest, GlViewportIndexIsSet)
 {
     const std::string &shaderString =
         "#version 300 es\n"
@@ -697,7 +697,7 @@
 
 // The test checks that the layer is selected after the initialization of ViewID_OVR for
 // GLSL and ESSL ouputs.
-TEST_F(OVRMultiviewVertexShaderOutputCodeTest, GlLayerIsSet)
+TEST_F(OVRMultiview2VertexShaderOutputCodeTest, GlLayerIsSet)
 {
     const std::string &shaderString =
         "#version 300 es\n"
diff --git a/src/tests/compiler_tests/OVR_multiview_test.cpp b/src/tests/compiler_tests/OVR_multiview_test.cpp
new file mode 100644
index 0000000..9dc94d6
--- /dev/null
+++ b/src/tests/compiler_tests/OVR_multiview_test.cpp
@@ -0,0 +1,719 @@
+//
+// Copyright 2019 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.
+//
+// OVR_multiview_test.cpp:
+//   Test that shaders with gl_ViewID_OVR are validated correctly.
+//
+
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/translator/tree_util/IntermTraverse.h"
+#include "tests/test_utils/ShaderCompileTreeTest.h"
+#include "tests/test_utils/compiler_test.h"
+
+using namespace sh;
+
+namespace
+{
+
+class SymbolOccurrenceCounter : public TIntermTraverser
+{
+  public:
+    SymbolOccurrenceCounter() : TIntermTraverser(true, false, false), mNumberOfOccurrences(0u) {}
+
+    void visitSymbol(TIntermSymbol *node) override
+    {
+        if (shouldCountSymbol(node))
+        {
+            ++mNumberOfOccurrences;
+        }
+    }
+
+    virtual bool shouldCountSymbol(const TIntermSymbol *node) const = 0;
+
+    unsigned getNumberOfOccurrences() const { return mNumberOfOccurrences; }
+
+  private:
+    unsigned mNumberOfOccurrences;
+};
+
+class SymbolOccurrenceCounterByQualifier : public SymbolOccurrenceCounter
+{
+  public:
+    SymbolOccurrenceCounterByQualifier(TQualifier symbolQualifier)
+        : mSymbolQualifier(symbolQualifier)
+    {}
+
+    bool shouldCountSymbol(const TIntermSymbol *node) const override
+    {
+        return node->getQualifier() == mSymbolQualifier;
+    }
+
+  private:
+    TQualifier mSymbolQualifier;
+};
+
+class SymbolOccurrenceCounterByName : public SymbolOccurrenceCounter
+{
+  public:
+    SymbolOccurrenceCounterByName(const ImmutableString &symbolName) : mSymbolName(symbolName) {}
+
+    bool shouldCountSymbol(const TIntermSymbol *node) const override
+    {
+        return node->variable().symbolType() != SymbolType::Empty && node->getName() == mSymbolName;
+    }
+
+  private:
+    ImmutableString mSymbolName;
+};
+
+class SymbolOccurrenceCounterByNameAndQualifier : public SymbolOccurrenceCounter
+{
+  public:
+    SymbolOccurrenceCounterByNameAndQualifier(const ImmutableString &symbolName,
+                                              TQualifier qualifier)
+        : mSymbolName(symbolName), mSymbolQualifier(qualifier)
+    {}
+
+    bool shouldCountSymbol(const TIntermSymbol *node) const override
+    {
+        return node->variable().symbolType() != SymbolType::Empty &&
+               node->getName() == mSymbolName && node->getQualifier() == mSymbolQualifier;
+    }
+
+  private:
+    ImmutableString mSymbolName;
+    TQualifier mSymbolQualifier;
+};
+
+class OVRMultiviewVertexShaderTest : public ShaderCompileTreeTest
+{
+  public:
+    OVRMultiviewVertexShaderTest() {}
+
+  protected:
+    ::GLenum getShaderType() const override { return GL_VERTEX_SHADER; }
+    ShShaderSpec getShaderSpec() const override { return SH_WEBGL3_SPEC; }
+    void initResources(ShBuiltInResources *resources) override
+    {
+        resources->OVR_multiview = 1;
+        resources->MaxViewsOVR   = 4;
+    }
+};
+
+class OVRMultiviewFragmentShaderTest : public ShaderCompileTreeTest
+{
+  public:
+    OVRMultiviewFragmentShaderTest() {}
+
+  protected:
+    ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
+    ShShaderSpec getShaderSpec() const override { return SH_WEBGL3_SPEC; }
+    void initResources(ShBuiltInResources *resources) override
+    {
+        resources->OVR_multiview = 1;
+        resources->MaxViewsOVR   = 4;
+    }
+};
+
+class OVRMultiviewOutputCodeTest : public MatchOutputCodeTest
+{
+  public:
+    OVRMultiviewOutputCodeTest(sh::GLenum shaderType)
+        : MatchOutputCodeTest(shaderType, 0, SH_ESSL_OUTPUT)
+    {
+        addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT);
+
+        getResources()->OVR_multiview = 1;
+        getResources()->MaxViewsOVR   = 4;
+    }
+
+    void requestHLSLOutput()
+    {
+#if defined(ANGLE_ENABLE_HLSL)
+        addOutputType(SH_HLSL_4_1_OUTPUT);
+#endif
+    }
+
+    bool foundInAllGLSLCode(const char *str)
+    {
+        return foundInGLSLCode(str) && foundInESSLCode(str);
+    }
+
+    bool foundInHLSLCode(const char *stringToFind) const
+    {
+#if defined(ANGLE_ENABLE_HLSL)
+        return foundInCode(SH_HLSL_4_1_OUTPUT, stringToFind);
+#else
+        return true;
+#endif
+    }
+};
+
+class OVRMultiviewVertexShaderOutputCodeTest : public OVRMultiviewOutputCodeTest
+{
+  public:
+    OVRMultiviewVertexShaderOutputCodeTest() : OVRMultiviewOutputCodeTest(GL_VERTEX_SHADER) {}
+};
+
+class OVRMultiviewFragmentShaderOutputCodeTest : public OVRMultiviewOutputCodeTest
+{
+  public:
+    OVRMultiviewFragmentShaderOutputCodeTest() : OVRMultiviewOutputCodeTest(GL_FRAGMENT_SHADER) {}
+};
+
+class OVRMultiviewComputeShaderOutputCodeTest : public OVRMultiviewOutputCodeTest
+{
+  public:
+    OVRMultiviewComputeShaderOutputCodeTest() : OVRMultiviewOutputCodeTest(GL_COMPUTE_SHADER) {}
+};
+
+void VariableOccursNTimes(TIntermBlock *root,
+                          const ImmutableString &varName,
+                          const TQualifier varQualifier,
+                          unsigned n)
+{
+    // Check that there are n occurrences of the variable with the given name and qualifier.
+    SymbolOccurrenceCounterByNameAndQualifier viewIDByNameAndQualifier(varName, varQualifier);
+    root->traverse(&viewIDByNameAndQualifier);
+    EXPECT_EQ(n, viewIDByNameAndQualifier.getNumberOfOccurrences());
+
+    // Check that there are n occurrences of the variable with the given name. By this we guarantee
+    // that there are no other occurrences of the variable with the same name but different
+    // qualifier.
+    SymbolOccurrenceCounterByName viewIDByName(varName);
+    root->traverse(&viewIDByName);
+    EXPECT_EQ(n, viewIDByName.getNumberOfOccurrences());
+}
+
+// Unsupported GL_OVR_multiview extension directive (GL_OVR_multiview spec only exposes
+// GL_OVR_multiview).
+TEST_F(OVRMultiviewVertexShaderTest, InvalidMultiview)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview2 : require\n"
+        "layout(num_views = 2) in;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position.x = (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
+        "    gl_Position.yzw = vec3(0, 0, 1);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Invalid combination of non-matching num_views declarations.
+TEST_F(OVRMultiviewVertexShaderTest, InvalidNumViewsMismatch)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 2) in;\n"
+        "layout(num_views = 1) in;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position.x = (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
+        "    gl_Position.yzw = vec3(0, 0, 1);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Invalid value zero for num_views.
+TEST_F(OVRMultiviewVertexShaderTest, InvalidNumViewsZero)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 0) in;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position.x = (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
+        "    gl_Position.yzw = vec3(0, 0, 1);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Too large value for num_views.
+TEST_F(OVRMultiviewVertexShaderTest, InvalidNumViewsGreaterThanMax)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 5) in;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position.x = (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
+        "    gl_Position.yzw = vec3(0, 0, 1);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Valid use of gl_ViewID_OVR.
+TEST_F(OVRMultiviewVertexShaderTest, ViewIDUsed)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 2) in;\n"
+        "layout(num_views = 2) in;  // Duplicated on purpose\n"
+        "in vec4 pos;\n"
+        "out float myOutput;\n"
+        "void main()\n"
+        "{\n"
+        "    if (gl_ViewID_OVR == 0u)\n"
+        "    {\n"
+        "        gl_Position = pos;\n"
+        "        myOutput = 1.0;\n"
+        "    }\n"
+        "    else\n"
+        "    {\n"
+        "        gl_Position = pos + vec4(1.0, 0.0, 0.0, 0.0);\n"
+        "        myOutput = 2.0;\n"
+        "    }\n"
+        "    gl_Position += (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Read gl_FragCoord in a OVR_multiview2 fragment shader.
+TEST_F(OVRMultiviewFragmentShaderTest, ReadOfFragCoord)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "precision highp float;\n"
+        "out vec4 outColor;\n"
+        "void main()\n"
+        "{\n"
+        "    outColor = vec4(gl_FragCoord.xy, 0, 1);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Read gl_ViewID_OVR in an OVR_multiview2 fragment shader.
+TEST_F(OVRMultiviewFragmentShaderTest, ReadOfViewID)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "precision highp float;\n"
+        "out vec4 outColor;\n"
+        "void main()\n"
+        "{\n"
+        "    outColor = vec4(gl_ViewID_OVR, 0, 0, 1);\n"
+        "}\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Correct use of GL_OVR_multiview macro.
+TEST_F(OVRMultiviewVertexShaderTest, UseOfExtensionMacro)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#ifdef GL_OVR_multiview\n"
+        "#if (GL_OVR_multiview == 1)\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
+        "}\n"
+        "#endif\n"
+        "#endif\n";
+    if (!compile(shaderString))
+    {
+        FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
+    }
+}
+
+// Test that gl_ViewID_OVR can't be used as an l-value.
+TEST_F(OVRMultiviewVertexShaderTest, ViewIdAsLValue)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 2) in;\n"
+        "void foo(out uint u)\n"
+        "{\n"
+        "    u = 3u;\n"
+        "}\n"
+        "void main()\n"
+        "{\n"
+        "    foo(gl_ViewID_OVR);\n"
+        "    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that compiling an ESSL 1.00 shader with multiview support fails.
+TEST_F(OVRMultiviewVertexShaderTest, ESSL1Shader)
+{
+    const std::string &shaderString =
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 2) in;\n"
+        "void main()\n"
+        "{\n"
+        "    if (gl_ViewID_OVR == 0)\n"
+        "    {\n"
+        "        gl_Position = vec4(-1.0, 0.0, 0.0, 1.0);\n"
+        "    }\n"
+        "    else\n"
+        "    {\n"
+        "        gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
+        "    }\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that compiling an ESSL 1.00 shader with an unsupported global layout qualifier fails.
+TEST_F(OVRMultiviewVertexShaderTest, ESSL1ShaderUnsupportedGlobalLayoutQualifier)
+{
+    const std::string &shaderString =
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 2) in;\n"
+        "layout(std140) uniform;\n"
+        "void main()\n"
+        "{\n"
+        "    if (gl_ViewID_OVR == 0)\n"
+        "    {\n"
+        "        gl_Position = vec4(-1.0, 0.0, 0.0, 1.0);\n"
+        "    }\n"
+        "    else\n"
+        "    {\n"
+        "        gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
+        "    }\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that compiling an ESSL 1.00 vertex shader with an unsupported input storage qualifier fails.
+TEST_F(OVRMultiviewVertexShaderTest, ESSL1ShaderUnsupportedInputStorageQualifier)
+{
+    const std::string &shaderString =
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 2) in;\n"
+        "in vec4 pos;\n"
+        "void main()\n"
+        "{\n"
+        "    if (gl_ViewID_OVR == 0)\n"
+        "    {\n"
+        "        gl_Position = vec4(-1.0, 0.0, 0.0, 1.0);\n"
+        "    }\n"
+        "    else\n"
+        "    {\n"
+        "        gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
+        "    }\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that compiling an ESSL 1.00 fragment shader with an unsupported input storage qualifier
+// fails.
+TEST_F(OVRMultiviewFragmentShaderTest, ESSL1ShaderUnsupportedInStorageQualifier)
+{
+    const std::string &shaderString =
+        "#extension GL_OVR_multiview : require\n"
+        "precision highp float;\n"
+        "in vec4 color;\n"
+        "void main()\n"
+        "{\n"
+        "    if (gl_ViewID_OVR == 0)\n"
+        "    {\n"
+        "        gl_FragColor = color;\n"
+        "    }\n"
+        "    else\n"
+        "    {\n"
+        "        gl_FragColor = color + vec4(1.0, 0.0, 0.0, 1.0);\n"
+        "    }\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
+    }
+}
+
+// Test that gl_InstanceID gets correctly replaced by InstanceID. gl_InstanceID should only be used
+// twice: once to initialize ViewID_OVR and once for InstanceID. The number of occurrences of
+// InstanceID in the AST should be the sum of two and the number of occurrences of gl_InstanceID
+// before any renaming.
+TEST_F(OVRMultiviewVertexShaderTest, GLInstanceIDIsRenamed)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 2) in;\n"
+        "flat out int myInstance;\n"
+        "out float myInstanceF;\n"
+        "out float myInstanceF2;\n"
+        "void main()\n"
+        "{\n"
+        "   gl_Position.x = gl_ViewID_OVR == 0u ? 0. : 1.;\n"
+        "   gl_Position.yzw = vec3(0., 0., 1.);\n"
+        "   myInstance = gl_InstanceID;\n"
+        "   myInstanceF = float(gl_InstanceID) + .5;\n"
+        "   myInstanceF2 = float(gl_InstanceID) + .1;\n"
+        "}\n";
+    mExtraCompileOptions |= SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW;
+    compileAssumeSuccess(shaderString);
+
+    SymbolOccurrenceCounterByName glInstanceIDByName(ImmutableString("gl_InstanceID"));
+    mASTRoot->traverse(&glInstanceIDByName);
+    EXPECT_EQ(2u, glInstanceIDByName.getNumberOfOccurrences());
+
+    SymbolOccurrenceCounterByQualifier glInstanceIDByQualifier(EvqInstanceID);
+    mASTRoot->traverse(&glInstanceIDByQualifier);
+    EXPECT_EQ(2u, glInstanceIDByQualifier.getNumberOfOccurrences());
+
+    SymbolOccurrenceCounterByName instanceIDByName(ImmutableString("InstanceID"));
+    mASTRoot->traverse(&instanceIDByName);
+    EXPECT_EQ(5u, instanceIDByName.getNumberOfOccurrences());
+}
+
+// Test that gl_ViewID_OVR gets correctly replaced by ViewID_OVR. gl_ViewID_OVR should not be found
+// by either name or qualifier. The number of occurrences of ViewID_OVR in the AST should be the sum
+// of two and the number of occurrences of gl_ViewID_OVR before any renaming.
+TEST_F(OVRMultiviewVertexShaderTest, GLViewIDIsRenamed)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 2) in;\n"
+        "flat out uint a;\n"
+        "void main()\n"
+        "{\n"
+        "   gl_Position.x = gl_ViewID_OVR == 0u ? 0. : 1.;\n"
+        "   gl_Position.yzw = vec3(0., 0., 1.);\n"
+        "   a = gl_ViewID_OVR == 0u ? (gl_ViewID_OVR+2u) : gl_ViewID_OVR;\n"
+        "}\n";
+    mExtraCompileOptions |= SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW;
+    compileAssumeSuccess(shaderString);
+
+    SymbolOccurrenceCounterByName glViewIDOVRByName(ImmutableString("gl_ViewID_OVR"));
+    mASTRoot->traverse(&glViewIDOVRByName);
+    EXPECT_EQ(0u, glViewIDOVRByName.getNumberOfOccurrences());
+
+    SymbolOccurrenceCounterByQualifier glViewIDOVRByQualifier(EvqViewIDOVR);
+    mASTRoot->traverse(&glViewIDOVRByQualifier);
+    EXPECT_EQ(0u, glViewIDOVRByQualifier.getNumberOfOccurrences());
+
+    SymbolOccurrenceCounterByNameAndQualifier viewIDByNameAndQualifier(
+        ImmutableString("ViewID_OVR"), EvqFlatOut);
+    mASTRoot->traverse(&viewIDByNameAndQualifier);
+    EXPECT_EQ(6u, viewIDByNameAndQualifier.getNumberOfOccurrences());
+}
+
+// The test checks that ViewID_OVR and InstanceID have the correct initializers based on the
+// number of views.
+TEST_F(OVRMultiviewVertexShaderOutputCodeTest, ViewIDAndInstanceIDHaveCorrectValues)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 3) in;\n"
+        "flat out int myInstance;\n"
+        "void main()\n"
+        "{\n"
+        "   gl_Position.x = gl_ViewID_OVR == 0u ? 0. : 1.;\n"
+        "   gl_Position.yzw = vec3(0., 0., 1.);\n"
+        "   myInstance = gl_InstanceID;\n"
+        "}\n";
+    requestHLSLOutput();
+    compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW);
+
+    EXPECT_TRUE(foundInAllGLSLCode("ViewID_OVR = (uint(gl_InstanceID) % 3u)"));
+    EXPECT_TRUE(foundInAllGLSLCode("InstanceID = int((uint(gl_InstanceID) / 3u))"));
+
+    EXPECT_TRUE(foundInHLSLCode("ViewID_OVR = (uint_ctor(gl_InstanceID) % 3)"));
+#if defined(ANGLE_ENABLE_HLSL)
+    EXPECT_FALSE(foundInHLSLCode("_ViewID_OVR = (uint_ctor(gl_InstanceID) % 3)"));
+#endif
+    EXPECT_TRUE(foundInHLSLCode("InstanceID = int_ctor((uint_ctor(gl_InstanceID) / 3))"));
+}
+
+// The test checks that the directive enabling GL_OVR_multiview is not outputted if the extension
+// is emulated.
+TEST_F(OVRMultiviewVertexShaderOutputCodeTest, StrippedOVRMultiviewDirective)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 3) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    // The directive must not be present if any of the multiview emulation options are set.
+    compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW);
+    EXPECT_FALSE(foundInESSLCode("GL_OVR_multiview"));
+    EXPECT_FALSE(foundInGLSLCode("GL_OVR_multiview"));
+
+    // The directive should be outputted from the ESSL translator with none of the options being
+    // set.
+    compile(shaderString);
+    EXPECT_TRUE(foundInESSLCode("GL_OVR_multiview"));
+}
+
+// Test that ViewID_OVR is declared as a flat input variable in an ESSL 3.00 fragment shader.
+TEST_F(OVRMultiviewFragmentShaderTest, ViewIDDeclaredAsFlatInput)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    mExtraCompileOptions |= SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW;
+    compileAssumeSuccess(shaderString);
+    VariableOccursNTimes(mASTRoot, ImmutableString("ViewID_OVR"), EvqFlatIn, 1u);
+}
+
+// Test that ViewID_OVR is declared as a flat output variable in an ESSL 1.00 vertex shader.
+TEST_F(OVRMultiviewVertexShaderTest, ViewIDDeclaredAsFlatOutput)
+{
+    const std::string &shaderString =
+        "#extension GL_OVR_multiview : require\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    mExtraCompileOptions |= SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW;
+    compileAssumeSuccess(shaderString);
+    VariableOccursNTimes(mASTRoot, ImmutableString("ViewID_OVR"), EvqFlatOut, 2u);
+}
+
+// The test checks that the GL_NV_viewport_array2 extension is emitted in a vertex shader if the
+// SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set.
+TEST_F(OVRMultiviewVertexShaderOutputCodeTest, ViewportArray2IsEmitted)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 3) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
+                              SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER);
+    EXPECT_TRUE(foundInAllGLSLCode("#extension GL_NV_viewport_array2 : require"));
+}
+
+// The test checks that the GL_NV_viewport_array2 extension is not emitted in a vertex shader if the
+// OVR_multiview2 extension is not requested in the shader source even if the
+// SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set.
+TEST_F(OVRMultiviewVertexShaderOutputCodeTest, ViewportArray2IsNotEmitted)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
+                              SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER);
+    EXPECT_FALSE(foundInGLSLCode("#extension GL_NV_viewport_array2"));
+    EXPECT_FALSE(foundInESSLCode("#extension GL_NV_viewport_array2"));
+}
+
+// The test checks that the GL_NV_viewport_array2 extension is not emitted in a fragment shader if
+// the SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set.
+TEST_F(OVRMultiviewFragmentShaderOutputCodeTest, ViewportArray2IsNotEmitted)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
+                              SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER);
+    EXPECT_FALSE(foundInGLSLCode("#extension GL_NV_viewport_array2"));
+    EXPECT_FALSE(foundInESSLCode("#extension GL_NV_viewport_array2"));
+}
+
+// The test checks that the GL_NV_viewport_array2 extension is not emitted in a compute shader if
+// the SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set.
+TEST_F(OVRMultiviewComputeShaderOutputCodeTest, ViewportArray2IsNotEmitted)
+{
+    const std::string &shaderString =
+        R"(#version 310 es
+        #extension GL_OVR_multiview : require
+        void main()
+        {
+        })";
+    compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
+                              SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER);
+    EXPECT_FALSE(foundInGLSLCode("#extension GL_NV_viewport_array2"));
+    EXPECT_FALSE(foundInESSLCode("#extension GL_NV_viewport_array2"));
+}
+
+// The test checks that the viewport index is selected after the initialization of ViewID_OVR for
+// GLSL and ESSL ouputs.
+TEST_F(OVRMultiviewVertexShaderOutputCodeTest, GlViewportIndexIsSet)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 3) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
+                              SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER);
+
+    std::vector<const char *> expectedStrings = {"ViewID_OVR = (uint(gl_InstanceID) % 3u)",
+                                                 "gl_ViewportIndex = int(ViewID_OVR)"};
+    EXPECT_TRUE(foundInCodeInOrder(SH_ESSL_OUTPUT, expectedStrings));
+    EXPECT_TRUE(foundInCodeInOrder(SH_GLSL_COMPATIBILITY_OUTPUT, expectedStrings));
+}
+
+// The test checks that the layer is selected after the initialization of ViewID_OVR for
+// GLSL and ESSL ouputs.
+TEST_F(OVRMultiviewVertexShaderOutputCodeTest, GlLayerIsSet)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "#extension GL_OVR_multiview : require\n"
+        "layout(num_views = 3) in;\n"
+        "void main()\n"
+        "{\n"
+        "}\n";
+    compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
+                              SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER);
+
+    std::vector<const char *> expectedStrings = {
+        "ViewID_OVR = (uint(gl_InstanceID) % 3u)",
+        "gl_Layer = (int(ViewID_OVR) + multiviewBaseViewLayerIndex)"};
+    EXPECT_TRUE(foundInCodeInOrder(SH_ESSL_OUTPUT, expectedStrings));
+    EXPECT_TRUE(foundInCodeInOrder(SH_GLSL_COMPATIBILITY_OUTPUT, expectedStrings));
+}
+
+}  // namespace
\ No newline at end of file
diff --git a/src/tests/gl_tests/FramebufferMultiviewTest.cpp b/src/tests/gl_tests/FramebufferMultiviewTest.cpp
index c2ba006..aa4c00b 100644
--- a/src/tests/gl_tests/FramebufferMultiviewTest.cpp
+++ b/src/tests/gl_tests/FramebufferMultiviewTest.cpp
@@ -756,7 +756,13 @@
     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
 }
 
-ANGLE_INSTANTIATE_TEST(FramebufferMultiviewTest, VertexShaderOpenGL(3, 0), GeomShaderD3D11(3, 0));
+ANGLE_INSTANTIATE_TEST(FramebufferMultiviewTest,
+                       VertexShaderOpenGL(3, 0, ExtensionName::multiview),
+                       GeomShaderD3D11(3, 0, ExtensionName::multiview),
+                       VertexShaderOpenGL(3, 0, ExtensionName::multiview2),
+                       GeomShaderD3D11(3, 0, ExtensionName::multiview2));
 ANGLE_INSTANTIATE_TEST(FramebufferMultiviewLayeredClearTest,
-                       VertexShaderOpenGL(3, 0),
-                       GeomShaderD3D11(3, 0));
+                       VertexShaderOpenGL(3, 0, ExtensionName::multiview),
+                       GeomShaderD3D11(3, 0, ExtensionName::multiview),
+                       VertexShaderOpenGL(3, 0, ExtensionName::multiview2),
+                       GeomShaderD3D11(3, 0, ExtensionName::multiview2));
diff --git a/src/tests/gl_tests/MultiviewDrawTest.cpp b/src/tests/gl_tests/MultiviewDrawTest.cpp
index 40390b2..ce3400b 100644
--- a/src/tests/gl_tests/MultiviewDrawTest.cpp
+++ b/src/tests/gl_tests/MultiviewDrawTest.cpp
@@ -57,7 +57,8 @@
     return os;
 }
 
-class MultiviewFramebufferTestBase : public MultiviewTestBase
+class MultiviewFramebufferTestBase : public MultiviewTestBase,
+                                     public ::testing::TestWithParam<MultiviewRenderTestParams>
 {
   protected:
     MultiviewFramebufferTestBase(const PlatformParameters &params, int samples)
@@ -181,6 +182,49 @@
         return ReadColor(x, y);
     }
 
+    // Requests the OVR_multiview(2) extension and returns true if the operation succeeds.
+    bool requestMultiviewExtension(bool requireMultiviewMultisample)
+    {
+        if (!EnsureGLExtensionEnabled(extensionName()))
+        {
+            std::cout << "Test skipped due to missing " << extensionName() << "." << std::endl;
+            return false;
+        }
+
+        if (requireMultiviewMultisample)
+        {
+            if (!EnsureGLExtensionEnabled("GL_OES_texture_storage_multisample_2d_array"))
+            {
+                std::cout << "Test skipped due to missing GL_ANGLE_multiview_multisample."
+                          << std::endl;
+                return false;
+            }
+
+            if (!EnsureGLExtensionEnabled("GL_ANGLE_multiview_multisample"))
+            {
+                std::cout << "Test skipped due to missing GL_ANGLE_multiview_multisample."
+                          << std::endl;
+                return false;
+            }
+        }
+        return true;
+    }
+
+    bool requestMultiviewExtension() { return requestMultiviewExtension(false); }
+    std::string extensionName()
+    {
+        switch (GetParam().mMultiviewExtension)
+        {
+            case multiview:
+                return "GL_OVR_multiview";
+            case multiview2:
+                return "GL_OVR_multiview2";
+            default:
+                // Ignore unknown.
+                return "";
+        }
+    }
+
     bool isMultisampled() { return mSamples > 0; }
 
     int mViewWidth;
@@ -236,8 +280,7 @@
     }
 };
 
-class MultiviewRenderTest : public MultiviewFramebufferTestBase,
-                            public ::testing::TestWithParam<MultiviewRenderTestParams>
+class MultiviewRenderTest : public MultiviewFramebufferTestBase
 {
   protected:
     MultiviewRenderTest() : MultiviewFramebufferTestBase(GetParam(), GetParam().mSamples) {}
@@ -263,24 +306,61 @@
     }
 };
 
-constexpr char kDualViewVSSource[] = R"(#version 300 es
-#extension GL_OVR_multiview2 : require
-layout(num_views = 2) in;
-in vec4 vPosition;
-void main()
+std::string DualViewVS(ExtensionName multiviewExtension)
 {
-   gl_Position.x = (gl_ViewID_OVR == 0u ? vPosition.x * 0.5 + 0.5 : vPosition.x * 0.5 - 0.5);
-   gl_Position.yzw = vPosition.yzw;
-})";
+    std::string ext;
+    switch (multiviewExtension)
+    {
+        case multiview:
+            ext = "GL_OVR_multiview";
+            break;
+        case multiview2:
+            ext = "GL_OVR_multiview2";
+            break;
+    }
 
-constexpr char kDualViewFSSource[] = R"(#version 300 es
-#extension GL_OVR_multiview2 : require
-precision mediump float;
-out vec4 col;
-void main()
+    std::string dualViewVSSource =
+        "#version 300 es\n"
+        "#extension " +
+        ext +
+        " : require\n"
+        "layout(num_views = 2) in;\n"
+        "in vec4 vPosition;\n"
+        "void main()\n"
+        "{\n"
+        "   gl_Position.x = (gl_ViewID_OVR == 0u ? vPosition.x * 0.5 + 0.5 : vPosition.x * 0.5 - "
+        "0.5);\n"
+        "   gl_Position.yzw = vPosition.yzw;\n"
+        "}\n";
+    return dualViewVSSource;
+}
+
+std::string DualViewFS(ExtensionName multiviewExtension)
 {
-   col = vec4(0,1,0,1);
-})";
+    std::string ext;
+    switch (multiviewExtension)
+    {
+        case multiview:
+            ext = "GL_OVR_multiview";
+            break;
+        case multiview2:
+            ext = "GL_OVR_multiview2";
+            break;
+    }
+
+    std::string dualViewFSSource =
+        "#version 300 es\n"
+        "#extension " +
+        ext +
+        " : require\n"
+        "precision mediump float;\n"
+        "out vec4 col;\n"
+        "void main()\n"
+        "{\n"
+        "  col = vec4(0,1,0,1);\n"
+        "}\n";
+    return dualViewFSSource;
+}
 
 class MultiviewRenderDualViewTest : public MultiviewRenderTest
 {
@@ -295,7 +375,8 @@
         }
 
         updateFBOs(2, 1, 2);
-        mProgram = CompileProgram(kDualViewVSSource, kDualViewFSSource);
+        mProgram = CompileProgram(DualViewVS(GetParam().mMultiviewExtension).c_str(),
+                                  DualViewFS(GetParam().mMultiviewExtension).c_str());
         ASSERT_NE(mProgram, 0u);
         glUseProgram(mProgram);
         ASSERT_GL_NO_ERROR();
@@ -367,12 +448,7 @@
 
     bool requestOcclusionQueryExtension()
     {
-        if (IsGLExtensionRequestable("GL_EXT_occlusion_query_boolean"))
-        {
-            glRequestExtensionANGLE("GL_EXT_occlusion_query_boolean");
-        }
-
-        if (!IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"))
+        if (!EnsureGLExtensionEnabled("GL_EXT_occlusion_query_boolean"))
         {
             std::cout << "Test skipped due to missing GL_EXT_occlusion_query_boolean." << std::endl;
             return false;
@@ -444,8 +520,7 @@
     GLuint mVBO;
 };
 
-class MultiviewLayeredRenderTest : public MultiviewFramebufferTestBase,
-                                   public ::testing::TestWithParam<MultiviewImplementationParams>
+class MultiviewLayeredRenderTest : public MultiviewFramebufferTestBase
 {
   protected:
     MultiviewLayeredRenderTest() : MultiviewFramebufferTestBase(GetParam(), 0) {}
@@ -462,9 +537,11 @@
 {
     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
 
-    constexpr char kFS[] =
+    const std::string FS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "precision mediump float;\n"
         "out vec4 color;\n"
         "void main()\n"
@@ -486,13 +563,15 @@
 
     // Check that no errors are generated with the framebuffer having 2 views.
     {
-        constexpr char kVS[] =
+        const std::string VS =
             "#version 300 es\n"
-            "#extension GL_OVR_multiview2 : require\n"
+            "#extension " +
+            extensionName() +
+            ": require\n"
             "layout(num_views = 2) in;\n"
             "void main()\n"
             "{}\n";
-        ANGLE_GL_PROGRAM(program, kVS, kFS);
+        ANGLE_GL_PROGRAM(program, VS.c_str(), FS.c_str());
         glUseProgram(program);
 
         GLTexture tex2DArray;
@@ -509,13 +588,15 @@
 
     // Check that no errors are generated if the number of views is 1.
     {
-        constexpr char kVS[] =
+        const std::string VS =
             "#version 300 es\n"
-            "#extension GL_OVR_multiview2 : require\n"
+            "#extension " +
+            extensionName() +
+            ": require\n"
             "layout(num_views = 1) in;\n"
             "void main()\n"
             "{}\n";
-        ANGLE_GL_PROGRAM(program, kVS, kFS);
+        ANGLE_GL_PROGRAM(program, VS.c_str(), FS.c_str());
         glUseProgram(program);
 
         GLTexture tex2D;
@@ -539,20 +620,24 @@
 {
     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
 
-    constexpr char kVS[] =
+    const std::string VS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "layout(num_views = 2) in;\n"
         "void main()\n"
         "{}\n";
-    constexpr char kFS[] =
+    const std::string FS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "precision mediump float;\n"
         "out vec4 color;\n"
         "void main()\n"
         "{color = vec4(1);}\n";
-    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    ANGLE_GL_PROGRAM(program, VS.c_str(), FS.c_str());
     glUseProgram(program);
 
     GLVertexArray vao;
@@ -663,7 +748,9 @@
 
     std::vector<std::string> dualViewTFVaryings;
     dualViewTFVaryings.emplace_back("gl_Position");
-    ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(dualViewProgram, kDualViewVSSource, kDualViewFSSource,
+    ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(dualViewProgram,
+                                        DualViewVS(GetParam().mMultiviewExtension).c_str(),
+                                        DualViewFS(GetParam().mMultiviewExtension).c_str(),
                                         dualViewTFVaryings, GL_SEPARATE_ATTRIBS);
 
     GLVertexArray vao;
@@ -757,7 +844,8 @@
     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_disjoint_timer_query"));
 
-    ANGLE_GL_PROGRAM(dualViewProgram, kDualViewVSSource, kDualViewFSSource);
+    ANGLE_GL_PROGRAM(dualViewProgram, DualViewVS(GetParam().mMultiviewExtension).c_str(),
+                     DualViewFS(GetParam().mMultiviewExtension).c_str());
 
     constexpr char kVS[] =
         "#version 300 es\n"
@@ -876,9 +964,11 @@
 {
     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension(isMultisampled()));
 
-    constexpr char kVS[] =
+    const std::string VS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        " : require\n"
         "layout(num_views = 4) in;\n"
         "in vec4 vPosition;\n"
         "void main()\n"
@@ -895,9 +985,11 @@
         "   gl_Position.yzw = vPosition.yzw;\n"
         "}\n";
 
-    constexpr char kFS[] =
+    const std::string FS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        " : require\n"
         "precision mediump float;\n"
         "out vec4 col;\n"
         "void main()\n"
@@ -906,7 +998,7 @@
         "}\n";
 
     updateFBOs(4, 1, 4);
-    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    ANGLE_GL_PROGRAM(program, VS.c_str(), FS.c_str());
 
     drawQuad(program, "vPosition", 0.0f, 1.0f, true);
     ASSERT_GL_NO_ERROR();
@@ -934,9 +1026,11 @@
 {
     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension(isMultisampled()));
 
-    constexpr char kVS[] =
+    const std::string VS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "layout(num_views = 2) in;\n"
         "in vec4 vPosition;\n"
         "void main()\n"
@@ -951,9 +1045,11 @@
         "       gl_Position.yzw = p.yzw;\n"
         "}\n";
 
-    constexpr char kFS[] =
+    const std::string FS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "precision mediump float;\n"
         "out vec4 col;\n"
         "void main()\n"
@@ -965,7 +1061,7 @@
     const int kViewHeight = 2;
     const int kNumViews   = 2;
     updateFBOs(kViewWidth, kViewHeight, kNumViews);
-    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    ANGLE_GL_PROGRAM(program, VS.c_str(), FS.c_str());
 
     drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 2u);
     ASSERT_GL_NO_ERROR();
@@ -1007,9 +1103,11 @@
         ignoreD3D11SDKLayersWarnings();
     }
 
-    constexpr char kVS[] =
+    const std::string VS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        " : require\n"
         "layout(num_views = 2) in;\n"
         "in vec3 vPosition;\n"
         "in float offsetX;\n"
@@ -1022,9 +1120,11 @@
         "       gl_Position.yzw = p.yzw;\n"
         "}\n";
 
-    constexpr char kFS[] =
+    const std::string FS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "precision mediump float;\n"
         "out vec4 col;\n"
         "void main()\n"
@@ -1036,7 +1136,7 @@
     const int kViewHeight = 4;
     const int kNumViews   = 2;
     updateFBOs(kViewWidth, kViewHeight, kNumViews);
-    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    ANGLE_GL_PROGRAM(program, VS.c_str(), FS.c_str());
 
     GLBuffer xOffsetVBO;
     glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
@@ -1087,9 +1187,11 @@
     updateFBOs(1, 1, 2);
 
     // Create multiview program.
-    constexpr char kVS[] =
+    const std::string VS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "layout(num_views = 2) in;\n"
         "layout(location = 0) in vec2 vPosition;\n"
         "layout(location = 1) in float offsetX;\n"
@@ -1100,9 +1202,11 @@
         "       gl_Position = p;\n"
         "}\n";
 
-    constexpr char kFS[] =
+    const std::string FS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        " : require\n"
         "precision mediump float;\n"
         "out vec4 col;\n"
         "void main()\n"
@@ -1110,7 +1214,7 @@
         "    col = vec4(0,1,0,1);\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    ANGLE_GL_PROGRAM(program, VS.c_str(), FS.c_str());
 
     constexpr char kDummyVS[] =
         "#version 300 es\n"
@@ -1247,9 +1351,11 @@
     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
     ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
 
-    constexpr char kVS[] =
+    const std::string VS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "layout(num_views = 2) in;\n"
         "in vec3 vPosition;\n"
         "void main()\n"
@@ -1258,16 +1364,18 @@
         "       gl_Position.yzw = vec3(vPosition.yz, 1.);\n"
         "}\n";
 
-    constexpr char kFS[] =
+    const std::string FS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        " : require\n"
         "precision mediump float;\n"
         "out vec4 col;\n"
         "void main()\n"
         "{\n"
         "    col = vec4(1,0,0,0);\n"
         "}\n";
-    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    ANGLE_GL_PROGRAM(program, VS.c_str(), FS.c_str());
     updateFBOs(1, 1, 2);
 
     GLuint result = drawAndRetrieveOcclusionQueryResult(program);
@@ -1282,9 +1390,11 @@
     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
     ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
 
-    constexpr char kVS[] =
+    const std::string VS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "layout(num_views = 2) in;\n"
         "in vec3 vPosition;\n"
         "void main()\n"
@@ -1293,16 +1403,18 @@
         "       gl_Position.yzw = vec3(vPosition.yz, 1.);\n"
         "}\n";
 
-    constexpr char kFS[] =
+    const std::string FS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "precision mediump float;\n"
         "out vec4 col;\n"
         "void main()\n"
         "{\n"
         "    col = vec4(1,0,0,0);\n"
         "}\n";
-    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    ANGLE_GL_PROGRAM(program, VS.c_str(), FS.c_str());
     updateFBOs(1, 1, 2);
 
     GLuint result = drawAndRetrieveOcclusionQueryResult(program);
@@ -1317,9 +1429,11 @@
     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
     ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
 
-    constexpr char kVS[] =
+    const std::string VS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "layout(num_views = 2) in;\n"
         "in vec3 vPosition;\n"
         "void main()\n"
@@ -1328,16 +1442,18 @@
         "       gl_Position.yzw = vec3(vPosition.yz, 1.);\n"
         "}\n";
 
-    constexpr char kFS[] =
+    const std::string FS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "precision mediump float;\n"
         "out vec4 col;\n"
         "void main()\n"
         "{\n"
         "    col = vec4(1,0,0,0);\n"
         "}\n";
-    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    ANGLE_GL_PROGRAM(program, VS.c_str(), FS.c_str());
     updateFBOs(1, 1, 2);
 
     GLuint result = drawAndRetrieveOcclusionQueryResult(program);
@@ -1354,23 +1470,27 @@
         return;
     }
 
-    constexpr char kVS[] =
+    const std::string VS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "layout(num_views = 2) in;\n"
         "void main()\n"
         "{\n"
         "}\n";
 
-    constexpr char kFS[] =
+    const std::string FS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "precision mediump float;\n"
         "void main()\n"
         "{\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    ANGLE_GL_PROGRAM(program, VS.c_str(), FS.c_str());
     glUseProgram(program);
 
     EXPECT_GL_NO_ERROR();
@@ -1385,9 +1505,11 @@
         return;
     }
 
-    constexpr char kVS[] =
+    const std::string VS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "layout(num_views = 2) in;\n"
         "void main()\n"
         "{\n"
@@ -1398,15 +1520,17 @@
         "   }\n"
         "}\n";
 
-    constexpr char kFS[] =
+    const std::string FS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "precision mediump float;\n"
         "void main()\n"
         "{\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    ANGLE_GL_PROGRAM(program, VS.c_str(), FS.c_str());
     glUseProgram(program);
 
     EXPECT_GL_NO_ERROR();
@@ -1421,17 +1545,21 @@
         return;
     }
 
-    constexpr char kVS[] =
+    const std::string VS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "layout(num_views = 2) in;\n"
         "void main()\n"
         "{\n"
         "}\n";
 
-    constexpr char kFS[] =
+    const std::string FS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "precision mediump float;\n"
         "out vec4 col;\n"
         "void main()\n"
@@ -1443,7 +1571,7 @@
         "   }\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    ANGLE_GL_PROGRAM(program, VS.c_str(), FS.c_str());
     glUseProgram(program);
 
     EXPECT_GL_NO_ERROR();
@@ -1460,9 +1588,11 @@
     // Test failing on P400 graphics card (anglebug.com/2228)
     ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11() && IsNVIDIA());
 
-    constexpr char kVS[] =
+    const std::string VS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "layout(num_views = 2) in;\n"
         "layout(location=0) in vec2 vPosition;\n"
         "void main()\n"
@@ -1471,16 +1601,18 @@
         "   gl_Position = vec4(vPosition.xy, 0.0, 1.0);\n"
         "}\n";
 
-    constexpr char kFS[] =
+    const std::string FS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "precision mediump float;\n"
         "out vec4 col;\n"
         "void main()\n"
         "{\n"
         "   col = vec4(0,1,0,1);\n"
         "}\n";
-    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    ANGLE_GL_PROGRAM(program, VS.c_str(), FS.c_str());
     glUseProgram(program);
 
     const int kViewWidth  = 4;
@@ -1513,7 +1645,7 @@
         return;
     }
 
-    GLuint program = CreateSimplePassthroughProgram(2);
+    GLuint program = CreateSimplePassthroughProgram(2, GetParam().mMultiviewExtension);
     ASSERT_NE(program, 0u);
     glUseProgram(program);
     ASSERT_GL_NO_ERROR();
@@ -1550,7 +1682,7 @@
         return;
     }
 
-    GLuint program = CreateSimplePassthroughProgram(2);
+    GLuint program = CreateSimplePassthroughProgram(2, GetParam().mMultiviewExtension);
     ASSERT_NE(program, 0u);
     glUseProgram(program);
     ASSERT_GL_NO_ERROR();
@@ -1587,7 +1719,7 @@
         return;
     }
 
-    GLuint program = CreateSimplePassthroughProgram(2);
+    GLuint program = CreateSimplePassthroughProgram(2, GetParam().mMultiviewExtension);
     ASSERT_NE(program, 0u);
     glUseProgram(program);
     ASSERT_GL_NO_ERROR();
@@ -1621,7 +1753,7 @@
         return;
     }
 
-    GLuint program = CreateSimplePassthroughProgram(2);
+    GLuint program = CreateSimplePassthroughProgram(2, GetParam().mMultiviewExtension);
     ASSERT_NE(program, 0u);
     glUseProgram(program);
     ASSERT_GL_NO_ERROR();
@@ -1652,7 +1784,7 @@
         return;
     }
 
-    GLuint program = CreateSimplePassthroughProgram(2);
+    GLuint program = CreateSimplePassthroughProgram(2, GetParam().mMultiviewExtension);
     ASSERT_NE(program, 0u);
     glUseProgram(program);
     ASSERT_GL_NO_ERROR();
@@ -1696,9 +1828,11 @@
     const int kViewHeight = 1;
     const int kNumViews   = 2;
 
-    constexpr char kFS[] =
+    const std::string FS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "precision mediump float;\n"
         "in vec4 oColor;\n"
         "out vec4 col;\n"
@@ -1707,10 +1841,12 @@
         "    col = oColor;\n"
         "}\n";
 
-    auto generateVertexShaderSource = [](int numViews) -> std::string {
+    auto generateVertexShaderSource = [](int numViews, std::string extensionName) -> std::string {
         std::string source =
             "#version 300 es\n"
-            "#extension GL_OVR_multiview2 : require\n"
+            "#extension " +
+            extensionName +
+            ": require\n"
             "layout(num_views = " +
             ToString(numViews) +
             ") in;\n"
@@ -1728,8 +1864,8 @@
         return source;
     };
 
-    std::string vsSource = generateVertexShaderSource(kNumViews);
-    ANGLE_GL_PROGRAM(program, vsSource.c_str(), kFS);
+    std::string vsSource = generateVertexShaderSource(kNumViews, extensionName());
+    ANGLE_GL_PROGRAM(program, vsSource.c_str(), FS.c_str());
     glUseProgram(program);
 
     GLint positionLoc;
@@ -1774,12 +1910,12 @@
 
     {
         const int kNewNumViews = 3;
-        vsSource               = generateVertexShaderSource(kNewNumViews);
+        vsSource               = generateVertexShaderSource(kNewNumViews, extensionName());
         updateFBOs(kViewWidth, kViewHeight, kNewNumViews);
 
         GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource.c_str());
         ASSERT_NE(0u, vs);
-        GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
+        GLuint fs = CompileShader(GL_FRAGMENT_SHADER, FS.c_str());
         ASSERT_NE(0u, fs);
 
         GLint numAttachedShaders = 0;
@@ -1859,7 +1995,7 @@
         updateFBOs(4, 1, numViews);
         ASSERT_GL_NO_ERROR();
 
-        GLuint program = CreateSimplePassthroughProgram(numViews);
+        GLuint program = CreateSimplePassthroughProgram(numViews, GetParam().mMultiviewExtension);
         ASSERT_NE(program, 0u);
         glUseProgram(program);
         ASSERT_GL_NO_ERROR();
@@ -1891,9 +2027,11 @@
         return;
     }
 
-    constexpr char kVS[] =
+    const std::string VS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "layout(num_views = 3) in;\n"
         "in vec3 vPosition;\n"
         "void main()\n"
@@ -1901,9 +2039,11 @@
         "   gl_Position = vec4(vPosition, 1.);\n"
         "}\n";
 
-    constexpr char kFS[] =
+    const std::string FS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "precision mediump float;\n"
         "out vec4 col;\n"
         "void main()\n"
@@ -1920,7 +2060,7 @@
         "}\n";
 
     updateFBOs(1, 1, 3);
-    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    ANGLE_GL_PROGRAM(program, VS.c_str(), FS.c_str());
 
     drawQuad(program, "vPosition", 0.0f, 1.0f, true);
     ASSERT_GL_NO_ERROR();
@@ -1940,9 +2080,11 @@
         return;
     }
 
-    constexpr char kVS[] =
+    const std::string VS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "layout(num_views = 2) in;\n"
         "in vec3 vPosition;\n"
         "void main()\n"
@@ -1950,9 +2092,11 @@
         "   gl_Position = vec4(vPosition, 1.);\n"
         "}\n";
 
-    constexpr char kFS[] =
+    const std::string FS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "precision mediump float;\n"
         "out vec4 col;\n"
         "void main()\n"
@@ -1961,7 +2105,7 @@
         "}\n";
 
     updateFBOs(1, 1, 2, 4, 1);
-    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    ANGLE_GL_PROGRAM(program, VS.c_str(), FS.c_str());
 
     drawQuad(program, "vPosition", 0.0f, 1.0f, true);
     ASSERT_GL_NO_ERROR();
@@ -1986,9 +2130,11 @@
         return;
     }
 
-    constexpr char kVS[] =
+    const std::string VS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "layout(num_views = 2) in;\n"
         "in vec3 vPosition;\n"
         "flat out int oInstanceID;\n"
@@ -1998,9 +2144,11 @@
         "   oInstanceID = gl_InstanceID;\n"
         "}\n";
 
-    constexpr char kFS[] =
+    const std::string FS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "precision mediump float;\n"
         "flat in int oInstanceID;\n"
         "out vec4 col;\n"
@@ -2017,7 +2165,7 @@
         "}\n";
 
     updateFBOs(1, 1, 2);
-    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    ANGLE_GL_PROGRAM(program, VS.c_str(), FS.c_str());
 
     drawQuad(program, "vPosition", 0.0f, 1.0f, true);
     ASSERT_GL_NO_ERROR();
@@ -2036,9 +2184,11 @@
         return;
     }
 
-    constexpr char kVS[] =
+    const std::string VS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "layout(num_views = 2) in;\n"
         "in vec3 vPosition;\n"
         "flat out int flatVarying;\n"
@@ -2048,9 +2198,11 @@
         "   flatVarying = int(gl_ViewID_OVR);\n"
         "}\n";
 
-    constexpr char kFS[] =
+    const std::string FS =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        extensionName() +
+        ": require\n"
         "precision mediump float;\n"
         "flat in int flatVarying;\n"
         "out vec4 col;\n"
@@ -2064,7 +2216,7 @@
         "}\n";
 
     updateFBOs(1, 1, 2);
-    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    ANGLE_GL_PROGRAM(program, VS.c_str(), FS.c_str());
 
     drawQuad(program, "vPosition", 0.0f, 1.0f, true);
     ASSERT_GL_NO_ERROR();
@@ -2074,56 +2226,81 @@
     EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
 }
 
-MultiviewRenderTestParams VertexShaderOpenGL()
+MultiviewRenderTestParams VertexShaderOpenGL(ExtensionName multiviewExtension)
 {
-    return MultiviewRenderTestParams(0, VertexShaderOpenGL(3, 0));
+    return MultiviewRenderTestParams(0, VertexShaderOpenGL(3, 0, multiviewExtension));
 }
 
-MultiviewRenderTestParams GeomShaderD3D11()
+MultiviewRenderTestParams GeomShaderD3D11(ExtensionName multiviewExtension)
 {
-    return MultiviewRenderTestParams(0, GeomShaderD3D11(3, 0));
+    return MultiviewRenderTestParams(0, GeomShaderD3D11(3, 0, multiviewExtension));
 }
 
-MultiviewRenderTestParams VertexShaderD3D11()
+MultiviewRenderTestParams VertexShaderD3D11(ExtensionName multiviewExtension)
 {
-    return MultiviewRenderTestParams(0, VertexShaderD3D11(3, 0));
+    return MultiviewRenderTestParams(0, VertexShaderD3D11(3, 0, multiviewExtension));
 }
 
-MultiviewRenderTestParams MultisampledVertexShaderOpenGL()
+MultiviewRenderTestParams MultisampledVertexShaderOpenGL(ExtensionName multiviewExtension)
 {
-    return MultiviewRenderTestParams(2, VertexShaderOpenGL(3, 1));
+    return MultiviewRenderTestParams(2, VertexShaderOpenGL(3, 1, multiviewExtension));
 }
 
-MultiviewRenderTestParams MultisampledVertexShaderD3D11()
+MultiviewRenderTestParams MultisampledVertexShaderD3D11(ExtensionName multiviewExtension)
 {
-    return MultiviewRenderTestParams(2, VertexShaderD3D11(3, 1));
+    return MultiviewRenderTestParams(2, VertexShaderD3D11(3, 1, multiviewExtension));
 }
 
 ANGLE_INSTANTIATE_TEST(MultiviewDrawValidationTest,
-                       VertexShaderOpenGL(3, 1),
-                       VertexShaderD3D11(3, 1));
+                       VertexShaderOpenGL(3, 1, ExtensionName::multiview),
+                       VertexShaderD3D11(3, 1, ExtensionName::multiview),
+                       VertexShaderOpenGL(3, 1, ExtensionName::multiview2),
+                       VertexShaderD3D11(3, 1, ExtensionName::multiview2));
 ANGLE_INSTANTIATE_TEST(MultiviewRenderDualViewTest,
-                       VertexShaderOpenGL(),
-                       MultisampledVertexShaderOpenGL(),
-                       GeomShaderD3D11(),
-                       VertexShaderD3D11(),
-                       MultisampledVertexShaderD3D11());
+                       VertexShaderOpenGL(ExtensionName::multiview),
+                       MultisampledVertexShaderOpenGL(ExtensionName::multiview),
+                       GeomShaderD3D11(ExtensionName::multiview),
+                       VertexShaderD3D11(ExtensionName::multiview),
+                       MultisampledVertexShaderD3D11(ExtensionName::multiview),
+                       VertexShaderOpenGL(ExtensionName::multiview2),
+                       MultisampledVertexShaderOpenGL(ExtensionName::multiview2),
+                       GeomShaderD3D11(ExtensionName::multiview2),
+                       VertexShaderD3D11(ExtensionName::multiview2),
+                       MultisampledVertexShaderD3D11(ExtensionName::multiview2));
 ANGLE_INSTANTIATE_TEST(MultiviewRenderTest,
-                       VertexShaderOpenGL(),
-                       MultisampledVertexShaderOpenGL(),
-                       GeomShaderD3D11(),
-                       VertexShaderD3D11(),
-                       MultisampledVertexShaderD3D11());
+                       VertexShaderOpenGL(ExtensionName::multiview),
+                       MultisampledVertexShaderOpenGL(ExtensionName::multiview),
+                       GeomShaderD3D11(ExtensionName::multiview),
+                       VertexShaderD3D11(ExtensionName::multiview),
+                       MultisampledVertexShaderD3D11(ExtensionName::multiview),
+                       VertexShaderOpenGL(ExtensionName::multiview2),
+                       MultisampledVertexShaderOpenGL(ExtensionName::multiview2),
+                       GeomShaderD3D11(ExtensionName::multiview2),
+                       VertexShaderD3D11(ExtensionName::multiview2),
+                       MultisampledVertexShaderD3D11(ExtensionName::multiview2));
 ANGLE_INSTANTIATE_TEST(MultiviewOcclusionQueryTest,
-                       VertexShaderOpenGL(),
-                       GeomShaderD3D11(),
-                       VertexShaderD3D11());
+                       VertexShaderOpenGL(ExtensionName::multiview),
+                       GeomShaderD3D11(ExtensionName::multiview),
+                       VertexShaderD3D11(ExtensionName::multiview),
+                       VertexShaderOpenGL(ExtensionName::multiview2),
+                       GeomShaderD3D11(ExtensionName::multiview2),
+                       VertexShaderD3D11(ExtensionName::multiview2));
 ANGLE_INSTANTIATE_TEST(MultiviewProgramGenerationTest,
-                       VertexShaderOpenGL(3, 0),
-                       GeomShaderD3D11(3, 0),
-                       VertexShaderD3D11(3, 0));
+                       VertexShaderOpenGL(3, 0, ExtensionName::multiview),
+                       GeomShaderD3D11(3, 0, ExtensionName::multiview),
+                       VertexShaderD3D11(3, 0, ExtensionName::multiview),
+                       VertexShaderOpenGL(3, 0, ExtensionName::multiview2),
+                       GeomShaderD3D11(3, 0, ExtensionName::multiview2),
+                       VertexShaderD3D11(3, 0, ExtensionName::multiview2));
 ANGLE_INSTANTIATE_TEST(MultiviewRenderPrimitiveTest,
-                       VertexShaderOpenGL(),
-                       GeomShaderD3D11(),
-                       VertexShaderD3D11());
-ANGLE_INSTANTIATE_TEST(MultiviewLayeredRenderTest, VertexShaderOpenGL(3, 0), GeomShaderD3D11(3, 0));
+                       VertexShaderOpenGL(ExtensionName::multiview),
+                       GeomShaderD3D11(ExtensionName::multiview),
+                       VertexShaderD3D11(ExtensionName::multiview),
+                       VertexShaderOpenGL(ExtensionName::multiview2),
+                       GeomShaderD3D11(ExtensionName::multiview2),
+                       VertexShaderD3D11(ExtensionName::multiview2));
+ANGLE_INSTANTIATE_TEST(MultiviewLayeredRenderTest,
+                       VertexShaderOpenGL(ExtensionName::multiview),
+                       GeomShaderD3D11(ExtensionName::multiview),
+                       VertexShaderOpenGL(ExtensionName::multiview2),
+                       GeomShaderD3D11(ExtensionName::multiview2));
diff --git a/src/tests/perf_tests/MultiviewPerf.cpp b/src/tests/perf_tests/MultiviewPerf.cpp
index df6408d..1fafb40 100644
--- a/src/tests/perf_tests/MultiviewPerf.cpp
+++ b/src/tests/perf_tests/MultiviewPerf.cpp
@@ -13,6 +13,7 @@
 #include "ANGLEPerfTest.h"
 #include "common/vector_utils.h"
 #include "platform/WorkaroundsD3D.h"
+#include "test_utils/MultiviewTest.h"
 #include "test_utils/gl_raii.h"
 #include "util/shader_utils.h"
 
@@ -23,19 +24,35 @@
 namespace
 {
 
-std::string GetShaderExtensionHeader(bool usesMultiview, int numViews, GLenum shaderType)
+std::string GetShaderExtensionHeader(bool usesMultiview,
+                                     int numViews,
+                                     GLenum shaderType,
+                                     ExtensionName multiviewExtension)
 {
     if (!usesMultiview)
     {
         return "";
     }
 
+    std::string ext;
+    switch (multiviewExtension)
+    {
+        case multiview:
+            ext = "GL_OVR_multiview";
+            break;
+        case multiview2:
+            ext = "GL_OVR_multiview2";
+            break;
+        default:
+            ext = "extension_error";
+    }
+
     if (shaderType == GL_VERTEX_SHADER)
     {
-        return "#extension GL_OVR_multiview2 : require\nlayout(num_views = " + ToString(numViews) +
+        return "#extension " + ext + " : require\nlayout(num_views = " + ToString(numViews) +
                ") in;\n";
     }
-    return "#extension GL_OVR_multiview2 : require\n";
+    return "#extension " + ext + " : require\n";
 }
 
 struct Vertex
@@ -59,16 +76,18 @@
 {
     MultiviewPerfParams(const EGLPlatformParameters &platformParametersIn,
                         const MultiviewPerfWorkload &workloadIn,
-                        MultiviewOption multiviewOptionIn)
+                        MultiviewOption multiviewOptionIn,
+                        ExtensionName multiviewExtensionIn)
     {
-        iterationsPerStep = 1;
-        majorVersion      = 3;
-        minorVersion      = 0;
-        eglParameters     = platformParametersIn;
-        windowWidth       = workloadIn.first;
-        windowHeight      = workloadIn.second;
-        multiviewOption   = multiviewOptionIn;
-        numViews          = 2;
+        iterationsPerStep  = 1;
+        majorVersion       = 3;
+        minorVersion       = 0;
+        eglParameters      = platformParametersIn;
+        windowWidth        = workloadIn.first;
+        windowHeight       = workloadIn.second;
+        multiviewOption    = multiviewOptionIn;
+        numViews           = 2;
+        multiviewExtension = multiviewExtensionIn;
     }
 
     std::string suffix() const override
@@ -89,12 +108,27 @@
                 name += "_error";
                 break;
         }
+        std::string ext;
+        switch (multiviewExtension)
+        {
+            case multiview:
+                ext = "GL_OVR_multiview";
+                break;
+            case multiview2:
+                ext = "GL_OVR_multiview2";
+                break;
+            default:
+                ext = "extension_error";
+                break;
+        }
+        name += "_" + ext;
         name += "_" + ToString(numViews) + "_views";
         return name;
     }
 
     MultiviewOption multiviewOption;
     int numViews;
+    angle::ExtensionName multiviewExtension;
 };
 
 std::ostream &operator<<(std::ostream &os, const MultiviewPerfParams &params)
@@ -110,7 +144,18 @@
     MultiviewBenchmark(const std::string &testName)
         : ANGLERenderTest(testName, GetParam()), mProgram(0)
     {
-        addExtensionPrerequisite("GL_OVR_multiview2");
+        switch (GetParam().multiviewExtension)
+        {
+            case multiview:
+                addExtensionPrerequisite("GL_OVR_multiview");
+                break;
+            case multiview2:
+                addExtensionPrerequisite("GL_OVR_multiview2");
+                break;
+            default:
+                // Unknown extension.
+                break;
+        }
     }
 
     virtual ~MultiviewBenchmark()
@@ -267,21 +312,22 @@
     const MultiviewPerfParams *params = static_cast<const MultiviewPerfParams *>(&mTestParams);
     const bool usesMultiview = (params->multiviewOption != MultiviewOption::NoAcceleration);
 
-    const std::string vs =
-        "#version 300 es\n" +
-        GetShaderExtensionHeader(usesMultiview, params->numViews, GL_VERTEX_SHADER) +
-        "layout(location=0) in vec4 vPosition;\n"
-        "uniform vec2 uOffset;\n"
-        "void main()\n"
-        "{\n"
-        "   vec4 v = vPosition;\n"
-        "   v.xy += uOffset;\n"
-        "	gl_Position = v;\n"
-        "}\n";
+    const std::string vs = "#version 300 es\n" +
+                           GetShaderExtensionHeader(usesMultiview, params->numViews,
+                                                    GL_VERTEX_SHADER, params->multiviewExtension) +
+                           "layout(location=0) in vec4 vPosition;\n"
+                           "uniform vec2 uOffset;\n"
+                           "void main()\n"
+                           "{\n"
+                           "   vec4 v = vPosition;\n"
+                           "   v.xy += uOffset;\n"
+                           "	gl_Position = v;\n"
+                           "}\n";
 
     const std::string fs =
         "#version 300 es\n" +
-        GetShaderExtensionHeader(usesMultiview, params->numViews, GL_FRAGMENT_SHADER) +
+        GetShaderExtensionHeader(usesMultiview, params->numViews, GL_FRAGMENT_SHADER,
+                                 params->multiviewExtension) +
         "precision mediump float;\n"
         "out vec4 col;\n"
         "uniform float uColor;\n"
@@ -350,36 +396,37 @@
     const MultiviewPerfParams *params = static_cast<const MultiviewPerfParams *>(&mTestParams);
     const bool usesMultiview = (params->multiviewOption != MultiviewOption::NoAcceleration);
 
-    const std::string &vs =
-        "#version 300 es\n" +
-        GetShaderExtensionHeader(usesMultiview, params->numViews, GL_VERTEX_SHADER) +
-        "layout(location=0) in vec4 vPosition;\n"
-        "layout(location=1) in vec4 vert_Col0;\n"
-        "layout(location=2) in vec4 vert_Col1;\n"
-        "layout(location=3) in vec4 vert_Col2;\n"
-        "layout(location=4) in vec4 vert_Col3;\n"
-        "layout(location=5) in vec4 vert_Col4;\n"
-        "layout(location=6) in vec4 vert_Col5;\n"
-        "out vec4 frag_Col0;\n"
-        "out vec4 frag_Col1;\n"
-        "out vec4 frag_Col2;\n"
-        "out vec4 frag_Col3;\n"
-        "out vec4 frag_Col4;\n"
-        "out vec4 frag_Col5;\n"
-        "void main()\n"
-        "{\n"
-        "   frag_Col0 = vert_Col0;\n"
-        "   frag_Col1 = vert_Col1;\n"
-        "   frag_Col2 = vert_Col2;\n"
-        "   frag_Col3 = vert_Col3;\n"
-        "   frag_Col4 = vert_Col4;\n"
-        "   frag_Col5 = vert_Col5;\n"
-        "	gl_Position = vPosition;\n"
-        "}\n";
+    const std::string &vs = "#version 300 es\n" +
+                            GetShaderExtensionHeader(usesMultiview, params->numViews,
+                                                     GL_VERTEX_SHADER, params->multiviewExtension) +
+                            "layout(location=0) in vec4 vPosition;\n"
+                            "layout(location=1) in vec4 vert_Col0;\n"
+                            "layout(location=2) in vec4 vert_Col1;\n"
+                            "layout(location=3) in vec4 vert_Col2;\n"
+                            "layout(location=4) in vec4 vert_Col3;\n"
+                            "layout(location=5) in vec4 vert_Col4;\n"
+                            "layout(location=6) in vec4 vert_Col5;\n"
+                            "out vec4 frag_Col0;\n"
+                            "out vec4 frag_Col1;\n"
+                            "out vec4 frag_Col2;\n"
+                            "out vec4 frag_Col3;\n"
+                            "out vec4 frag_Col4;\n"
+                            "out vec4 frag_Col5;\n"
+                            "void main()\n"
+                            "{\n"
+                            "   frag_Col0 = vert_Col0;\n"
+                            "   frag_Col1 = vert_Col1;\n"
+                            "   frag_Col2 = vert_Col2;\n"
+                            "   frag_Col3 = vert_Col3;\n"
+                            "   frag_Col4 = vert_Col4;\n"
+                            "   frag_Col5 = vert_Col5;\n"
+                            "	gl_Position = vPosition;\n"
+                            "}\n";
 
     const std::string &fs =
         "#version 300 es\n" +
-        GetShaderExtensionHeader(usesMultiview, params->numViews, GL_FRAGMENT_SHADER) +
+        GetShaderExtensionHeader(usesMultiview, params->numViews, GL_FRAGMENT_SHADER,
+                                 params->multiviewExtension) +
         "precision mediump float;\n"
         "in vec4 frag_Col0;\n"
         "in vec4 frag_Col1;\n"
@@ -492,22 +539,28 @@
 }
 
 MultiviewPerfParams NoAcceleration(const EGLPlatformParameters &eglParameters,
-                                   const MultiviewPerfWorkload &workload)
+                                   const MultiviewPerfWorkload &workload,
+                                   ExtensionName multiviewExtensionIn)
 {
-    return MultiviewPerfParams(eglParameters, workload, MultiviewOption::NoAcceleration);
+    return MultiviewPerfParams(eglParameters, workload, MultiviewOption::NoAcceleration,
+                               multiviewExtensionIn);
 }
 
-MultiviewPerfParams SelectViewInGeometryShader(const MultiviewPerfWorkload &workload)
+MultiviewPerfParams SelectViewInGeometryShader(const MultiviewPerfWorkload &workload,
+                                               ExtensionName multiviewExtensionIn)
 {
     return MultiviewPerfParams(egl_platform::D3D11(), workload,
-                               MultiviewOption::InstancedMultiviewGeometryShader);
+                               MultiviewOption::InstancedMultiviewGeometryShader,
+                               multiviewExtensionIn);
 }
 
 MultiviewPerfParams SelectViewInVertexShader(const EGLPlatformParameters &eglParameters,
-                                             const MultiviewPerfWorkload &workload)
+                                             const MultiviewPerfWorkload &workload,
+                                             ExtensionName multiviewExtensionIn)
 {
     return MultiviewPerfParams(eglParameters, workload,
-                               MultiviewOption::InstancedMultiviewVertexShader);
+                               MultiviewOption::InstancedMultiviewVertexShader,
+                               multiviewExtensionIn);
 }
 }  // namespace
 
@@ -516,24 +569,43 @@
     run();
 }
 
-ANGLE_INSTANTIATE_TEST(MultiviewCPUBoundBenchmark,
-                       NoAcceleration(egl_platform::OPENGL_OR_GLES(false), SmallWorkload()),
-                       NoAcceleration(egl_platform::D3D11(), SmallWorkload()),
-                       SelectViewInGeometryShader(SmallWorkload()),
-                       SelectViewInVertexShader(egl_platform::OPENGL_OR_GLES(false),
-                                                SmallWorkload()),
-                       SelectViewInVertexShader(egl_platform::D3D11(), SmallWorkload()));
+ANGLE_INSTANTIATE_TEST(
+    MultiviewCPUBoundBenchmark,
+    NoAcceleration(egl_platform::OPENGL_OR_GLES(false), SmallWorkload(), ExtensionName::multiview),
+    NoAcceleration(egl_platform::D3D11(), SmallWorkload(), ExtensionName::multiview),
+    SelectViewInGeometryShader(SmallWorkload(), ExtensionName::multiview),
+    SelectViewInVertexShader(egl_platform::OPENGL_OR_GLES(false),
+                             SmallWorkload(),
+                             ExtensionName::multiview),
+    SelectViewInVertexShader(egl_platform::D3D11(), SmallWorkload(), ExtensionName::multiview),
+    NoAcceleration(egl_platform::OPENGL_OR_GLES(false), SmallWorkload(), ExtensionName::multiview2),
+    NoAcceleration(egl_platform::D3D11(), SmallWorkload(), ExtensionName::multiview2),
+    SelectViewInGeometryShader(SmallWorkload(), ExtensionName::multiview2),
+    SelectViewInVertexShader(egl_platform::OPENGL_OR_GLES(false),
+                             SmallWorkload(),
+                             ExtensionName::multiview2),
+    SelectViewInVertexShader(egl_platform::D3D11(), SmallWorkload(), ExtensionName::multiview2));
 
 TEST_P(MultiviewGPUBoundBenchmark, Run)
 {
     run();
 }
 
-ANGLE_INSTANTIATE_TEST(MultiviewGPUBoundBenchmark,
-                       NoAcceleration(egl_platform::OPENGL_OR_GLES(false), BigWorkload()),
-                       NoAcceleration(egl_platform::D3D11(), BigWorkload()),
-                       SelectViewInGeometryShader(BigWorkload()),
-                       SelectViewInVertexShader(egl_platform::OPENGL_OR_GLES(false), BigWorkload()),
-                       SelectViewInVertexShader(egl_platform::D3D11(), BigWorkload()));
+ANGLE_INSTANTIATE_TEST(
+    MultiviewGPUBoundBenchmark,
+    NoAcceleration(egl_platform::OPENGL_OR_GLES(false), BigWorkload(), ExtensionName::multiview),
+    NoAcceleration(egl_platform::D3D11(), BigWorkload(), ExtensionName::multiview),
+    SelectViewInGeometryShader(BigWorkload(), ExtensionName::multiview),
+    SelectViewInVertexShader(egl_platform::OPENGL_OR_GLES(false),
+                             BigWorkload(),
+                             ExtensionName::multiview),
+    SelectViewInVertexShader(egl_platform::D3D11(), BigWorkload(), ExtensionName::multiview),
+    NoAcceleration(egl_platform::OPENGL_OR_GLES(false), BigWorkload(), ExtensionName::multiview2),
+    NoAcceleration(egl_platform::D3D11(), BigWorkload(), ExtensionName::multiview2),
+    SelectViewInGeometryShader(BigWorkload(), ExtensionName::multiview2),
+    SelectViewInVertexShader(egl_platform::OPENGL_OR_GLES(false),
+                             BigWorkload(),
+                             ExtensionName::multiview2),
+    SelectViewInVertexShader(egl_platform::D3D11(), BigWorkload(), ExtensionName::multiview2));
 
 }  // anonymous namespace
diff --git a/src/tests/test_utils/MultiviewTest.cpp b/src/tests/test_utils/MultiviewTest.cpp
index aa2f7aa..25d419d 100644
--- a/src/tests/test_utils/MultiviewTest.cpp
+++ b/src/tests/test_utils/MultiviewTest.cpp
@@ -14,11 +14,27 @@
 namespace angle
 {
 
-GLuint CreateSimplePassthroughProgram(int numViews)
+GLuint CreateSimplePassthroughProgram(int numViews, ExtensionName multiviewExtension)
 {
+    std::string ext;
+    switch (multiviewExtension)
+    {
+        case multiview:
+            ext = "GL_OVR_multiview";
+            break;
+        case multiview2:
+            ext = "GL_OVR_multiview2";
+            break;
+        default:
+            // Unknown extension.
+            break;
+    }
+
     const std::string vsSource =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        ext +
+        " : require\n"
         "layout(num_views = " +
         ToString(numViews) +
         ") in;\n"
@@ -29,16 +45,18 @@
         "   gl_Position = vec4(vPosition.xy, 0.0, 1.0);\n"
         "}\n";
 
-    constexpr char kFS[] =
+    const std::string fsSource =
         "#version 300 es\n"
-        "#extension GL_OVR_multiview2 : require\n"
+        "#extension " +
+        ext +
+        " : require\n"
         "precision mediump float;\n"
         "out vec4 col;\n"
         "void main()\n"
         "{\n"
         "   col = vec4(0,1,0,1);\n"
         "}\n";
-    return CompileProgram(vsSource.c_str(), kFS);
+    return CompileProgram(vsSource.c_str(), fsSource.c_str());
 }
 
 void CreateMultiviewBackingTextures(int samples,
@@ -210,22 +228,39 @@
     {
         os << "_vertex_shader";
     }
+    if (params.mMultiviewExtension)
+    {
+        os << "_multiview";
+    }
+    else
+    {
+        os << "_multiview2";
+    }
     return os;
 }
 
-MultiviewImplementationParams VertexShaderOpenGL(GLint majorVersion, GLint minorVersion)
+MultiviewImplementationParams VertexShaderOpenGL(GLint majorVersion,
+                                                 GLint minorVersion,
+                                                 ExtensionName multiviewExtension)
 {
-    return MultiviewImplementationParams(majorVersion, minorVersion, false, egl_platform::OPENGL());
+    return MultiviewImplementationParams(majorVersion, minorVersion, false, egl_platform::OPENGL(),
+                                         multiviewExtension);
 }
 
-MultiviewImplementationParams VertexShaderD3D11(GLint majorVersion, GLint minorVersion)
+MultiviewImplementationParams VertexShaderD3D11(GLint majorVersion,
+                                                GLint minorVersion,
+                                                ExtensionName multiviewExtension)
 {
-    return MultiviewImplementationParams(majorVersion, minorVersion, false, egl_platform::D3D11());
+    return MultiviewImplementationParams(majorVersion, minorVersion, false, egl_platform::D3D11(),
+                                         multiviewExtension);
 }
 
-MultiviewImplementationParams GeomShaderD3D11(GLint majorVersion, GLint minorVersion)
+MultiviewImplementationParams GeomShaderD3D11(GLint majorVersion,
+                                              GLint minorVersion,
+                                              ExtensionName multiviewExtension)
 {
-    return MultiviewImplementationParams(majorVersion, minorVersion, true, egl_platform::D3D11());
+    return MultiviewImplementationParams(majorVersion, minorVersion, true, egl_platform::D3D11(),
+                                         multiviewExtension);
 }
 
 void MultiviewTest::overrideWorkaroundsD3D(WorkaroundsD3D *workarounds)
diff --git a/src/tests/test_utils/MultiviewTest.h b/src/tests/test_utils/MultiviewTest.h
index ef83da6..13cf727 100644
--- a/src/tests/test_utils/MultiviewTest.h
+++ b/src/tests/test_utils/MultiviewTest.h
@@ -14,10 +14,15 @@
 
 namespace angle
 {
+enum ExtensionName
+{
+    multiview,
+    multiview2
+};
 
 // Creates a simple program that passes through two-dimensional vertices and renders green
 // fragments.
-GLuint CreateSimplePassthroughProgram(int numViews);
+GLuint CreateSimplePassthroughProgram(int numViews, ExtensionName multiviewExtension);
 
 // Create a 2D texture array to use for multiview rendering. Texture ids should be
 // created beforehand. If depthTexture or stencilTexture is 0, it will not be initialized.
@@ -60,17 +65,26 @@
     MultiviewImplementationParams(GLint majorVersion,
                                   GLint minorVersion,
                                   bool forceUseGeometryShaderOnD3D,
-                                  const EGLPlatformParameters &eglPlatformParameters)
+                                  const EGLPlatformParameters &eglPlatformParameters,
+                                  ExtensionName multiviewExtension)
         : PlatformParameters(majorVersion, minorVersion, eglPlatformParameters),
-          mForceUseGeometryShaderOnD3D(forceUseGeometryShaderOnD3D)
+          mForceUseGeometryShaderOnD3D(forceUseGeometryShaderOnD3D),
+          mMultiviewExtension(multiviewExtension)
     {}
     bool mForceUseGeometryShaderOnD3D;
+    ExtensionName mMultiviewExtension;
 };
 std::ostream &operator<<(std::ostream &os, const MultiviewImplementationParams &params);
 
-MultiviewImplementationParams VertexShaderOpenGL(GLint majorVersion, GLint minorVersion);
-MultiviewImplementationParams VertexShaderD3D11(GLint majorVersion, GLint minorVersion);
-MultiviewImplementationParams GeomShaderD3D11(GLint majorVersion, GLint minorVersion);
+MultiviewImplementationParams VertexShaderOpenGL(GLint majorVersion,
+                                                 GLint minorVersion,
+                                                 ExtensionName multiviewExtension);
+MultiviewImplementationParams VertexShaderD3D11(GLint majorVersion,
+                                                GLint minorVersion,
+                                                ExtensionName multiviewExtension);
+MultiviewImplementationParams GeomShaderD3D11(GLint majorVersion,
+                                              GLint minorVersion,
+                                              ExtensionName multiviewExtension);
 
 class MultiviewTestBase : public ANGLETestBase
 {
@@ -93,43 +107,6 @@
 
     void MultiviewTestBaseTearDown() { ANGLETestBase::ANGLETestTearDown(); }
 
-    // Requests the OVR_multiview2 extension and returns true if the operation succeeds.
-    bool requestMultiviewExtension(bool requireMultiviewMultisample)
-    {
-        if (IsGLExtensionRequestable("GL_OVR_multiview2"))
-        {
-            glRequestExtensionANGLE("GL_OVR_multiview2");
-        }
-
-        if (!IsGLExtensionEnabled("GL_OVR_multiview2"))
-        {
-            std::cout << "Test skipped due to missing GL_OVR_multiview2." << std::endl;
-            return false;
-        }
-
-        if (requireMultiviewMultisample)
-        {
-            if (IsGLExtensionRequestable("GL_OES_texture_storage_multisample_2d_array"))
-            {
-                glRequestExtensionANGLE("GL_OES_texture_storage_multisample_2d_array");
-            }
-            if (IsGLExtensionRequestable("GL_ANGLE_multiview_multisample"))
-            {
-                glRequestExtensionANGLE("GL_ANGLE_multiview_multisample");
-            }
-
-            if (!IsGLExtensionEnabled("GL_ANGLE_multiview_multisample"))
-            {
-                std::cout << "Test skipped due to missing GL_ANGLE_multiview_multisample."
-                          << std::endl;
-                return false;
-            }
-        }
-        return true;
-    }
-
-    bool requestMultiviewExtension() { return requestMultiviewExtension(false); }
-
     PFNGLREQUESTEXTENSIONANGLEPROC glRequestExtensionANGLE = nullptr;
 };
 
@@ -145,6 +122,50 @@
     virtual void testSetUp() {}
     virtual void testTearDown() {}
 
+    // Requests the OVR_multiview(2) extension and returns true if the operation succeeds.
+    bool requestMultiviewExtension(bool requireMultiviewMultisample)
+    {
+        if (!EnsureGLExtensionEnabled(extensionName()))
+        {
+            std::cout << "Test skipped due to missing " << extensionName() << "." << std::endl;
+            return false;
+        }
+
+        if (requireMultiviewMultisample)
+        {
+            if (!EnsureGLExtensionEnabled("GL_OES_texture_storage_multisample_2d_array"))
+            {
+                std::cout << "Test skipped due to missing GL_ANGLE_multiview_multisample."
+                          << std::endl;
+                return false;
+            }
+
+            if (!EnsureGLExtensionEnabled("GL_ANGLE_multiview_multisample"))
+            {
+                std::cout << "Test skipped due to missing GL_ANGLE_multiview_multisample."
+                          << std::endl;
+                return false;
+            }
+        }
+        return true;
+    }
+
+    bool requestMultiviewExtension() { return requestMultiviewExtension(false); }
+
+    std::string extensionName()
+    {
+        switch (GetParam().mMultiviewExtension)
+        {
+            case multiview:
+                return "GL_OVR_multiview";
+            case multiview2:
+                return "GL_OVR_multiview2";
+            default:
+                // Ignore unknown.
+                return "";
+        }
+    }
+
   private:
     void SetUp() override
     {
@@ -160,4 +181,4 @@
 
 }  // namespace angle
 
-#endif  // ANGLE_TESTS_TESTUTILS_MULTIVIEWTEST_H_
+#endif  // ANGLE_TESTS_TESTUTILS_MULTIVIEWTEST_H_
\ No newline at end of file