Merge remote-tracking branch 'aosp/upstream-mirror' into aosp-master

2018/04/23 Update to latest ANGLE.
Exempt-From-Owner-Approval: merge from upstream

Change-Id: I5fe242eb36c01d14c4d7285903264ce9a29d6fcb
diff --git a/BUILD.gn b/BUILD.gn
index 3011746..4b17f38 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -99,6 +99,7 @@
     cflags += [
       # Remove when crbug.com/428099 is resolved.
       "-Winconsistent-missing-override",
+      "-Wunneeded-internal-declaration",
     ]
   }
 }
@@ -421,18 +422,27 @@
     public_deps = [
       "$angle_root/third_party/vulkan-validation-layers:vulkan_headers",
     ]
-    data_deps = [
-      "$angle_root/third_party/vulkan-validation-layers:vulkan_validation_layers",
-    ]
     public_configs = [
       "$angle_root/third_party/glslang:glslang_config",
       "$angle_root/third_party/vulkan-validation-layers:vulkan_config",
     ]
+    data_deps = [ ]
     if (!is_android) {
       deps += [ "$angle_root/third_party/vulkan-validation-layers:libvulkan" ]
-      data_deps += [ "$angle_root/third_party/vulkan-validation-layers:vulkan_gen_json_files" ]
+      data_deps += [ "$angle_root/third_party/vulkan-validation-layers:VkICD_mock_icd" ]
       public_configs += [ "$angle_root/third_party/vulkan-validation-layers:vulkan_loader_config" ]
     }
+
+    if (angle_enable_vulkan_validation_layers) {
+      data_deps += [
+        "$angle_root/third_party/vulkan-validation-layers:vulkan_validation_layers",
+      ]
+      if (!is_android) {
+        data_deps += [
+          "$angle_root/third_party/vulkan-validation-layers:vulkan_gen_json_files",
+        ]
+      }
+    }
   }
 }
 
diff --git a/DEPS b/DEPS
index ced27cf..cf2f9dd 100644
--- a/DEPS
+++ b/DEPS
@@ -1,51 +1,54 @@
 vars = {
   'android_git': 'https://android.googlesource.com',
   'chromium_git': 'https://chromium.googlesource.com',
+
+  # This variable is set on the Chrome infra for compatiblity with gclient.
+  'root': '.',
 }
 
 deps = {
 
-  'build':
+  '{root}/build':
     Var('chromium_git') + '/chromium/src/build.git' + '@' + '2f3b6e8ce9e783b2a09496d70eef2974506a41c8',
 
-  'buildtools':
+  '{root}/buildtools':
     Var('chromium_git') + '/chromium/buildtools.git' + '@' + '461b345a815c1c745ac0534a6a4bd52d123abe68',
 
-  'testing':
+  '{root}/testing':
     Var('chromium_git') + '/chromium/src/testing' + '@' + '6dfa36ab2e5143fa2f7353e3af5d2935af2e61f7',
 
   # Cherry is a dEQP management GUI written in Go. We use it for viewing test results.
-  'third_party/cherry':
+  '{root}/third_party/cherry':
     Var('android_git') + '/platform/external/cherry' + '@' + '4f8fb08d33ca5ff05a1c638f04c85bbb8d8b52cc',
 
-  'third_party/deqp/src':
+  '{root}/third_party/deqp/src':
     Var('android_git') + '/platform/external/deqp' + '@' + '5bc346ba2d5465a2e6094e254f12b1586fd0097f',
 
-  'third_party/glslang/src':
+  '{root}/third_party/glslang/src':
     Var('android_git') + '/platform/external/shaderc/glslang' + '@' + '2edde6665d9a56ead5ea0e55b4e64d9a803e6164',
 
-  'third_party/googletest/src':
+  '{root}/third_party/googletest/src':
     Var('chromium_git') + '/external/github.com/google/googletest.git' + '@' + 'd175c8bf823e709d570772b038757fadf63bc632',
 
-  'third_party/libpng/src':
+  '{root}/third_party/libpng/src':
     Var('android_git') + '/platform/external/libpng' + '@' + '094e181e79a3d6c23fd005679025058b7df1ad6c',
 
-  'third_party/spirv-headers/src':
+  '{root}/third_party/spirv-headers/src':
     Var('android_git') + '/platform/external/shaderc/spirv-headers' + '@' + '98b01515724c428d0f0a5d01deffcce0f5f5e61c',
 
-  'third_party/spirv-tools/src':
+  '{root}/third_party/spirv-tools/src':
     Var('android_git') + '/platform/external/shaderc/spirv-tools' + '@' + '9996173f363729b3a97309685dbd4d78547a63a7',
 
-  'third_party/vulkan-validation-layers/src':
-    Var('android_git') + '/platform/external/vulkan-validation-layers' + '@' + '354ad3ba8b88136b82b712acab9b8fcb981beaff',
+  '{root}/third_party/vulkan-validation-layers/src':
+    Var('android_git') + '/platform/external/vulkan-validation-layers' + '@' + '88e43c8f9a750839a5d6d3f90098505bad3a98a1',
 
-  'third_party/zlib':
+  '{root}/third_party/zlib':
     Var('chromium_git') + '/chromium/src/third_party/zlib' + '@' + '24ab14872e8e068ba08cc31cc3d43bcc6d5cb832',
 
-  'tools/clang':
+  '{root}/tools/clang':
     Var('chromium_git') + '/chromium/src/tools/clang.git' + '@' + 'e70074db10b27867e6c873adc3ac7e5f9ee0ff6e',
 
-  'tools/gyp':
+  '{root}/tools/gyp':
     Var('chromium_git') + '/external/gyp' + '@' + '5e2b3ddde7cda5eb6bc09a5546a76b00e49d888f',
 }
 
@@ -60,7 +63,7 @@
                 '--platform=win32',
                 '--no_auth',
                 '--bucket', 'chromium-clang-format',
-                '-s', 'buildtools/win/clang-format.exe.sha1',
+                '-s', '{root}/buildtools/win/clang-format.exe.sha1',
     ],
   },
   {
@@ -72,7 +75,7 @@
                 '--platform=darwin',
                 '--no_auth',
                 '--bucket', 'chromium-clang-format',
-                '-s', 'buildtools/mac/clang-format.sha1',
+                '-s', '{root}/buildtools/mac/clang-format.sha1',
     ],
   },
   {
@@ -84,7 +87,7 @@
                 '--platform=linux*',
                 '--no_auth',
                 '--bucket', 'chromium-clang-format',
-                '-s', 'buildtools/linux64/clang-format.sha1',
+                '-s', '{root}/buildtools/linux64/clang-format.sha1',
     ],
   },
   # Pull GN binaries using checked-in hashes.
@@ -97,7 +100,7 @@
                 '--platform=win32',
                 '--no_auth',
                 '--bucket', 'chromium-gn',
-                '-s', 'buildtools/win/gn.exe.sha1',
+                '-s', '{root}/buildtools/win/gn.exe.sha1',
     ],
   },
   {
@@ -109,7 +112,7 @@
                 '--platform=darwin',
                 '--no_auth',
                 '--bucket', 'chromium-gn',
-                '-s', 'buildtools/mac/gn.sha1',
+                '-s', '{root}/buildtools/mac/gn.sha1',
     ],
   },
   {
@@ -121,14 +124,23 @@
                 '--platform=linux*',
                 '--no_auth',
                 '--bucket', 'chromium-gn',
-                '-s', 'buildtools/linux64/gn.sha1',
+                '-s', '{root}/buildtools/linux64/gn.sha1',
     ],
   },
+
+  {
+    # Update the Windows toolchain if necessary.  Must run before 'clang' below.
+    'name': 'win_toolchain',
+    'pattern': '.',
+    'condition': 'checkout_win',
+    'action': ['python', '{root}/build/vs_toolchain.py', 'update', '--force'],
+  },
+
   {
     # Note: On Win, this should run after win_toolchain, as it may use it.
     'name': 'clang',
     'pattern': '.',
-    'action': ['python', 'tools/clang/scripts/update.py', '--if-needed'],
+    'action': ['python', '{root}/tools/clang/scripts/update.py', '--if-needed'],
   },
 
   # Pull rc binaries using checked-in hashes.
@@ -140,18 +152,18 @@
                 '--no_resume',
                 '--no_auth',
                 '--bucket', 'chromium-browser-clang/rc',
-                '-s', 'build/toolchain/win/rc/win/rc.exe.sha1',
+                '-s', '{root}/build/toolchain/win/rc/win/rc.exe.sha1',
     ],
   },
 
   {
     # A change to a .gyp, .gypi, or to GYP itself should run the generator.
     'pattern': '.',
-    'action': ['python', 'gyp/gyp_angle'],
+    'action': ['python', '{root}/gyp/gyp_angle'],
   },
 ]
 
 recursedeps = [
   # buildtools provides clang_format.
-  'buildtools',
+  '{root}/buildtools',
 ]
diff --git a/DEPS.chromium b/DEPS.chromium
index 5902627..5c6f9ec 100644
--- a/DEPS.chromium
+++ b/DEPS.chromium
@@ -25,7 +25,7 @@
   'spirv_tools_revision': '9996173f363729b3a97309685dbd4d78547a63a7',
 
   # Current revision of the Vulkan Validation Layers SDK.
-  'vulkan_revision': '354ad3ba8b88136b82b712acab9b8fcb981beaff',
+  'vulkan_revision': '88e43c8f9a750839a5d6d3f90098505bad3a98a1',
 }
 
 deps = {
diff --git a/gni/angle.gni b/gni/angle.gni
index 2390949..e3fe971 100644
--- a/gni/angle.gni
+++ b/gni/angle.gni
@@ -50,6 +50,7 @@
 declare_args() {
   angle_enable_gl_null = angle_enable_gl
   angle_enable_hlsl = angle_enable_d3d9 || angle_enable_d3d11
+  angle_enable_vulkan_validation_layers = angle_enable_vulkan
 }
 
 if (is_win) {
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg
index be0ffd0..fd26e55 100644
--- a/infra/config/cq.cfg
+++ b/infra/config/cq.cfg
@@ -13,6 +13,12 @@
   }
   try_job {
     buckets {
+      name: "luci.angle.try"
+      builders { name: "linux" }
+      builders { name: "win" }
+      builders { name: "win-msvc" }
+    }
+    buckets {
       name: "luci.chromium.try"
       builders { name: "android_angle_rel_ng" }
       builders { name: "android_angle_deqp_rel_ng" }
@@ -22,33 +28,11 @@
       builders { name: "linux_angle_ozone_rel_ng" }
       builders { name: "mac_angle_rel_ng" }
       builders { name: "mac_angle_compile_dbg_ng" }
-    }
-    buckets {
-      name: "master.tryserver.chromium.angle"
-      builders {
-        name: "win_angle_rel_ng"
-        equivalent_to { bucket: "luci.chromium.try" percentage: 0 }
-      }
-      builders {
-        name: "win_angle_compile_dbg_ng"
-        equivalent_to { bucket: "luci.chromium.try" percentage: 0 }
-      }
-      builders {
-        name: "win_angle_compile_x64_rel_ng"
-        equivalent_to { bucket: "luci.chromium.try" percentage: 0 }
-      }
-      builders {
-        name: "win_angle_compile_x64_dbg_ng"
-        equivalent_to { bucket: "luci.chromium.try" percentage: 0 }
-      }
-      builders {
-        name: "win_angle_deqp_rel_ng"
-        equivalent_to { bucket: "luci.chromium.try" percentage: 0 }
-      }
-    }
-    buckets {
-      name: "master.tryserver.chromium.win"
-      builders { name: "win-msvc-rel" }
+      builders { name: "win_angle_rel_ng" }
+      builders { name: "win_angle_compile_dbg_ng" }
+      builders { name: "win_angle_compile_x64_rel_ng" }
+      builders { name: "win_angle_compile_x64_dbg_ng" }
+      builders { name: "win_angle_deqp_rel_ng" }
     }
   }
 }
diff --git a/samples/simple_texture_cubemap/SimpleTextureCubemap.cpp b/samples/simple_texture_cubemap/SimpleTextureCubemap.cpp
index 86feccb..0559980 100644
--- a/samples/simple_texture_cubemap/SimpleTextureCubemap.cpp
+++ b/samples/simple_texture_cubemap/SimpleTextureCubemap.cpp
@@ -21,8 +21,8 @@
 class SimpleTextureCubemapSample : public SampleApplication
 {
   public:
-    SimpleTextureCubemapSample()
-        : SampleApplication("SimpleTextureCubemap", 1280, 720)
+    SimpleTextureCubemapSample(EGLint displayType)
+        : SampleApplication("SimpleTextureCubemap", 1280, 720, 2, 0, displayType)
     {
     }
 
@@ -129,6 +129,13 @@
 
 int main(int argc, char **argv)
 {
-    SimpleTextureCubemapSample app;
+    EGLint displayType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
+
+    if (argc > 1)
+    {
+        displayType = GetDisplayTypeFromArg(argv[1]);
+    }
+
+    SimpleTextureCubemapSample app(displayType);
     return app.run();
 }
diff --git a/scripts/entry_point_packed_gl_enums.json b/scripts/entry_point_packed_gl_enums.json
index 9df1fbf..bcfb84d 100644
--- a/scripts/entry_point_packed_gl_enums.json
+++ b/scripts/entry_point_packed_gl_enums.json
@@ -76,9 +76,15 @@
     "glCullFace": {
         "mode": "CullFaceMode"
     },
+    "glDisableClientState": {
+        "array": "ClientVertexArrayType"
+    },
     "glEGLImageTargetTexture2DOES": {
         "target": "TextureType"
     },
+    "glEnableClientState": {
+        "array": "ClientVertexArrayType"
+    },
     "glFlushMappedBufferRange": {
         "target": "BufferBinding"
     },
diff --git a/scripts/gen_angle_gn_info_json.py b/scripts/gen_angle_gn_info_json.py
new file mode 100755
index 0000000..f79b373
--- /dev/null
+++ b/scripts/gen_angle_gn_info_json.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python
+
+#  Copyright 2018 The ANGLE Project Authors. All rights reserved.
+#  Use of this source code is governed by a BSD-style license that can be
+#  found in the LICENSE file.
+
+# This tool will create a json description of the GN build environment that
+# can then be used by gen_angle_android_bp.py to build an Android.bp file for
+# the Android Soong build system.
+# The input to this tool is a list of GN labels for which to capture the build
+# information in json:
+#
+# Generating angle.json needs to be done from within a Chromium build:
+#   cd <chromium>/src
+#   gen_angle_gn_info_json.py //third_party/angle:libGLESv2 //third_party/angle:libEGL
+#
+# This will output an angle.json that can be copied to the angle directory
+# within Android.
+#
+# Optional arguments:
+#  --gn_out <file>  GN output config to use (e.g., out/Default or out/Debug.)
+#  --output <file>  json file to create, default is angle.json
+#
+
+import argparse
+import json
+import logging
+import subprocess
+import sys
+
+
+def get_json_description(gn_out, target_name):
+    try:
+        text_desc = subprocess.check_output(
+            ['gn', 'desc', '--format=json', gn_out, target_name])
+    except subprocess.CalledProcessError as e:
+        logging.error("e.retcode = %s" % e.returncode)
+        logging.error("e.cmd = %s" % e.cmd)
+        logging.error("e.output = %s" % e.output)
+    try:
+        json_out = json.loads(text_desc)
+    except ValueError:
+        raise ValueError("Unable to decode JSON\ncmd: %s\noutput:\n%s" %
+                         (subprocess.list2cmdline(['gn', 'desc', '--format=json',
+                                                   gn_out, target_name]), text_desc))
+
+    return json_out
+
+def load_json_deps(desc, gn_out, target_name, all_desc, indent="  "):
+    """Extracts dependencies from the given target json description
+       and recursively extracts json descriptions.
+
+       desc: json description for target_name that includes dependencies
+       gn_out: GN output file with configuration info
+       target_name: name of target in desc to lookup deps
+       all_desc: dependent descriptions added here
+       indent: Print with indent to show recursion depth
+    """
+    target = desc[target_name]
+    text_descriptions = []
+    for dep in target.get('deps', []):
+        if dep not in all_desc:
+            logging.debug("dep: %s%s" % (indent,dep))
+            new_desc = get_json_description(gn_out, dep)
+            all_desc[dep] = new_desc[dep]
+            load_json_deps(new_desc, gn_out, dep, all_desc, indent+"  ")
+        else:
+            logging.debug("dup: %s%s" % (indent,dep))
+
+def create_build_description(gn_out, targets):
+    """Creates the JSON build description by running GN."""
+
+    logging.debug("targets = %s" % targets)
+    json_descriptions = {}
+    for target in targets:
+        logging.debug("target: %s" % (target))
+        target_desc = get_json_description(gn_out, target)
+        if (target in target_desc and target not in json_descriptions):
+            json_descriptions[target] = target_desc[target]
+            load_json_deps(target_desc, gn_out, target, json_descriptions)
+        else:
+            logging.debug("Invalid target: %s" % target)
+    return json_descriptions
+
+
+def main():
+    logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
+    parser = argparse.ArgumentParser(
+        description='Generate json build information from a GN description.')
+    parser.add_argument(
+        '--gn_out',
+        help=
+        'GN output config to use (e.g., out/Default or out/Debug.)',
+        default='out/Default',
+    )
+    parser.add_argument(
+        '--output',
+        help='json file to create',
+        default='angle.json',
+    )
+    parser.add_argument(
+        'targets',
+        nargs=argparse.REMAINDER,
+        help='Targets to include in the json (e.g., "//libEGL")')
+    args = parser.parse_args()
+
+    desc = create_build_description(args.gn_out, args.targets)
+    fh = open(args.output,"w")
+    fh.write(json.dumps(desc, indent=4, sort_keys=True))
+    fh.close()
+
+    print("Output written to: %s" % args.output)
+
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/scripts/generate_entry_points.py b/scripts/generate_entry_points.py
index 21b9422..2843877 100755
--- a/scripts/generate_entry_points.py
+++ b/scripts/generate_entry_points.py
@@ -13,7 +13,19 @@
 
 # List of supported extensions. Add to this list to enable new extensions
 # available in gl.xml.
-# TODO(jmadill): Support extensions not in gl.xml.
+
+angle_extensions = [
+    # ANGLE extensions
+    "GL_CHROMIUM_bind_uniform_location",
+    "GL_CHROMIUM_framebuffer_mixed_samples",
+    "GL_CHROMIUM_path_rendering",
+    "GL_CHROMIUM_copy_texture",
+    "GL_CHROMIUM_copy_compressed_texture",
+    "GL_ANGLE_request_extension",
+    "GL_ANGLE_robust_client_memory",
+    "GL_ANGLE_multiview",
+]
+
 gles1_extensions = [
     # ES1 (Possibly the min set of extensions needed by Android)
     "GL_OES_draw_texture",
@@ -35,7 +47,7 @@
     "glGetPointerv",
 ]
 
-supported_extensions = sorted(gles1_extensions + [
+supported_extensions = sorted(angle_extensions + gles1_extensions + [
     # ES2+
     "GL_ANGLE_framebuffer_blit",
     "GL_ANGLE_framebuffer_multisample",
@@ -66,7 +78,7 @@
 ])
 
 # Strip these suffixes from Context entry point names. NV is excluded (for now).
-strip_suffixes = ["ANGLE", "EXT", "KHR", "OES"]
+strip_suffixes = ["ANGLE", "EXT", "KHR", "OES", "CHROMIUM"]
 
 template_entry_point_header = """// GENERATED FILE - DO NOT EDIT.
 // Generated by {script_name} using data from {data_source_name}.
@@ -357,11 +369,11 @@
     return decls
 
 
-def write_file(annotation, comment, template, entry_points, suffix, includes):
+def write_file(annotation, comment, template, entry_points, suffix, includes, file):
 
     content = template.format(
         script_name = os.path.basename(sys.argv[0]),
-        data_source_name = "gl.xml",
+        data_source_name = file,
         year = date.today().year,
         annotation_lower = annotation.lower(),
         annotation_upper = annotation.upper(),
@@ -401,6 +413,21 @@
         out.write(content)
         out.close()
 
+def append_angle_extensions(base_root):
+    angle_ext_tree = etree.parse(script_relative('gl_angle_ext.xml'))
+    angle_ext_root = angle_ext_tree.getroot()
+
+    insertion_point = base_root.findall("./commands")[0]
+    for command in angle_ext_root.iter('commands'):
+        insertion_point.extend(command)
+
+    insertion_point = base_root.findall("./extensions")[0]
+    for extension in angle_ext_root.iter('extensions'):
+        insertion_point.extend(extension)
+    return base_root
+
+root = append_angle_extensions(root)
+
 all_commands = root.findall('commands/command')
 all_cmd_names = []
 
@@ -454,9 +481,9 @@
         annotation.lower(), major_version,minor_if_not_zero)
 
     write_file(annotation, comment, template_entry_point_header,
-               "\n".join(decls), "h", header_includes)
+               "\n".join(decls), "h", header_includes, "gl.xml")
     write_file(annotation, comment, template_entry_point_source,
-               "\n".join(defs), "cpp", source_includes)
+               "\n".join(defs), "cpp", source_includes, "gl.xml")
     if is_gles1:
         gles1decls['core'] = get_gles1_decls(all_commands, gles_commands)
 
@@ -547,9 +574,11 @@
 """
 
 write_file("ext", "extension", template_entry_point_header,
-           "\n".join([item for item in extension_decls]), "h", header_includes)
+           "\n".join([item for item in extension_decls]), "h", header_includes,
+           "gl.xml and gl_angle_ext.xml")
 write_file("ext", "extension", template_entry_point_source,
-           "\n".join([item for item in extension_defs]), "cpp", source_includes)
+           "\n".join([item for item in extension_defs]), "cpp", source_includes,
+           "gl.xml and gl_angle_ext.xml")
 
 write_context_api_decls("1_0", context_gles_header, gles1decls)
 
@@ -557,7 +586,7 @@
 
 entry_points_enum = template_entry_points_enum_header.format(
     script_name = os.path.basename(sys.argv[0]),
-    data_source_name = "gl.xml",
+    data_source_name = "gl.xml and gl_angle_ext.xml",
     year = date.today().year,
     entry_points_list = ",\n".join(["    " + cmd for cmd in sorted_cmd_names]))
 
diff --git a/scripts/gl_angle_ext.xml b/scripts/gl_angle_ext.xml
new file mode 100644
index 0000000..c1742d9
--- /dev/null
+++ b/scripts/gl_angle_ext.xml
@@ -0,0 +1,951 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<registry>
+    <comment>
+    Copyright 2018 The ANGLE Project Authors. All rights reserved.
+    Use of this source code is governed by a BSD-style license that can be
+    found in the LICENSE file.
+
+    gl_angle_ext.xml
+        Includes data used to generate ANGLE extension entry points using generate_entry_points.py
+    </comment>
+    <!-- SECTION: GL command definitions. -->
+    <commands namespace="GL">
+            <command>
+                <proto>void <name>glBindUniformLocationCHROMIUM</name></proto>
+                <param><ptype>GLuint</ptype> <name>program</name></param>
+                <param><ptype>GLint</ptype> <name>location</name></param>
+                <param><ptype>const GLchar*</ptype> <name>name</name></param>
+            </command>
+            <command>
+                <proto>void <name>glCoverageModulationCHROMIUM</name></proto>
+                <param><ptype>GLenum</ptype> <name>components</name></param>
+            </command>
+            <command>
+                <proto>void <name>glMatrixLoadfCHROMIUM</name></proto>
+                <param><ptype>GLenum</ptype> <name>matrixMode</name></param>
+                <param><ptype>const GLfloat *</ptype> <name>matrix</name></param>
+            </command>
+            <command>
+                <proto>void <name>glMatrixLoadIdentityCHROMIUM</name></proto>
+                <param><ptype>GLenum</ptype> <name>matrixMode</name></param>
+            </command>
+            <command>
+                <proto>GLuint <name>glGenPathsCHROMIUM</name></proto>
+                <param><ptype>GLsizei</ptype> <name>range</name></param>
+            </command>
+            <command>
+                <proto>void <name>glDeletePathsCHROMIUM</name></proto>
+                <param><ptype>GLuint</ptype> <name>first</name></param>
+                <param><ptype>GLsizei</ptype> <name>range</name></param>
+            </command>
+            <command>
+                <proto>GLboolean <name>glIsPathCHROMIUM</name></proto>
+                <param><ptype>GLuint</ptype> <name>path</name></param>
+            </command>
+            <command>
+                <proto>void <name>glPathCommandsCHROMIUM</name></proto>
+                <param><ptype>GLuint</ptype> <name>path</name></param>
+                <param><ptype>GLsizei</ptype> <name>numCommands</name></param>
+                <param><ptype>const GLubyte *</ptype> <name>commands</name></param>
+                <param><ptype>GLsizei</ptype> <name>numCoords</name></param>
+                <param><ptype>GLenum</ptype> <name>coordType</name></param>
+                <param><ptype>const void*</ptype> <name>coords</name></param>
+            </command>
+            <command>
+                <proto>void <name>glPathParameterfCHROMIUM</name></proto>
+                <param><ptype>GLuint</ptype> <name>path</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLfloat</ptype> <name>value</name></param>
+            </command>
+            <command>
+                <proto>void <name>glPathParameteriCHROMIUM</name></proto>
+                <param><ptype>GLuint</ptype> <name>path</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLint</ptype> <name>value</name></param>
+            </command>
+            <command>
+                <proto>void <name>glGetPathParameterfvCHROMIUM</name></proto>
+                <param><ptype>GLuint</ptype> <name>path</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLfloat *</ptype> <name>value</name></param>
+            </command>
+            <command>
+                <proto>void <name>glGetPathParameterivCHROMIUM</name></proto>
+                <param><ptype>GLuint</ptype> <name>path</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLint *</ptype> <name>value</name></param>
+            </command>
+            <command>
+                <proto>void <name>glPathStencilFuncCHROMIUM</name></proto>
+                <param><ptype>GLenum</ptype> <name>func</name></param>
+                <param><ptype>GLint</ptype> <name>ref</name></param>
+                <param><ptype>GLuint</ptype> <name>mask</name></param>
+            </command>
+            <command>
+                <proto>void <name>glStencilFillPathCHROMIUM</name></proto>
+                <param><ptype>GLuint</ptype> <name>path</name></param>
+                <param><ptype>GLenum</ptype> <name>fillMode</name></param>
+                <param><ptype>GLuint</ptype> <name>mask</name></param>
+            </command>
+            <command>
+                <proto>void <name>glStencilStrokePathCHROMIUM</name></proto>
+                <param><ptype>GLuint</ptype> <name>path</name></param>
+                <param><ptype>GLint</ptype> <name>reference</name></param>
+                <param><ptype>GLuint</ptype> <name>mask</name></param>
+            </command>
+            <command>
+                <proto>void <name>glCoverFillPathCHROMIUM</name></proto>
+                <param><ptype>GLuint</ptype> <name>path</name></param>
+                <param><ptype>GLenum</ptype> <name>coverMode</name></param>
+            </command>
+            <command>
+                <proto>void <name>glCoverStrokePathCHROMIUM</name></proto>
+                <param><ptype>GLuint</ptype> <name>path</name></param>
+                <param><ptype>GLenum</ptype> <name>coverMode</name></param>
+            </command>
+            <command>
+                <proto>void <name>glStencilThenCoverFillPathCHROMIUM</name></proto>
+                <param><ptype>GLuint</ptype> <name>path</name></param>
+                <param><ptype>GLenum</ptype> <name>fillMode</name></param>
+                <param><ptype>GLuint</ptype> <name>mask</name></param>
+                <param><ptype>GLenum</ptype> <name>coverMode</name></param>
+            </command>
+            <command>
+                <proto>void <name>glStencilThenCoverStrokePathCHROMIUM</name></proto>
+                <param><ptype>GLuint</ptype> <name>path</name></param>
+                <param><ptype>GLint</ptype> <name>reference</name></param>
+                <param><ptype>GLuint</ptype> <name>mask</name></param>
+                <param><ptype>GLenum</ptype> <name>coverMode</name></param>
+            </command>
+            <command>
+                <proto>void <name>glCoverFillPathInstancedCHROMIUM</name></proto>
+                <param><ptype>GLsizei</ptype> <name>numPath</name></param>
+                <param><ptype>GLenum</ptype> <name>pathNameType</name></param>
+                <param><ptype>const void *</ptype> <name>paths</name></param>
+                <param><ptype>GLuint</ptype> <name>pathBase</name></param>
+                <param><ptype>GLenum</ptype> <name>coverMode</name></param>
+                <param><ptype>GLenum</ptype> <name>transformType</name></param>
+                <param><ptype>const GLfloat *</ptype> <name>transformValues</name></param>
+            </command>
+            <command>
+                <proto>void <name>glCoverStrokePathInstancedCHROMIUM</name></proto>
+                <param><ptype>GLsizei</ptype> <name>numPath</name></param>
+                <param><ptype>GLenum</ptype> <name>pathNameType</name></param>
+                <param><ptype>const void *</ptype> <name>paths</name></param>
+                <param><ptype>GLuint</ptype> <name>pathBase</name></param>
+                <param><ptype>GLenum</ptype> <name>coverMode</name></param>
+                <param><ptype>GLenum</ptype> <name>transformType</name></param>
+                <param><ptype>const GLfloat *</ptype> <name>transformValues</name></param>
+            </command>
+            <command>
+                <proto>void <name>glStencilStrokePathInstancedCHROMIUM</name></proto>
+                <param><ptype>GLsizei</ptype> <name>numPath</name></param>
+                <param><ptype>GLenum</ptype> <name>pathNameType</name></param>
+                <param><ptype>const void *</ptype> <name>paths</name></param>
+                <param><ptype>GLuint</ptype> <name>pathBase</name></param>
+                <param><ptype>GLint</ptype> <name>reference</name></param>
+                <param><ptype>GLuint</ptype> <name>mask</name></param>
+                <param><ptype>GLenum</ptype> <name>transformType</name></param>
+                <param><ptype>const GLfloat *</ptype> <name>transformValues</name></param>
+            </command>
+            <command>
+                <proto>void <name>glStencilFillPathInstancedCHROMIUM</name></proto>
+                <param><ptype>GLsizei</ptype> <name>numPaths</name></param>
+                <param><ptype>GLenum</ptype> <name>pathNameType</name></param>
+                <param><ptype>const void *</ptype> <name>paths</name></param>
+                <param><ptype>GLuint</ptype> <name>pathBase</name></param>
+                <param><ptype>GLenum</ptype> <name>fillMode</name></param>
+                <param><ptype>GLuint</ptype> <name>mask</name></param>
+                <param><ptype>GLenum</ptype> <name>transformType</name></param>
+                <param><ptype>const GLfloat *</ptype> <name>transformValues</name></param>
+            </command>
+            <command>
+                <proto>void <name>glStencilThenCoverFillPathInstancedCHROMIUM</name></proto>
+                <param><ptype>GLsizei</ptype> <name>numPaths</name></param>
+                <param><ptype>GLenum</ptype> <name>pathNameType</name></param>
+                <param><ptype>const void *</ptype> <name>paths</name></param>
+                <param><ptype>GLuint</ptype> <name>pathBase</name></param>
+                <param><ptype>GLenum</ptype> <name>fillMode</name></param>
+                <param><ptype>GLuint</ptype> <name>mask</name></param>
+                <param><ptype>GLenum</ptype> <name>coverMode</name></param>
+                <param><ptype>GLenum</ptype> <name>transformType</name></param>
+                <param><ptype>const GLfloat *</ptype> <name>transformValues</name></param>
+            </command>
+            <command>
+                <proto>void <name>glStencilThenCoverStrokePathInstancedCHROMIUM</name></proto>
+                <param><ptype>GLsizei</ptype> <name>numPaths</name></param>
+                <param><ptype>GLenum</ptype> <name>pathNameType</name></param>
+                <param><ptype>const void *</ptype> <name>paths</name></param>
+                <param><ptype>GLuint</ptype> <name>pathBase</name></param>
+                <param><ptype>GLint</ptype> <name>reference</name></param>
+                <param><ptype>GLuint</ptype> <name>mask</name></param>
+                <param><ptype>GLenum</ptype> <name>coverMode</name></param>
+                <param><ptype>GLenum</ptype> <name>transformType</name></param>
+                <param><ptype>const GLfloat *</ptype> <name>transformValues</name></param>
+            </command>
+            <command>
+            <proto>void <name>glBindFragmentInputLocationCHROMIUM</name></proto>
+                <param><ptype>GLuint</ptype> <name>programs</name></param>
+                <param><ptype>GLint</ptype> <name>location</name></param>
+                <param><ptype>const GLchar *</ptype> <name>name</name></param>
+            </command>
+            <command>
+            <proto>void <name>glProgramPathFragmentInputGenCHROMIUM</name></proto>
+                <param><ptype>GLuint</ptype> <name>program</name></param>
+                <param><ptype>GLint</ptype> <name>location</name></param>
+                <param><ptype>GLenum</ptype> <name>genMode</name></param>
+                <param><ptype>GLint</ptype> <name>components</name></param>
+                <param><ptype>const GLfloat *</ptype> <name>coeffs</name></param>
+            </command>
+            <command>
+            <proto>void <name>glCopyTextureCHROMIUM</name></proto>
+                <param><ptype>GLuint</ptype> <name>sourceId</name></param>
+                <param><ptype>GLint</ptype> <name>sourceLevel</name></param>
+                <param><ptype>GLenum</ptype> <name>destTarget</name></param>
+                <param><ptype>GLuint</ptype> <name>destId</name></param>
+                <param><ptype>GLint</ptype> <name>destLevel</name></param>
+                <param><ptype>GLint</ptype> <name>internalFormat</name></param>
+                <param><ptype>GLenum</ptype> <name>destType</name></param>
+                <param><ptype>GLboolean</ptype> <name>unpackFlipY</name></param>
+                <param><ptype>GLboolean</ptype> <name>unpackPremultiplyAlpha</name></param>
+                <param><ptype>GLboolean</ptype> <name>unpackUnmultiplyAlpha</name></param>
+            </command>
+            <command>
+            <proto>void <name>glCopySubTextureCHROMIUM</name></proto>
+            <param><ptype>GLuint</ptype> <name>sourceId</name></param>
+            <param><ptype>GLint</ptype> <name>sourceLevel</name></param>
+            <param><ptype>GLenum</ptype> <name>destTarget</name></param>
+            <param><ptype>GLuint</ptype> <name>destId</name></param>
+            <param><ptype>GLint</ptype> <name>destLevel</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLint</ptype> <name>width</name></param>
+            <param><ptype>GLint</ptype> <name>height</name></param>
+            <param><ptype>GLboolean</ptype> <name>unpackFlipY</name></param>
+            <param><ptype>GLboolean</ptype> <name>unpackPremultiplyAlpha</name></param>
+            <param><ptype>GLboolean</ptype> <name>unpackUnmultiplyAlpha</name></param>
+            </command>
+            <command>
+            <proto>void <name>glCompressedCopyTextureCHROMIUM</name></proto>
+                <param><ptype>GLuint</ptype> <name>sourceId</name></param>
+                <param><ptype>GLuint</ptype> <name>destId</name></param>
+            </command>
+            <command>
+            <proto>void <name>glRequestExtensionANGLE</name></proto>
+                <param><ptype>const GLchar *</ptype> <name>name</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetBooleanvRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLboolean *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetBufferParameterivRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetFloatvRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLfloat *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetFramebufferAttachmentParameterivRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLenum</ptype> <name>attachment</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetIntegervRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>data</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetProgramivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>program</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetRenderbufferParameterivRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetShaderivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>shader</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetTexParameterfvRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLfloat *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetTexParameterivRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetUniformfvRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>program</name></param>
+                <param><ptype>GLint</ptype> <name>location</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLfloat *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetUniformivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>program</name></param>
+                <param><ptype>GLint</ptype> <name>location</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetVertexAttribfvRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>index</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLfloat *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetVertexAttribivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>index</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetVertexAttribPointervRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>index</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>void **</ptype> <name>pointer</name></param>
+            </command>
+            <command>
+            <proto>void <name>glReadPixelsRobustANGLE</name></proto>
+                <param><ptype>GLint</ptype> <name>x</name></param>
+                <param><ptype>GLint</ptype> <name>y</name></param>
+                <param><ptype>GLsizei</ptype> <name>width</name></param>
+                <param><ptype>GLsizei</ptype> <name>height</name></param>
+                <param><ptype>GLenum</ptype> <name>format</name></param>
+                <param><ptype>GLenum</ptype> <name>type</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLsizei *</ptype> <name>columns</name></param>
+                <param><ptype>GLsizei *</ptype> <name>rows</name></param>
+                <param><ptype>void *</ptype> <name>pixels</name></param>
+            </command>
+            <command>
+            <proto>void <name>glTexImage2DRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLint</ptype> <name>level</name></param>
+                <param><ptype>GLint</ptype> <name>internalformat</name></param>
+                <param><ptype>GLsizei</ptype> <name>width</name></param>
+                <param><ptype>GLsizei</ptype> <name>height</name></param>
+                <param><ptype>GLint</ptype> <name>border</name></param>
+                <param><ptype>GLenum</ptype> <name>format</name></param>
+                <param><ptype>GLenum</ptype> <name>type</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>const void *</ptype> <name>pixels</name></param>
+            </command>
+            <command>
+            <proto>void <name>glTexParameterfvRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>const GLfloat *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glTexParameterivRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>const GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glTexSubImage2DRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLint</ptype> <name>level</name></param>
+                <param><ptype>GLint</ptype> <name>xoffset</name></param>
+                <param><ptype>GLint</ptype> <name>yoffset</name></param>
+                <param><ptype>GLsizei</ptype> <name>width</name></param>
+                <param><ptype>GLsizei</ptype> <name>height</name></param>
+                <param><ptype>GLenum</ptype> <name>format</name></param>
+                <param><ptype>GLenum</ptype> <name>type</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>const void *</ptype> <name>pixels</name></param>
+            </command>
+            <command>
+            <proto>void <name>glTexImage3DRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLint</ptype> <name>level</name></param>
+                <param><ptype>GLint</ptype> <name>internalformat</name></param>
+                <param><ptype>GLsizei</ptype> <name>width</name></param>
+                <param><ptype>GLsizei</ptype> <name>height</name></param>
+                <param><ptype>GLsizei</ptype> <name>depth</name></param>
+                <param><ptype>GLint</ptype> <name>border</name></param>
+                <param><ptype>GLenum</ptype> <name>format</name></param>
+                <param><ptype>GLenum</ptype> <name>type</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>const void *</ptype> <name>pixels</name></param>
+            </command>
+            <command>
+            <proto>void <name>glTexSubImage3DRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLint</ptype> <name>level</name></param>
+                <param><ptype>GLint</ptype> <name>xoffset</name></param>
+                <param><ptype>GLint</ptype> <name>yoffset</name></param>
+                <param><ptype>GLint</ptype> <name>zoffset</name></param>
+                <param><ptype>GLsizei</ptype> <name>width</name></param>
+                <param><ptype>GLsizei</ptype> <name>height</name></param>
+                <param><ptype>GLsizei</ptype> <name>depth</name></param>
+                <param><ptype>GLenum</ptype> <name>format</name></param>
+                <param><ptype>GLenum</ptype> <name>type</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>const void *</ptype> <name>pixels</name></param>
+            </command>
+            <command>
+            <proto>void <name>glCompressedTexImage2DRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLint</ptype> <name>level</name></param>
+                <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+                <param><ptype>GLsizei</ptype> <name>width</name></param>
+                <param><ptype>GLsizei</ptype> <name>height</name></param>
+                <param><ptype>GLint</ptype> <name>border</name></param>
+                <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+                <param><ptype>GLsizei</ptype> <name>dataSize</name></param>
+                <param><ptype>const GLvoid *</ptype> <name>data</name></param>
+            </command>
+            <command>
+            <proto>void <name>glCompressedTexSubImage2DRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLint</ptype> <name>level</name></param>
+                <param><ptype>GLsizei</ptype> <name>xoffset</name></param>
+                <param><ptype>GLsizei</ptype> <name>yoffset</name></param>
+                <param><ptype>GLsizei</ptype> <name>width</name></param>
+                <param><ptype>GLsizei</ptype> <name>height</name></param>
+                <param><ptype>GLenum</ptype> <name>format</name></param>
+                <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+                <param><ptype>GLsizei</ptype> <name>dataSize</name></param>
+                <param><ptype>const GLvoid *</ptype> <name>data</name></param>
+            </command>
+            <command>
+            <proto>void <name>glCompressedTexImage3DRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLint</ptype> <name>level</name></param>
+                <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+                <param><ptype>GLsizei</ptype> <name>width</name></param>
+                <param><ptype>GLsizei</ptype> <name>height</name></param>
+                <param><ptype>GLsizei</ptype> <name>depth</name></param>
+                <param><ptype>GLint</ptype> <name>border</name></param>
+                <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+                <param><ptype>GLsizei</ptype> <name>dataSize</name></param>
+                <param><ptype>const GLvoid *</ptype> <name>data</name></param>
+            </command>
+            <command>
+            <proto>void <name>glCompressedTexSubImage3DRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLint</ptype> <name>level</name></param>
+                <param><ptype>GLint</ptype> <name>xoffset</name></param>
+                <param><ptype>GLint</ptype> <name>yoffset</name></param>
+                <param><ptype>GLint</ptype> <name>zoffset</name></param>
+                <param><ptype>GLsizei</ptype> <name>width</name></param>
+                <param><ptype>GLsizei</ptype> <name>height</name></param>
+                <param><ptype>GLsizei</ptype> <name>depth</name></param>
+                <param><ptype>GLenum</ptype> <name>format</name></param>
+                <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+                <param><ptype>GLsizei</ptype> <name>dataSize</name></param>
+                <param><ptype>const GLvoid *</ptype> <name>data</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetQueryivRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetQueryObjectuivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>id</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLuint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetBufferPointervRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>void **</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetIntegeri_vRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLuint</ptype> <name>index</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>data</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetInternalformativRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetVertexAttribIivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>index</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetVertexAttribIuivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>index</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLuint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetUniformuivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>program</name></param>
+                <param><ptype>GLint</ptype> <name>location</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLuint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetActiveUniformBlockivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>program</name></param>
+                <param><ptype>GLuint</ptype> <name>uniformBlockIndex</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetInteger64vRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint64 *</ptype> <name>data</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetInteger64i_vRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLuint</ptype> <name>index</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint64 *</ptype> <name>data</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetBufferParameteri64vRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint64 *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glSamplerParameterivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>sampler</name></param>
+                <param><ptype>GLuint</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>const GLint *</ptype> <name>param</name></param>
+            </command>
+            <command>
+            <proto>void <name>glSamplerParameterfvRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>sampler</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>const GLfloat *</ptype> <name>param</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetSamplerParameterivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>sampler</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetSamplerParameterfvRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>sampler</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLfloat *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetFramebufferParameterivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>sampler</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetProgramInterfaceivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>program</name></param>
+                <param><ptype>GLenum</ptype> <name>programInterface</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetBooleani_vRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLuint</ptype> <name>index</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLboolean *</ptype> <name>data</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetMultisamplefvRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLuint</ptype> <name>index</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLfloat *</ptype> <name>val</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetTexLevelParameterivRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLint</ptype> <name>level</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetTexLevelParameterfvRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLint</ptype> <name>level</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLfloat *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetPointervRobustANGLERobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>void **</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glReadnPixelsRobustANGLE</name></proto>
+                <param><ptype>GLint</ptype> <name>x</name></param>
+                <param><ptype>GLint</ptype> <name>y</name></param>
+                <param><ptype>GLsizei</ptype> <name>width</name></param>
+                <param><ptype>GLsizei</ptype> <name>height</name></param>
+                <param><ptype>GLenum</ptype> <name>format</name></param>
+                <param><ptype>GLenum</ptype> <name>type</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLsizei *</ptype> <name>columns</name></param>
+                <param><ptype>GLsizei *</ptype> <name>rows</name></param>
+                <param><ptype>void *</ptype> <name>data</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetnUniformfvRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>program</name></param>
+                <param><ptype>GLint</ptype> <name>location</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLfloat *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetnUniformivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>program</name></param>
+                <param><ptype>GLint</ptype> <name>location</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetnUniformuivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>program</name></param>
+                <param><ptype>GLint</ptype> <name>location</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLuint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glTexParameterIivRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>const GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glTexParameterIuivRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>const GLuint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetTexParameterIivRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetTexParameterIuivRobustANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLuint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glSamplerParameterIivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>sampler</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>const GLint *</ptype> <name>param</name></param>
+            </command>
+            <command>
+            <proto>void <name>glSamplerParameterIuivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>sampler</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>const GLuint *</ptype> <name>param</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetSamplerParameterIivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>sampler</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetSamplerParameterIuivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>sampler</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLuint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetQueryObjectivRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>id</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetQueryObjecti64vRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>id</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLint64 *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glGetQueryObjectui64vRobustANGLE</name></proto>
+                <param><ptype>GLuint</ptype> <name>id</name></param>
+                <param><ptype>GLenum</ptype> <name>pname</name></param>
+                <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+                <param><ptype>GLsizei *</ptype> <name>length</name></param>
+                <param><ptype>GLuint64 *</ptype> <name>params</name></param>
+            </command>
+            <command>
+            <proto>void <name>glFramebufferTextureMultiviewLayeredANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLenum</ptype> <name>attachment</name></param>
+                <param><ptype>GLuint</ptype> <name>texture</name></param>
+                <param><ptype>GLint</ptype> <name>level</name></param>
+                <param><ptype>GLint</ptype> <name>baseViewIndex</name></param>
+                <param><ptype>GLsizei</ptype> <name>numViews</name></param>
+            </command>
+            <command>
+            <proto>void <name>glFramebufferTextureMultiviewSideBySideANGLE</name></proto>
+                <param><ptype>GLenum</ptype> <name>target</name></param>
+                <param><ptype>GLenum</ptype> <name>attachment</name></param>
+                <param><ptype>GLuint</ptype> <name>texture</name></param>
+                <param><ptype>GLint</ptype> <name>level</name></param>
+                <param><ptype>GLsizei</ptype> <name>numViews</name></param>
+                <param><ptype>const GLint *</ptype> <name>viewportOffsets</name></param>
+            </command>
+    </commands>
+    <!-- SECTION: ANGLE extension interface definitions -->
+    <extensions>
+        <extension name="GL_CHROMIUM_bind_uniform_location" supported='gl'>
+            <require>
+                <command name="glBindUniformLocationCHROMIUM"/>
+            </require>
+        </extension>
+        <extension name="GL_CHROMIUM_framebuffer_mixed_samples" supported='gl'>
+            <require>
+                <command name="glMatrixLoadfCHROMIUM"/>
+                <command name="glMatrixLoadIdentityCHROMIUM"/>
+                <command name="glCoverageModulationCHROMIUM"/>
+            </require>
+        </extension>
+        <extension name="GL_CHROMIUM_path_rendering" supported='gl'>
+        <require>
+            <command name="glGenPathsCHROMIUM"/>
+            <command name="glDeletePathsCHROMIUM"/>
+            <command name="glIsPathCHROMIUM"/>
+            <command name="glPathCommandsCHROMIUM"/>
+            <command name="glPathParameterfCHROMIUM"/>
+            <command name="glPathParameteriCHROMIUM"/>
+            <command name="glGetPathParameterfvCHROMIUM"/>
+            <command name="glGetPathParameterivCHROMIUM"/>
+            <command name="glPathStencilFuncCHROMIUM"/>
+            <command name="glStencilFillPathCHROMIUM"/>
+            <command name="glStencilStrokePathCHROMIUM"/>
+            <command name="glCoverFillPathCHROMIUM"/>
+            <command name="glCoverStrokePathCHROMIUM"/>
+            <command name="glStencilThenCoverFillPathCHROMIUM"/>
+            <command name="glStencilThenCoverStrokePathCHROMIUM"/>
+            <command name="glCoverFillPathInstancedCHROMIUM"/>
+            <command name="glCoverStrokePathInstancedCHROMIUM"/>
+            <command name="glStencilFillPathInstancedCHROMIUM"/>
+            <command name="glStencilStrokePathInstancedCHROMIUM"/>
+            <command name="glStencilThenCoverFillPathInstancedCHROMIUM"/>
+            <command name="glStencilThenCoverStrokePathInstancedCHROMIUM"/>
+            <command name="glBindFragmentInputLocationCHROMIUM"/>
+            <command name="glProgramPathFragmentInputGenCHROMIUM"/>
+        </require>
+        </extension>
+        <extension name="GL_CHROMIUM_copy_texture" supported='gl'>
+            <require>
+                <command name="glCopyTextureCHROMIUM"/>
+                <command name="glCopySubTextureCHROMIUM"/>
+            </require>
+        </extension>
+        <extension name="GL_CHROMIUM_copy_compressed_texture" supported='gl'>
+            <require>
+                <command name="glCompressedCopyTextureCHROMIUM"/>
+            </require>
+        </extension>
+        <extension name="GL_ANGLE_request_extension" supported='gl'>
+            <require>
+                <command name="glRequestExtensionANGLE"/>
+            </require>
+        </extension>
+        <extension name="GL_ANGLE_robust_client_memory" supported='gl'>
+            <require>
+                <command name="glGetBooleanvRobustANGLE"/>
+                <command name="glGetBufferParameterivRobustANGLE"/>
+                <command name="glGetBufferParameteri64vRobustANGLE"/>
+                <command name="glGetFloatvRobustANGLE"/>
+                <command name="glGetFramebufferAttachmentParameterivRobustANGLE"/>
+                <command name="glGetIntegervRobustANGLE"/>
+                <command name="glGetProgramivRobustANGLE"/>
+                <command name="glGetRenderbufferParameterivRobustANGLE"/>
+                <command name="glGetShaderivRobustANGLE"/>
+                <command name="glGetTexParameterfvRobustANGLE"/>
+                <command name="glGetTexParameterivRobustANGLE"/>
+                <command name="glGetUniformfvRobustANGLE"/>
+                <command name="glGetUniformivRobustANGLE"/>
+                <command name="glGetVertexAttribfvRobustANGLE"/>
+                <command name="glGetVertexAttribivRobustANGLE"/>
+                <command name="glGetVertexAttribPointervRobustANGLE"/>
+                <command name="glReadPixelsRobustANGLE"/>
+                <command name="glTexImage2DRobustANGLE"/>
+                <command name="glTexParameterfvRobustANGLE"/>
+                <command name="glTexParameterivRobustANGLE"/>
+                <command name="glTexSubImage2DRobustANGLE"/>
+                <command name="glTexImage3DRobustANGLE"/>
+                <command name="glTexSubImage3DRobustANGLE"/>
+                <command name="glCompressedTexImage2DRobustANGLE"/>
+                <command name="glCompressedTexSubImage2DRobustANGLE"/>
+                <command name="glCompressedTexImage3DRobustANGLE"/>
+                <command name="glCompressedTexSubImage3DRobustANGLE"/>
+                <command name="glGetQueryivRobustANGLE"/>
+                <command name="glGetQueryObjectuivRobustANGLE"/>
+                <command name="glGetBufferPointervRobustANGLE"/>
+                <command name="glGetIntegeri_vRobustANGLE"/>
+                <command name="glGetInternalformativRobustANGLE"/>
+                <command name="glGetVertexAttribIivRobustANGLE"/>
+                <command name="glGetVertexAttribIuivRobustANGLE"/>
+                <command name="glGetUniformuivRobustANGLE"/>
+                <command name="glGetActiveUniformBlockivRobustANGLE"/>
+                <command name="glGetInteger64vRobustANGLE"/>
+                <command name="glGetInteger64i_vRobustANGLE"/>
+                <command name="glSamplerParameterivRobustANGLE"/>
+                <command name="glSamplerParameterfvRobustANGLE"/>
+                <command name="glGetSamplerParameterivRobustANGLE"/>
+                <command name="glGetSamplerParameterfvRobustANGLE"/>
+                <command name="glGetFramebufferParameterivRobustANGLE"/>
+                <command name="glGetProgramInterfaceivRobustANGLE"/>
+                <command name="glGetBooleani_vRobustANGLE"/>
+                <command name="glGetMultisamplefvRobustANGLE"/>
+                <command name="glGetTexLevelParameterivRobustANGLE"/>
+                <command name="glGetTexLevelParameterfvRobustANGLE"/>
+                <command name="glGetPointervRobustANGLERobustANGLE"/>
+                <command name="glReadnPixelsRobustANGLE"/>
+                <command name="glGetnUniformfvRobustANGLE"/>
+                <command name="glGetnUniformivRobustANGLE"/>
+                <command name="glGetnUniformuivRobustANGLE"/>
+                <command name="glTexParameterIivRobustANGLE"/>
+                <command name="glTexParameterIuivRobustANGLE"/>
+                <command name="glGetTexParameterIivRobustANGLE"/>
+                <command name="glGetTexParameterIuivRobustANGLE"/>
+                <command name="glSamplerParameterIivRobustANGLE"/>
+                <command name="glSamplerParameterIuivRobustANGLE"/>
+                <command name="glGetSamplerParameterIivRobustANGLE"/>
+                <command name="glGetSamplerParameterIuivRobustANGLE"/>
+                <command name="glGetQueryObjectivRobustANGLE"/>
+                <command name="glGetQueryObjecti64vRobustANGLE"/>
+                <command name="glGetQueryObjectui64vRobustANGLE"/>
+            </require>
+        </extension>
+        <extension name="GL_ANGLE_multiview" supported='gl'>
+            <require>
+                <command name="glFramebufferTextureMultiviewSideBySideANGLE"/>
+                <command name="glFramebufferTextureMultiviewLayeredANGLE"/>
+            </require>
+        </extension>
+    </extensions>
+</registry>
diff --git a/scripts/run_code_generation.py b/scripts/run_code_generation.py
index a3b9ee7..e5cac24 100755
--- a/scripts/run_code_generation.py
+++ b/scripts/run_code_generation.py
@@ -115,11 +115,14 @@
         ],
         'script': 'src/libANGLE/renderer/gl/generate_gl_dispatch_table.py',
     },
-    'packed GLenum': {
+    'packed enum': {
         'inputs': [
             'src/libANGLE/packed_gl_enums.json',
+            'src/libANGLE/packed_egl_enums.json',
         ],
         'outputs': [
+            'src/libANGLE/PackedEGLEnums_autogen.cpp',
+            'src/libANGLE/PackedEGLEnums_autogen.h',
             'src/libANGLE/PackedGLEnums_autogen.cpp',
             'src/libANGLE/PackedGLEnums_autogen.h',
         ],
diff --git a/src/commit_id.py b/src/commit_id.py
old mode 100644
new mode 100755
index 57651a5..a430103
--- a/src/commit_id.py
+++ b/src/commit_id.py
@@ -1,3 +1,11 @@
+#!/usr/bin/env python
+#  Copyright 2018 The ANGLE Project Authors. All rights reserved.
+#  Use of this source code is governed by a BSD-style license that can be
+#  found in the LICENSE file.
+
+# Generate commit.h with git commit hash.
+#
+
 import subprocess as sp
 import sys
 import os
diff --git a/src/common/debug.cpp b/src/common/debug.cpp
index 9206391..64016fb 100644
--- a/src/common/debug.cpp
+++ b/src/common/debug.cpp
@@ -45,7 +45,7 @@
 #if defined(ANGLE_TRACE_ENABLED)
     return true;
 #elif defined(ANGLE_ENABLE_ASSERTS)
-    return severity == LOG_ERR;
+    return severity != LOG_EVENT;
 #else
     return false;
 #endif
diff --git a/src/common/debug.h b/src/common/debug.h
index 068be45..199137b 100644
--- a/src/common/debug.h
+++ b/src/common/debug.h
@@ -272,10 +272,13 @@
     ANGLE_EMPTY_STATEMENT
 
 // A macro for code which is not expected to be reached under valid assumptions
-#define UNREACHABLE()                                                                            \
-    ((ERR() << "\t! Unreachable reached: " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ \
-            << ")"),                                                                             \
-     ASSERT(false))
+#define UNREACHABLE()                                                                              \
+    {                                                                                              \
+        ERR() << "\t! Unreachable reached: " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ \
+              << ")";                                                                              \
+        ASSERT(false);                                                                             \
+    }                                                                                              \
+    ANGLE_EMPTY_STATEMENT
 #else
 #define UNIMPLEMENTED()                 \
     {                                   \
@@ -284,7 +287,11 @@
     ANGLE_EMPTY_STATEMENT
 
 // A macro for code which is not expected to be reached under valid assumptions
-#define UNREACHABLE() ASSERT(false)
+#define UNREACHABLE()  \
+    {                  \
+        ASSERT(false); \
+    }                  \
+    ANGLE_EMPTY_STATEMENT
 #endif  // defined(ANGLE_TRACE_ENABLED) || defined(ANGLE_ENABLE_ASSERTS)
 
 #endif   // COMMON_DEBUG_H_
diff --git a/src/common/platform.h b/src/common/platform.h
index 57a2b92..1f1d85d 100644
--- a/src/common/platform.h
+++ b/src/common/platform.h
@@ -101,4 +101,15 @@
 // We will undef the macro so that the function name does not get replaced
 #undef MemoryBarrier
 
+// Macro for hinting that an expression is likely to be true/false.
+#if !defined(ANGLE_LIKELY) || !defined(ANGLE_UNLIKELY)
+#if defined(__GNUC__) || defined(__clang__)
+#define ANGLE_LIKELY(x) __builtin_expect(!!(x), 1)
+#define ANGLE_UNLIKELY(x) __builtin_expect(!!(x), 0)
+#else
+#define ANGLE_LIKELY(x) (x)
+#define ANGLE_UNLIKELY(x) (x)
+#endif  // defined(__GNUC__) || defined(__clang__)
+#endif  // !defined(ANGLE_LIKELY) || !defined(ANGLE_UNLIKELY)
+
 #endif // COMMON_PLATFORM_H_
diff --git a/src/common/third_party/base/anglebase/logging.h b/src/common/third_party/base/anglebase/logging.h
index 85ad82b..cd174fd 100644
--- a/src/common/third_party/base/anglebase/logging.h
+++ b/src/common/third_party/base/anglebase/logging.h
@@ -20,7 +20,7 @@
 
 // Unfortunately ANGLE relies on ASSERT being an empty statement, which these libs don't respect.
 #ifndef NOTREACHED
-#define NOTREACHED() UNREACHABLE()
+#define NOTREACHED() ({ UNREACHABLE(); })
 #endif
 
 #endif  // ANGLEBASE_LOGGING_H_
diff --git a/src/compiler/translator/CollectVariables.cpp b/src/compiler/translator/CollectVariables.cpp
index 635f364..f7fbd60 100644
--- a/src/compiler/translator/CollectVariables.cpp
+++ b/src/compiler/translator/CollectVariables.cpp
@@ -284,7 +284,7 @@
         setBuiltInInfoFromSymbol(variable, &info);
         info.staticUse   = true;
         info.active      = true;
-        info.isInvariant = mSymbolTable->isVaryingInvariant(variable.name());
+        info.isInvariant = mSymbolTable->isVaryingInvariant(variable);
         varyings->push_back(info);
         (*addedFlag) = true;
     }
@@ -668,7 +668,7 @@
         case EvqFlatOut:
         case EvqCentroidOut:
         case EvqGeometryOut:
-            if (mSymbolTable->isVaryingInvariant(variable.getName()) || type.isInvariant())
+            if (mSymbolTable->isVaryingInvariant(variable.variable()) || type.isInvariant())
             {
                 varying.isInvariant = true;
             }
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index 553d6c1..14140eb 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -214,6 +214,15 @@
     out << ") ";
 }
 
+void TOutputGLSLBase::writeQualifier(TQualifier qualifier, const TSymbol *symbol)
+{
+    const char *result = mapQualifierToString(qualifier);
+    if (result && result[0] != '\0')
+    {
+        objSink() << result << " ";
+    }
+}
+
 const char *TOutputGLSLBase::mapQualifierToString(TQualifier qualifier)
 {
     if (sh::IsGLSL410OrOlder(mOutput) && mShaderVersion >= 300 &&
@@ -250,7 +259,7 @@
     return sh::getQualifierString(qualifier);
 }
 
-void TOutputGLSLBase::writeVariableType(const TType &type)
+void TOutputGLSLBase::writeVariableType(const TType &type, const TSymbol *symbol)
 {
     TQualifier qualifier = type.getQualifier();
     TInfoSinkBase &out   = objSink();
@@ -265,11 +274,7 @@
     }
     if (qualifier != EvqTemporary && qualifier != EvqGlobal)
     {
-        const char *qualifierString = mapQualifierToString(qualifier);
-        if (qualifierString && qualifierString[0] != '\0')
-        {
-            out << qualifierString << " ";
-        }
+        writeQualifier(qualifier, symbol);
     }
 
     const TMemoryQualifier &memoryQualifier = type.getMemoryQualifier();
@@ -309,11 +314,6 @@
         const TStructure *structure = type.getStruct();
 
         declareStruct(structure);
-
-        if (structure->symbolType() != SymbolType::Empty)
-        {
-            mDeclaredStructs.insert(structure->uniqueId().get());
-        }
     }
     else if (type.getBasicType() == EbtInterfaceBlock)
     {
@@ -336,7 +336,7 @@
     {
         const TVariable *param = func->getParam(i);
         const TType &type      = param->getType();
-        writeVariableType(type);
+        writeVariableType(type, param);
 
         if (param->symbolType() != SymbolType::Empty)
             out << " " << hashName(param);
@@ -894,7 +894,7 @@
     TInfoSinkBase &out = objSink();
 
     const TType &type = node->getType();
-    writeVariableType(type);
+    writeVariableType(type, node->getFunction());
     if (type.isArray())
         out << ArrayString(type);
 
@@ -995,7 +995,8 @@
         const TIntermSequence &sequence = *(node->getSequence());
         TIntermTyped *variable          = sequence.front()->getAsTyped();
         writeLayoutQualifier(variable);
-        writeVariableType(variable->getType());
+        TIntermSymbol *symbolNode = variable->getAsSymbolNode();
+        writeVariableType(variable->getType(), symbolNode ? &symbolNode->variable() : nullptr);
         if (variable->getAsSymbolNode() == nullptr ||
             variable->getAsSymbolNode()->variable().symbolType() != SymbolType::Empty)
         {
@@ -1174,6 +1175,11 @@
         out << ";\n";
     }
     out << "}";
+
+    if (structure->symbolType() != SymbolType::Empty)
+    {
+        mDeclaredStructs.insert(structure->uniqueId().get());
+    }
 }
 
 void TOutputGLSLBase::declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock)
diff --git a/src/compiler/translator/OutputGLSLBase.h b/src/compiler/translator/OutputGLSLBase.h
index 6009cbf..20c2146 100644
--- a/src/compiler/translator/OutputGLSLBase.h
+++ b/src/compiler/translator/OutputGLSLBase.h
@@ -42,7 +42,7 @@
     void writeTriplet(Visit visit, const char *preStr, const char *inStr, const char *postStr);
     virtual void writeLayoutQualifier(TIntermTyped *variable);
     void writeInvariantQualifier(const TType &type);
-    void writeVariableType(const TType &type);
+    void writeVariableType(const TType &type, const TSymbol *symbol);
     virtual bool writeVariablePrecision(TPrecision precision) = 0;
     void writeFunctionParameters(const TFunction *func);
     const TConstantUnion *writeConstantUnion(const TType &type, const TConstantUnion *pConstUnion);
@@ -77,16 +77,17 @@
     virtual ImmutableString translateTextureFunction(const ImmutableString &name) { return name; }
 
     void declareStruct(const TStructure *structure);
+    virtual void writeQualifier(TQualifier qualifier, const TSymbol *symbol);
+    bool structDeclared(const TStructure *structure) const;
 
   private:
-    bool structDeclared(const TStructure *structure) const;
 
     void declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock);
     void declareInterfaceBlock(const TInterfaceBlock *interfaceBlock);
 
     void writeBuiltInFunctionTriplet(Visit visit, TOperator op, bool useEmulatedFunction);
 
-    const char *mapQualifierToString(TQualifier qialifier);
+    const char *mapQualifierToString(TQualifier qualifier);
 
     TInfoSinkBase &mObjSink;
     bool mDeclaringVariable;
diff --git a/src/compiler/translator/OutputVulkanGLSL.cpp b/src/compiler/translator/OutputVulkanGLSL.cpp
index bd7c4e3..99b0e40 100644
--- a/src/compiler/translator/OutputVulkanGLSL.cpp
+++ b/src/compiler/translator/OutputVulkanGLSL.cpp
@@ -11,6 +11,7 @@
 
 #include "compiler/translator/OutputVulkanGLSL.h"
 
+#include "compiler/translator/Symbol.h"
 #include "compiler/translator/util.h"
 
 namespace sh
@@ -54,7 +55,6 @@
 
     TInfoSinkBase &out                      = objSink();
     const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
-    out << "layout(";
 
     // This isn't super clean, but it gets the job done.
     // See corresponding code in GlslangWrapper.cpp.
@@ -67,6 +67,10 @@
     {
         out << "@@ LAYOUT-" << symbol->getName() << " @@";
     }
+    else
+    {
+        out << "layout(";
+    }
 
     if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified)
     {
@@ -74,13 +78,39 @@
         out << getImageInternalFormatString(layoutQualifier.imageInternalFormat);
     }
 
-    out << ") ";
+    if (!needsCustomLayout)
+    {
+        out << ") ";
+    }
+}
+
+void TOutputVulkanGLSL::writeQualifier(TQualifier qualifier, const TSymbol *symbol)
+{
+    if (qualifier != EvqUniform && qualifier != EvqVaryingIn && qualifier != EvqVaryingOut &&
+        qualifier != EvqAttribute)
+    {
+        TOutputGLSLBase::writeQualifier(qualifier, symbol);
+        return;
+    }
+
+    if (symbol == nullptr)
+    {
+        return;
+    }
+
+    TInfoSinkBase &out = objSink();
+    out << "@@ QUALIFIER-";
+    out << symbol->name().data();
+    out << " @@ ";
 }
 
 void TOutputVulkanGLSL::writeStructType(const TStructure *structure)
 {
-    declareStruct(structure);
-    objSink() << ";\n";
+    if (!structDeclared(structure))
+    {
+        declareStruct(structure);
+        objSink() << ";\n";
+    }
 }
 
 }  // namespace sh
diff --git a/src/compiler/translator/OutputVulkanGLSL.h b/src/compiler/translator/OutputVulkanGLSL.h
index 80561e5..d98517b 100644
--- a/src/compiler/translator/OutputVulkanGLSL.h
+++ b/src/compiler/translator/OutputVulkanGLSL.h
@@ -31,6 +31,7 @@
 
   protected:
     void writeLayoutQualifier(TIntermTyped *variable) override;
+    void writeQualifier(TQualifier qualifier, const TSymbol *symbol) override;
 };
 
 }  // namespace sh
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 6cf0eb9..5f3c928 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -2632,7 +2632,7 @@
                                     typeQualifier.line);
     checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
 
-    symbolTable.addInvariantVarying(identifier);
+    symbolTable.addInvariantVarying(*variable);
 
     TIntermSymbol *intermSymbol = new TIntermSymbol(variable);
     intermSymbol->setLine(identifierLoc);
diff --git a/src/compiler/translator/SymbolTable.cpp b/src/compiler/translator/SymbolTable.cpp
index 3d479fb..782045a 100644
--- a/src/compiler/translator/SymbolTable.cpp
+++ b/src/compiler/translator/SymbolTable.cpp
@@ -13,9 +13,6 @@
 
 #include "compiler/translator/SymbolTable.h"
 
-#include <algorithm>
-#include <set>
-
 #include "angle_gl.h"
 #include "compiler/translator/ImmutableString.h"
 #include "compiler/translator/IntermNode.h"
@@ -27,7 +24,7 @@
 class TSymbolTable::TSymbolTableLevel
 {
   public:
-    TSymbolTableLevel() : mGlobalInvariant(false) {}
+    TSymbolTableLevel() {}
 
     bool insert(TSymbol *symbol);
 
@@ -36,15 +33,6 @@
 
     TSymbol *find(const ImmutableString &name) const;
 
-    void addInvariantVarying(const ImmutableString &name) { mInvariantVaryings.insert(name); }
-
-    bool isVaryingInvariant(const ImmutableString &name)
-    {
-        return (mGlobalInvariant || mInvariantVaryings.count(name) > 0);
-    }
-
-    void setGlobalInvariant(bool invariant) { mGlobalInvariant = invariant; }
-
   private:
     using tLevel        = TUnorderedMap<ImmutableString,
                                  TSymbol *,
@@ -53,9 +41,6 @@
     using tInsertResult = std::pair<tLevel::iterator, bool>;
 
     tLevel level;
-
-    std::set<ImmutableString> mInvariantVaryings;
-    bool mGlobalInvariant;
 };
 
 bool TSymbolTable::TSymbolTableLevel::insert(TSymbol *symbol)
@@ -80,7 +65,10 @@
 }
 
 TSymbolTable::TSymbolTable()
-    : mUniqueIdCounter(0), mShaderType(GL_FRAGMENT_SHADER), mGlInVariableWithArraySize(nullptr)
+    : mGlobalInvariant(false),
+      mUniqueIdCounter(0),
+      mShaderType(GL_FRAGMENT_SHADER),
+      mGlInVariableWithArraySize(nullptr)
 {
 }
 
@@ -168,26 +156,26 @@
     return mVar_gl_SecondaryFragDataEXT;
 }
 
-void TSymbolTable::markStaticWrite(const TVariable &variable)
-{
-    int id    = variable.uniqueId().get();
+TSymbolTable::VariableMetadata *TSymbolTable::getOrCreateVariableMetadata(const TVariable &variable) {
+    int id = variable.uniqueId().get();
     auto iter = mVariableMetadata.find(id);
     if (iter == mVariableMetadata.end())
     {
         iter = mVariableMetadata.insert(std::make_pair(id, VariableMetadata())).first;
     }
-    iter->second.staticWrite = true;
+    return &iter->second;
+}
+
+void TSymbolTable::markStaticWrite(const TVariable &variable)
+{
+    auto metadata = getOrCreateVariableMetadata(variable);
+    metadata->staticWrite = true;
 }
 
 void TSymbolTable::markStaticRead(const TVariable &variable)
 {
-    int id    = variable.uniqueId().get();
-    auto iter = mVariableMetadata.find(id);
-    if (iter == mVariableMetadata.end())
-    {
-        iter = mVariableMetadata.insert(std::make_pair(id, VariableMetadata())).first;
-    }
-    iter->second.staticRead = true;
+    auto metadata = getOrCreateVariableMetadata(variable);
+    metadata->staticRead = true;
 }
 
 bool TSymbolTable::isStaticallyUsed(const TVariable &variable) const
@@ -195,7 +183,32 @@
     ASSERT(!variable.getConstPointer());
     int id    = variable.uniqueId().get();
     auto iter = mVariableMetadata.find(id);
-    return iter != mVariableMetadata.end();
+    return iter != mVariableMetadata.end() && (iter->second.staticRead || iter->second.staticWrite);
+}
+
+void TSymbolTable::addInvariantVarying(const TVariable &variable)
+{
+    ASSERT(atGlobalLevel());
+    auto metadata = getOrCreateVariableMetadata(variable);
+    metadata->invariant = true;
+}
+
+bool TSymbolTable::isVaryingInvariant(const TVariable &variable) const
+{
+    ASSERT(atGlobalLevel());
+    if (mGlobalInvariant)
+    {
+        return true;
+    }
+    int id = variable.uniqueId().get();
+    auto iter = mVariableMetadata.find(id);
+    return iter != mVariableMetadata.end() && iter->second.invariant;
+}
+
+void TSymbolTable::setGlobalInvariant(bool invariant)
+{
+    ASSERT(atGlobalLevel());
+    mGlobalInvariant = invariant;
 }
 
 const TSymbol *TSymbolTable::find(const ImmutableString &name, int shaderVersion) const
@@ -278,26 +291,9 @@
     return prec;
 }
 
-void TSymbolTable::addInvariantVarying(const ImmutableString &originalName)
-{
-    ASSERT(atGlobalLevel());
-    mTable.back()->addInvariantVarying(originalName);
-}
-
-bool TSymbolTable::isVaryingInvariant(const ImmutableString &originalName) const
-{
-    ASSERT(atGlobalLevel());
-    return mTable.back()->isVaryingInvariant(originalName);
-}
-
-void TSymbolTable::setGlobalInvariant(bool invariant)
-{
-    ASSERT(atGlobalLevel());
-    mTable.back()->setGlobalInvariant(invariant);
-}
-
 void TSymbolTable::clearCompilationResults()
 {
+    mGlobalInvariant = false;
     mUniqueIdCounter = kLastBuiltInId + 1;
     mVariableMetadata.clear();
     mGlInVariableWithArraySize = nullptr;
@@ -360,7 +356,7 @@
     setDefaultPrecision(samplerType, EbpLow);
 }
 
-TSymbolTable::VariableMetadata::VariableMetadata() : staticRead(false), staticWrite(false)
+TSymbolTable::VariableMetadata::VariableMetadata() : staticRead(false), staticWrite(false), invariant(false)
 {
 }
 
diff --git a/src/compiler/translator/SymbolTable.h b/src/compiler/translator/SymbolTable.h
index e3667c6..ae0456f 100644
--- a/src/compiler/translator/SymbolTable.h
+++ b/src/compiler/translator/SymbolTable.h
@@ -31,6 +31,7 @@
 //
 
 #include <memory>
+#include <set>
 
 #include "common/angleutils.h"
 #include "compiler/translator/ExtensionBehavior.h"
@@ -117,15 +118,11 @@
     // for the specified TBasicType
     TPrecision getDefaultPrecision(TBasicType type) const;
 
-    // This records invariant varyings declared through
-    // "invariant varying_name;".
-    void addInvariantVarying(const ImmutableString &originalName);
+    // This records invariant varyings declared through "invariant varying_name;".
+    void addInvariantVarying(const TVariable &variable);
 
-    // If this returns false, the varying could still be invariant
-    // if it is set as invariant during the varying variable
-    // declaration - this piece of information is stored in the
-    // variable's type, not here.
-    bool isVaryingInvariant(const ImmutableString &originalName) const;
+    // If this returns false, the varying could still be invariant if it is set as invariant during the varying variable declaration - this piece of information is stored in the variable's type, not here.
+    bool isVaryingInvariant(const TVariable &variable) const;
 
     void setGlobalInvariant(bool invariant);
 
@@ -142,6 +139,15 @@
 
   private:
     friend class TSymbolUniqueId;
+
+    struct VariableMetadata
+    {
+        VariableMetadata();
+        bool staticRead;
+        bool staticWrite;
+        bool invariant;
+    };
+
     int nextUniqueIdValue();
 
     class TSymbolTableLevel;
@@ -154,6 +160,8 @@
                                     ShShaderSpec spec,
                                     const ShBuiltInResources &resources);
 
+    VariableMetadata *getOrCreateVariableMetadata(const TVariable &variable);
+
     std::vector<std::unique_ptr<TSymbolTableLevel>> mTable;
 
     // There's one precision stack level for predefined precisions and then one level for each scope
@@ -161,6 +169,8 @@
     typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
     std::vector<std::unique_ptr<PrecisionStackLevel>> mPrecisionStack;
 
+    bool mGlobalInvariant;
+
     int mUniqueIdCounter;
 
     static const int kLastBuiltInId;
@@ -168,13 +178,6 @@
     sh::GLenum mShaderType;
     ShBuiltInResources mResources;
 
-    struct VariableMetadata
-    {
-        VariableMetadata();
-        bool staticRead;
-        bool staticWrite;
-    };
-
     // Indexed by unique id. Map instead of vector since the variables are fairly sparse.
     std::map<int, VariableMetadata> mVariableMetadata;
 
diff --git a/src/compiler/translator/TranslatorVulkan.cpp b/src/compiler/translator/TranslatorVulkan.cpp
index f427d56..2dd790e 100644
--- a/src/compiler/translator/TranslatorVulkan.cpp
+++ b/src/compiler/translator/TranslatorVulkan.cpp
@@ -41,9 +41,6 @@
 
         if (!mInGlobalScope)
         {
-            // We only want to declare the global structs in this traverser.
-            // TODO(lucferron): Add a test in GLSLTest for this specific case.
-            // http://anglebug.com/2459
             return false;
         }
 
@@ -53,22 +50,16 @@
 
         if (type.isStructSpecifier())
         {
-            TIntermSymbol *symbolNode = declarator->getAsSymbolNode();
-            if (symbolNode != nullptr && symbolNode->variable().symbolType() == SymbolType::Empty)
-            {
-                mOutputVulkanGLSL->writeStructType(type.getStruct());
+            mOutputVulkanGLSL->writeStructType(type.getStruct());
 
+            TIntermSymbol *symbolNode = declarator->getAsSymbolNode();
+            if (symbolNode && symbolNode->variable().symbolType() == SymbolType::Empty)
+            {
                 // Remove the struct specifier declaration from the tree so it isn't parsed again.
                 TIntermSequence emptyReplacement;
                 mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node,
                                                 emptyReplacement);
             }
-            else
-            {
-                // TODO(lucferron): Support structs with initializers correctly.
-                // http://anglebug.com/2459
-                UNIMPLEMENTED();
-            }
         }
 
         return false;
@@ -256,7 +247,7 @@
         bool hasGLFragColor = false;
         bool hasGLFragData  = false;
 
-        for (const auto &outputVar : outputVariables)
+        for (const OutputVariable &outputVar : outputVariables)
         {
             if (outputVar.name == "gl_FragColor")
             {
diff --git a/src/compiler/translator/glslang.l b/src/compiler/translator/glslang.l
index da52369..e7c0624 100644
--- a/src/compiler/translator/glslang.l
+++ b/src/compiler/translator/glslang.l
@@ -66,6 +66,7 @@
 #endif
 #endif
 
+#define YY_NO_INPUT
 #define YY_USER_ACTION                                 \
     yylloc->first_file = yylloc->last_file = yycolumn; \
     yylloc->first_line = yylloc->last_line = yylineno;
diff --git a/src/compiler/translator/glslang_lex.cpp b/src/compiler/translator/glslang_lex.cpp
index 4e60164..85e013a 100644
--- a/src/compiler/translator/glslang_lex.cpp
+++ b/src/compiler/translator/glslang_lex.cpp
@@ -1205,6 +1205,7 @@
 #endif
 #endif
 
+#define YY_NO_INPUT
 #define YY_USER_ACTION                                 \
     yylloc->first_file = yylloc->last_file = yycolumn; \
     yylloc->first_line = yylloc->last_line = yylineno;
diff --git a/src/libANGLE/AttributeMap.h b/src/libANGLE/AttributeMap.h
index eddc1b7..722c73f 100644
--- a/src/libANGLE/AttributeMap.h
+++ b/src/libANGLE/AttributeMap.h
@@ -7,6 +7,7 @@
 #ifndef LIBANGLE_ATTRIBUTEMAP_H_
 #define LIBANGLE_ATTRIBUTEMAP_H_
 
+#include "libANGLE/PackedEnums.h"
 
 #include <EGL/egl.h>
 
@@ -25,10 +26,27 @@
 
     void insert(EGLAttrib key, EGLAttrib value);
     bool contains(EGLAttrib key) const;
+
     EGLAttrib get(EGLAttrib key) const;
     EGLAttrib get(EGLAttrib key, EGLAttrib defaultValue) const;
     EGLint getAsInt(EGLAttrib key) const;
     EGLint getAsInt(EGLAttrib key, EGLint defaultValue) const;
+
+    template <typename PackedEnumT>
+    PackedEnumT getAsPackedEnum(EGLAttrib key) const
+    {
+        return FromEGLenum<PackedEnumT>(static_cast<EGLenum>(get(key)));
+    }
+
+    template <typename PackedEnumT>
+    PackedEnumT getAsPackedEnum(EGLAttrib key, PackedEnumT defaultValue) const
+    {
+        auto iter = mAttributes.find(key);
+        return (mAttributes.find(key) != mAttributes.end())
+                   ? FromEGLenum<PackedEnumT>(static_cast<EGLenum>(iter->second))
+                   : defaultValue;
+    }
+
     bool isEmpty() const;
     std::vector<EGLint> toIntVector() const;
 
diff --git a/src/libANGLE/Buffer.cpp b/src/libANGLE/Buffer.cpp
index 17b2526..4450afc 100644
--- a/src/libANGLE/Buffer.cpp
+++ b/src/libANGLE/Buffer.cpp
@@ -88,8 +88,8 @@
     mState.mUsage = usage;
     mState.mSize  = size;
 
-    // Notify when data changes.
-    mImpl->onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
+    // Notify when storage changes.
+    mImpl->onStateChange(context, angle::SubjectMessage::STORAGE_CHANGED);
 
     return NoError();
 }
diff --git a/src/libANGLE/Buffer.h b/src/libANGLE/Buffer.h
index 55a6bde..221ec52 100644
--- a/src/libANGLE/Buffer.h
+++ b/src/libANGLE/Buffer.h
@@ -15,7 +15,7 @@
 #include "libANGLE/Debug.h"
 #include "libANGLE/Error.h"
 #include "libANGLE/IndexRangeCache.h"
-#include "libANGLE/PackedGLEnums.h"
+#include "libANGLE/PackedEnums.h"
 #include "libANGLE/RefCountObject.h"
 
 namespace rx
diff --git a/src/libANGLE/Caps.cpp b/src/libANGLE/Caps.cpp
index 1bf0b35..a5792fe 100644
--- a/src/libANGLE/Caps.cpp
+++ b/src/libANGLE/Caps.cpp
@@ -226,7 +226,8 @@
       robustResourceInitialization(false),
       programCacheControl(false),
       textureRectangle(false),
-      geometryShader(false)
+      geometryShader(false),
+      pointSizeArray(false)
 {
 }
 
@@ -641,7 +642,7 @@
         map["GL_EXT_sRGB"] = enableableExtension(&Extensions::sRGB);
         map["GL_ANGLE_depth_texture"] = esOnlyExtension(&Extensions::depthTextures);
         map["GL_OES_depth32"] = esOnlyExtension(&Extensions::depth32);
-        map["GL_EXT_texture_storage"] = esOnlyExtension(&Extensions::textureStorage);
+        map["GL_EXT_texture_storage"] = enableableExtension(&Extensions::textureStorage);
         map["GL_OES_texture_npot"] = enableableExtension(&Extensions::textureNPOT);
         map["GL_EXT_draw_buffers"] = enableableExtension(&Extensions::drawBuffers);
         map["GL_EXT_texture_filter_anisotropic"] = enableableExtension(&Extensions::textureFilterAnisotropic);
@@ -664,14 +665,14 @@
         map["GL_OES_fbo_render_mipmap"] = enableableExtension(&Extensions::fboRenderMipmap);
         map["GL_EXT_discard_framebuffer"] = esOnlyExtension(&Extensions::discardFramebuffer);
         map["GL_EXT_debug_marker"] = esOnlyExtension(&Extensions::debugMarker);
-        map["GL_OES_EGL_image"] = esOnlyExtension(&Extensions::eglImage);
-        map["GL_OES_EGL_image_external"] = esOnlyExtension(&Extensions::eglImageExternal);
-        map["GL_OES_EGL_image_external_essl3"] = esOnlyExtension(&Extensions::eglImageExternalEssl3);
-        map["GL_NV_EGL_stream_consumer_external"] = esOnlyExtension(&Extensions::eglStreamConsumerExternal);
+        map["GL_OES_EGL_image"] = enableableExtension(&Extensions::eglImage);
+        map["GL_OES_EGL_image_external"] = enableableExtension(&Extensions::eglImageExternal);
+        map["GL_OES_EGL_image_external_essl3"] = enableableExtension(&Extensions::eglImageExternalEssl3);
+        map["GL_NV_EGL_stream_consumer_external"] = enableableExtension(&Extensions::eglStreamConsumerExternal);
         map["GL_EXT_unpack_subimage"] = enableableExtension(&Extensions::unpackSubimage);
         map["GL_NV_pack_subimage"] = enableableExtension(&Extensions::packSubimage);
         map["GL_EXT_color_buffer_float"] = enableableExtension(&Extensions::colorBufferFloat);
-        map["GL_OES_vertex_array_object"] = esOnlyExtension(&Extensions::vertexArrayObject);
+        map["GL_OES_vertex_array_object"] = enableableExtension(&Extensions::vertexArrayObject);
         map["GL_KHR_debug"] = esOnlyExtension(&Extensions::debug);
         // TODO(jmadill): Enable this when complete.
         //map["GL_KHR_no_error"] = esOnlyExtension(&Extensions::noError);
@@ -698,6 +699,8 @@
         map["GL_ANGLE_program_cache_control"] = esOnlyExtension(&Extensions::programCacheControl);
         map["GL_ANGLE_texture_rectangle"] = enableableExtension(&Extensions::textureRectangle);
         map["GL_EXT_geometry_shader"] = enableableExtension(&Extensions::geometryShader);
+        // GLES1 extensinos
+        map["GL_OES_point_size_array"] = enableableExtension(&Extensions::pointSizeArray);
         // clang-format on
 
         return map;
diff --git a/src/libANGLE/Caps.h b/src/libANGLE/Caps.h
index 9e34092..c2b83d8 100644
--- a/src/libANGLE/Caps.h
+++ b/src/libANGLE/Caps.h
@@ -374,6 +374,9 @@
 
     // GL_EXT_geometry_shader
     bool geometryShader;
+
+    // GLES1 emulation: GLES1 extensions
+    bool pointSizeArray;
 };
 
 struct ExtensionInfo
diff --git a/src/libANGLE/Compiler.cpp b/src/libANGLE/Compiler.cpp
index d2319b3..c819002 100644
--- a/src/libANGLE/Compiler.cpp
+++ b/src/libANGLE/Compiler.cpp
@@ -55,10 +55,7 @@
                              state.getExtensions().webglCompatibility)),
       mOutputType(mImplementation->getTranslatorOutputType()),
       mResources(),
-      mFragmentCompiler(nullptr),
-      mVertexCompiler(nullptr),
-      mComputeCompiler(nullptr),
-      mGeometryCompiler(nullptr)
+      mShaderCompilers({})
 {
     ASSERT(state.getClientMajorVersion() == 2 || state.getClientMajorVersion() == 3);
 
@@ -156,40 +153,17 @@
 
 Compiler::~Compiler()
 {
-    if (mFragmentCompiler)
+    for (ShaderType shaderType : AllShaderTypes())
     {
-        sh::Destruct(mFragmentCompiler);
-        mFragmentCompiler = nullptr;
+        ShHandle compilerHandle = mShaderCompilers[shaderType];
+        if (compilerHandle)
+        {
+            sh::Destruct(compilerHandle);
+            mShaderCompilers[shaderType] = nullptr;
 
-        ASSERT(activeCompilerHandles > 0);
-        activeCompilerHandles--;
-    }
-
-    if (mVertexCompiler)
-    {
-        sh::Destruct(mVertexCompiler);
-        mVertexCompiler = nullptr;
-
-        ASSERT(activeCompilerHandles > 0);
-        activeCompilerHandles--;
-    }
-
-    if (mComputeCompiler)
-    {
-        sh::Destruct(mComputeCompiler);
-        mComputeCompiler = nullptr;
-
-        ASSERT(activeCompilerHandles > 0);
-        activeCompilerHandles--;
-    }
-
-    if (mGeometryCompiler)
-    {
-        sh::Destruct(mGeometryCompiler);
-        mGeometryCompiler = nullptr;
-
-        ASSERT(activeCompilerHandles > 0);
-        activeCompilerHandles--;
+            ASSERT(activeCompilerHandles > 0);
+            activeCompilerHandles--;
+        }
     }
 
     if (activeCompilerHandles == 0)
@@ -202,26 +176,8 @@
 
 ShHandle Compiler::getCompilerHandle(ShaderType type)
 {
-    ShHandle *compiler = nullptr;
-    switch (type)
-    {
-        case ShaderType::Vertex:
-            compiler = &mVertexCompiler;
-            break;
-
-        case ShaderType::Fragment:
-            compiler = &mFragmentCompiler;
-            break;
-        case ShaderType::Compute:
-            compiler = &mComputeCompiler;
-            break;
-        case ShaderType::Geometry:
-            compiler = &mGeometryCompiler;
-            break;
-        default:
-            UNREACHABLE();
-            return nullptr;
-    }
+    ASSERT(type != ShaderType::InvalidEnum);
+    ShHandle *compiler = &mShaderCompilers[type];
 
     if (!(*compiler))
     {
diff --git a/src/libANGLE/Compiler.h b/src/libANGLE/Compiler.h
index b84357e..2806984 100644
--- a/src/libANGLE/Compiler.h
+++ b/src/libANGLE/Compiler.h
@@ -12,7 +12,7 @@
 
 #include "GLSLANG/ShaderLang.h"
 #include "libANGLE/Error.h"
-#include "libANGLE/PackedGLEnums_autogen.h"
+#include "libANGLE/PackedEnums.h"
 #include "libANGLE/RefCountObject.h"
 
 namespace rx
@@ -41,10 +41,7 @@
     ShShaderOutput mOutputType;
     ShBuiltInResources mResources;
 
-    ShHandle mFragmentCompiler;
-    ShHandle mVertexCompiler;
-    ShHandle mComputeCompiler;
-    ShHandle mGeometryCompiler;
+    ShaderMap<ShHandle> mShaderCompilers;
 };
 
 }  // namespace gl
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index aea253a..2a24712 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -350,15 +350,14 @@
         }
     }
 
-    const Extensions &nativeExtensions = mImplementation->getNativeExtensions();
-    if (nativeExtensions.textureRectangle)
+    if (mSupportedExtensions.textureRectangle)
     {
         Texture *zeroTextureRectangle =
             new Texture(mImplementation.get(), 0, TextureType::Rectangle);
         mZeroTextures[TextureType::Rectangle].set(this, zeroTextureRectangle);
     }
 
-    if (nativeExtensions.eglImageExternal || nativeExtensions.eglStreamConsumerExternal)
+    if (mSupportedExtensions.eglImageExternal || mSupportedExtensions.eglStreamConsumerExternal)
     {
         Texture *zeroTextureExternal = new Texture(mImplementation.get(), 0, TextureType::External);
         mZeroTextures[TextureType::External].set(this, zeroTextureExternal);
@@ -1665,6 +1664,38 @@
         case GL_MAX_TEXTURE_STACK_DEPTH:
             *params = mCaps.maxTextureMatrixStackDepth;
             break;
+        // GLES1 emulation: Vertex attribute queries
+        case GL_VERTEX_ARRAY_BUFFER_BINDING:
+        case GL_NORMAL_ARRAY_BUFFER_BINDING:
+        case GL_COLOR_ARRAY_BUFFER_BINDING:
+        case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES:
+        case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
+            getVertexAttribiv(static_cast<GLuint>(vertexArrayIndex(ParamToVertexArrayType(pname))),
+                              GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, params);
+            break;
+        case GL_VERTEX_ARRAY_STRIDE:
+        case GL_NORMAL_ARRAY_STRIDE:
+        case GL_COLOR_ARRAY_STRIDE:
+        case GL_POINT_SIZE_ARRAY_STRIDE_OES:
+        case GL_TEXTURE_COORD_ARRAY_STRIDE:
+            getVertexAttribiv(static_cast<GLuint>(vertexArrayIndex(ParamToVertexArrayType(pname))),
+                              GL_VERTEX_ATTRIB_ARRAY_STRIDE, params);
+            break;
+        case GL_VERTEX_ARRAY_SIZE:
+        case GL_COLOR_ARRAY_SIZE:
+        case GL_TEXTURE_COORD_ARRAY_SIZE:
+            getVertexAttribiv(static_cast<GLuint>(vertexArrayIndex(ParamToVertexArrayType(pname))),
+                              GL_VERTEX_ATTRIB_ARRAY_SIZE, params);
+            break;
+        case GL_VERTEX_ARRAY_TYPE:
+        case GL_COLOR_ARRAY_TYPE:
+        case GL_NORMAL_ARRAY_TYPE:
+        case GL_POINT_SIZE_ARRAY_TYPE_OES:
+        case GL_TEXTURE_COORD_ARRAY_TYPE:
+            getVertexAttribiv(static_cast<GLuint>(vertexArrayIndex(ParamToVertexArrayType(pname))),
+                              GL_VERTEX_ATTRIB_ARRAY_TYPE, params);
+            break;
+
         default:
             handleError(mGLState.getIntegerv(this, pname, params));
             break;
@@ -1709,7 +1740,7 @@
 
 void Context::getPointerv(GLenum pname, void **params) const
 {
-    mGLState.getPointerv(pname, params);
+    mGLState.getPointerv(this, pname, params);
 }
 
 void Context::getPointervRobustANGLERobust(GLenum pname,
@@ -2420,9 +2451,9 @@
     UNIMPLEMENTED();
 }
 
-void Context::handleError(const Error &error)
+void Context::handleError(const Error &error) const
 {
-    if (error.isError())
+    if (ANGLE_UNLIKELY(error.isError()))
     {
         GLenum code = error.getCode();
         mErrors.insert(code);
@@ -2454,7 +2485,7 @@
 }
 
 // NOTE: this function should not assume that this context is current!
-void Context::markContextLost()
+void Context::markContextLost() const
 {
     if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT)
     {
@@ -2464,7 +2495,7 @@
     mContextLost = true;
 }
 
-bool Context::isContextLost()
+bool Context::isContextLost() const
 {
     return mContextLost;
 }
@@ -2839,14 +2870,12 @@
     }
     mExtensionString = mergeExtensionStrings(mExtensionStrings);
 
-    const gl::Extensions &nativeExtensions = mImplementation->getNativeExtensions();
-
     mRequestableExtensionStrings.clear();
     for (const auto &extensionInfo : GetExtensionInfoMap())
     {
         if (extensionInfo.second.Requestable &&
             !(mExtensions.*(extensionInfo.second.ExtensionsMember)) &&
-            nativeExtensions.*(extensionInfo.second.ExtensionsMember))
+            mSupportedExtensions.*(extensionInfo.second.ExtensionsMember))
         {
             mRequestableExtensionStrings.push_back(MakeStaticString(extensionInfo.first));
         }
@@ -2908,9 +2937,8 @@
     const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
     auto extension                         = extensionInfos.find(name);
 
-    const Extensions &nativeExtensions = mImplementation->getNativeExtensions();
     return extension != extensionInfos.end() && extension->second.Requestable &&
-           nativeExtensions.*(extension->second.ExtensionsMember);
+           mSupportedExtensions.*(extension->second.ExtensionsMember);
 }
 
 void Context::requestExtension(const char *name)
@@ -2919,7 +2947,7 @@
     ASSERT(extensionInfos.find(name) != extensionInfos.end());
     const auto &extension = extensionInfos.at(name);
     ASSERT(extension.Requestable);
-    ASSERT(mImplementation->getNativeExtensions().*(extension.ExtensionsMember));
+    ASSERT(isExtensionRequestable(name));
 
     if (mExtensions.*(extension.ExtensionsMember))
     {
@@ -2974,10 +3002,85 @@
     return false;
 }
 
+Extensions Context::generateSupportedExtensions(const egl::DisplayExtensions &displayExtensions,
+                                                bool robustResourceInit) const
+{
+    Extensions supportedExtensions = mImplementation->getNativeExtensions();
+
+    if (getClientVersion() < ES_2_0)
+    {
+        // Default extensions for GLES1
+        supportedExtensions.pointSizeArray = true;
+    }
+
+    if (getClientVersion() < ES_3_0)
+    {
+        // Disable ES3+ extensions
+        supportedExtensions.colorBufferFloat      = false;
+        supportedExtensions.eglImageExternalEssl3 = false;
+        supportedExtensions.textureNorm16         = false;
+        supportedExtensions.multiview             = false;
+        supportedExtensions.maxViews              = 1u;
+    }
+
+    if (getClientVersion() < ES_3_1)
+    {
+        // Disable ES3.1+ extensions
+        supportedExtensions.geometryShader = false;
+    }
+
+    if (getClientVersion() > ES_2_0)
+    {
+        // FIXME(geofflang): Don't support EXT_sRGB in non-ES2 contexts
+        // supportedExtensions.sRGB = false;
+    }
+
+    // Some extensions are always available because they are implemented in the GL layer.
+    supportedExtensions.bindUniformLocation   = true;
+    supportedExtensions.vertexArrayObject     = true;
+    supportedExtensions.bindGeneratesResource = true;
+    supportedExtensions.clientArrays          = true;
+    supportedExtensions.requestExtension      = true;
+
+    // Enable the no error extension if the context was created with the flag.
+    supportedExtensions.noError = mSkipValidation;
+
+    // Enable surfaceless to advertise we'll have the correct behavior when there is no default FBO
+    supportedExtensions.surfacelessContext = displayExtensions.surfacelessContext;
+
+    // Explicitly enable GL_KHR_debug
+    supportedExtensions.debug                   = true;
+    supportedExtensions.maxDebugMessageLength   = 1024;
+    supportedExtensions.maxDebugLoggedMessages  = 1024;
+    supportedExtensions.maxDebugGroupStackDepth = 1024;
+    supportedExtensions.maxLabelLength          = 1024;
+
+    // Explicitly enable GL_ANGLE_robust_client_memory
+    supportedExtensions.robustClientMemory = true;
+
+    // Determine robust resource init availability from EGL.
+    supportedExtensions.robustResourceInitialization = robustResourceInit;
+
+    // mExtensions.robustBufferAccessBehavior is true only if robust access is true and the backend
+    // supports it.
+    supportedExtensions.robustBufferAccessBehavior =
+        mRobustAccess && supportedExtensions.robustBufferAccessBehavior;
+
+    // Enable the cache control query unconditionally.
+    supportedExtensions.programCacheControl = true;
+
+    return supportedExtensions;
+}
+
 void Context::initCaps(const egl::DisplayExtensions &displayExtensions, bool robustResourceInit)
 {
     mCaps = mImplementation->getNativeCaps();
 
+    mSupportedExtensions = generateSupportedExtensions(displayExtensions, robustResourceInit);
+    mExtensions          = mSupportedExtensions;
+
+    mLimitations = mImplementation->getNativeLimitations();
+
     // GLES1 emulation: Initialize caps (Table 6.20 / 6.22 in the ES 1.1 spec)
     if (getClientVersion() < Version(2, 0))
     {
@@ -2989,66 +3092,6 @@
         mCaps.maxTextureMatrixStackDepth    = Caps::GlobalMatrixStackDepth;
     }
 
-    mExtensions = mImplementation->getNativeExtensions();
-
-    mLimitations = mImplementation->getNativeLimitations();
-
-    if (getClientVersion() < Version(3, 0))
-    {
-        // Disable ES3+ extensions
-        mExtensions.colorBufferFloat      = false;
-        mExtensions.eglImageExternalEssl3 = false;
-        mExtensions.textureNorm16         = false;
-        mExtensions.multiview             = false;
-        mExtensions.maxViews              = 1u;
-    }
-
-    if (getClientVersion() < ES_3_1)
-    {
-        // Disable ES3.1+ extensions
-        mExtensions.geometryShader = false;
-    }
-
-    if (getClientVersion() > Version(2, 0))
-    {
-        // FIXME(geofflang): Don't support EXT_sRGB in non-ES2 contexts
-        // mExtensions.sRGB = false;
-    }
-
-    // Some extensions are always available because they are implemented in the GL layer.
-    mExtensions.bindUniformLocation   = true;
-    mExtensions.vertexArrayObject     = true;
-    mExtensions.bindGeneratesResource = true;
-    mExtensions.clientArrays          = true;
-    mExtensions.requestExtension      = true;
-
-    // Enable the no error extension if the context was created with the flag.
-    mExtensions.noError = mSkipValidation;
-
-    // Enable surfaceless to advertise we'll have the correct behavior when there is no default FBO
-    mExtensions.surfacelessContext = displayExtensions.surfacelessContext;
-
-    // Explicitly enable GL_KHR_debug
-    mExtensions.debug                   = true;
-    mExtensions.maxDebugMessageLength   = 1024;
-    mExtensions.maxDebugLoggedMessages  = 1024;
-    mExtensions.maxDebugGroupStackDepth = 1024;
-    mExtensions.maxLabelLength          = 1024;
-
-    // Explicitly enable GL_ANGLE_robust_client_memory
-    mExtensions.robustClientMemory = true;
-
-    // Determine robust resource init availability from EGL.
-    mExtensions.robustResourceInitialization = robustResourceInit;
-
-    // mExtensions.robustBufferAccessBehavior is true only if robust access is true and the backend
-    // supports it.
-    mExtensions.robustBufferAccessBehavior =
-        mRobustAccess && mExtensions.robustBufferAccessBehavior;
-
-    // Enable the cache control query unconditionally.
-    mExtensions.programCacheControl = true;
-
     // Apply implementation limits
     LimitCap(&mCaps.maxVertexAttributes, MAX_VERTEX_ATTRIBS);
 
@@ -3172,7 +3215,7 @@
     }
 
     // If program binary is disabled, blank out the memory cache pointer.
-    if (!mImplementation->getNativeExtensions().getProgramBinary)
+    if (!mSupportedExtensions.getProgramBinary)
     {
         mMemoryProgramCache = nullptr;
     }
@@ -3493,28 +3536,7 @@
     if (texture != 0)
     {
         Texture *textureObj = getTexture(texture);
-
-        ImageIndex index = ImageIndex::MakeInvalid();
-
-        if (textarget == TextureTarget::_2D)
-        {
-            index = ImageIndex::Make2D(level);
-        }
-        else if (textarget == TextureTarget::Rectangle)
-        {
-            index = ImageIndex::MakeRectangle(level);
-        }
-        else if (textarget == TextureTarget::_2DMultisample)
-        {
-            ASSERT(level == 0);
-            index = ImageIndex::Make2DMultisample();
-        }
-        else
-        {
-            ASSERT(TextureTargetToType(textarget) == TextureType::CubeMap);
-            index = ImageIndex::MakeCube(textarget, level);
-        }
-
+        ImageIndex index    = ImageIndex::MakeFromTarget(textarget, level);
         framebuffer->setAttachment(this, GL_TEXTURE, attachment, index, textureObj);
     }
     else
@@ -3537,7 +3559,7 @@
     {
         Renderbuffer *renderbufferObject = getRenderbuffer(renderbuffer);
 
-        framebuffer->setAttachment(this, GL_RENDERBUFFER, attachment, gl::ImageIndex::MakeInvalid(),
+        framebuffer->setAttachment(this, GL_RENDERBUFFER, attachment, gl::ImageIndex(),
                                    renderbufferObject);
     }
     else
@@ -3560,19 +3582,7 @@
     if (texture != 0)
     {
         Texture *textureObject = getTexture(texture);
-
-        ImageIndex index = ImageIndex::MakeInvalid();
-
-        if (textureObject->getType() == TextureType::_3D)
-        {
-            index = ImageIndex::Make3D(level, layer);
-        }
-        else
-        {
-            ASSERT(textureObject->getType() == TextureType::_2DArray);
-            index = ImageIndex::Make2DArray(level, layer);
-        }
-
+        ImageIndex index       = ImageIndex::MakeFromType(textureObject->getType(), level, layer);
         framebuffer->setAttachment(this, GL_TEXTURE, attachment, index, textureObject);
     }
     else
@@ -3673,9 +3683,7 @@
     Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
     ASSERT(framebuffer);
 
-    bool complete = false;
-    ANGLE_CONTEXT_TRY(framebuffer->isComplete(this, &complete));
-    if (!complete)
+    if (!framebuffer->isComplete(this))
     {
         return;
     }
@@ -3697,9 +3705,7 @@
     Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
     ASSERT(framebuffer);
 
-    bool complete = false;
-    ANGLE_CONTEXT_TRY(framebuffer->isComplete(this, &complete));
-    if (!complete)
+    if (!framebuffer->isComplete(this))
     {
         return;
     }
@@ -4948,15 +4954,7 @@
 {
     Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
     ASSERT(framebuffer);
-
-    GLenum status = GL_NONE;
-    Error err     = framebuffer->checkStatus(this, &status);
-    if (err.isError())
-    {
-        handleError(err);
-        return 0;
-    }
-    return status;
+    return framebuffer->checkStatus(this);
 }
 
 void Context::compileShader(GLuint shader)
@@ -7020,6 +7018,24 @@
             case GL_MAX_MODELVIEW_STACK_DEPTH:
             case GL_MAX_PROJECTION_STACK_DEPTH:
             case GL_MAX_TEXTURE_STACK_DEPTH:
+            case GL_VERTEX_ARRAY_STRIDE:
+            case GL_NORMAL_ARRAY_STRIDE:
+            case GL_COLOR_ARRAY_STRIDE:
+            case GL_TEXTURE_COORD_ARRAY_STRIDE:
+            case GL_VERTEX_ARRAY_SIZE:
+            case GL_COLOR_ARRAY_SIZE:
+            case GL_TEXTURE_COORD_ARRAY_SIZE:
+            case GL_VERTEX_ARRAY_TYPE:
+            case GL_NORMAL_ARRAY_TYPE:
+            case GL_COLOR_ARRAY_TYPE:
+            case GL_TEXTURE_COORD_ARRAY_TYPE:
+            case GL_VERTEX_ARRAY_BUFFER_BINDING:
+            case GL_NORMAL_ARRAY_BUFFER_BINDING:
+            case GL_COLOR_ARRAY_BUFFER_BINDING:
+            case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
+            case GL_POINT_SIZE_ARRAY_STRIDE_OES:
+            case GL_POINT_SIZE_ARRAY_TYPE_OES:
+            case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES:
                 *type      = GL_INT;
                 *numParams = 1;
                 return true;
diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h
index e011652..8ebbc12 100644
--- a/src/libANGLE/Context.h
+++ b/src/libANGLE/Context.h
@@ -22,7 +22,7 @@
 #include "libANGLE/Context_gles_1_0_autogen.h"
 #include "libANGLE/Error.h"
 #include "libANGLE/HandleAllocator.h"
-#include "libANGLE/PackedGLEnums.h"
+#include "libANGLE/PackedEnums.h"
 #include "libANGLE/RefCountObject.h"
 #include "libANGLE/ResourceMap.h"
 #include "libANGLE/VertexAttribute.h"
@@ -1374,11 +1374,11 @@
     void memoryBarrierByRegion(GLbitfield barriers);
 
     // Consumes the error.
-    void handleError(const Error &error);
+    void handleError(const Error &error) const;
 
     GLenum getError();
-    void markContextLost();
-    bool isContextLost();
+    void markContextLost() const;
+    bool isContextLost() const;
     GLenum getGraphicsResetStatus();
     bool isResetNotificationEnabled();
 
@@ -1457,6 +1457,9 @@
 
     bool isValidBufferBinding(BufferBinding binding) const { return mValidBufferBindings[binding]; }
 
+    // GLES1 emulation: Renderer level (for validation)
+    int vertexArrayIndex(ClientVertexArrayType type) const;
+
   private:
     Error prepareForDraw();
     Error prepareForClear(GLbitfield mask);
@@ -1487,6 +1490,8 @@
     void initVersionStrings();
     void initExtensionStrings();
 
+    Extensions generateSupportedExtensions(const egl::DisplayExtensions &displayExtensions,
+                                           bool robustResourceInit) const;
     void initCaps(const egl::DisplayExtensions &displayExtensions, bool robustResourceInit);
     void updateCaps();
     void initWorkarounds();
@@ -1514,6 +1519,10 @@
     Extensions mExtensions;
     Limitations mLimitations;
 
+    // Extensions supported by the implementation plus extensions that are implemented entirely
+    // within the frontend.
+    Extensions mSupportedExtensions;
+
     // Shader compiler. Lazily initialized hence the mutable value.
     mutable BindingPointer<Compiler> mCompiler;
 
@@ -1546,13 +1555,13 @@
 
     // Recorded errors
     typedef std::set<GLenum> ErrorSet;
-    ErrorSet mErrors;
+    mutable ErrorSet mErrors;
 
     // Current/lost context flags
     bool mHasBeenCurrent;
-    bool mContextLost;
-    GLenum mResetStatus;
-    bool mContextLostForced;
+    mutable bool mContextLost;
+    mutable GLenum mResetStatus;
+    mutable bool mContextLostForced;
     GLenum mResetStrategy;
     bool mRobustAccess;
     egl::Surface *mCurrentSurface;
diff --git a/src/libANGLE/Context_gles_1_0.cpp b/src/libANGLE/Context_gles_1_0.cpp
index 970d8cd..9acf82e 100644
--- a/src/libANGLE/Context_gles_1_0.cpp
+++ b/src/libANGLE/Context_gles_1_0.cpp
@@ -87,7 +87,8 @@
 
 void Context::colorPointer(GLint size, GLenum type, GLsizei stride, const void *ptr)
 {
-    UNIMPLEMENTED();
+    vertexAttribPointer(vertexArrayIndex(ClientVertexArrayType::Color), size, type, GL_FALSE,
+                        stride, ptr);
 }
 
 void Context::depthRangex(GLfixed n, GLfixed f)
@@ -95,14 +96,16 @@
     UNIMPLEMENTED();
 }
 
-void Context::disableClientState(GLenum clientState)
+void Context::disableClientState(ClientVertexArrayType clientState)
 {
-    UNIMPLEMENTED();
+    mGLState.gles1().setClientStateEnabled(clientState, false);
+    disableVertexAttribArray(vertexArrayIndex(clientState));
 }
 
-void Context::enableClientState(GLenum clientState)
+void Context::enableClientState(ClientVertexArrayType clientState)
 {
-    UNIMPLEMENTED();
+    mGLState.gles1().setClientStateEnabled(clientState, true);
+    enableVertexAttribArray(vertexArrayIndex(clientState));
 }
 
 void Context::fogf(GLenum pname, GLfloat param)
@@ -125,19 +128,16 @@
     UNIMPLEMENTED();
 }
 
-void Context::frustumf(GLfloat left,
-                       GLfloat right,
-                       GLfloat bottom,
-                       GLfloat top,
-                       GLfloat zNear,
-                       GLfloat zFar)
+void Context::frustumf(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f)
 {
-    UNIMPLEMENTED();
+    mGLState.gles1().multMatrix(angle::Mat4::Frustum(l, r, b, t, n, f));
 }
 
 void Context::frustumx(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f)
 {
-    UNIMPLEMENTED();
+    mGLState.gles1().multMatrix(angle::Mat4::Frustum(FixedToFloat(l), FixedToFloat(r),
+                                                     FixedToFloat(b), FixedToFloat(t),
+                                                     FixedToFloat(n), FixedToFloat(f)));
 }
 
 void Context::getClipPlanef(GLenum plane, GLfloat *equation)
@@ -322,7 +322,8 @@
 
 void Context::normalPointer(GLenum type, GLsizei stride, const void *ptr)
 {
-    UNIMPLEMENTED();
+    vertexAttribPointer(vertexArrayIndex(ClientVertexArrayType::Normal), 3, type, GL_FALSE, stride,
+                        ptr);
 }
 
 void Context::orthof(GLfloat left,
@@ -332,12 +333,14 @@
                      GLfloat zNear,
                      GLfloat zFar)
 {
-    UNIMPLEMENTED();
+    mGLState.gles1().multMatrix(angle::Mat4::Ortho(left, right, bottom, top, zNear, zFar));
 }
 
 void Context::orthox(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f)
 {
-    UNIMPLEMENTED();
+    mGLState.gles1().multMatrix(angle::Mat4::Ortho(FixedToFloat(l), FixedToFloat(r),
+                                                   FixedToFloat(b), FixedToFloat(t),
+                                                   FixedToFloat(n), FixedToFloat(f)));
 }
 
 void Context::pointParameterf(GLenum pname, GLfloat param)
@@ -387,12 +390,13 @@
 
 void Context::rotatef(float angle, float x, float y, float z)
 {
-    UNIMPLEMENTED();
+    mGLState.gles1().multMatrix(angle::Mat4::Rotate(angle, angle::Vector3(x, y, z)));
 }
 
 void Context::rotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
 {
-    UNIMPLEMENTED();
+    mGLState.gles1().multMatrix(angle::Mat4::Rotate(
+        FixedToFloat(angle), angle::Vector3(FixedToFloat(x), FixedToFloat(y), FixedToFloat(z))));
 }
 
 void Context::sampleCoveragex(GLclampx value, GLboolean invert)
@@ -402,12 +406,13 @@
 
 void Context::scalef(float x, float y, float z)
 {
-    UNIMPLEMENTED();
+    mGLState.gles1().multMatrix(angle::Mat4::Scale(angle::Vector3(x, y, z)));
 }
 
 void Context::scalex(GLfixed x, GLfixed y, GLfixed z)
 {
-    UNIMPLEMENTED();
+    mGLState.gles1().multMatrix(
+        angle::Mat4::Scale(angle::Vector3(FixedToFloat(x), FixedToFloat(y), FixedToFloat(z))));
 }
 
 void Context::shadeModel(GLenum mode)
@@ -417,7 +422,8 @@
 
 void Context::texCoordPointer(GLint size, GLenum type, GLsizei stride, const void *ptr)
 {
-    UNIMPLEMENTED();
+    vertexAttribPointer(vertexArrayIndex(ClientVertexArrayType::TextureCoord), size, type, GL_FALSE,
+                        stride, ptr);
 }
 
 void Context::texEnvf(GLenum target, GLenum pname, GLfloat param)
@@ -462,17 +468,19 @@
 
 void Context::translatef(float x, float y, float z)
 {
-    UNIMPLEMENTED();
+    mGLState.gles1().multMatrix(angle::Mat4::Translate(angle::Vector3(x, y, z)));
 }
 
 void Context::translatex(GLfixed x, GLfixed y, GLfixed z)
 {
-    UNIMPLEMENTED();
+    mGLState.gles1().multMatrix(
+        angle::Mat4::Translate(angle::Vector3(FixedToFloat(x), FixedToFloat(y), FixedToFloat(z))));
 }
 
 void Context::vertexPointer(GLint size, GLenum type, GLsizei stride, const void *ptr)
 {
-    UNIMPLEMENTED();
+    vertexAttribPointer(vertexArrayIndex(ClientVertexArrayType::Vertex), size, type, GL_FALSE,
+                        stride, ptr);
 }
 
 // GL_OES_draw_texture
@@ -540,7 +548,8 @@
 // GL_OES_point_size_array
 void Context::pointSizePointer(GLenum type, GLsizei stride, const void *ptr)
 {
-    UNIMPLEMENTED();
+    vertexAttribPointer(vertexArrayIndex(ClientVertexArrayType::PointSize), 1, type, GL_FALSE,
+                        stride, ptr);
 }
 
 // GL_OES_query_matrix
@@ -596,4 +605,25 @@
     UNIMPLEMENTED();
 }
 
+int Context::vertexArrayIndex(ClientVertexArrayType type) const
+{
+    switch (type)
+    {
+        case ClientVertexArrayType::Vertex:
+            return 0;
+        case ClientVertexArrayType::Normal:
+            return 1;
+        case ClientVertexArrayType::Color:
+            return 2;
+        case ClientVertexArrayType::PointSize:
+            return 3;
+        case ClientVertexArrayType::TextureCoord:
+            return 4 + mGLState.gles1().getClientTextureUnit();
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+// static
 }  // namespace gl
diff --git a/src/libANGLE/Context_gles_1_0_autogen.h b/src/libANGLE/Context_gles_1_0_autogen.h
index 8dd4ab4..0584898 100644
--- a/src/libANGLE/Context_gles_1_0_autogen.h
+++ b/src/libANGLE/Context_gles_1_0_autogen.h
@@ -23,8 +23,8 @@
     void color4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);                 \
     void colorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer);       \
     void depthRangex(GLfixed n, GLfixed f);                                                \
-    void disableClientState(GLenum array);                                                 \
-    void enableClientState(GLenum array);                                                  \
+    void disableClientState(ClientVertexArrayType arrayPacked);                            \
+    void enableClientState(ClientVertexArrayType arrayPacked);                             \
     void fogf(GLenum pname, GLfloat param);                                                \
     void fogfv(GLenum pname, const GLfloat *params);                                       \
     void fogx(GLenum pname, GLfixed param);                                                \
diff --git a/src/libANGLE/Debug.cpp b/src/libANGLE/Debug.cpp
index 96f30df..0e534a8 100644
--- a/src/libANGLE/Debug.cpp
+++ b/src/libANGLE/Debug.cpp
@@ -97,7 +97,7 @@
                           GLenum type,
                           GLuint id,
                           GLenum severity,
-                          const std::string &message)
+                          const std::string &message) const
 {
     std::string messageCopy(message);
     insertMessage(source, type, id, severity, std::move(messageCopy));
@@ -107,7 +107,7 @@
                           GLenum type,
                           GLuint id,
                           GLenum severity,
-                          std::string &&message)
+                          std::string &&message) const
 {
     if (!isMessageEnabled(source, type, id, severity))
     {
diff --git a/src/libANGLE/Debug.h b/src/libANGLE/Debug.h
index 2c15c25..dc7c0e3 100644
--- a/src/libANGLE/Debug.h
+++ b/src/libANGLE/Debug.h
@@ -49,12 +49,12 @@
                        GLenum type,
                        GLuint id,
                        GLenum severity,
-                       const std::string &message);
+                       const std::string &message) const;
     void insertMessage(GLenum source,
                        GLenum type,
                        GLuint id,
                        GLenum severity,
-                       std::string &&message);
+                       std::string &&message) const;
 
     void setMessageControl(GLenum source,
                            GLenum type,
@@ -119,7 +119,7 @@
     bool mOutputEnabled;
     GLDEBUGPROCKHR mCallbackFunction;
     const void *mCallbackUserParam;
-    std::deque<Message> mMessages;
+    mutable std::deque<Message> mMessages;
     GLuint mMaxLoggedMessages;
     bool mOutputSynchronous;
     std::vector<Group> mGroups;
diff --git a/src/libANGLE/Error.h b/src/libANGLE/Error.h
index 5084e01..bf66d44 100644
--- a/src/libANGLE/Error.h
+++ b/src/libANGLE/Error.h
@@ -223,35 +223,35 @@
 #define ANGLE_CONCAT2(x, y) ANGLE_CONCAT1(x, y)
 #define ANGLE_LOCAL_VAR ANGLE_CONCAT2(_localVar, __LINE__)
 
-#define ANGLE_TRY_TEMPLATE(EXPR, FUNC) \
-    {                                  \
-        auto ANGLE_LOCAL_VAR = EXPR;   \
-        if (ANGLE_LOCAL_VAR.isError()) \
-        {                              \
-            FUNC(ANGLE_LOCAL_VAR);     \
-        }                              \
-    }                                  \
+#define ANGLE_TRY_TEMPLATE(EXPR, FUNC)                 \
+    {                                                  \
+        auto ANGLE_LOCAL_VAR = EXPR;                   \
+        if (ANGLE_UNLIKELY(ANGLE_LOCAL_VAR.isError())) \
+        {                                              \
+            FUNC(ANGLE_LOCAL_VAR);                     \
+        }                                              \
+    }                                                  \
     ANGLE_EMPTY_STATEMENT
 
 #define ANGLE_RETURN(X) return X;
 #define ANGLE_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_RETURN);
 
-#define ANGLE_TRY_RESULT(EXPR, RESULT)         \
-    {                                          \
-        auto ANGLE_LOCAL_VAR = EXPR;           \
-        if (ANGLE_LOCAL_VAR.isError())         \
-        {                                      \
-            return ANGLE_LOCAL_VAR.getError(); \
-        }                                      \
-        RESULT = ANGLE_LOCAL_VAR.getResult();  \
-    }                                          \
+#define ANGLE_TRY_RESULT(EXPR, RESULT)                 \
+    {                                                  \
+        auto ANGLE_LOCAL_VAR = EXPR;                   \
+        if (ANGLE_UNLIKELY(ANGLE_LOCAL_VAR.isError())) \
+        {                                              \
+            return ANGLE_LOCAL_VAR.getError();         \
+        }                                              \
+        RESULT = ANGLE_LOCAL_VAR.getResult();          \
+    }                                                  \
     ANGLE_EMPTY_STATEMENT
 
 // TODO(jmadill): Introduce way to store errors to a const Context.
 #define ANGLE_SWALLOW_ERR(EXPR)                                       \
     {                                                                 \
         auto ANGLE_LOCAL_VAR = EXPR;                                  \
-        if (ANGLE_LOCAL_VAR.isError())                                \
+        if (ANGLE_UNLIKELY(ANGLE_LOCAL_VAR.isError()))                \
         {                                                             \
             ERR() << "Unhandled internal error: " << ANGLE_LOCAL_VAR; \
         }                                                             \
diff --git a/src/libANGLE/ErrorStrings.h b/src/libANGLE/ErrorStrings.h
index 5a7f403..99eedd9 100644
--- a/src/libANGLE/ErrorStrings.h
+++ b/src/libANGLE/ErrorStrings.h
@@ -64,6 +64,7 @@
 ERRMSG(InvalidBufferTypes, "Invalid buffer target enum.");
 ERRMSG(InvalidBufferUsage, "Invalid buffer usage enum.");
 ERRMSG(InvalidClearMask, "Invalid mask bits.");
+ERRMSG(InvalidClientState, "Invalid client vertex array type.");
 ERRMSG(InvalidCombinedImageUnit,
        "Specified unit must be in [GL_TEXTURE0, GL_TEXTURE0 + GL_MAX_COMBINED_IMAGE_UNITS)");
 ERRMSG(InvalidConstantColor,
@@ -98,8 +99,12 @@
 ERRMSG(InvalidName, "Invalid name.");
 ERRMSG(InvalidNameCharacters, "Name contains invalid characters.");
 ERRMSG(InvalidPname, "Invalid pname.");
+ERRMSG(InvalidPointerQuery, "Invalid pointer query.");
 ERRMSG(InvalidPrecision, "Invalid or unsupported precision type.");
 ERRMSG(InvalidProgramName, "Program object expected.");
+ERRMSG(InvalidProjectionMatrix,
+       "Invalid projection matrix. Left/right, top/bottom, near/far intervals cannot be zero, and "
+       "near/far cannot be less than zero.");
 ERRMSG(InvalidQueryId, "Invalid query Id.");
 ERRMSG(InvalidQueryTarget, "Invalid query target.");
 ERRMSG(InvalidQueryType, "Invalid query type.");
@@ -125,6 +130,9 @@
 ERRMSG(InvalidTypePureInt, "Invalid type, should be integer");
 ERRMSG(InvalidUnpackAlignment, "Unpack alignment must be 1, 2, 4, or 8.");
 ERRMSG(InvalidVertexAttrSize, "Vertex attribute size must be 1, 2, 3, or 4.");
+ERRMSG(InvalidVertexPointerSize, "Size for built-in vertex attribute is outside allowed range.");
+ERRMSG(InvalidVertexPointerStride, "Invalid stride for built-in vertex attribute.");
+ERRMSG(InvalidVertexPointerType, "Invalid type for built-in vertex attribute.");
 ERRMSG(InvalidWidth, "Invalid width.");
 ERRMSG(InvalidWrapModeTexture, "Invalid wrap mode for texture type.");
 ERRMSG(LevelNotZero, "Texture level must be zero.");
@@ -169,6 +177,7 @@
 ERRMSG(
     PixelUnpackBufferBoundForTransformFeedback,
     "It is undefined behavior to use a pixel unpack buffer that is bound for transform feedback.");
+ERRMSG(PointSizeArrayExtensionNotEnabled, "GL_OES_point_size_array not enabled.");
 ERRMSG(ProgramDoesNotExist, "Program doesn't exist.");
 ERRMSG(ProgramNotBound, "A program must be bound.");
 ERRMSG(ProgramNotLinked, "Program not linked.");
diff --git a/src/libANGLE/Framebuffer.cpp b/src/libANGLE/Framebuffer.cpp
index 666c0ff..ef058fb 100644
--- a/src/libANGLE/Framebuffer.cpp
+++ b/src/libANGLE/Framebuffer.cpp
@@ -146,8 +146,8 @@
 
         // ES3.1 (section 9.4) requires that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS should be
         // the same for all attached textures.
-        bool fixedSampleloc = texture->getFixedSampleLocations(attachmentImageIndex.target,
-                                                               attachmentImageIndex.mipIndex);
+        bool fixedSampleloc = texture->getFixedSampleLocations(
+            attachmentImageIndex.getTarget(), attachmentImageIndex.getLevelIndex());
         if (fixedSampleLocations->valid() && fixedSampleloc != fixedSampleLocations->value())
         {
             return false;
@@ -642,16 +642,16 @@
 
     const Context *proxyContext = display->getProxyContext();
 
-    setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex::MakeInvalid(),
-                      surface, FramebufferAttachment::kDefaultNumViews,
+    setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), surface,
+                      FramebufferAttachment::kDefaultNumViews,
                       FramebufferAttachment::kDefaultBaseViewIndex,
                       FramebufferAttachment::kDefaultMultiviewLayout,
                       FramebufferAttachment::kDefaultViewportOffsets);
 
     if (surface->getConfig()->depthSize > 0)
     {
-        setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, ImageIndex::MakeInvalid(),
-                          surface, FramebufferAttachment::kDefaultNumViews,
+        setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, ImageIndex(), surface,
+                          FramebufferAttachment::kDefaultNumViews,
                           FramebufferAttachment::kDefaultBaseViewIndex,
                           FramebufferAttachment::kDefaultMultiviewLayout,
                           FramebufferAttachment::kDefaultViewportOffsets);
@@ -659,11 +659,11 @@
 
     if (surface->getConfig()->stencilSize > 0)
     {
-        setAttachmentImpl(
-            proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, ImageIndex::MakeInvalid(), surface,
-            FramebufferAttachment::kDefaultNumViews, FramebufferAttachment::kDefaultBaseViewIndex,
-            FramebufferAttachment::kDefaultMultiviewLayout,
-            FramebufferAttachment::kDefaultViewportOffsets);
+        setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, ImageIndex(), surface,
+                          FramebufferAttachment::kDefaultNumViews,
+                          FramebufferAttachment::kDefaultBaseViewIndex,
+                          FramebufferAttachment::kDefaultMultiviewLayout,
+                          FramebufferAttachment::kDefaultViewportOffsets);
     }
     mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(0), 0);
 }
@@ -981,7 +981,7 @@
     }
 }
 
-Error Framebuffer::checkStatus(const Context *context, GLenum *statusOut)
+GLenum Framebuffer::checkStatus(const Context *context)
 {
     // The default framebuffer is always complete except when it is surfaceless in which
     // case it is always unsupported. We return early because the default framebuffer may
@@ -991,8 +991,7 @@
         ASSERT(mCachedStatus.valid());
         ASSERT(mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE ||
                mCachedStatus.value() == GL_FRAMEBUFFER_UNDEFINED_OES);
-        *statusOut = mCachedStatus.value();
-        return NoError();
+        return mCachedStatus.value();
     }
 
     if (hasAnyDirtyBit() || !mCachedStatus.valid())
@@ -1001,7 +1000,12 @@
 
         if (mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE)
         {
-            ANGLE_TRY(syncState(context));
+            Error err = syncState(context);
+            if (err.isError())
+            {
+                context->handleError(err);
+                return GetDefaultReturnValue<EntryPoint::CheckFramebufferStatus, GLenum>();
+            }
             if (!mImpl->checkStatus(context))
             {
                 mCachedStatus = GL_FRAMEBUFFER_UNSUPPORTED;
@@ -1009,8 +1013,7 @@
         }
     }
 
-    *statusOut = mCachedStatus.value();
-    return NoError();
+    return mCachedStatus.value();
 }
 
 GLenum Framebuffer::checkStatusWithGLFrontEnd(const Context *context)
@@ -1433,12 +1436,9 @@
     return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
 }
 
-Error Framebuffer::getSamples(const Context *context, int *samplesOut)
+int Framebuffer::getSamples(const Context *context)
 {
-    bool completeness = false;
-    ANGLE_TRY(isComplete(context, &completeness));
-    *samplesOut = completeness ? getCachedSamples(context) : 0;
-    return NoError();
+    return (isComplete(context) ? getCachedSamples(context) : 0);
 }
 
 int Framebuffer::getCachedSamples(const Context *context)
@@ -1589,7 +1589,7 @@
         }
         else
         {
-            return ImageIndex::MakeInvalid();
+            return ImageIndex();
         }
     };
 
@@ -1599,14 +1599,14 @@
         setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
                           getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
                           baseViewIndex, multiviewLayout, viewportOffsets);
-        setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(),
-                          nullptr, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
+        setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
+                          baseViewIndex, multiviewLayout, viewportOffsets);
     }
     else if (mState.mWebGLStencilAttachment.isAttached())
     {
         const auto &stencil = mState.mWebGLStencilAttachment;
-        setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr,
-                          numViews, baseViewIndex, multiviewLayout, viewportOffsets);
+        setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
+                          baseViewIndex, multiviewLayout, viewportOffsets);
         setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
                           getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
                           numViews, baseViewIndex, multiviewLayout, viewportOffsets);
@@ -1625,10 +1625,10 @@
     }
     else
     {
-        setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr,
-                          numViews, baseViewIndex, multiviewLayout, viewportOffsets);
-        setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(),
-                          nullptr, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
+        setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
+                          baseViewIndex, multiviewLayout, viewportOffsets);
+        setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
+                          baseViewIndex, multiviewLayout, viewportOffsets);
     }
 }
 
@@ -1736,7 +1736,7 @@
 
 void Framebuffer::resetAttachment(const Context *context, GLenum binding)
 {
-    setAttachment(context, GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
+    setAttachment(context, GL_NONE, binding, ImageIndex(), nullptr);
 }
 
 Error Framebuffer::syncState(const Context *context)
@@ -1792,12 +1792,9 @@
     }
 }
 
-Error Framebuffer::isComplete(const Context *context, bool *completeOut)
+bool Framebuffer::isComplete(const Context *context)
 {
-    GLenum status = GL_NONE;
-    ANGLE_TRY(checkStatus(context, &status));
-    *completeOut = (status == GL_FRAMEBUFFER_COMPLETE);
-    return NoError();
+    return (checkStatus(context) == GL_FRAMEBUFFER_COMPLETE);
 }
 
 bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
@@ -1879,12 +1876,11 @@
     if (readAttachment->isTextureWithId(copyTextureID))
     {
         const auto &imageIndex = readAttachment->getTextureImageIndex();
-        if (imageIndex.mipIndex == copyTextureLevel)
+        if (imageIndex.getLevelIndex() == copyTextureLevel)
         {
             // Check 3D/Array texture layers.
-            return imageIndex.layerIndex == ImageIndex::ENTIRE_LEVEL ||
-                   copyTextureLayer == ImageIndex::ENTIRE_LEVEL ||
-                   imageIndex.layerIndex == copyTextureLayer;
+            return !imageIndex.hasLayer() || copyTextureLayer == ImageIndex::kEntireLevel ||
+                   imageIndex.getLayerIndex() == copyTextureLayer;
         }
     }
     return false;
diff --git a/src/libANGLE/Framebuffer.h b/src/libANGLE/Framebuffer.h
index 4e99a89..db60147 100644
--- a/src/libANGLE/Framebuffer.h
+++ b/src/libANGLE/Framebuffer.h
@@ -40,13 +40,13 @@
 class Context;
 class ContextState;
 class Framebuffer;
+class ImageIndex;
 class Renderbuffer;
 class State;
 class Texture;
 class TextureCapsMap;
 struct Caps;
 struct Extensions;
-struct ImageIndex;
 struct Rectangle;
 
 class FramebufferState final : angle::NonCopyable
@@ -214,7 +214,7 @@
     bool usingExtendedDrawBuffers() const;
 
     // This method calls checkStatus.
-    Error getSamples(const Context *context, int *samplesOut);
+    int getSamples(const Context *context);
 
     Error getSamplePosition(size_t index, GLfloat *xy) const;
 
@@ -229,13 +229,13 @@
 
     void invalidateCompletenessCache();
 
-    Error checkStatus(const Context *context, GLenum *statusOut);
+    GLenum checkStatus(const Context *context);
 
     // For when we don't want to check completeness in getSamples().
     int getCachedSamples(const Context *context);
 
     // Helper for checkStatus == GL_FRAMEBUFFER_COMPLETE.
-    Error isComplete(const Context *context, bool *completeOut);
+    bool isComplete(const Context *context);
 
     bool hasValidDepthStencil() const;
 
diff --git a/src/libANGLE/FramebufferAttachment.cpp b/src/libANGLE/FramebufferAttachment.cpp
index baac201..9566e72 100644
--- a/src/libANGLE/FramebufferAttachment.cpp
+++ b/src/libANGLE/FramebufferAttachment.cpp
@@ -53,9 +53,7 @@
         FramebufferAttachment::kDefaultViewportOffsets, FramebufferAttachment::kDefaultNumViews);
 }
 
-FramebufferAttachment::Target::Target()
-    : mBinding(GL_NONE),
-      mTextureIndex(ImageIndex::MakeInvalid())
+FramebufferAttachment::Target::Target() : mBinding(GL_NONE), mTextureIndex()
 {
 }
 
@@ -182,32 +180,32 @@
 
 GLuint FramebufferAttachment::getRedSize() const
 {
-    return getSize().empty() ? 0 : getFormat().info->redBits;
+    return getFormat().info->redBits;
 }
 
 GLuint FramebufferAttachment::getGreenSize() const
 {
-    return getSize().empty() ? 0 : getFormat().info->greenBits;
+    return getFormat().info->greenBits;
 }
 
 GLuint FramebufferAttachment::getBlueSize() const
 {
-    return getSize().empty() ? 0 : getFormat().info->blueBits;
+    return getFormat().info->blueBits;
 }
 
 GLuint FramebufferAttachment::getAlphaSize() const
 {
-    return getSize().empty() ? 0 : getFormat().info->alphaBits;
+    return getFormat().info->alphaBits;
 }
 
 GLuint FramebufferAttachment::getDepthSize() const
 {
-    return getSize().empty() ? 0 : getFormat().info->depthBits;
+    return getFormat().info->depthBits;
 }
 
 GLuint FramebufferAttachment::getStencilSize() const
 {
-    return getSize().empty() ? 0 : getFormat().info->stencilBits;
+    return getFormat().info->stencilBits;
 }
 
 GLenum FramebufferAttachment::getComponentType() const
@@ -236,21 +234,21 @@
     ASSERT(mType == GL_TEXTURE);
 
     const auto &index = mTarget.textureIndex();
-    return index.type == TextureType::CubeMap ? index.target : TextureTarget::InvalidEnum;
+    return index.getType() == TextureType::CubeMap ? index.getTarget() : TextureTarget::InvalidEnum;
 }
 
 GLint FramebufferAttachment::mipLevel() const
 {
     ASSERT(type() == GL_TEXTURE);
-    return mTarget.textureIndex().mipIndex;
+    return mTarget.textureIndex().getLevelIndex();
 }
 
 GLint FramebufferAttachment::layer() const
 {
     ASSERT(mType == GL_TEXTURE);
 
-    const auto &index = mTarget.textureIndex();
-    return index.hasLayer() ? index.layerIndex : 0;
+    const gl::ImageIndex &index = mTarget.textureIndex();
+    return (index.has3DLayer() ? index.getLayerIndex() : 0);
 }
 
 GLsizei FramebufferAttachment::getNumViews() const
@@ -370,10 +368,10 @@
 
     // Because gl::Texture cannot support tracking individual layer dirtiness, we only handle
     // initializing entire mip levels for 2D array textures.
-    if (imageIndex.type == TextureType::_2DArray && imageIndex.hasLayer())
+    if (imageIndex.getType() == TextureType::_2DArray && imageIndex.hasLayer())
     {
-        ImageIndex fullMipIndex = imageIndex;
-        fullMipIndex.layerIndex = ImageIndex::ENTIRE_LEVEL;
+        ImageIndex fullMipIndex =
+            ImageIndex::Make2DArray(imageIndex.getLevelIndex(), ImageIndex::kEntireLevel);
         return getAttachmentImpl()->initializeContents(context, fullMipIndex);
     }
     else
diff --git a/src/libANGLE/GLES1State.cpp b/src/libANGLE/GLES1State.cpp
index de9cf67..7a3c932 100644
--- a/src/libANGLE/GLES1State.cpp
+++ b/src/libANGLE/GLES1State.cpp
@@ -264,8 +264,53 @@
 
 void GLES1State::multMatrix(const angle::Mat4 &m)
 {
-    angle::Mat4 currentMatrix             = currentMatrixStack().back();
+    angle::Mat4 currentMatrix   = currentMatrixStack().back();
     currentMatrixStack().back() = currentMatrix.product(m);
 }
 
+void GLES1State::setClientStateEnabled(ClientVertexArrayType clientState, bool enable)
+{
+    switch (clientState)
+    {
+        case ClientVertexArrayType::Vertex:
+            mVertexArrayEnabled = enable;
+            break;
+        case ClientVertexArrayType::Normal:
+            mNormalArrayEnabled = enable;
+            break;
+        case ClientVertexArrayType::Color:
+            mColorArrayEnabled = enable;
+            break;
+        case ClientVertexArrayType::PointSize:
+            mPointSizeArrayEnabled = enable;
+            break;
+        case ClientVertexArrayType::TextureCoord:
+            mTexCoordArrayEnabled[mClientActiveTexture] = enable;
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+bool GLES1State::isClientStateEnabled(ClientVertexArrayType clientState) const
+{
+    switch (clientState)
+    {
+        case ClientVertexArrayType::Vertex:
+            return mVertexArrayEnabled;
+        case ClientVertexArrayType::Normal:
+            return mNormalArrayEnabled;
+        case ClientVertexArrayType::Color:
+            return mColorArrayEnabled;
+        case ClientVertexArrayType::PointSize:
+            return mPointSizeArrayEnabled;
+        case ClientVertexArrayType::TextureCoord:
+            return mTexCoordArrayEnabled[mClientActiveTexture];
+        default:
+            UNREACHABLE();
+            return false;
+    }
+}
+
 }  // namespace gl
diff --git a/src/libANGLE/GLES1State.h b/src/libANGLE/GLES1State.h
index b9582b1..c6d7a44 100644
--- a/src/libANGLE/GLES1State.h
+++ b/src/libANGLE/GLES1State.h
@@ -150,6 +150,9 @@
     void loadMatrix(const angle::Mat4 &m);
     void multMatrix(const angle::Mat4 &m);
 
+    void setClientStateEnabled(ClientVertexArrayType clientState, bool enable);
+    bool isClientStateEnabled(ClientVertexArrayType clientState) const;
+
   private:
     friend class State;
 
diff --git a/src/libANGLE/Image.cpp b/src/libANGLE/Image.cpp
index e0e40b0..bfdb926 100644
--- a/src/libANGLE/Image.cpp
+++ b/src/libANGLE/Image.cpp
@@ -26,7 +26,7 @@
 {
     if (eglTarget == EGL_GL_RENDERBUFFER)
     {
-        return gl::ImageIndex::MakeInvalid();
+        return gl::ImageIndex();
     }
 
     gl::TextureTarget target = egl_gl::EGLImageTargetToTextureTarget(eglTarget);
@@ -40,7 +40,7 @@
     else
     {
         ASSERT(layer == 0);
-        return gl::ImageIndex::MakeGeneric(target, mip);
+        return gl::ImageIndex::MakeFromTarget(target, mip);
     }
 }
 }  // anonymous namespace
diff --git a/src/libANGLE/ImageIndex.cpp b/src/libANGLE/ImageIndex.cpp
index d46c0c5..d86b9b4 100644
--- a/src/libANGLE/ImageIndex.cpp
+++ b/src/libANGLE/ImageIndex.cpp
@@ -1,4 +1,3 @@
-#include "ImageIndex.h"
 //
 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
@@ -8,186 +7,253 @@
 // ImageIndex.cpp: Implementation for ImageIndex methods.
 
 #include "libANGLE/ImageIndex.h"
-#include "libANGLE/Constants.h"
+
 #include "common/utilities.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/angletypes.h"
 
 #include <tuple>
 
 namespace gl
 {
+namespace
+{
+GLint TextureTargetToLayer(TextureTarget target)
+{
+    switch (target)
+    {
+        case TextureTarget::CubeMapPositiveX:
+            return 0;
+        case TextureTarget::CubeMapNegativeX:
+            return 1;
+        case TextureTarget::CubeMapPositiveY:
+            return 2;
+        case TextureTarget::CubeMapNegativeY:
+            return 3;
+        case TextureTarget::CubeMapPositiveZ:
+            return 4;
+        case TextureTarget::CubeMapNegativeZ:
+            return 5;
+        case TextureTarget::External:
+            return ImageIndex::kEntireLevel;
+        case TextureTarget::Rectangle:
+            return ImageIndex::kEntireLevel;
+        case TextureTarget::_2D:
+            return ImageIndex::kEntireLevel;
+        case TextureTarget::_2DArray:
+            return ImageIndex::kEntireLevel;
+        case TextureTarget::_2DMultisample:
+            return ImageIndex::kEntireLevel;
+        case TextureTarget::_3D:
+            return ImageIndex::kEntireLevel;
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+TextureTarget TextureTypeToTarget(TextureType type, GLint layerIndex)
+{
+    if (type == TextureType::CubeMap)
+    {
+        return CubeFaceIndexToTextureTarget(layerIndex);
+    }
+    else
+    {
+        return NonCubeTextureTypeToTarget(type);
+    }
+}
+}  // anonymous namespace
+
+ImageIndex::ImageIndex()
+    : mType(TextureType::InvalidEnum), mLevelIndex(0), mLayerIndex(0), mLayerCount(kEntireLevel)
+{
+}
 
 ImageIndex::ImageIndex(const ImageIndex &other) = default;
+
 ImageIndex &ImageIndex::operator=(const ImageIndex &other) = default;
 
-bool ImageIndex::is3D() const
+bool ImageIndex::hasLayer() const
 {
-    return type == TextureType::_3D || type == TextureType::_2DArray;
+    return mLayerIndex != kEntireLevel;
+}
+
+bool ImageIndex::has3DLayer() const
+{
+    // It's quicker to check != CubeMap than calling usesTex3D, which checks multiple types. This
+    // ASSERT validates the check gives the same result.
+    ASSERT(!hasLayer() || (mType != TextureType::CubeMap == usesTex3D()));
+    return (hasLayer() && mType != TextureType::CubeMap);
+}
+
+bool ImageIndex::usesTex3D() const
+{
+    return mType == TextureType::_3D || mType == TextureType::_2DArray;
+}
+
+TextureTarget ImageIndex::getTarget() const
+{
+    return TextureTypeToTarget(mType, mLayerIndex);
 }
 
 GLint ImageIndex::cubeMapFaceIndex() const
 {
-    ASSERT(type == TextureType::CubeMap);
-    ASSERT(TextureTargetToType(target) == TextureType::CubeMap);
-    return static_cast<GLint>(CubeMapTextureTargetToFaceIndex(target));
+    ASSERT(mType == TextureType::CubeMap);
+    ASSERT(mLayerIndex == kEntireLevel || mLayerIndex < static_cast<GLint>(CUBE_FACE_COUNT));
+    return mLayerIndex;
 }
 
 bool ImageIndex::valid() const
 {
-    return type != TextureType::InvalidEnum;
+    return mType != TextureType::InvalidEnum;
 }
 
-ImageIndex ImageIndex::Make2D(GLint mipIndex)
+ImageIndex ImageIndex::Make2D(GLint levelIndex)
 {
-    return ImageIndex(TextureType::_2D, TextureTarget::_2D, mipIndex, ENTIRE_LEVEL, 1);
+    return ImageIndex(TextureType::_2D, levelIndex, kEntireLevel, 1);
 }
 
-ImageIndex ImageIndex::MakeRectangle(GLint mipIndex)
+ImageIndex ImageIndex::MakeRectangle(GLint levelIndex)
 {
-    return ImageIndex(TextureType::Rectangle, TextureTarget::Rectangle, mipIndex, ENTIRE_LEVEL, 1);
+    return ImageIndex(TextureType::Rectangle, levelIndex, kEntireLevel, 1);
 }
 
-ImageIndex ImageIndex::MakeCube(TextureTarget target, GLint mipIndex)
+ImageIndex ImageIndex::MakeCube(TextureTarget target, GLint levelIndex)
 {
     ASSERT(TextureTargetToType(target) == TextureType::CubeMap);
-    return ImageIndex(TextureType::CubeMap, target, mipIndex, ENTIRE_LEVEL, 1);
+    return ImageIndex(TextureType::CubeMap, levelIndex, TextureTargetToLayer(target), 1);
 }
 
-ImageIndex ImageIndex::Make2DArray(GLint mipIndex, GLint layerIndex)
+ImageIndex ImageIndex::Make2DArray(GLint levelIndex, GLint layerIndex)
 {
-    return ImageIndex(TextureType::_2DArray, TextureTarget::_2DArray, mipIndex, layerIndex, 1);
+    return ImageIndex(TextureType::_2DArray, levelIndex, layerIndex, 1);
 }
 
-ImageIndex ImageIndex::Make2DArrayRange(GLint mipIndex, GLint layerIndex, GLint numLayers)
+ImageIndex ImageIndex::Make2DArrayRange(GLint levelIndex, GLint layerIndex, GLint numLayers)
 {
-    return ImageIndex(TextureType::_2DArray, TextureTarget::_2DArray, mipIndex, layerIndex,
-                      numLayers);
+    return ImageIndex(TextureType::_2DArray, levelIndex, layerIndex, numLayers);
 }
 
-ImageIndex ImageIndex::Make3D(GLint mipIndex, GLint layerIndex)
+ImageIndex ImageIndex::Make3D(GLint levelIndex, GLint layerIndex)
 {
-    return ImageIndex(TextureType::_3D, TextureTarget::_3D, mipIndex, layerIndex, 1);
+    return ImageIndex(TextureType::_3D, levelIndex, layerIndex, 1);
 }
 
-ImageIndex ImageIndex::MakeGeneric(TextureTarget target, GLint mipIndex)
+ImageIndex ImageIndex::MakeFromTarget(TextureTarget target, GLint levelIndex)
 {
-    return ImageIndex(TextureTargetToType(target), target, mipIndex, ENTIRE_LEVEL, 1);
+    return ImageIndex(TextureTargetToType(target), levelIndex, TextureTargetToLayer(target), 1);
+}
+
+ImageIndex ImageIndex::MakeFromType(TextureType type,
+                                    GLint levelIndex,
+                                    GLint layerIndex,
+                                    GLint layerCount)
+{
+    GLint overrideLayerCount =
+        (type == TextureType::CubeMap && layerIndex == kEntireLevel ? CUBE_FACE_COUNT : layerCount);
+    return ImageIndex(type, levelIndex, layerIndex, overrideLayerCount);
 }
 
 ImageIndex ImageIndex::Make2DMultisample()
 {
-    return ImageIndex(TextureType::_2DMultisample, TextureTarget::_2DMultisample, 0, ENTIRE_LEVEL,
-                      1);
+    return ImageIndex(TextureType::_2DMultisample, 0, kEntireLevel, 1);
 }
 
-ImageIndex ImageIndex::MakeInvalid()
+bool ImageIndex::operator<(const ImageIndex &b) const
 {
-    return ImageIndex(TextureType::InvalidEnum, TextureTarget::InvalidEnum, -1, -1, -1);
+    return std::tie(mType, mLevelIndex, mLayerIndex, mLayerCount) <
+           std::tie(b.mType, b.mLevelIndex, b.mLayerIndex, b.mLayerCount);
 }
 
-bool operator<(const ImageIndex &a, const ImageIndex &b)
+bool ImageIndex::operator==(const ImageIndex &b) const
 {
-    return std::tie(a.type, a.target, a.mipIndex, a.layerIndex, a.numLayers) <
-           std::tie(b.type, b.target, b.mipIndex, b.layerIndex, b.numLayers);
+    return std::tie(mType, mLevelIndex, mLayerIndex, mLayerCount) ==
+           std::tie(b.mType, b.mLevelIndex, b.mLayerIndex, b.mLayerCount);
 }
 
-bool operator==(const ImageIndex &a, const ImageIndex &b)
+bool ImageIndex::operator!=(const ImageIndex &b) const
 {
-    return std::tie(a.type, a.target, a.mipIndex, a.layerIndex, a.numLayers) ==
-           std::tie(b.type, b.target, b.mipIndex, b.layerIndex, b.numLayers);
+    return !(*this == b);
 }
 
-bool operator!=(const ImageIndex &a, const ImageIndex &b)
-{
-    return !(a == b);
-}
-
-ImageIndex::ImageIndex(TextureType typeIn,
-                       TextureTarget targetIn,
-                       GLint mipIndexIn,
-                       GLint layerIndexIn,
-                       GLint numLayersIn)
-    : type(typeIn),
-      target(targetIn),
-      mipIndex(mipIndexIn),
-      layerIndex(layerIndexIn),
-      numLayers(numLayersIn)
+ImageIndex::ImageIndex(TextureType type, GLint levelIndex, GLint layerIndex, GLint layerCount)
+    : mType(type), mLevelIndex(levelIndex), mLayerIndex(layerIndex), mLayerCount(layerCount)
 {}
 
+ImageIndexIterator ImageIndex::getLayerIterator(GLint layerCount) const
+{
+    ASSERT(mType != TextureType::_2D && !hasLayer());
+    return ImageIndexIterator::MakeGeneric(mType, mLevelIndex, mLevelIndex + 1, 0, layerCount);
+}
+
 ImageIndexIterator::ImageIndexIterator(const ImageIndexIterator &other) = default;
 
 ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip)
 {
-    return ImageIndexIterator(
-        TextureType::_2D, TextureTarget::_2D, TextureTarget::_2D, Range<GLint>(minMip, maxMip),
-        Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL), nullptr);
+    return ImageIndexIterator(TextureType::_2D, Range<GLint>(minMip, maxMip),
+                              Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
+                              nullptr);
 }
 
 ImageIndexIterator ImageIndexIterator::MakeRectangle(GLint minMip, GLint maxMip)
 {
-    return ImageIndexIterator(TextureType::Rectangle, TextureTarget::Rectangle,
-                              TextureTarget::Rectangle, Range<GLint>(minMip, maxMip),
-                              Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL),
+    return ImageIndexIterator(TextureType::Rectangle, Range<GLint>(minMip, maxMip),
+                              Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
                               nullptr);
 }
 
 ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip)
 {
-    return ImageIndexIterator(TextureType::CubeMap, kCubeMapTextureTargetMin,
-                              kCubeMapTextureTargetMax, Range<GLint>(minMip, maxMip),
-                              Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL),
-                              nullptr);
+    return ImageIndexIterator(TextureType::CubeMap, Range<GLint>(minMip, maxMip),
+                              Range<GLint>(0, 6), nullptr);
 }
 
 ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip, GLint maxMip,
                                               GLint minLayer, GLint maxLayer)
 {
-    return ImageIndexIterator(TextureType::_3D, TextureTarget::_3D, TextureTarget::_3D,
-                              Range<GLint>(minMip, maxMip), Range<GLint>(minLayer, maxLayer),
-                              nullptr);
+    return ImageIndexIterator(TextureType::_3D, Range<GLint>(minMip, maxMip),
+                              Range<GLint>(minLayer, maxLayer), nullptr);
 }
 
 ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip, GLint maxMip,
                                                    const GLsizei *layerCounts)
 {
-    return ImageIndexIterator(TextureType::_2DArray, TextureTarget::_2DArray,
-                              TextureTarget::_2DArray, Range<GLint>(minMip, maxMip),
+    return ImageIndexIterator(TextureType::_2DArray, Range<GLint>(minMip, maxMip),
                               Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS),
                               layerCounts);
 }
 
 ImageIndexIterator ImageIndexIterator::Make2DMultisample()
 {
-    return ImageIndexIterator(TextureType::_2DMultisample, TextureTarget::_2DMultisample,
-                              TextureTarget::_2DMultisample, Range<GLint>(0, 0),
-                              Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL),
+    return ImageIndexIterator(TextureType::_2DMultisample, Range<GLint>(0, 0),
+                              Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
                               nullptr);
 }
 
-ImageIndexIterator ImageIndexIterator::MakeGeneric(TextureType type, GLint minMip, GLint maxMip)
+ImageIndexIterator ImageIndexIterator::MakeGeneric(TextureType type,
+                                                   GLint minMip,
+                                                   GLint maxMip,
+                                                   GLint minLayer,
+                                                   GLint maxLayer)
 {
     if (type == TextureType::CubeMap)
     {
         return MakeCube(minMip, maxMip);
     }
 
-    TextureTarget target = NonCubeTextureTypeToTarget(type);
-    return ImageIndexIterator(type, target, target, Range<GLint>(minMip, maxMip),
-                              Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL),
+    return ImageIndexIterator(type, Range<GLint>(minMip, maxMip), Range<GLint>(minLayer, maxLayer),
                               nullptr);
 }
 
 ImageIndexIterator::ImageIndexIterator(TextureType type,
-                                       angle::EnumIterator<TextureTarget> targetLow,
-                                       angle::EnumIterator<TextureTarget> targetHigh,
                                        const Range<GLint> &mipRange,
                                        const Range<GLint> &layerRange,
                                        const GLsizei *layerCounts)
-    : mTargetLow(targetLow),
-      mTargetHigh(targetHigh),
-      mMipRange(mipRange),
+    : mMipRange(mipRange),
       mLayerRange(layerRange),
       mLayerCounts(layerCounts),
-      mCurrentIndex(type, *targetLow, mipRange.low(), layerRange.low(), 1)
+      mCurrentIndex(type, mipRange.low(), layerRange.low(), 1)
 {}
 
 GLint ImageIndexIterator::maxLayer() const
@@ -195,8 +261,9 @@
     if (mLayerCounts)
     {
         ASSERT(mCurrentIndex.hasLayer());
-        return (mCurrentIndex.mipIndex < mMipRange.high()) ? mLayerCounts[mCurrentIndex.mipIndex]
-                                                           : 0;
+        return (mCurrentIndex.getLevelIndex() < mMipRange.high())
+                   ? mLayerCounts[mCurrentIndex.getLevelIndex()]
+                   : 0;
     }
     return mLayerRange.high();
 }
@@ -211,26 +278,18 @@
     // Iterate layers in the inner loop for now. We can add switchable
     // layer or mip iteration if we need it.
 
-    angle::EnumIterator<TextureTarget> currentTarget = mCurrentIndex.target;
-    if (currentTarget != mTargetHigh)
+    if (mCurrentIndex.hasLayer() && mCurrentIndex.getLayerIndex() < maxLayer() - 1)
     {
-        ++currentTarget;
-        mCurrentIndex.target = *currentTarget;
+        mCurrentIndex.mLayerIndex++;
     }
-    else if (mCurrentIndex.hasLayer() && mCurrentIndex.layerIndex < maxLayer() - 1)
+    else if (mCurrentIndex.mLevelIndex < mMipRange.high() - 1)
     {
-        mCurrentIndex.target = *mTargetLow;
-        mCurrentIndex.layerIndex++;
-    }
-    else if (mCurrentIndex.mipIndex < mMipRange.high() - 1)
-    {
-        mCurrentIndex.target     = *mTargetLow;
-        mCurrentIndex.layerIndex = mLayerRange.low();
-        mCurrentIndex.mipIndex++;
+        mCurrentIndex.mLayerIndex = mLayerRange.low();
+        mCurrentIndex.mLevelIndex++;
     }
     else
     {
-        mCurrentIndex = ImageIndex::MakeInvalid();
+        mCurrentIndex = ImageIndex();
     }
 
     return previousIndex;
diff --git a/src/libANGLE/ImageIndex.h b/src/libANGLE/ImageIndex.h
index af6fca3..83a89d7 100644
--- a/src/libANGLE/ImageIndex.h
+++ b/src/libANGLE/ImageIndex.h
@@ -10,7 +10,7 @@
 #define LIBANGLE_IMAGE_INDEX_H_
 
 #include "common/mathutil.h"
-#include "libANGLE/PackedGLEnums.h"
+#include "libANGLE/PackedEnums.h"
 
 #include "angle_gl.h"
 
@@ -19,50 +19,57 @@
 
 class ImageIndexIterator;
 
-struct ImageIndex
+class ImageIndex
 {
-    TextureType type;
-    TextureTarget target;
-
-    GLint mipIndex;
-
-    GLint layerIndex;
-    GLint numLayers;
-
+  public:
+    ImageIndex();
     ImageIndex(const ImageIndex &other);
     ImageIndex &operator=(const ImageIndex &other);
 
-    bool hasLayer() const { return layerIndex != ENTIRE_LEVEL; }
-    bool is3D() const;
+    TextureType getType() const { return mType; }
+    GLint getLevelIndex() const { return mLevelIndex; }
+    GLint getLayerIndex() const { return mLayerIndex; }
+    GLint getLayerCount() const { return mLayerCount; }
+
+    bool hasLayer() const;
+    bool has3DLayer() const;
+    bool usesTex3D() const;
     GLint cubeMapFaceIndex() const;
     bool valid() const;
+    TextureTarget getTarget() const;
 
-    static ImageIndex Make2D(GLint mipIndex);
-    static ImageIndex MakeRectangle(GLint mipIndex);
-    static ImageIndex MakeCube(TextureTarget target, GLint mipIndex);
-    static ImageIndex Make2DArray(GLint mipIndex, GLint layerIndex);
-    static ImageIndex Make2DArrayRange(GLint mipIndex, GLint layerIndex, GLint numLayers);
-    static ImageIndex Make3D(GLint mipIndex, GLint layerIndex = ENTIRE_LEVEL);
-    static ImageIndex MakeGeneric(TextureTarget target, GLint mipIndex);
+    static ImageIndex Make2D(GLint levelIndex);
+    static ImageIndex MakeRectangle(GLint levelIndex);
+    static ImageIndex MakeCube(TextureTarget target, GLint levelIndex);
+    static ImageIndex Make2DArray(GLint levelIndex, GLint layerIndex);
+    static ImageIndex Make2DArrayRange(GLint levelIndex, GLint layerIndex, GLint layerCount);
+    static ImageIndex Make3D(GLint levelIndex, GLint layerIndex = kEntireLevel);
+    static ImageIndex MakeFromTarget(TextureTarget target, GLint levelIndex);
+    static ImageIndex MakeFromType(TextureType type,
+                                   GLint levelIndex,
+                                   GLint layerIndex = kEntireLevel,
+                                   GLint layerCount = 1);
     static ImageIndex Make2DMultisample();
 
-    static ImageIndex MakeInvalid();
+    static constexpr GLint kEntireLevel = static_cast<GLint>(-1);
 
-    static const GLint ENTIRE_LEVEL = static_cast<GLint>(-1);
+    bool operator<(const ImageIndex &b) const;
+    bool operator==(const ImageIndex &b) const;
+    bool operator!=(const ImageIndex &b) const;
+
+    // Only valid for 3D/Cube textures with layers.
+    ImageIndexIterator getLayerIterator(GLint layerCount) const;
 
   private:
     friend class ImageIndexIterator;
 
-    ImageIndex(TextureType typeIn,
-               TextureTarget targetIn,
-               GLint mipIndexIn,
-               GLint layerIndexIn,
-               GLint numLayersIn);
-};
+    ImageIndex(TextureType type, GLint leveIndex, GLint layerIndex, GLint layerCount);
 
-bool operator<(const ImageIndex &a, const ImageIndex &b);
-bool operator==(const ImageIndex &a, const ImageIndex &b);
-bool operator!=(const ImageIndex &a, const ImageIndex &b);
+    TextureType mType;
+    GLint mLevelIndex;
+    GLint mLayerIndex;
+    GLint mLayerCount;
+};
 
 // To be used like this:
 //
@@ -82,7 +89,11 @@
     static ImageIndexIterator Make3D(GLint minMip, GLint maxMip, GLint minLayer, GLint maxLayer);
     static ImageIndexIterator Make2DArray(GLint minMip, GLint maxMip, const GLsizei *layerCounts);
     static ImageIndexIterator Make2DMultisample();
-    static ImageIndexIterator MakeGeneric(TextureType type, GLint minMip, GLint maxMip);
+    static ImageIndexIterator MakeGeneric(TextureType type,
+                                          GLint minMip,
+                                          GLint maxMip,
+                                          GLint minLayer,
+                                          GLint maxLayer);
 
     ImageIndex next();
     ImageIndex current() const;
@@ -90,23 +101,18 @@
 
   private:
     ImageIndexIterator(TextureType type,
-                       angle::EnumIterator<TextureTarget> targetLow,
-                       angle::EnumIterator<TextureTarget> targetHigh,
                        const Range<GLint> &mipRange,
                        const Range<GLint> &layerRange,
                        const GLsizei *layerCounts);
 
     GLint maxLayer() const;
 
-    const angle::EnumIterator<TextureTarget> mTargetLow;
-    const angle::EnumIterator<TextureTarget> mTargetHigh;
     const Range<GLint> mMipRange;
     const Range<GLint> mLayerRange;
     const GLsizei *const mLayerCounts;
 
     ImageIndex mCurrentIndex;
 };
-
-}
+}  // namespace gl
 
 #endif // LIBANGLE_IMAGE_INDEX_H_
diff --git a/src/libANGLE/ImageIndexIterator_unittest.cpp b/src/libANGLE/ImageIndexIterator_unittest.cpp
index 2b656e2..9ffb195 100644
--- a/src/libANGLE/ImageIndexIterator_unittest.cpp
+++ b/src/libANGLE/ImageIndexIterator_unittest.cpp
@@ -32,15 +32,16 @@
         ImageIndex current = iter.current();
         ImageIndex nextIndex = iter.next();
 
-        EXPECT_EQ(TextureType::_2D, nextIndex.type);
-        EXPECT_EQ(TextureTarget::_2D, nextIndex.target);
-        EXPECT_EQ(mip, nextIndex.mipIndex);
+        EXPECT_EQ(TextureType::_2D, nextIndex.getType());
+        EXPECT_EQ(TextureTarget::_2D, nextIndex.getTarget());
+        EXPECT_EQ(mip, nextIndex.getLevelIndex());
         EXPECT_FALSE(nextIndex.hasLayer());
+        EXPECT_FALSE(nextIndex.has3DLayer());
 
         // Also test current
-        EXPECT_EQ(current.type, nextIndex.type);
-        EXPECT_EQ(current.mipIndex, nextIndex.mipIndex);
-        EXPECT_EQ(current.layerIndex, nextIndex.layerIndex);
+        EXPECT_EQ(current.getType(), nextIndex.getType());
+        EXPECT_EQ(current.getLevelIndex(), nextIndex.getLevelIndex());
+        EXPECT_EQ(current.getLayerIndex(), nextIndex.getLayerIndex());
     }
 
     EXPECT_FALSE(iter.hasNext());
@@ -59,10 +60,11 @@
             EXPECT_TRUE(iter.hasNext());
             ImageIndex nextIndex = iter.next();
 
-            EXPECT_EQ(TextureType::CubeMap, nextIndex.type);
-            EXPECT_EQ(target, nextIndex.target);
-            EXPECT_EQ(mip, nextIndex.mipIndex);
-            EXPECT_FALSE(nextIndex.hasLayer());
+            EXPECT_EQ(TextureType::CubeMap, nextIndex.getType());
+            EXPECT_EQ(target, nextIndex.getTarget());
+            EXPECT_EQ(mip, nextIndex.getLevelIndex());
+            EXPECT_TRUE(nextIndex.hasLayer());
+            EXPECT_FALSE(nextIndex.has3DLayer());
         }
     }
 
@@ -82,11 +84,12 @@
             EXPECT_TRUE(iter.hasNext());
             ImageIndex nextIndex = iter.next();
 
-            EXPECT_EQ(TextureType::_3D, nextIndex.type);
-            EXPECT_EQ(TextureTarget::_3D, nextIndex.target);
-            EXPECT_EQ(mip, nextIndex.mipIndex);
-            EXPECT_EQ(layer, nextIndex.layerIndex);
+            EXPECT_EQ(TextureType::_3D, nextIndex.getType());
+            EXPECT_EQ(TextureTarget::_3D, nextIndex.getTarget());
+            EXPECT_EQ(mip, nextIndex.getLevelIndex());
+            EXPECT_EQ(layer, nextIndex.getLayerIndex());
             EXPECT_TRUE(nextIndex.hasLayer());
+            EXPECT_TRUE(nextIndex.has3DLayer());
         }
     }
 
@@ -109,15 +112,47 @@
             EXPECT_TRUE(iter.hasNext());
             ImageIndex nextIndex = iter.next();
 
-            EXPECT_EQ(TextureType::_2DArray, nextIndex.type);
-            EXPECT_EQ(TextureTarget::_2DArray, nextIndex.target);
-            EXPECT_EQ(mip, nextIndex.mipIndex);
-            EXPECT_EQ(layer, nextIndex.layerIndex);
+            EXPECT_EQ(TextureType::_2DArray, nextIndex.getType());
+            EXPECT_EQ(TextureTarget::_2DArray, nextIndex.getTarget());
+            EXPECT_EQ(mip, nextIndex.getLevelIndex());
+            EXPECT_EQ(layer, nextIndex.getLayerIndex());
             EXPECT_TRUE(nextIndex.hasLayer());
+            EXPECT_TRUE(nextIndex.has3DLayer());
         }
     }
 
     EXPECT_FALSE(iter.hasNext());
 }
 
+TEST(ImageIndexTest, LayerIterator2DArray)
+{
+    GLsizei layerCounts[] = {1, 3, 5, 2};
+
+    ASSERT_GE(0, minMip);
+    ASSERT_EQ(ArraySize(layerCounts), static_cast<size_t>(maxMip));
+
+    for (GLint mip = minMip; mip < maxMip; mip++)
+    {
+        // Make a layer iterator.
+        ImageIndex mipImageIndex = ImageIndex::Make2DArray(mip, ImageIndex::kEntireLevel);
+        ImageIndexIterator iter  = mipImageIndex.getLayerIterator(layerCounts[mip]);
+
+        for (GLint layer = 0; layer < layerCounts[mip]; layer++)
+        {
+            EXPECT_TRUE(iter.hasNext());
+            ImageIndex nextIndex = iter.next();
+
+            EXPECT_EQ(TextureType::_2DArray, nextIndex.getType());
+            EXPECT_EQ(TextureTarget::_2DArray, nextIndex.getTarget());
+            EXPECT_EQ(mip, nextIndex.getLevelIndex());
+            EXPECT_EQ(layer, nextIndex.getLayerIndex());
+            EXPECT_TRUE(nextIndex.hasLayer());
+            EXPECT_TRUE(nextIndex.has3DLayer());
+            EXPECT_LT(nextIndex.getLayerIndex(), layerCounts[mip]);
+        }
+
+        EXPECT_FALSE(iter.hasNext());
+    }
+}
+
 } // namespace
diff --git a/src/libANGLE/PackedEGLEnums_autogen.cpp b/src/libANGLE/PackedEGLEnums_autogen.cpp
new file mode 100644
index 0000000..d4c26c7
--- /dev/null
+++ b/src/libANGLE/PackedEGLEnums_autogen.cpp
@@ -0,0 +1,50 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_packed_gl_enums.py using data from packed_egl_enums.json.
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// PackedEGLEnums_autogen.cpp:
+//   Implements ANGLE-specific enums classes for EGLenums and functions operating
+//   on them.
+
+#include "libANGLE/PackedEGLEnums_autogen.h"
+#include "common/debug.h"
+
+namespace egl
+{
+
+template <>
+TextureFormat FromEGLenum<TextureFormat>(EGLenum from)
+{
+    switch (from)
+    {
+        case EGL_NO_TEXTURE:
+            return TextureFormat::NoTexture;
+        case EGL_TEXTURE_RGB:
+            return TextureFormat::RGB;
+        case EGL_TEXTURE_RGBA:
+            return TextureFormat::RGBA;
+        default:
+            return TextureFormat::InvalidEnum;
+    }
+}
+
+EGLenum ToEGLenum(TextureFormat from)
+{
+    switch (from)
+    {
+        case TextureFormat::NoTexture:
+            return EGL_NO_TEXTURE;
+        case TextureFormat::RGB:
+            return EGL_TEXTURE_RGB;
+        case TextureFormat::RGBA:
+            return EGL_TEXTURE_RGBA;
+        default:
+            UNREACHABLE();
+            return 0;
+    }
+}
+
+}  // namespace egl
diff --git a/src/libANGLE/PackedEGLEnums_autogen.h b/src/libANGLE/PackedEGLEnums_autogen.h
new file mode 100644
index 0000000..4a58164
--- /dev/null
+++ b/src/libANGLE/PackedEGLEnums_autogen.h
@@ -0,0 +1,43 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_packed_gl_enums.py using data from packed_egl_enums.json.
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// PackedEGLEnums_autogen.h:
+//   Declares ANGLE-specific enums classes for EGLenums and functions operating
+//   on them.
+
+#ifndef LIBANGLE_PACKEDEGLENUMS_AUTOGEN_H_
+#define LIBANGLE_PACKEDEGLENUMS_AUTOGEN_H_
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <angle_gl.h>
+
+#include <cstdint>
+
+namespace egl
+{
+
+template <typename Enum>
+Enum FromEGLenum(EGLenum from);
+
+enum class TextureFormat : uint8_t
+{
+    NoTexture = 0,
+    RGB       = 1,
+    RGBA      = 2,
+
+    InvalidEnum = 3,
+    EnumCount   = 3,
+};
+
+template <>
+TextureFormat FromEGLenum<TextureFormat>(EGLenum from);
+EGLenum ToEGLenum(TextureFormat from);
+
+}  // namespace egl
+
+#endif  // LIBANGLE_PACKEDEGLENUMS_AUTOGEN_H_
diff --git a/src/libANGLE/PackedGLEnums.cpp b/src/libANGLE/PackedEnums.cpp
similarity index 99%
rename from src/libANGLE/PackedGLEnums.cpp
rename to src/libANGLE/PackedEnums.cpp
index 675a05d..87cf4fd 100644
--- a/src/libANGLE/PackedGLEnums.cpp
+++ b/src/libANGLE/PackedEnums.cpp
@@ -6,7 +6,7 @@
 //   Declares ANGLE-specific enums classes for GLEnum and functions operating
 //   on them.
 
-#include "libANGLE/PackedGLEnums.h"
+#include "libANGLE/PackedEnums.h"
 
 #include "common/utilities.h"
 
diff --git a/src/libANGLE/PackedGLEnums.h b/src/libANGLE/PackedEnums.h
similarity index 92%
rename from src/libANGLE/PackedGLEnums.h
rename to src/libANGLE/PackedEnums.h
index 3559845..31d9c47 100644
--- a/src/libANGLE/PackedGLEnums.h
+++ b/src/libANGLE/PackedEnums.h
@@ -9,6 +9,7 @@
 #ifndef LIBANGLE_PACKEDGLENUMS_H_
 #define LIBANGLE_PACKEDGLENUMS_H_
 
+#include "libANGLE/PackedEGLEnums_autogen.h"
 #include "libANGLE/PackedGLEnums_autogen.h"
 
 #include <array>
@@ -70,8 +71,8 @@
 class PackedEnumMap
 {
   private:
-    using UnderlyingType          = typename std::underlying_type<E>::type;
-    using Storage                 = std::array<T, EnumSize<E>()>;
+    using UnderlyingType = typename std::underlying_type<E>::type;
+    using Storage        = std::array<T, EnumSize<E>()>;
 
     Storage mData;
 
@@ -172,8 +173,16 @@
     angle::EnumIterator<ShaderType> end() const { return kAfterShaderTypeMax; }
 };
 
+constexpr size_t kGraphicsShaderCount = static_cast<size_t>(ShaderType::EnumCount) - 1u;
+// Arrange the shader types in the order of rendering pipeline
+constexpr std::array<ShaderType, kGraphicsShaderCount> kAllGraphicsShaderTypes = {
+    ShaderType::Vertex, ShaderType::Geometry, ShaderType::Fragment};
+
 using ShaderBitSet = angle::PackedEnumBitSet<ShaderType>;
 
+template <typename T>
+using ShaderMap = angle::PackedEnumMap<ShaderType, T>;
+
 TextureType SamplerTypeToTextureType(GLenum samplerType);
 
 }  // namespace gl
diff --git a/src/libANGLE/PackedGLEnums_autogen.cpp b/src/libANGLE/PackedGLEnums_autogen.cpp
index 81f2c8d..23af4ab 100644
--- a/src/libANGLE/PackedGLEnums_autogen.cpp
+++ b/src/libANGLE/PackedGLEnums_autogen.cpp
@@ -6,7 +6,7 @@
 // found in the LICENSE file.
 //
 // PackedGLEnums_autogen.cpp:
-//   Implements ANGLE-specific enums classes for GLEnum and functions operating
+//   Implements ANGLE-specific enums classes for GLenums and functions operating
 //   on them.
 
 #include "libANGLE/PackedGLEnums_autogen.h"
@@ -63,7 +63,7 @@
             return GL_NOTEQUAL;
         default:
             UNREACHABLE();
-            return GL_NONE;
+            return 0;
     }
 }
 
@@ -131,7 +131,7 @@
             return GL_UNIFORM_BUFFER;
         default:
             UNREACHABLE();
-            return GL_NONE;
+            return 0;
     }
 }
 
@@ -187,7 +187,47 @@
             return GL_STREAM_READ;
         default:
             UNREACHABLE();
-            return GL_NONE;
+            return 0;
+    }
+}
+
+template <>
+ClientVertexArrayType FromGLenum<ClientVertexArrayType>(GLenum from)
+{
+    switch (from)
+    {
+        case GL_COLOR_ARRAY:
+            return ClientVertexArrayType::Color;
+        case GL_NORMAL_ARRAY:
+            return ClientVertexArrayType::Normal;
+        case GL_POINT_SIZE_ARRAY_OES:
+            return ClientVertexArrayType::PointSize;
+        case GL_TEXTURE_COORD_ARRAY:
+            return ClientVertexArrayType::TextureCoord;
+        case GL_VERTEX_ARRAY:
+            return ClientVertexArrayType::Vertex;
+        default:
+            return ClientVertexArrayType::InvalidEnum;
+    }
+}
+
+GLenum ToGLenum(ClientVertexArrayType from)
+{
+    switch (from)
+    {
+        case ClientVertexArrayType::Color:
+            return GL_COLOR_ARRAY;
+        case ClientVertexArrayType::Normal:
+            return GL_NORMAL_ARRAY;
+        case ClientVertexArrayType::PointSize:
+            return GL_POINT_SIZE_ARRAY_OES;
+        case ClientVertexArrayType::TextureCoord:
+            return GL_TEXTURE_COORD_ARRAY;
+        case ClientVertexArrayType::Vertex:
+            return GL_VERTEX_ARRAY;
+        default:
+            UNREACHABLE();
+            return 0;
     }
 }
 
@@ -219,7 +259,7 @@
             return GL_FRONT_AND_BACK;
         default:
             UNREACHABLE();
-            return GL_NONE;
+            return 0;
     }
 }
 
@@ -251,7 +291,7 @@
             return GL_LINEAR;
         default:
             UNREACHABLE();
-            return GL_NONE;
+            return 0;
     }
 }
 
@@ -283,7 +323,7 @@
             return GL_NICEST;
         default:
             UNREACHABLE();
-            return GL_NONE;
+            return 0;
     }
 }
 
@@ -367,7 +407,7 @@
             return GL_XOR;
         default:
             UNREACHABLE();
-            return GL_NONE;
+            return 0;
     }
 }
 
@@ -399,7 +439,7 @@
             return GL_TEXTURE;
         default:
             UNREACHABLE();
-            return GL_NONE;
+            return 0;
     }
 }
 
@@ -435,7 +475,7 @@
             return GL_COMPUTE_SHADER;
         default:
             UNREACHABLE();
-            return GL_NONE;
+            return 0;
     }
 }
 
@@ -463,7 +503,7 @@
             return GL_SMOOTH;
         default:
             UNREACHABLE();
-            return GL_NONE;
+            return 0;
     }
 }
 
@@ -515,7 +555,7 @@
             return GL_SUBTRACT;
         default:
             UNREACHABLE();
-            return GL_NONE;
+            return 0;
     }
 }
 
@@ -559,7 +599,7 @@
             return GL_REPLACE;
         default:
             UNREACHABLE();
-            return GL_NONE;
+            return 0;
     }
 }
 
@@ -595,7 +635,7 @@
             return GL_SRC_COLOR;
         default:
             UNREACHABLE();
-            return GL_NONE;
+            return 0;
     }
 }
 
@@ -631,7 +671,7 @@
             return GL_TEXTURE;
         default:
             UNREACHABLE();
-            return GL_NONE;
+            return 0;
     }
 }
 
@@ -699,7 +739,7 @@
             return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
         default:
             UNREACHABLE();
-            return GL_NONE;
+            return 0;
     }
 }
 
@@ -747,7 +787,7 @@
             return GL_TEXTURE_CUBE_MAP;
         default:
             UNREACHABLE();
-            return GL_NONE;
+            return 0;
     }
 }
 
@@ -787,7 +827,7 @@
             return GL_VERTEX_ARRAY;
         default:
             UNREACHABLE();
-            return GL_NONE;
+            return 0;
     }
 }
 
diff --git a/src/libANGLE/PackedGLEnums_autogen.h b/src/libANGLE/PackedGLEnums_autogen.h
index 79d263a..6be0597 100644
--- a/src/libANGLE/PackedGLEnums_autogen.h
+++ b/src/libANGLE/PackedGLEnums_autogen.h
@@ -6,12 +6,14 @@
 // found in the LICENSE file.
 //
 // PackedGLEnums_autogen.h:
-//   Declares ANGLE-specific enums classes for GLEnum and functions operating
+//   Declares ANGLE-specific enums classes for GLenums and functions operating
 //   on them.
 
 #ifndef LIBANGLE_PACKEDGLENUMS_AUTOGEN_H_
 #define LIBANGLE_PACKEDGLENUMS_AUTOGEN_H_
 
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
 #include <angle_gl.h>
 
 #include <cstdint>
@@ -84,6 +86,22 @@
 BufferUsage FromGLenum<BufferUsage>(GLenum from);
 GLenum ToGLenum(BufferUsage from);
 
+enum class ClientVertexArrayType : uint8_t
+{
+    Color        = 0,
+    Normal       = 1,
+    PointSize    = 2,
+    TextureCoord = 3,
+    Vertex       = 4,
+
+    InvalidEnum = 5,
+    EnumCount   = 5,
+};
+
+template <>
+ClientVertexArrayType FromGLenum<ClientVertexArrayType>(GLenum from);
+GLenum ToGLenum(ClientVertexArrayType from);
+
 enum class CullFaceMode : uint8_t
 {
     Back         = 0,
diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp
index df8fa6d..52dddc9 100644
--- a/src/libANGLE/Program.cpp
+++ b/src/libANGLE/Program.cpp
@@ -205,9 +205,60 @@
     return false;
 }
 
+std::string GetInterfaceBlockLimitName(ShaderType shaderType, sh::BlockType blockType)
+{
+    std::ostringstream stream;
+    stream << "GL_MAX_" << GetShaderTypeString(shaderType) << "_";
+
+    switch (blockType)
+    {
+        case sh::BlockType::BLOCK_UNIFORM:
+            stream << "UNIFORM_BUFFERS";
+            break;
+        case sh::BlockType::BLOCK_BUFFER:
+            stream << "SHADER_STORAGE_BLOCKS";
+            break;
+        default:
+            UNREACHABLE();
+            return "";
+    }
+
+    if (shaderType == ShaderType::Geometry)
+    {
+        stream << "_EXT";
+    }
+
+    return stream.str();
+}
+
+const char *GetInterfaceBlockTypeString(sh::BlockType blockType)
+{
+    switch (blockType)
+    {
+        case sh::BlockType::BLOCK_UNIFORM:
+            return "uniform block";
+        case sh::BlockType::BLOCK_BUFFER:
+            return "shader storage block";
+        default:
+            UNREACHABLE();
+            return "";
+    }
+}
+
+void LogInterfaceBlocksExceedLimit(InfoLog &infoLog,
+                                   ShaderType shaderType,
+                                   sh::BlockType blockType,
+                                   GLuint limit)
+{
+    infoLog << GetShaderTypeString(shaderType) << " shader "
+            << GetInterfaceBlockTypeString(blockType) << " count exceeds "
+            << GetInterfaceBlockLimitName(shaderType, blockType) << " (" << limit << ")";
+}
+
 bool ValidateInterfaceBlocksCount(GLuint maxInterfaceBlocks,
                                   const std::vector<sh::InterfaceBlock> &interfaceBlocks,
-                                  const std::string &errorMessage,
+                                  ShaderType shaderType,
+                                  sh::BlockType blockType,
                                   InfoLog &infoLog)
 {
     GLuint blockCount = 0;
@@ -218,7 +269,7 @@
             blockCount += (block.arraySize ? block.arraySize : 1);
             if (blockCount > maxInterfaceBlocks)
             {
-                infoLog << errorMessage << maxInterfaceBlocks << ")";
+                LogInterfaceBlocksExceedLimit(infoLog, shaderType, blockType, maxInterfaceBlocks);
                 return false;
             }
         }
@@ -440,44 +491,57 @@
     return LinkMismatchError::NO_MISMATCH;
 }
 
-bool ValidateGraphicsInterfaceBlocks(const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks,
-                                     const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks,
-                                     InfoLog &infoLog,
-                                     bool webglCompatibility,
-                                     sh::BlockType blockType,
-                                     GLuint maxCombinedInterfaceBlocks)
-{
-    // Check that interface blocks defined in the vertex and fragment shaders are identical
-    typedef std::map<std::string, const sh::InterfaceBlock *> InterfaceBlockMap;
-    InterfaceBlockMap linkedInterfaceBlocks;
-    GLuint blockCount = 0;
+using ShaderInterfaceBlock = std::pair<ShaderType, const sh::InterfaceBlock *>;
+using InterfaceBlockMap    = std::map<std::string, ShaderInterfaceBlock>;
 
-    for (const sh::InterfaceBlock &vertexInterfaceBlock : vertexInterfaceBlocks)
+void InitializeInterfaceBlockMap(const std::vector<sh::InterfaceBlock> &interfaceBlocks,
+                                 ShaderType shaderType,
+                                 InterfaceBlockMap *linkedInterfaceBlocks,
+                                 GLuint *blockCount)
+{
+    ASSERT(linkedInterfaceBlocks && blockCount);
+
+    for (const sh::InterfaceBlock &interfaceBlock : interfaceBlocks)
     {
-        linkedInterfaceBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock;
-        if (IsActiveInterfaceBlock(vertexInterfaceBlock))
+        (*linkedInterfaceBlocks)[interfaceBlock.name] = std::make_pair(shaderType, &interfaceBlock);
+        if (IsActiveInterfaceBlock(interfaceBlock))
         {
-            blockCount += std::max(vertexInterfaceBlock.arraySize, 1u);
+            *blockCount += std::max(interfaceBlock.arraySize, 1u);
         }
     }
+}
 
-    for (const sh::InterfaceBlock &fragmentInterfaceBlock : fragmentInterfaceBlocks)
+bool ValidateGraphicsInterfaceBlocksPerShader(
+    const std::vector<sh::InterfaceBlock> &interfaceBlocksToLink,
+    ShaderType shaderType,
+    bool webglCompatibility,
+    InterfaceBlockMap *linkedBlocks,
+    GLuint *combinedInterfaceBlockCount,
+    InfoLog &infoLog)
+{
+    ASSERT(linkedBlocks && combinedInterfaceBlockCount);
+
+    for (const sh::InterfaceBlock &block : interfaceBlocksToLink)
     {
-        auto entry = linkedInterfaceBlocks.find(fragmentInterfaceBlock.name);
-        if (entry != linkedInterfaceBlocks.end())
+        const auto &entry = linkedBlocks->find(block.name);
+        if (entry != linkedBlocks->end())
         {
-            const sh::InterfaceBlock &vertexInterfaceBlock = *(entry->second);
-            std::string mismatchedBlockFieldName;
-            LinkMismatchError linkError =
-                AreMatchingInterfaceBlocks(vertexInterfaceBlock, fragmentInterfaceBlock,
-                                           webglCompatibility, &mismatchedBlockFieldName);
+            const sh::InterfaceBlock &linkedBlock = *(entry->second.second);
+            std::string mismatchedStructFieldName;
+            LinkMismatchError linkError = AreMatchingInterfaceBlocks(
+                block, linkedBlock, webglCompatibility, &mismatchedStructFieldName);
             if (linkError != LinkMismatchError::NO_MISMATCH)
             {
-                LogLinkMismatch(infoLog, fragmentInterfaceBlock.name, "interface block", linkError,
-                                mismatchedBlockFieldName, ShaderType::Vertex, ShaderType::Fragment);
+                LogLinkMismatch(infoLog, block.name, GetInterfaceBlockTypeString(block.blockType),
+                                linkError, mismatchedStructFieldName, entry->second.first,
+                                shaderType);
                 return false;
             }
         }
+        else
+        {
+            (*linkedBlocks)[block.name] = std::make_pair(shaderType, &block);
+        }
 
         // [OpenGL ES 3.1] Chapter 7.6.2 Page 105:
         // If a uniform block is used by multiple shader stages, each such use counts separately
@@ -485,9 +549,46 @@
         // [OpenGL ES 3.1] Chapter 7.8 Page 111:
         // If a shader storage block in a program is referenced by multiple shaders, each such
         // reference counts separately against this combined limit.
-        if (IsActiveInterfaceBlock(fragmentInterfaceBlock))
+        if (IsActiveInterfaceBlock(block))
         {
-            blockCount += std::max(fragmentInterfaceBlock.arraySize, 1u);
+            *combinedInterfaceBlockCount += std::max(block.arraySize, 1u);
+        }
+    }
+
+    return true;
+}
+
+bool ValidateGraphicsInterfaceBlocks(
+    const ShaderMap<const std::vector<sh::InterfaceBlock> *> &shaderInterfaceBlocks,
+    InfoLog &infoLog,
+    bool webglCompatibility,
+    sh::BlockType blockType,
+    GLuint maxCombinedInterfaceBlocks)
+{
+    // Check that interface blocks defined in the graphics shaders are identical
+
+    InterfaceBlockMap linkedInterfaceBlocks;
+    GLuint blockCount = 0u;
+
+    bool interfaceBlockMapInitialized = false;
+    for (ShaderType shaderType : kAllGraphicsShaderTypes)
+    {
+        if (!shaderInterfaceBlocks[shaderType])
+        {
+            continue;
+        }
+
+        if (!interfaceBlockMapInitialized)
+        {
+            InitializeInterfaceBlockMap(*shaderInterfaceBlocks[shaderType], shaderType,
+                                        &linkedInterfaceBlocks, &blockCount);
+            interfaceBlockMapInitialized = true;
+        }
+        else if (!ValidateGraphicsInterfaceBlocksPerShader(
+                     *shaderInterfaceBlocks[shaderType], shaderType, webglCompatibility,
+                     &linkedInterfaceBlocks, &blockCount, infoLog))
+        {
+            return false;
         }
     }
 
@@ -700,10 +801,7 @@
 // ProgramState implementation.
 ProgramState::ProgramState()
     : mLabel(),
-      mAttachedFragmentShader(nullptr),
-      mAttachedVertexShader(nullptr),
-      mAttachedComputeShader(nullptr),
-      mAttachedGeometryShader(nullptr),
+      mAttachedShaders({}),
       mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
       mMaxActiveAttribLocation(0),
       mSamplerUniformRange(0, 0),
@@ -722,8 +820,7 @@
 
 ProgramState::~ProgramState()
 {
-    ASSERT(!mAttachedVertexShader && !mAttachedFragmentShader && !mAttachedComputeShader &&
-           !mAttachedGeometryShader);
+    ASSERT(!hasAttachedShader());
 }
 
 const std::string &ProgramState::getLabel()
@@ -733,20 +830,8 @@
 
 Shader *ProgramState::getAttachedShader(ShaderType shaderType) const
 {
-    switch (shaderType)
-    {
-        case ShaderType::Vertex:
-            return mAttachedVertexShader;
-        case ShaderType::Fragment:
-            return mAttachedFragmentShader;
-        case ShaderType::Compute:
-            return mAttachedComputeShader;
-        case ShaderType::Geometry:
-            return mAttachedGeometryShader;
-        default:
-            UNREACHABLE();
-            return nullptr;
-    }
+    ASSERT(shaderType != ShaderType::InvalidEnum);
+    return mAttachedShaders[shaderType];
 }
 
 GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
@@ -800,6 +885,18 @@
     return static_cast<GLuint>(-1);
 }
 
+bool ProgramState::hasAttachedShader() const
+{
+    for (const Shader *shader : mAttachedShaders)
+    {
+        if (shader)
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
 Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, GLuint handle)
     : mProgram(factory->createProgram(mState)),
       mValidated(false),
@@ -821,35 +918,19 @@
 
 void Program::onDestroy(const Context *context)
 {
-    if (mState.mAttachedVertexShader != nullptr)
+    for (ShaderType shaderType : AllShaderTypes())
     {
-        mState.mAttachedVertexShader->release(context);
-        mState.mAttachedVertexShader = nullptr;
-    }
-
-    if (mState.mAttachedFragmentShader != nullptr)
-    {
-        mState.mAttachedFragmentShader->release(context);
-        mState.mAttachedFragmentShader = nullptr;
-    }
-
-    if (mState.mAttachedComputeShader != nullptr)
-    {
-        mState.mAttachedComputeShader->release(context);
-        mState.mAttachedComputeShader = nullptr;
-    }
-
-    if (mState.mAttachedGeometryShader != nullptr)
-    {
-        mState.mAttachedGeometryShader->release(context);
-        mState.mAttachedGeometryShader = nullptr;
+        if (mState.mAttachedShaders[shaderType])
+        {
+            mState.mAttachedShaders[shaderType]->release(context);
+            mState.mAttachedShaders[shaderType] = nullptr;
+        }
     }
 
     // TODO(jmadill): Handle error in the Context.
     ANGLE_SWALLOW_ERR(mProgram->destroy(context));
 
-    ASSERT(!mState.mAttachedVertexShader && !mState.mAttachedFragmentShader &&
-           !mState.mAttachedComputeShader && !mState.mAttachedGeometryShader);
+    ASSERT(!mState.hasAttachedShader());
     SafeDelete(mProgram);
 
     delete this;
@@ -867,82 +948,35 @@
 
 void Program::attachShader(Shader *shader)
 {
-    switch (shader->getType())
-    {
-        case ShaderType::Vertex:
-        {
-            ASSERT(!mState.mAttachedVertexShader);
-            mState.mAttachedVertexShader = shader;
-            mState.mAttachedVertexShader->addRef();
-            break;
-        }
-        case ShaderType::Fragment:
-        {
-            ASSERT(!mState.mAttachedFragmentShader);
-            mState.mAttachedFragmentShader = shader;
-            mState.mAttachedFragmentShader->addRef();
-            break;
-        }
-        case ShaderType::Compute:
-        {
-            ASSERT(!mState.mAttachedComputeShader);
-            mState.mAttachedComputeShader = shader;
-            mState.mAttachedComputeShader->addRef();
-            break;
-        }
-        case ShaderType::Geometry:
-        {
-            ASSERT(!mState.mAttachedGeometryShader);
-            mState.mAttachedGeometryShader = shader;
-            mState.mAttachedGeometryShader->addRef();
-            break;
-        }
-        default:
-            UNREACHABLE();
-    }
+    ShaderType shaderType = shader->getType();
+    ASSERT(shaderType != ShaderType::InvalidEnum);
+
+    mState.mAttachedShaders[shaderType] = shader;
+    mState.mAttachedShaders[shaderType]->addRef();
 }
 
 void Program::detachShader(const Context *context, Shader *shader)
 {
-    switch (shader->getType())
-    {
-        case ShaderType::Vertex:
-        {
-            ASSERT(mState.mAttachedVertexShader == shader);
-            shader->release(context);
-            mState.mAttachedVertexShader = nullptr;
-            break;
-        }
-        case ShaderType::Fragment:
-        {
-            ASSERT(mState.mAttachedFragmentShader == shader);
-            shader->release(context);
-            mState.mAttachedFragmentShader = nullptr;
-            break;
-        }
-        case ShaderType::Compute:
-        {
-            ASSERT(mState.mAttachedComputeShader == shader);
-            shader->release(context);
-            mState.mAttachedComputeShader = nullptr;
-            break;
-        }
-        case ShaderType::Geometry:
-        {
-            ASSERT(mState.mAttachedGeometryShader == shader);
-            shader->release(context);
-            mState.mAttachedGeometryShader = nullptr;
-            break;
-        }
-        default:
-            UNREACHABLE();
-    }
+    ShaderType shaderType = shader->getType();
+    ASSERT(shaderType != ShaderType::InvalidEnum);
+
+    ASSERT(mState.mAttachedShaders[shaderType] == shader);
+    shader->release(context);
+    mState.mAttachedShaders[shaderType] = nullptr;
 }
 
 int Program::getAttachedShadersCount() const
 {
-    return (mState.mAttachedVertexShader ? 1 : 0) + (mState.mAttachedFragmentShader ? 1 : 0) +
-           (mState.mAttachedComputeShader ? 1 : 0) + (mState.mAttachedGeometryShader ? 1 : 0);
+    int numAttachedShaders = 0;
+    for (const Shader *shader : mState.mAttachedShaders)
+    {
+        if (shader)
+        {
+            ++numAttachedShaders;
+        }
+    }
+
+    return numAttachedShaders;
 }
 
 const Shader *Program::getAttachedShader(ShaderType shaderType) const
@@ -1079,7 +1113,7 @@
     // Re-link shaders after the unlink call.
     ASSERT(linkValidateShaders(context, mInfoLog));
 
-    if (mState.mAttachedComputeShader)
+    if (mState.mAttachedShaders[ShaderType::Compute])
     {
         if (!linkUniforms(context, mInfoLog, mUniformLocationBindings))
         {
@@ -1135,8 +1169,8 @@
 
         const auto &mergedVaryings = getMergedVaryings(context);
 
-        ASSERT(mState.mAttachedVertexShader);
-        mState.mNumViews = mState.mAttachedVertexShader->getNumViews(context);
+        ASSERT(mState.mAttachedShaders[ShaderType::Vertex]);
+        mState.mNumViews = mState.mAttachedShaders[ShaderType::Vertex]->getNumViews(context);
 
         linkOutputVariables(context);
 
@@ -1212,24 +1246,12 @@
 {
     mState.mLinkedShaderStages.reset();
 
-    if (mState.mAttachedVertexShader)
+    for (const Shader *shader : mState.mAttachedShaders)
     {
-        mState.mLinkedShaderStages.set(ShaderType::Vertex);
-    }
-
-    if (mState.mAttachedFragmentShader)
-    {
-        mState.mLinkedShaderStages.set(ShaderType::Fragment);
-    }
-
-    if (mState.mAttachedComputeShader)
-    {
-        mState.mLinkedShaderStages.set(ShaderType::Compute);
-    }
-
-    if (mState.mAttachedGeometryShader)
-    {
-        mState.mLinkedShaderStages.set(ShaderType::Geometry);
+        if (shader)
+        {
+            mState.mLinkedShaderStages.set(shader->getType());
+        }
     }
 }
 
@@ -1451,39 +1473,12 @@
 {
     int total = 0;
 
-    if (mState.mAttachedComputeShader)
+    for (const Shader *shader : mState.mAttachedShaders)
     {
-        if (total < maxCount)
+        if (shader && (total < maxCount))
         {
-            shaders[total] = mState.mAttachedComputeShader->getHandle();
-            total++;
-        }
-    }
-
-    if (mState.mAttachedVertexShader)
-    {
-        if (total < maxCount)
-        {
-            shaders[total] = mState.mAttachedVertexShader->getHandle();
-            total++;
-        }
-    }
-
-    if (mState.mAttachedFragmentShader)
-    {
-        if (total < maxCount)
-        {
-            shaders[total] = mState.mAttachedFragmentShader->getHandle();
-            total++;
-        }
-    }
-
-    if (mState.mAttachedGeometryShader)
-    {
-        if (total < maxCount)
-        {
-            shaders[total] = mState.mAttachedGeometryShader->getHandle();
-            total++;
+            shaders[total] = shader->getHandle();
+            ++total;
         }
     }
 
@@ -2261,10 +2256,10 @@
 
 bool Program::linkValidateShaders(const Context *context, InfoLog &infoLog)
 {
-    Shader *vertexShader   = mState.mAttachedVertexShader;
-    Shader *fragmentShader = mState.mAttachedFragmentShader;
-    Shader *computeShader  = mState.mAttachedComputeShader;
-    Shader *geometryShader = mState.mAttachedGeometryShader;
+    Shader *vertexShader   = mState.mAttachedShaders[ShaderType::Vertex];
+    Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
+    Shader *computeShader  = mState.mAttachedShaders[ShaderType::Compute];
+    Shader *geometryShader = mState.mAttachedShaders[ShaderType::Geometry];
 
     bool isComputeShaderAttached  = (computeShader != nullptr);
     bool isGraphicsShaderAttached =
@@ -2400,22 +2395,24 @@
 
 bool Program::linkVaryings(const Context *context, InfoLog &infoLog) const
 {
-    std::vector<Shader *> activeShaders;
-    activeShaders.push_back(mState.mAttachedVertexShader);
-    if (mState.mAttachedGeometryShader)
+    Shader *previousShader = nullptr;
+    for (ShaderType shaderType : kAllGraphicsShaderTypes)
     {
-        activeShaders.push_back(mState.mAttachedGeometryShader);
-    }
-    activeShaders.push_back(mState.mAttachedFragmentShader);
-
-    const size_t activeShaderCount = activeShaders.size();
-    for (size_t shaderIndex = 0; shaderIndex < activeShaderCount - 1; ++shaderIndex)
-    {
-        if (!linkValidateShaderInterfaceMatching(context, activeShaders[shaderIndex],
-                                                 activeShaders[shaderIndex + 1], infoLog))
+        Shader *currentShader = mState.mAttachedShaders[shaderType];
+        if (!currentShader)
         {
-            return false;
+            continue;
         }
+
+        if (previousShader)
+        {
+            if (!linkValidateShaderInterfaceMatching(context, previousShader, currentShader,
+                                                     infoLog))
+            {
+                return false;
+            }
+        }
+        previousShader = currentShader;
     }
 
     if (!linkValidateBuiltInVaryings(context, infoLog))
@@ -2498,12 +2495,12 @@
 
 bool Program::linkValidateFragmentInputBindings(const Context *context, gl::InfoLog &infoLog) const
 {
-    ASSERT(mState.mAttachedFragmentShader);
+    ASSERT(mState.mAttachedShaders[ShaderType::Fragment]);
 
     std::map<GLuint, std::string> staticFragmentInputLocations;
 
     const std::vector<sh::Varying> &fragmentInputVaryings =
-        mState.mAttachedFragmentShader->getInputVaryings(context);
+        mState.mAttachedShaders[ShaderType::Fragment]->getInputVaryings(context);
     for (const sh::Varying &input : fragmentInputVaryings)
     {
         if (input.isBuiltIn() || !input.staticUse)
@@ -2812,69 +2809,55 @@
 {
     const auto &caps = context->getCaps();
 
-    if (mState.mAttachedComputeShader)
+    if (mState.mAttachedShaders[ShaderType::Compute])
     {
-        Shader &computeShader              = *mState.mAttachedComputeShader;
+        Shader &computeShader              = *mState.mAttachedShaders[ShaderType::Compute];
         const auto &computeUniformBlocks   = computeShader.getUniformBlocks(context);
 
-        if (!ValidateInterfaceBlocksCount(
-                caps.maxComputeUniformBlocks, computeUniformBlocks,
-                "Compute shader uniform block count exceeds GL_MAX_COMPUTE_UNIFORM_BLOCKS (",
-                infoLog))
+        if (!ValidateInterfaceBlocksCount(caps.maxComputeUniformBlocks, computeUniformBlocks,
+                                          ShaderType::Compute, sh::BlockType::BLOCK_UNIFORM,
+                                          infoLog))
         {
             return false;
         }
 
         const auto &computeShaderStorageBlocks = computeShader.getShaderStorageBlocks(context);
         if (!ValidateInterfaceBlocksCount(caps.maxComputeShaderStorageBlocks,
-                                          computeShaderStorageBlocks,
-                                          "Compute shader shader storage block count exceeds "
-                                          "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS (",
-                                          infoLog))
+                                          computeShaderStorageBlocks, ShaderType::Compute,
+                                          sh::BlockType::BLOCK_BUFFER, infoLog))
         {
             return false;
         }
         return true;
     }
 
-    Shader &vertexShader   = *mState.mAttachedVertexShader;
-    Shader &fragmentShader = *mState.mAttachedFragmentShader;
+    ShaderMap<GLuint> maxShaderUniformBlocks         = {};
+    maxShaderUniformBlocks[gl::ShaderType::Vertex]   = caps.maxVertexUniformBlocks;
+    maxShaderUniformBlocks[gl::ShaderType::Fragment] = caps.maxFragmentUniformBlocks;
+    maxShaderUniformBlocks[gl::ShaderType::Geometry] = caps.maxGeometryUniformBlocks;
 
-    const auto &vertexUniformBlocks   = vertexShader.getUniformBlocks(context);
-    const auto &fragmentUniformBlocks = fragmentShader.getUniformBlocks(context);
-
-    if (!ValidateInterfaceBlocksCount(
-            caps.maxVertexUniformBlocks, vertexUniformBlocks,
-            "Vertex shader uniform block count exceeds GL_MAX_VERTEX_UNIFORM_BLOCKS (", infoLog))
+    ShaderMap<const std::vector<sh::InterfaceBlock> *> graphicsShaderUniformBlocks = {};
+    for (ShaderType shaderType : kAllGraphicsShaderTypes)
     {
-        return false;
-    }
-    if (!ValidateInterfaceBlocksCount(
-            caps.maxFragmentUniformBlocks, fragmentUniformBlocks,
-            "Fragment shader uniform block count exceeds GL_MAX_FRAGMENT_UNIFORM_BLOCKS (",
-            infoLog))
-    {
+        Shader *shader = mState.mAttachedShaders[shaderType];
+        if (!shader)
+        {
+            continue;
+        }
 
-        return false;
-    }
-
-    Shader *geometryShader = mState.mAttachedGeometryShader;
-    if (geometryShader)
-    {
-        const auto &geometryUniformBlocks = geometryShader->getUniformBlocks(context);
-        if (!ValidateInterfaceBlocksCount(
-                caps.maxGeometryUniformBlocks, geometryUniformBlocks,
-                "Geometry shader uniform block count exceeds GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT (",
-                infoLog))
+        const auto &uniformBlocks = mState.mAttachedShaders[shaderType]->getUniformBlocks(context);
+        if (!ValidateInterfaceBlocksCount(maxShaderUniformBlocks[shaderType], uniformBlocks,
+                                          shaderType, sh::BlockType::BLOCK_UNIFORM, infoLog))
         {
             return false;
         }
+
+        graphicsShaderUniformBlocks[shaderType] = &uniformBlocks;
     }
 
-    // TODO(jiawei.shao@intel.com): validate geometry shader uniform blocks.
     bool webglCompatibility = context->getExtensions().webglCompatibility;
-    if (!ValidateGraphicsInterfaceBlocks(vertexUniformBlocks, fragmentUniformBlocks, infoLog,
-                                         webglCompatibility, sh::BlockType::BLOCK_UNIFORM,
+    if (!ValidateGraphicsInterfaceBlocks(graphicsShaderUniformBlocks, infoLog, webglCompatibility,
+                                         sh::BlockType::BLOCK_UNIFORM,
                                          caps.maxCombinedUniformBlocks))
     {
         return false;
@@ -2882,45 +2865,34 @@
 
     if (context->getClientVersion() >= Version(3, 1))
     {
-        const auto &vertexShaderStorageBlocks   = vertexShader.getShaderStorageBlocks(context);
-        const auto &fragmentShaderStorageBlocks = fragmentShader.getShaderStorageBlocks(context);
+        ShaderMap<GLuint> maxShaderStorageBlocks     = {};
+        maxShaderStorageBlocks[ShaderType::Vertex]   = caps.maxVertexShaderStorageBlocks;
+        maxShaderStorageBlocks[ShaderType::Fragment] = caps.maxFragmentShaderStorageBlocks;
+        maxShaderStorageBlocks[ShaderType::Geometry] = caps.maxGeometryShaderStorageBlocks;
 
-        if (!ValidateInterfaceBlocksCount(caps.maxVertexShaderStorageBlocks,
-                                          vertexShaderStorageBlocks,
-                                          "Vertex shader shader storage block count exceeds "
-                                          "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS (",
-                                          infoLog))
+        ShaderMap<const std::vector<sh::InterfaceBlock> *> graphicsShaderStorageBlocks = {};
+        for (ShaderType shaderType : kAllGraphicsShaderTypes)
         {
-            return false;
-        }
-        if (!ValidateInterfaceBlocksCount(caps.maxFragmentShaderStorageBlocks,
-                                          fragmentShaderStorageBlocks,
-                                          "Fragment shader shader storage block count exceeds "
-                                          "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS (",
-                                          infoLog))
-        {
+            Shader *shader = mState.mAttachedShaders[shaderType];
+            if (!shader)
+            {
+                continue;
+            }
 
-            return false;
-        }
-
-        if (geometryShader)
-        {
-            const auto &geometryShaderStorageBlocks =
-                geometryShader->getShaderStorageBlocks(context);
-            if (!ValidateInterfaceBlocksCount(caps.maxGeometryShaderStorageBlocks,
-                                              geometryShaderStorageBlocks,
-                                              "Geometry shader shader storage block count exceeds "
-                                              "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT (",
-                                              infoLog))
+            const auto &shaderStorageBlocks = shader->getShaderStorageBlocks(context);
+            if (!ValidateInterfaceBlocksCount(maxShaderStorageBlocks[shaderType],
+                                              shaderStorageBlocks, shaderType,
+                                              sh::BlockType::BLOCK_BUFFER, infoLog))
             {
                 return false;
             }
+
+            graphicsShaderStorageBlocks[shaderType] = &shaderStorageBlocks;
         }
 
-        // TODO(jiawei.shao@intel.com): validate geometry shader shader storage blocks.
-        if (!ValidateGraphicsInterfaceBlocks(
-                vertexShaderStorageBlocks, fragmentShaderStorageBlocks, infoLog, webglCompatibility,
-                sh::BlockType::BLOCK_BUFFER, caps.maxCombinedShaderStorageBlocks))
+        if (!ValidateGraphicsInterfaceBlocks(graphicsShaderStorageBlocks, infoLog,
+                                             webglCompatibility, sh::BlockType::BLOCK_BUFFER,
+                                             caps.maxCombinedShaderStorageBlocks))
         {
             return false;
         }
@@ -3029,8 +3001,8 @@
 
 bool Program::linkValidateBuiltInVaryings(const Context *context, InfoLog &infoLog) const
 {
-    Shader *vertexShader         = mState.mAttachedVertexShader;
-    Shader *fragmentShader       = mState.mAttachedFragmentShader;
+    Shader *vertexShader         = mState.mAttachedShaders[ShaderType::Vertex];
+    Shader *fragmentShader       = mState.mAttachedShaders[ShaderType::Fragment];
     const auto &vertexVaryings   = vertexShader->getOutputVaryings(context);
     const auto &fragmentVaryings = fragmentShader->getInputVaryings(context);
     int shaderVersion            = vertexShader->getShaderVersion(context);
@@ -3215,36 +3187,21 @@
 
 bool Program::linkValidateGlobalNames(const Context *context, InfoLog &infoLog) const
 {
-    const std::vector<sh::Uniform> &vertexUniforms =
-        mState.mAttachedVertexShader->getUniforms(context);
-    const std::vector<sh::Uniform> &fragmentUniforms =
-        mState.mAttachedFragmentShader->getUniforms(context);
-    const std::vector<sh::Uniform> *geometryUniforms =
-        (mState.mAttachedGeometryShader) ? &mState.mAttachedGeometryShader->getUniforms(context)
-                                         : nullptr;
     const std::vector<sh::Attribute> &attributes =
-        mState.mAttachedVertexShader->getActiveAttributes(context);
+        mState.mAttachedShaders[ShaderType::Vertex]->getActiveAttributes(context);
+
     for (const auto &attrib : attributes)
     {
-        for (const auto &uniform : vertexUniforms)
+        for (ShaderType shaderType : kAllGraphicsShaderTypes)
         {
-            if (uniform.name == attrib.name)
+            Shader *shader = mState.mAttachedShaders[shaderType];
+            if (!shader)
             {
-                infoLog << "Name conflicts between a uniform and an attribute: " << attrib.name;
-                return false;
+                continue;
             }
-        }
-        for (const auto &uniform : fragmentUniforms)
-        {
-            if (uniform.name == attrib.name)
-            {
-                infoLog << "Name conflicts between a uniform and an attribute: " << attrib.name;
-                return false;
-            }
-        }
-        if (geometryUniforms)
-        {
-            for (const auto &uniform : *geometryUniforms)
+
+            const std::vector<sh::Uniform> &uniforms = shader->getUniforms(context);
+            for (const auto &uniform : uniforms)
             {
                 if (uniform.name == attrib.name)
                 {
@@ -3254,6 +3211,7 @@
             }
         }
     }
+
     return true;
 }
 
@@ -3297,12 +3255,14 @@
 {
     ProgramMergedVaryings merged;
 
-    for (const sh::Varying &varying : mState.mAttachedVertexShader->getOutputVaryings(context))
+    for (const sh::Varying &varying :
+         mState.mAttachedShaders[ShaderType::Vertex]->getOutputVaryings(context))
     {
         merged[varying.name].vertex = &varying;
     }
 
-    for (const sh::Varying &varying : mState.mAttachedFragmentShader->getInputVaryings(context))
+    for (const sh::Varying &varying :
+         mState.mAttachedShaders[ShaderType::Fragment]->getInputVaryings(context))
     {
         merged[varying.name].fragment = &varying;
     }
@@ -3312,7 +3272,7 @@
 
 void Program::linkOutputVariables(const Context *context)
 {
-    Shader *fragmentShader = mState.mAttachedFragmentShader;
+    Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
     ASSERT(fragmentShader != nullptr);
 
     ASSERT(mState.mOutputVariableTypes.empty());
diff --git a/src/libANGLE/Program.h b/src/libANGLE/Program.h
index 8f59c09..bc86a37 100644
--- a/src/libANGLE/Program.h
+++ b/src/libANGLE/Program.h
@@ -352,6 +352,8 @@
 
     const ShaderBitSet &getLinkedShaderStages() const { return mLinkedShaderStages; }
 
+    bool hasAttachedShader() const;
+
   private:
     friend class MemoryProgramCache;
     friend class Program;
@@ -362,10 +364,7 @@
 
     sh::WorkGroupSize mComputeShaderLocalSize;
 
-    Shader *mAttachedFragmentShader;
-    Shader *mAttachedVertexShader;
-    Shader *mAttachedComputeShader;
-    Shader *mAttachedGeometryShader;
+    ShaderMap<Shader *> mAttachedShaders;
 
     std::vector<std::string> mTransformFeedbackVaryingNames;
     std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings;
diff --git a/src/libANGLE/ProgramLinkedResources.cpp b/src/libANGLE/ProgramLinkedResources.cpp
index 9ef76b7..b2c2559 100644
--- a/src/libANGLE/ProgramLinkedResources.cpp
+++ b/src/libANGLE/ProgramLinkedResources.cpp
@@ -188,27 +188,29 @@
 {
     // Check that uniforms defined in the graphics shaders are identical
     std::map<std::string, ShaderUniform> linkedUniforms;
-    for (const sh::Uniform &vertexUniform :
-         mState.getAttachedShader(ShaderType::Vertex)->getUniforms(context))
-    {
-        linkedUniforms[vertexUniform.name] = std::make_pair(ShaderType::Vertex, &vertexUniform);
-    }
 
-    std::vector<Shader *> activeShadersToLink;
-    if (mState.getAttachedShader(ShaderType::Geometry))
+    for (ShaderType shaderType : kAllGraphicsShaderTypes)
     {
-        activeShadersToLink.push_back(mState.getAttachedShader(ShaderType::Geometry));
-    }
-    activeShadersToLink.push_back(mState.getAttachedShader(ShaderType::Fragment));
-
-    const size_t numActiveShadersToLink = activeShadersToLink.size();
-    for (size_t shaderIndex = 0; shaderIndex < numActiveShadersToLink; ++shaderIndex)
-    {
-        bool isLastShader = (shaderIndex == numActiveShadersToLink - 1);
-        if (!ValidateGraphicsUniformsPerShader(context, activeShadersToLink[shaderIndex],
-                                               !isLastShader, &linkedUniforms, infoLog))
+        Shader *currentShader = mState.getAttachedShader(shaderType);
+        if (currentShader)
         {
-            return false;
+            if (shaderType == ShaderType::Vertex)
+            {
+                for (const sh::Uniform &vertexUniform : currentShader->getUniforms(context))
+                {
+                    linkedUniforms[vertexUniform.name] =
+                        std::make_pair(ShaderType::Vertex, &vertexUniform);
+                }
+            }
+            else
+            {
+                bool isLastShader = (shaderType == ShaderType::Fragment);
+                if (!ValidateGraphicsUniformsPerShader(context, currentShader, !isLastShader,
+                                                       &linkedUniforms, infoLog))
+                {
+                    return false;
+                }
+            }
         }
     }
 
@@ -802,7 +804,7 @@
 
 // InterfaceBlockLinker implementation.
 InterfaceBlockLinker::InterfaceBlockLinker(std::vector<InterfaceBlock> *blocksOut)
-    : mBlocksOut(blocksOut)
+    : mShaderBlocks({}), mBlocksOut(blocksOut)
 {
 }
 
@@ -810,10 +812,10 @@
 {
 }
 
-void InterfaceBlockLinker::addShaderBlocks(ShaderType shader,
+void InterfaceBlockLinker::addShaderBlocks(ShaderType shaderType,
                                            const std::vector<sh::InterfaceBlock> *blocks)
 {
-    mShaderBlocks.push_back(std::make_pair(shader, blocks));
+    mShaderBlocks[shaderType] = blocks;
 }
 
 void InterfaceBlockLinker::linkBlocks(const GetBlockSize &getBlockSize,
@@ -823,11 +825,14 @@
 
     std::set<std::string> visitedList;
 
-    for (const auto &shaderBlocks : mShaderBlocks)
+    for (ShaderType shaderType : AllShaderTypes())
     {
-        const ShaderType shaderType = shaderBlocks.first;
+        if (!mShaderBlocks[shaderType])
+        {
+            continue;
+        }
 
-        for (const auto &block : *shaderBlocks.second)
+        for (const auto &block : *mShaderBlocks[shaderType])
         {
             if (!IsActiveInterfaceBlock(block))
                 continue;
diff --git a/src/libANGLE/ProgramLinkedResources.h b/src/libANGLE/ProgramLinkedResources.h
index ce6d7b5..f359f5f 100644
--- a/src/libANGLE/ProgramLinkedResources.h
+++ b/src/libANGLE/ProgramLinkedResources.h
@@ -13,7 +13,7 @@
 
 #include "angle_gl.h"
 #include "common/angleutils.h"
-#include "libANGLE/PackedGLEnums_autogen.h"
+#include "libANGLE/PackedEnums.h"
 #include "libANGLE/VaryingPacking.h"
 
 #include <functional>
@@ -234,8 +234,7 @@
                                              ShaderType shaderType,
                                              bool active) const                 = 0;
 
-    using ShaderBlocks = std::pair<ShaderType, const std::vector<sh::InterfaceBlock> *>;
-    std::vector<ShaderBlocks> mShaderBlocks;
+    ShaderMap<const std::vector<sh::InterfaceBlock> *> mShaderBlocks;
 
     std::vector<InterfaceBlock> *mBlocksOut;
 
diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp
index a81fe6f..fd5f219 100644
--- a/src/libANGLE/State.cpp
+++ b/src/libANGLE/State.cpp
@@ -23,6 +23,7 @@
 #include "libANGLE/VertexArray.h"
 #include "libANGLE/formatutils.h"
 #include "libANGLE/queryconversions.h"
+#include "libANGLE/queryutils.h"
 #include "libANGLE/renderer/ContextImpl.h"
 
 namespace
@@ -827,6 +828,16 @@
         // GLES1 emulation
         case GL_ALPHA_TEST:
             return mGLES1State.mAlphaTestEnabled;
+        case GL_VERTEX_ARRAY:
+            return mGLES1State.mVertexArrayEnabled;
+        case GL_NORMAL_ARRAY:
+            return mGLES1State.mNormalArrayEnabled;
+        case GL_COLOR_ARRAY:
+            return mGLES1State.mColorArrayEnabled;
+        case GL_POINT_SIZE_ARRAY_OES:
+            return mGLES1State.mPointSizeArrayEnabled;
+        case GL_TEXTURE_COORD_ARRAY:
+            return mGLES1State.mTexCoordArrayEnabled[mGLES1State.mClientActiveTexture];
 
         default:
             UNREACHABLE();
@@ -2138,12 +2149,9 @@
         case GL_SAMPLES:
         {
             Framebuffer *framebuffer = mDrawFramebuffer;
-            bool complete            = false;
-            ANGLE_TRY(framebuffer->isComplete(context, &complete));
-            if (complete)
+            if (framebuffer->isComplete(context))
             {
-                GLint samples = 0;
-                ANGLE_TRY(framebuffer->getSamples(context, &samples));
+                GLint samples = framebuffer->getSamples(context);
                 switch (pname)
                 {
                     case GL_SAMPLE_BUFFERS:
@@ -2354,7 +2362,7 @@
     return NoError();
 }
 
-void State::getPointerv(GLenum pname, void **params) const
+void State::getPointerv(const Context *context, GLenum pname, void **params) const
 {
     switch (pname)
     {
@@ -2364,6 +2372,15 @@
         case GL_DEBUG_CALLBACK_USER_PARAM:
             *params = const_cast<void *>(mDebug.getUserParam());
             break;
+        case GL_VERTEX_ARRAY_POINTER:
+        case GL_NORMAL_ARRAY_POINTER:
+        case GL_COLOR_ARRAY_POINTER:
+        case GL_TEXTURE_COORD_ARRAY_POINTER:
+        case GL_POINT_SIZE_ARRAY_POINTER_OES:
+            QueryVertexAttribPointerv(getVertexArray()->getVertexAttribute(
+                                          context->vertexArrayIndex(ParamToVertexArrayType(pname))),
+                                      GL_VERTEX_ATTRIB_ARRAY_POINTER, params);
+            return;
         default:
             UNREACHABLE();
             break;
@@ -2546,7 +2563,7 @@
                 ANGLE_TRY(mVertexArray->syncState(context));
                 break;
             case DIRTY_OBJECT_PROGRAM_TEXTURES:
-                syncProgramTextures(context);
+                ANGLE_TRY(syncProgramTextures(context));
                 break;
 
             default:
@@ -2559,12 +2576,12 @@
     return NoError();
 }
 
-void State::syncProgramTextures(const Context *context)
+Error State::syncProgramTextures(const Context *context)
 {
     // TODO(jmadill): Fine-grained updates.
     if (!mProgram)
     {
-        return;
+        return NoError();
     }
 
     ASSERT(mDirtyObjects[DIRTY_OBJECT_PROGRAM_TEXTURES]);
@@ -2596,7 +2613,7 @@
             if (texture->isSamplerComplete(context, sampler) &&
                 !mDrawFramebuffer->hasTextureAttachment(texture))
             {
-                texture->syncState();
+                ANGLE_TRY(texture->syncState(context));
                 mCompleteTextureCache[textureUnitIndex] = texture;
             }
             else
@@ -2632,6 +2649,8 @@
             mActiveTexturesMask.reset(textureIndex);
         }
     }
+
+    return NoError();
 }
 
 Error State::syncDirtyObject(const Context *context, GLenum target)
diff --git a/src/libANGLE/State.h b/src/libANGLE/State.h
index e6657f7..ed2487d 100644
--- a/src/libANGLE/State.h
+++ b/src/libANGLE/State.h
@@ -335,7 +335,7 @@
     void getBooleanv(GLenum pname, GLboolean *params);
     void getFloatv(GLenum pname, GLfloat *params);
     Error getIntegerv(const Context *context, GLenum pname, GLint *params);
-    void getPointerv(GLenum pname, void **params) const;
+    void getPointerv(const Context *context, GLenum pname, void **params) const;
     void getIntegeri_v(GLenum target, GLuint index, GLint *data);
     void getInteger64i_v(GLenum target, GLuint index, GLint64 *data);
     void getBooleani_v(GLenum target, GLuint index, GLboolean *data);
@@ -479,7 +479,7 @@
     const GLES1State &gles1() const { return mGLES1State; }
 
   private:
-    void syncProgramTextures(const Context *context);
+    Error syncProgramTextures(const Context *context);
 
     // Cached values from Context's caps
     GLuint mMaxDrawBuffers;
diff --git a/src/libANGLE/Surface.cpp b/src/libANGLE/Surface.cpp
index 7ca82a8..034da42 100644
--- a/src/libANGLE/Surface.cpp
+++ b/src/libANGLE/Surface.cpp
@@ -53,7 +53,7 @@
       mFixedSize(false),
       mFixedWidth(0),
       mFixedHeight(0),
-      mTextureFormat(EGL_NO_TEXTURE),
+      mTextureFormat(TextureFormat::NoTexture),
       mTextureTarget(EGL_NO_TEXTURE),
       // FIXME: Determine actual pixel aspect ratio
       mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)),
@@ -99,7 +99,7 @@
 
     if (mType != EGL_WINDOW_BIT)
     {
-        mTextureFormat = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE));
+        mTextureFormat = attributes.getAsPackedEnum(EGL_TEXTURE_FORMAT, TextureFormat::NoTexture);
         mTextureTarget = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE));
     }
 
@@ -312,7 +312,7 @@
     return mSwapBehavior;
 }
 
-EGLenum Surface::getTextureFormat() const
+TextureFormat Surface::getTextureFormat() const
 {
     return mTextureFormat;
 }
diff --git a/src/libANGLE/Surface.h b/src/libANGLE/Surface.h
index d66245d..3ce5c91 100644
--- a/src/libANGLE/Surface.h
+++ b/src/libANGLE/Surface.h
@@ -17,6 +17,7 @@
 #include "libANGLE/AttributeMap.h"
 #include "libANGLE/Error.h"
 #include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/PackedEnums.h"
 #include "libANGLE/RefCountObject.h"
 #include "libANGLE/formatutils.h"
 #include "libANGLE/renderer/SurfaceImpl.h"
@@ -85,7 +86,7 @@
     EGLint getPixelAspectRatio() const;
     EGLenum getRenderBuffer() const;
     EGLenum getSwapBehavior() const;
-    EGLenum getTextureFormat() const;
+    TextureFormat getTextureFormat() const;
     EGLenum getTextureTarget() const;
     bool getLargestPbuffer() const;
     EGLenum getGLColorspace() const;
@@ -170,7 +171,7 @@
 
     bool mRobustResourceInitialization;
 
-    EGLenum mTextureFormat;
+    TextureFormat mTextureFormat;
     EGLenum mTextureTarget;
 
     EGLint mPixelAspectRatio;      // Display aspect ratio
diff --git a/src/libANGLE/Texture.cpp b/src/libANGLE/Texture.cpp
index d7953ae..bccd823 100644
--- a/src/libANGLE/Texture.cpp
+++ b/src/libANGLE/Texture.cpp
@@ -513,7 +513,7 @@
 
 const ImageDesc &TextureState::getImageDesc(const ImageIndex &imageIndex) const
 {
-    return getImageDesc(imageIndex.target, imageIndex.mipIndex);
+    return getImageDesc(imageIndex.getTarget(), imageIndex.getLevelIndex());
 }
 
 void TextureState::setImageDescChain(GLuint baseLevel,
@@ -944,7 +944,7 @@
     ANGLE_TRY(releaseTexImageInternal(context));
     ANGLE_TRY(orphanImages(context));
 
-    ImageIndex index = ImageIndex::MakeGeneric(target, level);
+    ImageIndex index = ImageIndex::MakeFromTarget(target, level);
 
     ANGLE_TRY(mTexture->setImage(context, index, internalFormat, size, format, type, unpackState,
                                  pixels));
@@ -969,7 +969,7 @@
 
     ANGLE_TRY(ensureSubImageInitialized(context, target, level, area));
 
-    ImageIndex index = ImageIndex::MakeGeneric(target, level);
+    ImageIndex index = ImageIndex::MakeFromTarget(target, level);
 
     return mTexture->setSubImage(context, index, area, format, type, unpackState, pixels);
 }
@@ -989,7 +989,7 @@
     ANGLE_TRY(releaseTexImageInternal(context));
     ANGLE_TRY(orphanImages(context));
 
-    ImageIndex index = ImageIndex::MakeGeneric(target, level);
+    ImageIndex index = ImageIndex::MakeFromTarget(target, level);
 
     ANGLE_TRY(mTexture->setCompressedImage(context, index, internalFormat, size, unpackState,
                                            imageSize, pixels));
@@ -1014,7 +1014,7 @@
 
     ANGLE_TRY(ensureSubImageInitialized(context, target, level, area));
 
-    ImageIndex index = ImageIndex::MakeGeneric(target, level);
+    ImageIndex index = ImageIndex::MakeFromTarget(target, level);
 
     return mTexture->setCompressedSubImage(context, index, area, format, unpackState, imageSize,
                                            pixels);
@@ -1040,7 +1040,7 @@
     Box destBox(0, 0, 0, sourceArea.width, sourceArea.height, 1);
     ANGLE_TRY(ensureSubImageInitialized(context, target, level, destBox));
 
-    ImageIndex index = ImageIndex::MakeGeneric(target, level);
+    ImageIndex index = ImageIndex::MakeFromTarget(target, level);
 
     ANGLE_TRY(mTexture->copyImage(context, index, sourceArea, internalFormat, source));
 
@@ -1072,7 +1072,7 @@
     Box destBox(destOffset.x, destOffset.y, destOffset.y, sourceArea.width, sourceArea.height, 1);
     ANGLE_TRY(ensureSubImageInitialized(context, target, level, destBox));
 
-    ImageIndex index = ImageIndex::MakeGeneric(target, level);
+    ImageIndex index = ImageIndex::MakeFromTarget(target, level);
 
     return mTexture->copySubImage(context, index, destOffset, sourceArea, source);
 }
@@ -1099,7 +1099,7 @@
     // Note: we don't have a way to notify which portions of the image changed currently.
     ANGLE_TRY(source->ensureInitialized(context));
 
-    ImageIndex index = ImageIndex::MakeGeneric(target, level);
+    ImageIndex index = ImageIndex::MakeFromTarget(target, level);
 
     ANGLE_TRY(mTexture->copyTexture(context, index, internalFormat, type, sourceLevel, unpackFlipY,
                                     unpackPremultiplyAlpha, unpackUnmultiplyAlpha, source));
@@ -1135,7 +1135,7 @@
     Box destBox(destOffset.x, destOffset.y, destOffset.y, sourceArea.width, sourceArea.height, 1);
     ANGLE_TRY(ensureSubImageInitialized(context, target, level, destBox));
 
-    ImageIndex index = ImageIndex::MakeGeneric(target, level);
+    ImageIndex index = ImageIndex::MakeFromTarget(target, level);
 
     return mTexture->copySubTexture(context, index, destOffset, sourceLevel, sourceArea,
                                     unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha,
@@ -1236,17 +1236,18 @@
     {
         return NoError();
     }
-    syncState();
+    ANGLE_TRY(syncState(context));
 
     // Clear the base image(s) immediately if needed
     if (context->isRobustResourceInitEnabled())
     {
         ImageIndexIterator it =
-            ImageIndexIterator::MakeGeneric(mState.mType, baseLevel, baseLevel + 1);
+            ImageIndexIterator::MakeGeneric(mState.mType, baseLevel, baseLevel + 1,
+                                            ImageIndex::kEntireLevel, ImageIndex::kEntireLevel);
         while (it.hasNext())
         {
             const ImageIndex index = it.next();
-            const ImageDesc &desc  = mState.getImageDesc(index.target, index.mipIndex);
+            const ImageDesc &desc  = mState.getImageDesc(index.getTarget(), index.getLevelIndex());
 
             if (desc.initState == InitState::MayNeedInit)
             {
@@ -1396,7 +1397,7 @@
 
 GLsizei Texture::getAttachmentSamples(const ImageIndex &imageIndex) const
 {
-    return getSamples(imageIndex.target, 0);
+    return getSamples(imageIndex.getTarget(), 0);
 }
 
 void Texture::setCrop(const gl::Rectangle& rect)
@@ -1434,10 +1435,11 @@
     return id();
 }
 
-void Texture::syncState()
+Error Texture::syncState(const Context *context)
 {
-    mTexture->syncState(mDirtyBits);
+    ANGLE_TRY(mTexture->syncState(context, mDirtyBits));
     mDirtyBits.reset();
+    return NoError();
 }
 
 rx::FramebufferAttachmentObjectImpl *Texture::getAttachmentImpl() const
@@ -1483,11 +1485,13 @@
     bool anyDirty = false;
 
     ImageIndexIterator it =
-        ImageIndexIterator::MakeGeneric(mState.mType, 0, IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1);
+        ImageIndexIterator::MakeGeneric(mState.mType, 0, IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1,
+                                        ImageIndex::kEntireLevel, ImageIndex::kEntireLevel);
     while (it.hasNext())
     {
         const ImageIndex index = it.next();
-        ImageDesc &desc = mState.mImageDescs[GetImageDescIndex(index.target, index.mipIndex)];
+        ImageDesc &desc =
+            mState.mImageDescs[GetImageDescIndex(index.getTarget(), index.getLevelIndex())];
         if (desc.initState == InitState::MayNeedInit)
         {
             ASSERT(mState.mInitState == InitState::MayNeedInit);
@@ -1519,7 +1523,7 @@
 {
     ImageDesc newDesc = mState.getImageDesc(imageIndex);
     newDesc.initState = initState;
-    mState.setImageDesc(imageIndex.target, imageIndex.mipIndex, newDesc);
+    mState.setImageDesc(imageIndex.getTarget(), imageIndex.getLevelIndex(), newDesc);
 }
 
 Error Texture::ensureSubImageInitialized(const Context *context,
@@ -1534,7 +1538,7 @@
 
     // Pre-initialize the texture contents if necessary.
     // TODO(jmadill): Check if area overlaps the entire texture.
-    ImageIndex imageIndex  = ImageIndex::MakeGeneric(target, static_cast<GLint>(level));
+    ImageIndex imageIndex  = ImageIndex::MakeFromTarget(target, static_cast<GLint>(level));
     const auto &desc       = mState.getImageDesc(imageIndex);
     if (desc.initState == InitState::MayNeedInit)
     {
diff --git a/src/libANGLE/Texture.h b/src/libANGLE/Texture.h
index b77ea85..db22381 100644
--- a/src/libANGLE/Texture.h
+++ b/src/libANGLE/Texture.h
@@ -426,7 +426,7 @@
     };
     using DirtyBits = angle::BitSet<DIRTY_BIT_COUNT>;
 
-    void syncState();
+    Error syncState(const Context *context);
     bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
 
   private:
diff --git a/src/libANGLE/TransformFeedback.cpp b/src/libANGLE/TransformFeedback.cpp
index 0471b5b..4392b7f 100644
--- a/src/libANGLE/TransformFeedback.cpp
+++ b/src/libANGLE/TransformFeedback.cpp
@@ -41,7 +41,7 @@
         case GL_POINTS:
             return checkedPrimcount * checkedCount;
         default:
-            NOTREACHED();
+            UNREACHABLE();
             return checkedPrimcount * checkedCount;
     }
 }
diff --git a/src/libANGLE/VaryingPacking.cpp b/src/libANGLE/VaryingPacking.cpp
index e88c019..d1466aa 100644
--- a/src/libANGLE/VaryingPacking.cpp
+++ b/src/libANGLE/VaryingPacking.cpp
@@ -332,12 +332,14 @@
             }
         }
 
-        // Keep Transform FB varyings in the merged list always.
+        // If the varying is not used in the VS, we know it is inactive.
         if (!input)
         {
+            mInactiveVaryingNames.push_back(ref.first);
             continue;
         }
 
+        // Keep Transform FB varyings in the merged list always.
         for (const std::string &tfVarying : tfVaryings)
         {
             std::vector<unsigned int> subscripts;
@@ -384,6 +386,11 @@
                 }
             }
         }
+
+        if (uniqueFullNames.count(ref.first) == 0)
+        {
+            mInactiveVaryingNames.push_back(ref.first);
+        }
     }
 
     std::sort(mPackedVaryings.begin(), mPackedVaryings.end(), ComparePackedVarying);
@@ -429,4 +436,8 @@
     return true;
 }
 
+const std::vector<std::string> &VaryingPacking::getInactiveVaryingNames() const
+{
+    return mInactiveVaryingNames;
+}
 }  // namespace rx
diff --git a/src/libANGLE/VaryingPacking.h b/src/libANGLE/VaryingPacking.h
index c02c598..f2d86ea 100644
--- a/src/libANGLE/VaryingPacking.h
+++ b/src/libANGLE/VaryingPacking.h
@@ -179,6 +179,8 @@
         return static_cast<unsigned int>(mRegisterList.size());
     }
 
+    const std::vector<std::string> &getInactiveVaryingNames() const;
+
   private:
     bool packVarying(const PackedVarying &packedVarying);
     bool isFree(unsigned int registerRow,
@@ -192,6 +194,7 @@
     std::vector<Register> mRegisterMap;
     std::vector<PackedVaryingRegister> mRegisterList;
     std::vector<PackedVarying> mPackedVaryings;
+    std::vector<std::string> mInactiveVaryingNames;
 
     PackMode mPackMode;
 };
diff --git a/src/libANGLE/VertexArray.cpp b/src/libANGLE/VertexArray.cpp
index 0735c2a..a750c86 100644
--- a/src/libANGLE/VertexArray.cpp
+++ b/src/libANGLE/VertexArray.cpp
@@ -15,7 +15,7 @@
 
 namespace gl
 {
-
+// VertexArrayState implementation.
 VertexArrayState::VertexArrayState(size_t maxAttribs, size_t maxAttribBindings)
     : mLabel(), mVertexBindings(maxAttribBindings)
 {
@@ -31,6 +31,17 @@
 {
 }
 
+gl::AttributesMask VertexArrayState::getEnabledClientMemoryAttribsMask() const
+{
+    return (mClientMemoryAttribsMask & mEnabledAttributesMask);
+}
+
+bool VertexArrayState::hasEnabledNullPointerClientArray() const
+{
+    return (mNullPointerClientMemoryAttribsMask & mEnabledAttributesMask).any();
+}
+
+// VertexArray implementation.
 VertexArray::VertexArray(rx::GLImplFactory *factory,
                          GLuint id,
                          size_t maxAttribs,
@@ -49,7 +60,7 @@
 void VertexArray::onDestroy(const Context *context)
 {
     bool isBound = context->isCurrentVertexArray(this);
-    for (auto &binding : mState.mVertexBindings)
+    for (VertexBinding &binding : mState.mVertexBindings)
     {
         binding.setBuffer(context, nullptr, isBound);
     }
@@ -148,6 +159,7 @@
     binding->setStride(stride);
 
     updateObserverBinding(bindingIndex);
+    updateCachedBufferBindingSize(bindingIndex);
 }
 
 void VertexArray::bindVertexBuffer(const Context *context,
@@ -202,7 +214,7 @@
     attrib->pureInteger    = pureInteger;
     attrib->relativeOffset = relativeOffset;
     mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(*attrib), attribIndex);
-    mState.mEnabledAttributesMask.set(attribIndex);
+    attrib->updateCachedSizePlusRelativeOffset();
 }
 
 void VertexArray::setVertexAttribFormat(size_t attribIndex,
@@ -265,6 +277,10 @@
     bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
 
     setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
+
+    mState.mClientMemoryAttribsMask.set(attribIndex, boundBuffer == nullptr);
+    mState.mNullPointerClientMemoryAttribsMask.set(attribIndex,
+                                                   boundBuffer == nullptr && pointer == nullptr);
 }
 
 void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer)
@@ -335,6 +351,12 @@
     ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
     mDirtyBits.set(dirtyBit);
     context->getGLState().setVertexArrayDirty(this);
+
+    if (message == angle::SubjectMessage::STORAGE_CHANGED &&
+        index < mArrayBufferObserverBindings.size())
+    {
+        updateCachedBufferBindingSize(index);
+    }
 }
 
 void VertexArray::updateObserverBinding(size_t bindingIndex)
@@ -344,4 +366,14 @@
                                                                 : nullptr);
 }
 
+void VertexArray::updateCachedVertexAttributeSize(size_t attribIndex)
+{
+    mState.mVertexAttributes[attribIndex].updateCachedSizePlusRelativeOffset();
+}
+
+void VertexArray::updateCachedBufferBindingSize(size_t bindingIndex)
+{
+    mState.mVertexBindings[bindingIndex].updateCachedBufferSizeMinusOffset();
+}
+
 }  // namespace gl
diff --git a/src/libANGLE/VertexArray.h b/src/libANGLE/VertexArray.h
index 6ceb080..83d1ac8 100644
--- a/src/libANGLE/VertexArray.h
+++ b/src/libANGLE/VertexArray.h
@@ -63,6 +63,12 @@
         return mVertexAttributes[attribIndex].bindingIndex;
     }
 
+    // Combines mClientMemoryAttribsMask with mEnabledAttributesMask.
+    gl::AttributesMask getEnabledClientMemoryAttribsMask() const;
+
+    // Extra validation performed on the Vertex Array.
+    bool hasEnabledNullPointerClientArray() const;
+
   private:
     friend class VertexArray;
     std::string mLabel;
@@ -71,6 +77,13 @@
     std::vector<VertexBinding> mVertexBindings;
     AttributesMask mEnabledAttributesMask;
     ComponentTypeMask mVertexAttributesTypeMask;
+
+    // From the GLES 3.1 spec:
+    // When a generic attribute array is sourced from client memory, the vertex attribute binding
+    // state is ignored. Thus we don't have to worry about binding state when using client memory
+    // attribs.
+    gl::AttributesMask mClientMemoryAttribsMask;
+    gl::AttributesMask mNullPointerClientMemoryAttribsMask;
 };
 
 class VertexArray final : public angle::ObserverInterface, public LabeledObject
@@ -154,6 +167,16 @@
         return mState.getEnabledAttributesMask();
     }
 
+    gl::AttributesMask getEnabledClientMemoryAttribsMask() const
+    {
+        return mState.getEnabledClientMemoryAttribsMask();
+    }
+
+    bool hasEnabledNullPointerClientArray() const
+    {
+        return mState.hasEnabledNullPointerClientArray();
+    }
+
     // Observer implementation
     void onSubjectStateChange(const gl::Context *context,
                               angle::SubjectIndex index,
@@ -232,6 +255,10 @@
     void updateObserverBinding(size_t bindingIndex);
     DirtyBitType getDirtyBitFromIndex(bool contentsChanged, angle::SubjectIndex index) const;
 
+    // These are used to optimize draw call validation.
+    void updateCachedVertexAttributeSize(size_t attribIndex);
+    void updateCachedBufferBindingSize(size_t bindingIndex);
+
     GLuint mId;
 
     VertexArrayState mState;
diff --git a/src/libANGLE/VertexAttribute.cpp b/src/libANGLE/VertexAttribute.cpp
index 0cb5788..e55c844 100644
--- a/src/libANGLE/VertexAttribute.cpp
+++ b/src/libANGLE/VertexAttribute.cpp
@@ -13,7 +13,8 @@
 
 // [OpenGL ES 3.1] (November 3, 2016) Section 20 Page 361
 // Table 20.2: Vertex Array Object State
-VertexBinding::VertexBinding() : mStride(16u), mDivisor(0), mOffset(0)
+VertexBinding::VertexBinding()
+    : mStride(16u), mDivisor(0), mOffset(0), mCachedBufferSizeMinusOffset(0)
 {
 }
 
@@ -34,6 +35,7 @@
         mDivisor = binding.mDivisor;
         mOffset  = binding.mOffset;
         std::swap(binding.mBuffer, mBuffer);
+        mCachedBufferSizeMinusOffset = binding.mCachedBufferSizeMinusOffset;
     }
     return *this;
 }
@@ -53,6 +55,27 @@
         mBuffer->onBindingChanged(bound, BufferBinding::Array);
 }
 
+void VertexBinding::updateCachedBufferSizeMinusOffset()
+{
+    if (mBuffer.get())
+    {
+        angle::CheckedNumeric<GLuint64> checkedSize(mBuffer->getSize());
+        angle::CheckedNumeric<GLuint64> checkedOffset(mOffset);
+
+        // Use a default value of zero so checks will fail on overflow.
+        mCachedBufferSizeMinusOffset = (checkedSize - checkedOffset).ValueOrDefault(0);
+    }
+    else
+    {
+        mCachedBufferSizeMinusOffset = 0;
+    }
+}
+
+GLuint64 VertexBinding::getCachedBufferSizeMinusOffset() const
+{
+    return mCachedBufferSizeMinusOffset;
+}
+
 VertexAttribute::VertexAttribute(GLuint bindingIndex)
     : enabled(false),
       type(GL_FLOAT),
@@ -62,7 +85,8 @@
       pointer(nullptr),
       relativeOffset(0),
       vertexAttribArrayStride(0),
-      bindingIndex(bindingIndex)
+      bindingIndex(bindingIndex),
+      cachedSizePlusRelativeOffset(16)
 {
 }
 
@@ -75,7 +99,8 @@
       pointer(attrib.pointer),
       relativeOffset(attrib.relativeOffset),
       vertexAttribArrayStride(attrib.vertexAttribArrayStride),
-      bindingIndex(attrib.bindingIndex)
+      bindingIndex(attrib.bindingIndex),
+      cachedSizePlusRelativeOffset(attrib.cachedSizePlusRelativeOffset)
 {
 }
 
@@ -92,10 +117,19 @@
         relativeOffset          = attrib.relativeOffset;
         vertexAttribArrayStride = attrib.vertexAttribArrayStride;
         bindingIndex            = attrib.bindingIndex;
+        cachedSizePlusRelativeOffset = attrib.cachedSizePlusRelativeOffset;
     }
     return *this;
 }
 
+void VertexAttribute::updateCachedSizePlusRelativeOffset()
+{
+    ASSERT(relativeOffset <=
+           std::numeric_limits<GLuint64>::max() - ComputeVertexAttributeTypeSize(*this));
+    cachedSizePlusRelativeOffset =
+        relativeOffset + static_cast<GLuint64>(ComputeVertexAttributeTypeSize(*this));
+}
+
 size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib)
 {
     GLuint size = attrib.size;
diff --git a/src/libANGLE/VertexAttribute.h b/src/libANGLE/VertexAttribute.h
index d442b99..2cfdc7a 100644
--- a/src/libANGLE/VertexAttribute.h
+++ b/src/libANGLE/VertexAttribute.h
@@ -40,12 +40,19 @@
     void setBuffer(const gl::Context *context, Buffer *bufferIn, bool containerIsBound);
     void onContainerBindingChanged(bool bound);
 
+    // Called from VertexArray.
+    void updateCachedBufferSizeMinusOffset();
+    GLuint64 getCachedBufferSizeMinusOffset() const;
+
   private:
     GLuint mStride;
     GLuint mDivisor;
     GLintptr mOffset;
 
     BindingPointer<Buffer> mBuffer;
+
+    // This is kept in sync by the VertexArray. It is used to optimize draw call validation.
+    GLuint64 mCachedBufferSizeMinusOffset;
 };
 
 //
@@ -57,6 +64,9 @@
     VertexAttribute(VertexAttribute &&attrib);
     VertexAttribute &operator=(VertexAttribute &&attrib);
 
+    // Called from VertexArray.
+    void updateCachedSizePlusRelativeOffset();
+
     bool enabled;  // For glEnable/DisableVertexAttribArray
     GLenum type;
     GLuint size;
@@ -68,6 +78,9 @@
 
     GLuint vertexAttribArrayStride;  // ONLY for queries of VERTEX_ATTRIB_ARRAY_STRIDE
     GLuint bindingIndex;
+
+    // This is kept in sync by the VertexArray. It is used to optimize draw call validation.
+    GLuint64 cachedSizePlusRelativeOffset;
 };
 
 size_t ComputeVertexAttributeTypeSize(const VertexAttribute &attrib);
diff --git a/src/libANGLE/angletypes.h b/src/libANGLE/angletypes.h
index 405ad4f..399b4df 100644
--- a/src/libANGLE/angletypes.h
+++ b/src/libANGLE/angletypes.h
@@ -14,7 +14,7 @@
 #include "common/vector_utils.h"
 #include "libANGLE/Constants.h"
 #include "libANGLE/Error.h"
-#include "libANGLE/PackedGLEnums.h"
+#include "libANGLE/PackedEnums.h"
 #include "libANGLE/RefCountObject.h"
 
 #include <stdint.h>
@@ -45,7 +45,7 @@
 struct Rectangle
 {
     Rectangle() : x(0), y(0), width(0), height(0) {}
-    Rectangle(int x_in, int y_in, int width_in, int height_in)
+    constexpr Rectangle(int x_in, int y_in, int width_in, int height_in)
         : x(x_in), y(y_in), width(width_in), height(height_in)
     {
     }
diff --git a/src/libANGLE/entry_points_enum_autogen.h b/src/libANGLE/entry_points_enum_autogen.h
index f899b88..ab80447 100644
--- a/src/libANGLE/entry_points_enum_autogen.h
+++ b/src/libANGLE/entry_points_enum_autogen.h
@@ -1,5 +1,5 @@
 // GENERATED FILE - DO NOT EDIT.
-// Generated by generate_entry_points.py using data from gl.xml.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
 //
 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
@@ -28,6 +28,7 @@
     BindBuffer,
     BindBufferBase,
     BindBufferRange,
+    BindFragmentInputLocationCHROMIUM,
     BindFramebuffer,
     BindFramebufferOES,
     BindImageTexture,
@@ -37,6 +38,7 @@
     BindSampler,
     BindTexture,
     BindTransformFeedback,
+    BindUniformLocationCHROMIUM,
     BindVertexArray,
     BindVertexArrayOES,
     BindVertexBuffer,
@@ -71,14 +73,26 @@
     ColorMask,
     ColorPointer,
     CompileShader,
+    CompressedCopyTextureCHROMIUM,
     CompressedTexImage2D,
+    CompressedTexImage2DRobustANGLE,
     CompressedTexImage3D,
+    CompressedTexImage3DRobustANGLE,
     CompressedTexSubImage2D,
+    CompressedTexSubImage2DRobustANGLE,
     CompressedTexSubImage3D,
+    CompressedTexSubImage3DRobustANGLE,
     CopyBufferSubData,
+    CopySubTextureCHROMIUM,
     CopyTexImage2D,
     CopyTexSubImage2D,
     CopyTexSubImage3D,
+    CopyTextureCHROMIUM,
+    CoverFillPathCHROMIUM,
+    CoverFillPathInstancedCHROMIUM,
+    CoverStrokePathCHROMIUM,
+    CoverStrokePathInstancedCHROMIUM,
+    CoverageModulationCHROMIUM,
     CreateProgram,
     CreateShader,
     CreateShaderProgramv,
@@ -91,6 +105,7 @@
     DeleteFencesNV,
     DeleteFramebuffers,
     DeleteFramebuffersOES,
+    DeletePathsCHROMIUM,
     DeleteProgram,
     DeleteProgramPipelines,
     DeleteQueries,
@@ -158,6 +173,8 @@
     FramebufferTexture2D,
     FramebufferTexture2DOES,
     FramebufferTextureLayer,
+    FramebufferTextureMultiviewLayeredANGLE,
+    FramebufferTextureMultiviewSideBySideANGLE,
     FrontFace,
     Frustumf,
     Frustumx,
@@ -165,6 +182,7 @@
     GenFencesNV,
     GenFramebuffers,
     GenFramebuffersOES,
+    GenPathsCHROMIUM,
     GenProgramPipelines,
     GenQueries,
     GenQueriesEXT,
@@ -181,15 +199,21 @@
     GetActiveUniform,
     GetActiveUniformBlockName,
     GetActiveUniformBlockiv,
+    GetActiveUniformBlockivRobustANGLE,
     GetActiveUniformsiv,
     GetAttachedShaders,
     GetAttribLocation,
     GetBooleani_v,
+    GetBooleani_vRobustANGLE,
     GetBooleanv,
+    GetBooleanvRobustANGLE,
     GetBufferParameteri64v,
+    GetBufferParameteri64vRobustANGLE,
     GetBufferParameteriv,
+    GetBufferParameterivRobustANGLE,
     GetBufferPointerv,
     GetBufferPointervOES,
+    GetBufferPointervRobustANGLE,
     GetClipPlanef,
     GetClipPlanex,
     GetDebugMessageLogKHR,
@@ -197,29 +221,42 @@
     GetFenceivNV,
     GetFixedv,
     GetFloatv,
+    GetFloatvRobustANGLE,
     GetFragDataLocation,
     GetFramebufferAttachmentParameteriv,
     GetFramebufferAttachmentParameterivOES,
+    GetFramebufferAttachmentParameterivRobustANGLE,
     GetFramebufferParameteriv,
+    GetFramebufferParameterivRobustANGLE,
     GetGraphicsResetStatusEXT,
     GetInteger64i_v,
+    GetInteger64i_vRobustANGLE,
     GetInteger64v,
+    GetInteger64vRobustANGLE,
     GetIntegeri_v,
+    GetIntegeri_vRobustANGLE,
     GetIntegerv,
+    GetIntegervRobustANGLE,
     GetInternalformativ,
+    GetInternalformativRobustANGLE,
     GetLightfv,
     GetLightxv,
     GetMaterialfv,
     GetMaterialxv,
     GetMultisamplefv,
+    GetMultisamplefvRobustANGLE,
     GetObjectLabelKHR,
     GetObjectPtrLabelKHR,
+    GetPathParameterfvCHROMIUM,
+    GetPathParameterivCHROMIUM,
     GetPointerv,
     GetPointervKHR,
+    GetPointervRobustANGLERobustANGLE,
     GetProgramBinary,
     GetProgramBinaryOES,
     GetProgramInfoLog,
     GetProgramInterfaceiv,
+    GetProgramInterfaceivRobustANGLE,
     GetProgramPipelineInfoLog,
     GetProgramPipelineiv,
     GetProgramResourceIndex,
@@ -227,21 +264,33 @@
     GetProgramResourceName,
     GetProgramResourceiv,
     GetProgramiv,
+    GetProgramivRobustANGLE,
     GetQueryObjecti64vEXT,
+    GetQueryObjecti64vRobustANGLE,
     GetQueryObjectivEXT,
+    GetQueryObjectivRobustANGLE,
     GetQueryObjectui64vEXT,
+    GetQueryObjectui64vRobustANGLE,
     GetQueryObjectuiv,
     GetQueryObjectuivEXT,
+    GetQueryObjectuivRobustANGLE,
     GetQueryiv,
     GetQueryivEXT,
+    GetQueryivRobustANGLE,
     GetRenderbufferParameteriv,
     GetRenderbufferParameterivOES,
+    GetRenderbufferParameterivRobustANGLE,
+    GetSamplerParameterIivRobustANGLE,
+    GetSamplerParameterIuivRobustANGLE,
     GetSamplerParameterfv,
+    GetSamplerParameterfvRobustANGLE,
     GetSamplerParameteriv,
+    GetSamplerParameterivRobustANGLE,
     GetShaderInfoLog,
     GetShaderPrecisionFormat,
     GetShaderSource,
     GetShaderiv,
+    GetShaderivRobustANGLE,
     GetString,
     GetStringi,
     GetSynciv,
@@ -252,9 +301,15 @@
     GetTexGenivOES,
     GetTexGenxvOES,
     GetTexLevelParameterfv,
+    GetTexLevelParameterfvRobustANGLE,
     GetTexLevelParameteriv,
+    GetTexLevelParameterivRobustANGLE,
+    GetTexParameterIivRobustANGLE,
+    GetTexParameterIuivRobustANGLE,
     GetTexParameterfv,
+    GetTexParameterfvRobustANGLE,
     GetTexParameteriv,
+    GetTexParameterivRobustANGLE,
     GetTexParameterxv,
     GetTransformFeedbackVarying,
     GetTranslatedShaderSourceANGLE,
@@ -262,15 +317,26 @@
     GetUniformIndices,
     GetUniformLocation,
     GetUniformfv,
+    GetUniformfvRobustANGLE,
     GetUniformiv,
+    GetUniformivRobustANGLE,
     GetUniformuiv,
+    GetUniformuivRobustANGLE,
     GetVertexAttribIiv,
+    GetVertexAttribIivRobustANGLE,
     GetVertexAttribIuiv,
+    GetVertexAttribIuivRobustANGLE,
     GetVertexAttribPointerv,
+    GetVertexAttribPointervRobustANGLE,
     GetVertexAttribfv,
+    GetVertexAttribfvRobustANGLE,
     GetVertexAttribiv,
+    GetVertexAttribivRobustANGLE,
     GetnUniformfvEXT,
+    GetnUniformfvRobustANGLE,
     GetnUniformivEXT,
+    GetnUniformivRobustANGLE,
+    GetnUniformuivRobustANGLE,
     Hint,
     InsertEventMarkerEXT,
     InvalidateFramebuffer,
@@ -280,6 +346,7 @@
     IsFenceNV,
     IsFramebuffer,
     IsFramebufferOES,
+    IsPathCHROMIUM,
     IsProgram,
     IsProgramPipeline,
     IsQuery,
@@ -317,6 +384,8 @@
     Materialx,
     Materialxv,
     MatrixIndexPointerOES,
+    MatrixLoadIdentityCHROMIUM,
+    MatrixLoadfCHROMIUM,
     MatrixMode,
     MemoryBarrier,
     MemoryBarrierByRegion,
@@ -331,6 +400,10 @@
     ObjectPtrLabelKHR,
     Orthof,
     Orthox,
+    PathCommandsCHROMIUM,
+    PathParameterfCHROMIUM,
+    PathParameteriCHROMIUM,
+    PathStencilFuncCHROMIUM,
     PauseTransformFeedback,
     PixelStorei,
     PointParameterf,
@@ -348,6 +421,7 @@
     ProgramBinary,
     ProgramBinaryOES,
     ProgramParameteri,
+    ProgramPathFragmentInputGenCHROMIUM,
     ProgramUniform1f,
     ProgramUniform1fv,
     ProgramUniform1i,
@@ -388,22 +462,29 @@
     QueryMatrixxOES,
     ReadBuffer,
     ReadPixels,
+    ReadPixelsRobustANGLE,
     ReadnPixelsEXT,
+    ReadnPixelsRobustANGLE,
     ReleaseShaderCompiler,
     RenderbufferStorage,
     RenderbufferStorageMultisample,
     RenderbufferStorageMultisampleANGLE,
     RenderbufferStorageOES,
+    RequestExtensionANGLE,
     ResumeTransformFeedback,
     Rotatef,
     Rotatex,
     SampleCoverage,
     SampleCoveragex,
     SampleMaski,
+    SamplerParameterIivRobustANGLE,
+    SamplerParameterIuivRobustANGLE,
     SamplerParameterf,
     SamplerParameterfv,
+    SamplerParameterfvRobustANGLE,
     SamplerParameteri,
     SamplerParameteriv,
+    SamplerParameterivRobustANGLE,
     Scalef,
     Scalex,
     Scissor,
@@ -411,12 +492,20 @@
     ShadeModel,
     ShaderBinary,
     ShaderSource,
+    StencilFillPathCHROMIUM,
+    StencilFillPathInstancedCHROMIUM,
     StencilFunc,
     StencilFuncSeparate,
     StencilMask,
     StencilMaskSeparate,
     StencilOp,
     StencilOpSeparate,
+    StencilStrokePathCHROMIUM,
+    StencilStrokePathInstancedCHROMIUM,
+    StencilThenCoverFillPathCHROMIUM,
+    StencilThenCoverFillPathInstancedCHROMIUM,
+    StencilThenCoverStrokePathCHROMIUM,
+    StencilThenCoverStrokePathInstancedCHROMIUM,
     TestFenceNV,
     TexCoordPointer,
     TexEnvf,
@@ -432,11 +521,17 @@
     TexGenxOES,
     TexGenxvOES,
     TexImage2D,
+    TexImage2DRobustANGLE,
     TexImage3D,
+    TexImage3DRobustANGLE,
+    TexParameterIivRobustANGLE,
+    TexParameterIuivRobustANGLE,
     TexParameterf,
     TexParameterfv,
+    TexParameterfvRobustANGLE,
     TexParameteri,
     TexParameteriv,
+    TexParameterivRobustANGLE,
     TexParameterx,
     TexParameterxv,
     TexStorage1DEXT,
@@ -446,7 +541,9 @@
     TexStorage3D,
     TexStorage3DEXT,
     TexSubImage2D,
+    TexSubImage2DRobustANGLE,
     TexSubImage3D,
+    TexSubImage3DRobustANGLE,
     TransformFeedbackVaryings,
     Translatef,
     Translatex,
diff --git a/src/libANGLE/formatutils.cpp b/src/libANGLE/formatutils.cpp
index 5e0a6a6..7a6594b 100644
--- a/src/libANGLE/formatutils.cpp
+++ b/src/libANGLE/formatutils.cpp
@@ -850,23 +850,23 @@
     AddRGBAFormat(&map, GL_RGBA16_SNORM_EXT, true, 16, 16, 16, 16, 0, GL_RGBA,         GL_SHORT,                        GL_SIGNED_NORMALIZED,   false, RequireExt<&Extensions::textureNorm16>,    NeverSupported,                            AlwaysSupported);
 
     // Unsized formats
-    //                 | Internal format    |sized | R | G | B | A |S | Format         | Type                           | Component type        | SRGB | Texture supported                           | Renderable                                  | Filterable    |
-    AddRGBAFormat(&map, GL_RED,              false,  8,  0,  0,  0, 0, GL_RED,          GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureRG>,           AlwaysSupported,                              AlwaysSupported);
-    AddRGBAFormat(&map, GL_RED,              false,  8,  0,  0,  0, 0, GL_RED,          GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, NeverSupported,                               NeverSupported,                               NeverSupported );
-    AddRGBAFormat(&map, GL_RG,               false,  8,  8,  0,  0, 0, GL_RG,           GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureRG>,           AlwaysSupported,                              AlwaysSupported);
-    AddRGBAFormat(&map, GL_RG,               false,  8,  8,  0,  0, 0, GL_RG,           GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, NeverSupported,                               NeverSupported,                               NeverSupported );
-    AddRGBAFormat(&map, GL_RGB,              false,  8,  8,  8,  0, 0, GL_RGB,          GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireES<1, 0>,                              AlwaysSupported,                              AlwaysSupported);
-    AddRGBAFormat(&map, GL_RGB,              false,  5,  6,  5,  0, 0, GL_RGB,          GL_UNSIGNED_SHORT_5_6_5,         GL_UNSIGNED_NORMALIZED, false, RequireES<1, 0>,                              RequireES<1, 0>,                              AlwaysSupported);
-    AddRGBAFormat(&map, GL_RGB,              false,  8,  8,  8,  0, 0, GL_RGB,          GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, NeverSupported,                               NeverSupported,                               NeverSupported );
-    AddRGBAFormat(&map, GL_RGBA,             false,  4,  4,  4,  4, 0, GL_RGBA,         GL_UNSIGNED_SHORT_4_4_4_4,       GL_UNSIGNED_NORMALIZED, false, RequireES<1, 0>,                              RequireES<1, 0>,                              AlwaysSupported);
-    AddRGBAFormat(&map, GL_RGBA,             false,  5,  5,  5,  1, 0, GL_RGBA,         GL_UNSIGNED_SHORT_5_5_5_1,       GL_UNSIGNED_NORMALIZED, false, RequireES<1, 0>,                              RequireES<1, 0>,                              AlwaysSupported);
-    AddRGBAFormat(&map, GL_RGBA,             false,  8,  8,  8,  8, 0, GL_RGBA,         GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireES<1, 0>,                              RequireES<1, 0>,                              AlwaysSupported);
-    AddRGBAFormat(&map, GL_RGBA,             false, 10, 10, 10,  2, 0, GL_RGBA,         GL_UNSIGNED_INT_2_10_10_10_REV,  GL_UNSIGNED_NORMALIZED, false, RequireES<1, 0>,                              RequireES<1, 0>,                              AlwaysSupported);
-    AddRGBAFormat(&map, GL_RGBA,             false,  8,  8,  8,  8, 0, GL_RGBA,         GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, NeverSupported,                               NeverSupported,                               NeverSupported );
-    AddRGBAFormat(&map, GL_SRGB,             false,  8,  8,  8,  0, 0, GL_RGB,          GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, true,  RequireExt<&Extensions::sRGB>,                NeverSupported,                               AlwaysSupported);
-    AddRGBAFormat(&map, GL_SRGB_ALPHA_EXT,   false,  8,  8,  8,  8, 0, GL_RGBA,         GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, true,  RequireExt<&Extensions::sRGB>,                RequireExt<&Extensions::sRGB>,                AlwaysSupported);
+    //                 | Internal format    |sized | R | G | B | A |S | Format           | Type                           | Component type        | SRGB | Texture supported                           | Renderable                                  | Filterable    |
+    AddRGBAFormat(&map, GL_RED,              false,  8,  0,  0,  0, 0, GL_RED,            GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureRG>,           AlwaysSupported,                              AlwaysSupported);
+    AddRGBAFormat(&map, GL_RED,              false,  8,  0,  0,  0, 0, GL_RED,            GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, NeverSupported,                               NeverSupported,                               NeverSupported );
+    AddRGBAFormat(&map, GL_RG,               false,  8,  8,  0,  0, 0, GL_RG,             GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureRG>,           AlwaysSupported,                              AlwaysSupported);
+    AddRGBAFormat(&map, GL_RG,               false,  8,  8,  0,  0, 0, GL_RG,             GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, NeverSupported,                               NeverSupported,                               NeverSupported );
+    AddRGBAFormat(&map, GL_RGB,              false,  8,  8,  8,  0, 0, GL_RGB,            GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireES<1, 0>,                              AlwaysSupported,                              AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGB,              false,  5,  6,  5,  0, 0, GL_RGB,            GL_UNSIGNED_SHORT_5_6_5,         GL_UNSIGNED_NORMALIZED, false, RequireES<1, 0>,                              RequireES<1, 0>,                              AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGB,              false,  8,  8,  8,  0, 0, GL_RGB,            GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, NeverSupported,                               NeverSupported,                               NeverSupported );
+    AddRGBAFormat(&map, GL_RGBA,             false,  4,  4,  4,  4, 0, GL_RGBA,           GL_UNSIGNED_SHORT_4_4_4_4,       GL_UNSIGNED_NORMALIZED, false, RequireES<1, 0>,                              RequireES<1, 0>,                              AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGBA,             false,  5,  5,  5,  1, 0, GL_RGBA,           GL_UNSIGNED_SHORT_5_5_5_1,       GL_UNSIGNED_NORMALIZED, false, RequireES<1, 0>,                              RequireES<1, 0>,                              AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGBA,             false,  8,  8,  8,  8, 0, GL_RGBA,           GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireES<1, 0>,                              RequireES<1, 0>,                              AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGBA,             false, 10, 10, 10,  2, 0, GL_RGBA,           GL_UNSIGNED_INT_2_10_10_10_REV,  GL_UNSIGNED_NORMALIZED, false, RequireES<1, 0>,                              RequireES<1, 0>,                              AlwaysSupported);
+    AddRGBAFormat(&map, GL_RGBA,             false,  8,  8,  8,  8, 0, GL_RGBA,           GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, NeverSupported,                               NeverSupported,                               NeverSupported );
+    AddRGBAFormat(&map, GL_SRGB,             false,  8,  8,  8,  0, 0, GL_SRGB,           GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, true,  RequireExt<&Extensions::sRGB>,                NeverSupported,                               AlwaysSupported);
+    AddRGBAFormat(&map, GL_SRGB_ALPHA_EXT,   false,  8,  8,  8,  8, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, true,  RequireExt<&Extensions::sRGB>,                RequireExt<&Extensions::sRGB>,                AlwaysSupported);
 
-    AddRGBAFormat(&map, GL_BGRA_EXT,         false,  8,  8,  8,  8, 0, GL_BGRA_EXT,     GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported);
+    AddRGBAFormat(&map, GL_BGRA_EXT,         false,  8,  8,  8,  8, 0, GL_BGRA_EXT,       GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported);
 
     // Unsized integer formats
     //                 |Internal format |sized | R | G | B | A |S | Format         | Type                          | Component type | SRGB | Texture        | Renderable    | Filterable   |
diff --git a/src/libANGLE/gen_packed_gl_enums.py b/src/libANGLE/gen_packed_gl_enums.py
index 501e6f3..0f94036 100644
--- a/src/libANGLE/gen_packed_gl_enums.py
+++ b/src/libANGLE/gen_packed_gl_enums.py
@@ -1,9 +1,9 @@
-# Copyright 2016 The ANGLE Project Authors. All rights reserved.
+# Copyright 2018 The ANGLE Project Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 #
 # gen_packed_gl_enums.py:
-#  Code generation for the packed GL enums.
+#  Code generation for the packed enums.
 
 import datetime, json, os, sys
 from collections import namedtuple
@@ -11,7 +11,20 @@
 Enum = namedtuple('Enum', ['name', 'values', 'max_value'])
 EnumValue = namedtuple('EnumValue', ['name', 'gl_name', 'value'])
 
-kJsonFileName = "packed_gl_enums.json"
+Generators = [
+    {
+        'json': 'packed_gl_enums.json',
+        'output': 'PackedGLEnums',
+        'namespace': 'gl',
+        'enum_type': 'GLenum',
+    },
+    {
+        'json': 'packed_egl_enums.json',
+        'output': 'PackedEGLEnums',
+        'namespace': 'egl',
+        'enum_type': 'EGLenum',
+    },
+]
 
 def load_enums(path):
     with open(path) as map_file:
@@ -41,6 +54,12 @@
     enums.sort(key=lambda enum: enum.name)
     return enums
 
+def generate_include_guard(path):
+    return path.replace(".", "_").upper()
+
+def header_name_from_cpp_name(path):
+    return path.replace(".cpp", ".h")
+
 header_template = """// GENERATED FILE - DO NOT EDIT.
 // Generated by {script_name} using data from {data_source_name}.
 //
@@ -48,26 +67,28 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// PackedGLEnums_autogen.h:
-//   Declares ANGLE-specific enums classes for GLEnum and functions operating
+// {file_name}:
+//   Declares ANGLE-specific enums classes for {api_enum_name}s and functions operating
 //   on them.
 
-#ifndef LIBANGLE_PACKEDGLENUMS_AUTOGEN_H_
-#define LIBANGLE_PACKEDGLENUMS_AUTOGEN_H_
+#ifndef LIBANGLE_{include_guard}_
+#define LIBANGLE_{include_guard}_
 
 #include <angle_gl.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
 
 #include <cstdint>
 
-namespace gl
+namespace {namespace}
 {{
 
 template<typename Enum>
-Enum FromGLenum(GLenum from);
+Enum From{api_enum_name}({api_enum_name} from);
 {content}
-}}  // namespace gl
+}}  // namespace {namespace}
 
-#endif // LIBANGLE_PACKEDGLENUMS_AUTOGEN_H_
+#endif // LIBANGLE_{include_guard}_
 """
 
 enum_declaration_template = """
@@ -80,11 +101,11 @@
 }};
 
 template<>
-{enum_name} FromGLenum<{enum_name}>(GLenum from);
-GLenum ToGLenum({enum_name} from);
+{enum_name} From{api_enum_name}<{enum_name}>({api_enum_name} from);
+{api_enum_name} To{api_enum_name}({enum_name} from);
 """
 
-def write_header(enums, path):
+def write_header(enums, path_prefix, file_name, data_source_name, namespace, api_enum_name):
     content = ['']
 
     for enum in enums:
@@ -95,17 +116,22 @@
         content.append(enum_declaration_template.format(
             enum_name = enum.name,
             max_value = str(enum.max_value),
-            value_declarations = '\n'.join(value_declarations)
+            value_declarations = '\n'.join(value_declarations),
+            api_enum_name = api_enum_name
         ))
 
     header = header_template.format(
         content = ''.join(content),
         copyright_year = datetime.date.today().year,
-        data_source_name = kJsonFileName,
-        script_name = sys.argv[0]
+        data_source_name = data_source_name,
+        script_name = sys.argv[0],
+        file_name = file_name,
+        include_guard = generate_include_guard(file_name),
+        namespace = namespace,
+        api_enum_name = api_enum_name
     )
 
-    with (open(path, 'wt')) as f:
+    with (open(path_prefix + file_name, 'wt')) as f:
         f.write(header)
 
 cpp_template = """// GENERATED FILE - DO NOT EDIT.
@@ -115,22 +141,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// PackedGLEnums_autogen.cpp:
-//   Implements ANGLE-specific enums classes for GLEnum and functions operating
+// {file_name}:
+//   Implements ANGLE-specific enums classes for {api_enum_name}s and functions operating
 //   on them.
 
 #include "common/debug.h"
-#include "libANGLE/PackedGLEnums_autogen.h"
+#include "libANGLE/{header_name}"
 
-namespace gl
+namespace {namespace}
 {{
 {content}
-}}  // namespace gl
+}}  // namespace {namespace}
 """
 
 enum_implementation_template = """
 template<>
-{enum_name} FromGLenum<{enum_name}>(GLenum from)
+{enum_name} From{api_enum_name}<{enum_name}>({api_enum_name} from)
 {{
     switch(from)
     {{
@@ -139,17 +165,17 @@
     }}
 }}
 
-GLenum ToGLenum({enum_name} from)
+{api_enum_name} To{api_enum_name}({enum_name} from)
 {{
     switch(from)
     {{
 {to_glenum_cases}
-        default: UNREACHABLE(); return GL_NONE;
+        default: UNREACHABLE(); return 0;
     }}
 }}
 """
 
-def write_cpp(enums, path):
+def write_cpp(enums, path_prefix, file_name, data_source_name, namespace, api_enum_name):
     content = ['']
 
     for enum in enums:
@@ -164,22 +190,32 @@
             enum_name = enum.name,
             from_glenum_cases = '\n'.join(from_glenum_cases),
             max_value = str(enum.max_value),
-            to_glenum_cases = '\n'.join(to_glenum_cases)
+            to_glenum_cases = '\n'.join(to_glenum_cases),
+            api_enum_name = api_enum_name
         ))
 
     cpp = cpp_template.format(
         content = ''.join(content),
         copyright_year = datetime.date.today().year,
-        data_source_name = kJsonFileName,
-        script_name = sys.argv[0]
+        data_source_name = data_source_name,
+        script_name = sys.argv[0],
+        file_name = file_name,
+        header_name = header_name_from_cpp_name(file_name),
+        namespace = namespace,
+        api_enum_name = api_enum_name
     )
 
-    with (open(path, 'wt')) as f:
+    with (open(path_prefix + file_name, 'wt')) as f:
         f.write(cpp)
 
 if __name__ == '__main__':
     path_prefix = os.path.dirname(os.path.realpath(__file__)) + os.path.sep
-    enums = load_enums(path_prefix + kJsonFileName)
 
-    write_header(enums, path_prefix + 'PackedGLEnums_autogen.h')
-    write_cpp(enums, path_prefix + 'PackedGLEnums_autogen.cpp')
+    for generator in Generators:
+        json_file = generator['json']
+        output_file = generator['output']
+        namespace = generator['namespace']
+        enum_type = generator['enum_type']
+        enums = load_enums(path_prefix + json_file)
+        write_header(enums, path_prefix, output_file + '_autogen.h', json_file, namespace, enum_type)
+        write_cpp(enums, path_prefix, output_file + '_autogen.cpp', json_file, namespace, enum_type)
diff --git a/src/libANGLE/packed_egl_enums.json b/src/libANGLE/packed_egl_enums.json
new file mode 100644
index 0000000..dc946b6
--- /dev/null
+++ b/src/libANGLE/packed_egl_enums.json
@@ -0,0 +1,8 @@
+{
+    "TextureFormat":
+    {
+        "NoTexture": "EGL_NO_TEXTURE",
+        "RGB": "EGL_TEXTURE_RGB",
+        "RGBA": "EGL_TEXTURE_RGBA"
+    }
+}
diff --git a/src/libANGLE/packed_gl_enums.json b/src/libANGLE/packed_gl_enums.json
index 936e5f3..53b840e 100644
--- a/src/libANGLE/packed_gl_enums.json
+++ b/src/libANGLE/packed_gl_enums.json
@@ -37,6 +37,14 @@
         "StreamDraw": "GL_STREAM_DRAW",
         "StreamRead": "GL_STREAM_READ"
     },
+    "ClientVertexArrayType":
+    {
+        "Vertex": "GL_VERTEX_ARRAY",
+        "Normal": "GL_NORMAL_ARRAY",
+        "Color": "GL_COLOR_ARRAY",
+        "PointSize": "GL_POINT_SIZE_ARRAY_OES",
+        "TextureCoord": "GL_TEXTURE_COORD_ARRAY"
+    },
     "CullFaceMode":
     {
         "Back": "GL_BACK",
diff --git a/src/libANGLE/queryutils.cpp b/src/libANGLE/queryutils.cpp
index 04792c6..aced901 100644
--- a/src/libANGLE/queryutils.cpp
+++ b/src/libANGLE/queryutils.cpp
@@ -1688,6 +1688,49 @@
     }
 }
 
+ClientVertexArrayType ParamToVertexArrayType(GLenum param)
+{
+    switch (param)
+    {
+        case GL_VERTEX_ARRAY:
+        case GL_VERTEX_ARRAY_BUFFER_BINDING:
+        case GL_VERTEX_ARRAY_STRIDE:
+        case GL_VERTEX_ARRAY_SIZE:
+        case GL_VERTEX_ARRAY_TYPE:
+        case GL_VERTEX_ARRAY_POINTER:
+            return ClientVertexArrayType::Vertex;
+        case GL_NORMAL_ARRAY:
+        case GL_NORMAL_ARRAY_BUFFER_BINDING:
+        case GL_NORMAL_ARRAY_STRIDE:
+        case GL_NORMAL_ARRAY_TYPE:
+        case GL_NORMAL_ARRAY_POINTER:
+            return ClientVertexArrayType::Normal;
+        case GL_COLOR_ARRAY:
+        case GL_COLOR_ARRAY_BUFFER_BINDING:
+        case GL_COLOR_ARRAY_STRIDE:
+        case GL_COLOR_ARRAY_SIZE:
+        case GL_COLOR_ARRAY_TYPE:
+        case GL_COLOR_ARRAY_POINTER:
+            return ClientVertexArrayType::Color;
+        case GL_POINT_SIZE_ARRAY_OES:
+        case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES:
+        case GL_POINT_SIZE_ARRAY_STRIDE_OES:
+        case GL_POINT_SIZE_ARRAY_TYPE_OES:
+        case GL_POINT_SIZE_ARRAY_POINTER_OES:
+            return ClientVertexArrayType::PointSize;
+        case GL_TEXTURE_COORD_ARRAY:
+        case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
+        case GL_TEXTURE_COORD_ARRAY_STRIDE:
+        case GL_TEXTURE_COORD_ARRAY_SIZE:
+        case GL_TEXTURE_COORD_ARRAY_TYPE:
+        case GL_TEXTURE_COORD_ARRAY_POINTER:
+            return ClientVertexArrayType::TextureCoord;
+        default:
+            UNREACHABLE();
+            return ClientVertexArrayType::InvalidEnum;
+    }
+}
+
 }  // namespace gl
 
 namespace egl
@@ -1894,7 +1937,7 @@
             // The EGL spec states that value is not written if the surface is not a pbuffer
             if (surface->getType() == EGL_PBUFFER_BIT)
             {
-                *value = surface->getTextureFormat();
+                *value = ToEGLenum(surface->getTextureFormat());
             }
             break;
         case EGL_TEXTURE_TARGET:
diff --git a/src/libANGLE/queryutils.h b/src/libANGLE/queryutils.h
index 90d0e32..c20e8a3 100644
--- a/src/libANGLE/queryutils.h
+++ b/src/libANGLE/queryutils.h
@@ -11,7 +11,7 @@
 
 #include "angle_gl.h"
 #include "common/angleutils.h"
-#include "libANGLE/PackedGLEnums.h"
+#include "libANGLE/PackedEnums.h"
 
 #include <EGL/egl.h>
 
@@ -145,6 +145,8 @@
                              GLenum pname,
                              GLint *params);
 
+ClientVertexArrayType ParamToVertexArrayType(GLenum param);
+
 }  // namespace gl
 
 namespace egl
diff --git a/src/libANGLE/renderer/BufferImpl.h b/src/libANGLE/renderer/BufferImpl.h
index 0ed8e2e..ed044f3 100644
--- a/src/libANGLE/renderer/BufferImpl.h
+++ b/src/libANGLE/renderer/BufferImpl.h
@@ -13,7 +13,7 @@
 #include "common/mathutil.h"
 #include "libANGLE/Error.h"
 #include "libANGLE/Observer.h"
-#include "libANGLE/PackedGLEnums.h"
+#include "libANGLE/PackedEnums.h"
 
 #include <stdint.h>
 
diff --git a/src/libANGLE/renderer/TextureImpl.h b/src/libANGLE/renderer/TextureImpl.h
index 655e9aa..859e84a 100644
--- a/src/libANGLE/renderer/TextureImpl.h
+++ b/src/libANGLE/renderer/TextureImpl.h
@@ -140,7 +140,8 @@
     virtual gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) = 0;
     virtual gl::Error releaseTexImage(const gl::Context *context) = 0;
 
-    virtual void syncState(const gl::Texture::DirtyBits &dirtyBits) = 0;
+    virtual gl::Error syncState(const gl::Context *context,
+                                const gl::Texture::DirtyBits &dirtyBits) = 0;
 
   protected:
     const gl::TextureState &mState;
diff --git a/src/libANGLE/renderer/TextureImpl_mock.h b/src/libANGLE/renderer/TextureImpl_mock.h
index 450df09..a628afe 100644
--- a/src/libANGLE/renderer/TextureImpl_mock.h
+++ b/src/libANGLE/renderer/TextureImpl_mock.h
@@ -112,7 +112,7 @@
 
     MOCK_METHOD2(setBaseLevel, gl::Error(const gl::Context *, GLuint));
 
-    MOCK_METHOD1(syncState, void(const gl::Texture::DirtyBits &));
+    MOCK_METHOD2(syncState, gl::Error(const gl::Context *, const gl::Texture::DirtyBits &));
 
     MOCK_METHOD0(destructor, void());
 
diff --git a/src/libANGLE/renderer/VertexArrayImpl.h b/src/libANGLE/renderer/VertexArrayImpl.h
index 778dd69..c15e816 100644
--- a/src/libANGLE/renderer/VertexArrayImpl.h
+++ b/src/libANGLE/renderer/VertexArrayImpl.h
@@ -13,6 +13,17 @@
 #include "libANGLE/Buffer.h"
 #include "libANGLE/VertexArray.h"
 
+// This is a helper X macro for iterating over all dirty attribs/bindings. Useful for dirty bits.
+static_assert(gl::MAX_VERTEX_ATTRIBS == 16, "Invalid max vertex attribs");
+static_assert(gl::MAX_VERTEX_ATTRIB_BINDINGS == 16, "Invalid max vertex bindings");
+#define ANGLE_VERTEX_INDEX_CASES(FUNC) \
+    FUNC(0)                            \
+    FUNC(1)                            \
+    FUNC(2)                            \
+    FUNC(3)                            \
+    FUNC(4)                            \
+    FUNC(5) FUNC(6) FUNC(7) FUNC(8) FUNC(9) FUNC(10) FUNC(11) FUNC(12) FUNC(13) FUNC(14) FUNC(15)
+
 namespace rx
 {
 class ContextImpl;
diff --git a/src/libANGLE/renderer/d3d/ImageD3D.h b/src/libANGLE/renderer/d3d/ImageD3D.h
index aca10f1..2600162 100644
--- a/src/libANGLE/renderer/d3d/ImageD3D.h
+++ b/src/libANGLE/renderer/d3d/ImageD3D.h
@@ -14,13 +14,13 @@
 #include "common/debug.h"
 
 #include "libANGLE/Error.h"
-#include "libANGLE/PackedGLEnums.h"
+#include "libANGLE/PackedEnums.h"
 
 namespace gl
 {
 class Context;
 class Framebuffer;
-struct ImageIndex;
+class ImageIndex;
 struct Box;
 struct Extents;
 struct Offset;
diff --git a/src/libANGLE/renderer/d3d/TextureD3D.cpp b/src/libANGLE/renderer/d3d/TextureD3D.cpp
index 2963fa4..adc7ad0 100644
--- a/src/libANGLE/renderer/d3d/TextureD3D.cpp
+++ b/src/libANGLE/renderer/d3d/TextureD3D.cpp
@@ -242,8 +242,8 @@
         else
         {
             gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
-            ANGLE_TRY(
-                image->loadData(context, fullImageArea, unpack, type, pixelData, index.is3D()));
+            ANGLE_TRY(image->loadData(context, fullImageArea, unpack, type, pixelData,
+                                      index.usesTex3D()));
         }
 
         mDirtyImages = true;
@@ -277,7 +277,7 @@
             return mTexStorage->setData(context, index, image, &area, type, unpack, pixelData);
         }
 
-        ANGLE_TRY(image->loadData(context, area, unpack, type, pixelData, index.is3D()));
+        ANGLE_TRY(image->loadData(context, area, unpack, type, pixelData, index.usesTex3D()));
         ANGLE_TRY(commitRegion(context, index, area));
         mDirtyImages = true;
     }
@@ -577,7 +577,7 @@
 
 bool TextureD3D::canCreateRenderTargetForImage(const gl::ImageIndex &index) const
 {
-    if (index.type == gl::TextureType::_2DMultisample)
+    if (index.getType() == gl::TextureType::_2DMultisample)
         return true;
 
     ImageD3D *image = getImage(index);
@@ -637,9 +637,10 @@
     return gl::NoError();
 }
 
-void TextureD3D::syncState(const gl::Texture::DirtyBits &dirtyBits)
+gl::Error TextureD3D::syncState(const gl::Context *context, const gl::Texture::DirtyBits &dirtyBits)
 {
     // TODO(geofflang): Use dirty bits
+    return gl::NoError();
 }
 
 gl::Error TextureD3D::releaseTexStorage(const gl::Context *context)
@@ -669,17 +670,22 @@
     // Special case for D3D11 3D textures. We can't create render targets for individual layers of a
     // 3D texture, so force the clear to the entire mip. There shouldn't ever be a case where we
     // would lose existing data.
-    if (imageIndex.type == gl::TextureType::_3D)
+    if (imageIndexIn.getType() == gl::TextureType::_3D)
     {
-        imageIndex.layerIndex = gl::ImageIndex::ENTIRE_LEVEL;
+        imageIndex =
+            gl::ImageIndex::Make3D(imageIndexIn.getLevelIndex(), gl::ImageIndex::kEntireLevel);
     }
-    else if (imageIndex.type == gl::TextureType::_2DArray &&
-             imageIndex.layerIndex == gl::ImageIndex::ENTIRE_LEVEL)
+    else if (imageIndexIn.getType() == gl::TextureType::_2DArray && !imageIndexIn.hasLayer())
     {
-        GLsizei layerCount = getLayerCount(imageIndex.mipIndex);
-        for (imageIndex.layerIndex = 0; imageIndex.layerIndex < layerCount; ++imageIndex.layerIndex)
+        std::array<GLint, gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS> tempLayerCounts;
+
+        GLint levelIndex            = imageIndexIn.getLevelIndex();
+        tempLayerCounts[levelIndex] = getLayerCount(levelIndex);
+        gl::ImageIndexIterator iterator =
+            gl::ImageIndexIterator::Make2DArray(levelIndex, levelIndex + 1, tempLayerCounts.data());
+        while (iterator.hasNext())
         {
-            ANGLE_TRY(initializeContents(context, imageIndex));
+            ANGLE_TRY(initializeContents(context, iterator.next()));
         }
         return gl::NoError();
     }
@@ -692,7 +698,10 @@
     }
 
     // Fast path: can use a render target clear.
-    if (canCreateRenderTargetForImage(imageIndex))
+    // We don't use the fast path with the zero max lod workaround because it would introduce a race
+    // between the rendertarget and the staging images.
+    if (canCreateRenderTargetForImage(imageIndex) &&
+        !mRenderer->getWorkarounds().zeroMaxLodWorkaround)
     {
         ANGLE_TRY(ensureRenderTarget(context));
         ASSERT(mTexStorage);
@@ -774,10 +783,10 @@
 
 ImageD3D *TextureD3D_2D::getImage(const gl::ImageIndex &index) const
 {
-    ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    ASSERT(index.getLevelIndex() < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
     ASSERT(!index.hasLayer());
-    ASSERT(index.type == gl::TextureType::_2D);
-    return mImageArray[index.mipIndex].get();
+    ASSERT(index.getType() == gl::TextureType::_2D);
+    return mImageArray[index.getLevelIndex()].get();
 }
 
 GLsizei TextureD3D_2D::getLayerCount(int level) const
@@ -829,32 +838,33 @@
                                   const gl::PixelUnpackState &unpack,
                                   const uint8_t *pixels)
 {
-    ASSERT(index.target == gl::TextureTarget::_2D && size.depth == 1);
+    ASSERT(index.getTarget() == gl::TextureTarget::_2D && size.depth == 1);
 
     const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
 
     bool fastUnpacked = false;
 
-    ANGLE_TRY(redefineImage(context, index.mipIndex, internalFormatInfo.sizedInternalFormat, size,
-                            false));
+    ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormatInfo.sizedInternalFormat,
+                            size, false));
 
     // Attempt a fast gpu copy of the pixel data to the surface
     gl::Buffer *unpackBuffer =
         context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
     if (isFastUnpackable(unpackBuffer, internalFormatInfo.sizedInternalFormat) &&
-        isLevelComplete(index.mipIndex))
+        isLevelComplete(index.getLevelIndex()))
     {
         // Will try to create RT storage if it does not exist
         RenderTargetD3D *destRenderTarget = nullptr;
         ANGLE_TRY(getRenderTarget(context, index, &destRenderTarget));
 
-        gl::Box destArea(0, 0, 0, getWidth(index.mipIndex), getHeight(index.mipIndex), 1);
+        gl::Box destArea(0, 0, 0, getWidth(index.getLevelIndex()), getHeight(index.getLevelIndex()),
+                         1);
 
         ANGLE_TRY(fastUnpackPixels(context, unpack, pixels, destArea,
                                    internalFormatInfo.sizedInternalFormat, type, destRenderTarget));
 
         // Ensure we don't overwrite our newly initialized data
-        mImageArray[index.mipIndex]->markClean();
+        mImageArray[index.getLevelIndex()]->markClean();
 
         fastUnpacked = true;
     }
@@ -875,16 +885,16 @@
                                      const gl::PixelUnpackState &unpack,
                                      const uint8_t *pixels)
 {
-    ASSERT(index.target == gl::TextureTarget::_2D && area.depth == 1 && area.z == 0);
+    ASSERT(index.getTarget() == gl::TextureTarget::_2D && area.depth == 1 && area.z == 0);
 
     gl::Buffer *unpackBuffer =
         context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
-    GLenum mipFormat = getInternalFormat(index.mipIndex);
-    if (isFastUnpackable(unpackBuffer, mipFormat) && isLevelComplete(index.mipIndex))
+    GLenum mipFormat = getInternalFormat(index.getLevelIndex());
+    if (isFastUnpackable(unpackBuffer, mipFormat) && isLevelComplete(index.getLevelIndex()))
     {
         RenderTargetD3D *renderTarget = nullptr;
         ANGLE_TRY(getRenderTarget(context, index, &renderTarget));
-        ASSERT(!mImageArray[index.mipIndex]->isDirty());
+        ASSERT(!mImageArray[index.getLevelIndex()]->isDirty());
 
         return fastUnpackPixels(context, unpack, pixels, area, mipFormat, type, renderTarget);
     }
@@ -902,10 +912,10 @@
                                             size_t imageSize,
                                             const uint8_t *pixels)
 {
-    ASSERT(index.target == gl::TextureTarget::_2D && size.depth == 1);
+    ASSERT(index.getTarget() == gl::TextureTarget::_2D && size.depth == 1);
 
     // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
-    ANGLE_TRY(redefineImage(context, index.mipIndex, internalFormat, size, false));
+    ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormat, size, false));
 
     return setCompressedImageImpl(context, index, unpack, pixels, 0);
 }
@@ -918,7 +928,7 @@
                                                size_t imageSize,
                                                const uint8_t *pixels)
 {
-    ASSERT(index.target == gl::TextureTarget::_2D && area.depth == 1 && area.z == 0);
+    ASSERT(index.getTarget() == gl::TextureTarget::_2D && area.depth == 1 && area.z == 0);
     ANGLE_TRY(TextureD3D::subImageCompressed(context, index, area, format, unpack, pixels, 0));
 
     return commitRegion(context, index, area);
@@ -930,12 +940,12 @@
                                    GLenum internalFormat,
                                    gl::Framebuffer *source)
 {
-    ASSERT(index.target == gl::TextureTarget::_2D);
+    ASSERT(index.getTarget() == gl::TextureTarget::_2D);
 
     const gl::InternalFormat &internalFormatInfo =
         gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
     gl::Extents sourceExtents(origSourceArea.width, origSourceArea.height, 1);
-    ANGLE_TRY(redefineImage(context, index.mipIndex, internalFormatInfo.sizedInternalFormat,
+    ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormatInfo.sizedInternalFormat,
                             sourceExtents, false));
 
     gl::Extents fbSize = source->getReadColorbuffer()->getSize();
@@ -945,21 +955,13 @@
                    origSourceArea.x + origSourceArea.width > fbSize.width ||
                    origSourceArea.y + origSourceArea.height > fbSize.height;
 
-    // In WebGL mode we need to zero the texture outside the framebuffer.
-    // If we have robust resource init, it was already zeroed by redefineImage() above, otherwise
-    // zero it explicitly.
-    // TODO(fjhenigman): When robust resource is fully implemented look into making it a
-    // prerequisite for WebGL and deleting this code.
+    // WebGL requires that pixels that would be outside the framebuffer are treated as zero values,
+    // so clear the mip level to 0 prior to making the copy if any pixel would be sampled outside.
+    // Same thing for robust resource init.
     if (outside &&
         (context->getExtensions().webglCompatibility || context->isRobustResourceInitEnabled()))
     {
-        angle::MemoryBuffer *zero;
-        ANGLE_TRY(context->getZeroFilledBuffer(
-            origSourceArea.width * origSourceArea.height * internalFormatInfo.pixelBytes, &zero));
-        gl::PixelUnpackState unpack;
-        unpack.alignment = 1;
-        ANGLE_TRY(setImage(context, index, internalFormat, sourceExtents, internalFormatInfo.format,
-                           internalFormatInfo.type, unpack, zero->data()));
+        ANGLE_TRY(initializeContents(context, index));
     }
 
     gl::Rectangle sourceArea;
@@ -976,19 +978,19 @@
     // so we should use the non-rendering copy path.
     if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
     {
-        ANGLE_TRY(mImageArray[index.mipIndex]->copyFromFramebuffer(context, destOffset, sourceArea,
-                                                                   source));
+        ANGLE_TRY(mImageArray[index.getLevelIndex()]->copyFromFramebuffer(context, destOffset,
+                                                                          sourceArea, source));
         mDirtyImages = true;
     }
     else
     {
         ANGLE_TRY(ensureRenderTarget(context));
 
-        if (sourceArea.width != 0 && sourceArea.height != 0 && isValidLevel(index.mipIndex))
+        if (sourceArea.width != 0 && sourceArea.height != 0 && isValidLevel(index.getLevelIndex()))
         {
-            ANGLE_TRY(updateStorageLevel(context, index.mipIndex));
+            ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
             ANGLE_TRY(mRenderer->copyImage2D(context, source, sourceArea, internalFormat,
-                                             destOffset, mTexStorage, index.mipIndex));
+                                             destOffset, mTexStorage, index.getLevelIndex()));
         }
     }
 
@@ -1001,7 +1003,7 @@
                                       const gl::Rectangle &origSourceArea,
                                       gl::Framebuffer *source)
 {
-    ASSERT(index.target == gl::TextureTarget::_2D && origDestOffset.z == 0);
+    ASSERT(index.getTarget() == gl::TextureTarget::_2D && origDestOffset.z == 0);
 
     gl::Extents fbSize = source->getReadColorbuffer()->getSize();
     gl::Rectangle sourceArea;
@@ -1020,20 +1022,20 @@
     // so we should use the non-rendering copy path.
     if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
     {
-        ANGLE_TRY(mImageArray[index.mipIndex]->copyFromFramebuffer(context, destOffset, sourceArea,
-                                                                   source));
+        ANGLE_TRY(mImageArray[index.getLevelIndex()]->copyFromFramebuffer(context, destOffset,
+                                                                          sourceArea, source));
         mDirtyImages = true;
     }
     else
     {
         ANGLE_TRY(ensureRenderTarget(context));
 
-        if (isValidLevel(index.mipIndex))
+        if (isValidLevel(index.getLevelIndex()))
         {
-            ANGLE_TRY(updateStorageLevel(context, index.mipIndex));
+            ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
             ANGLE_TRY(mRenderer->copyImage2D(context, source, sourceArea,
                                              gl::GetUnsizedFormat(getBaseLevelInternalFormat()),
-                                             destOffset, mTexStorage, index.mipIndex));
+                                             destOffset, mTexStorage, index.getLevelIndex()));
         }
     }
 
@@ -1050,7 +1052,7 @@
                                      bool unpackUnmultiplyAlpha,
                                      const gl::Texture *source)
 {
-    ASSERT(index.target == gl::TextureTarget::_2D);
+    ASSERT(index.getTarget() == gl::TextureTarget::_2D);
 
     gl::TextureType sourceType = source->getType();
 
@@ -1059,22 +1061,22 @@
         static_cast<int>(source->getWidth(NonCubeTextureTypeToTarget(sourceType), sourceLevel)),
         static_cast<int>(source->getHeight(NonCubeTextureTypeToTarget(sourceType), sourceLevel)),
         1);
-    ANGLE_TRY(redefineImage(context, index.mipIndex, internalFormatInfo.sizedInternalFormat, size,
-                            false));
+    ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormatInfo.sizedInternalFormat,
+                            size, false));
 
     gl::Rectangle sourceRect(0, 0, size.width, size.height);
     gl::Offset destOffset(0, 0, 0);
 
-    if (!isSRGB(index.mipIndex) && canCreateRenderTargetForImage(index))
+    if (!isSRGB(index.getLevelIndex()) && canCreateRenderTargetForImage(index))
     {
         ANGLE_TRY(ensureRenderTarget(context));
-        ASSERT(isValidLevel(index.mipIndex));
-        ANGLE_TRY(updateStorageLevel(context, index.mipIndex));
+        ASSERT(isValidLevel(index.getLevelIndex()));
+        ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
 
         ANGLE_TRY(mRenderer->copyTexture(
             context, source, static_cast<GLint>(sourceLevel), sourceRect, internalFormatInfo.format,
-            internalFormatInfo.type, destOffset, mTexStorage, index.target, index.mipIndex,
-            unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+            internalFormatInfo.type, destOffset, mTexStorage, index.getTarget(),
+            index.getLevelIndex(), unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
     }
     else
     {
@@ -1108,20 +1110,20 @@
                                         bool unpackUnmultiplyAlpha,
                                         const gl::Texture *source)
 {
-    ASSERT(index.target == gl::TextureTarget::_2D);
+    ASSERT(index.getTarget() == gl::TextureTarget::_2D);
 
-    if (!isSRGB(index.mipIndex) && canCreateRenderTargetForImage(index))
+    if (!isSRGB(index.getLevelIndex()) && canCreateRenderTargetForImage(index))
     {
         ANGLE_TRY(ensureRenderTarget(context));
-        ASSERT(isValidLevel(index.mipIndex));
-        ANGLE_TRY(updateStorageLevel(context, index.mipIndex));
+        ASSERT(isValidLevel(index.getLevelIndex()));
+        ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
 
         const gl::InternalFormat &internalFormatInfo =
-            gl::GetSizedInternalFormatInfo(getInternalFormat(index.mipIndex));
+            gl::GetSizedInternalFormatInfo(getInternalFormat(index.getLevelIndex()));
         ANGLE_TRY(mRenderer->copyTexture(
             context, source, static_cast<GLint>(sourceLevel), sourceArea, internalFormatInfo.format,
-            internalFormatInfo.type, destOffset, mTexStorage, index.target, index.mipIndex,
-            unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+            internalFormatInfo.type, destOffset, mTexStorage, index.getTarget(),
+            index.getLevelIndex(), unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
     }
     else
     {
@@ -1297,7 +1299,7 @@
 
     // ensure the underlying texture is created
     ANGLE_TRY(ensureRenderTarget(context));
-    ANGLE_TRY(updateStorageLevel(context, index.mipIndex));
+    ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
 
     return mTexStorage->getRenderTarget(context, index, outRT);
 }
@@ -1352,7 +1354,7 @@
 
 bool TextureD3D_2D::isImageComplete(const gl::ImageIndex &index) const
 {
-    return isLevelComplete(index.mipIndex);
+    return isLevelComplete(index.getLevelIndex());
 }
 
 // Constructs a native texture resource from the texture images
@@ -1532,8 +1534,8 @@
 
 bool TextureD3D_2D::isValidIndex(const gl::ImageIndex &index) const
 {
-    return (mTexStorage && index.type == gl::TextureType::_2D && index.mipIndex >= 0 &&
-            index.mipIndex < mTexStorage->getLevelCount());
+    return (mTexStorage && index.getType() == gl::TextureType::_2D && index.getLevelIndex() >= 0 &&
+            index.getLevelIndex() < mTexStorage->getLevelCount());
 }
 
 void TextureD3D_2D::markAllImagesDirty()
@@ -1585,9 +1587,9 @@
 
 ImageD3D *TextureD3D_Cube::getImage(const gl::ImageIndex &index) const
 {
-    ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
-    ASSERT(gl::TextureTargetToType(index.target) == gl::TextureType::CubeMap);
-    return mImageArray[index.cubeMapFaceIndex()][index.mipIndex].get();
+    ASSERT(index.getLevelIndex() < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    ASSERT(gl::TextureTargetToType(index.getTarget()) == gl::TextureType::CubeMap);
+    return mImageArray[index.cubeMapFaceIndex()][index.getLevelIndex()].get();
 }
 
 GLsizei TextureD3D_Cube::getLayerCount(int level) const
@@ -1634,7 +1636,7 @@
     ASSERT(size.depth == 1);
 
     const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
-    ANGLE_TRY(redefineImage(context, index.cubeMapFaceIndex(), index.mipIndex,
+    ANGLE_TRY(redefineImage(context, index.cubeMapFaceIndex(), index.getLevelIndex(),
                             internalFormatInfo.sizedInternalFormat, size, false));
 
     return setImageImpl(context, index, type, unpack, pixels, 0);
@@ -1663,8 +1665,8 @@
     ASSERT(size.depth == 1);
 
     // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
-    ANGLE_TRY(redefineImage(context, index.cubeMapFaceIndex(), index.mipIndex, internalFormat, size,
-                            false));
+    ANGLE_TRY(redefineImage(context, index.cubeMapFaceIndex(), index.getLevelIndex(),
+                            internalFormat, size, false));
 
     return setCompressedImageImpl(context, index, unpack, pixels, 0);
 }
@@ -1694,7 +1696,7 @@
         gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
 
     gl::Extents size(origSourceArea.width, origSourceArea.height, 1);
-    ANGLE_TRY(redefineImage(context, faceIndex, index.mipIndex,
+    ANGLE_TRY(redefineImage(context, faceIndex, index.getLevelIndex(),
                             internalFormatInfo.sizedInternalFormat, size, false));
 
     gl::Extents fbSize = source->getReadColorbuffer()->getSize();
@@ -1704,21 +1706,13 @@
                    origSourceArea.x + origSourceArea.width > fbSize.width ||
                    origSourceArea.y + origSourceArea.height > fbSize.height;
 
-    // In WebGL mode we need to zero the texture outside the framebuffer.
-    // If we have robust resource init, it was already zeroed by redefineImage() above, otherwise
-    // zero it explicitly.
-    // TODO(fjhenigman): When robust resource is fully implemented look into making it a
-    // prerequisite for WebGL and deleting this code.
-    if (outside && context->getExtensions().webglCompatibility &&
-        !context->isRobustResourceInitEnabled())
+    // WebGL requires that pixels that would be outside the framebuffer are treated as zero values,
+    // so clear the mip level to 0 prior to making the copy if any pixel would be sampled outside.
+    // Same thing for robust resource init.
+    if (outside &&
+        (context->getExtensions().webglCompatibility || context->isRobustResourceInitEnabled()))
     {
-        angle::MemoryBuffer *zero;
-        ANGLE_TRY(context->getZeroFilledBuffer(
-            origSourceArea.width * origSourceArea.height * internalFormatInfo.pixelBytes, &zero));
-        gl::PixelUnpackState unpack;
-        unpack.alignment = 1;
-        ANGLE_TRY(setImage(context, index, internalFormat, size, internalFormatInfo.format,
-                           internalFormatInfo.type, unpack, zero->data()));
+        ANGLE_TRY(initializeContents(context, index));
     }
 
     gl::Rectangle sourceArea;
@@ -1735,8 +1729,8 @@
     // so we should use the non-rendering copy path.
     if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
     {
-        ANGLE_TRY(mImageArray[faceIndex][index.mipIndex]->copyFromFramebuffer(context, destOffset,
-                                                                              sourceArea, source));
+        ANGLE_TRY(mImageArray[faceIndex][index.getLevelIndex()]->copyFromFramebuffer(
+            context, destOffset, sourceArea, source));
         mDirtyImages = true;
     }
     else
@@ -1745,12 +1739,12 @@
 
         ASSERT(size.width == size.height);
 
-        if (size.width > 0 && isValidFaceLevel(faceIndex, index.mipIndex))
+        if (size.width > 0 && isValidFaceLevel(faceIndex, index.getLevelIndex()))
         {
-            ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, index.mipIndex));
+            ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, index.getLevelIndex()));
             ANGLE_TRY(mRenderer->copyImageCube(context, source, sourceArea, internalFormat,
-                                               destOffset, mTexStorage, index.target,
-                                               index.mipIndex));
+                                               destOffset, mTexStorage, index.getTarget(),
+                                               index.getLevelIndex()));
         }
     }
 
@@ -1779,19 +1773,19 @@
     // so we should use the non-rendering copy path.
     if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
     {
-        ANGLE_TRY(mImageArray[faceIndex][index.mipIndex]->copyFromFramebuffer(context, destOffset,
-                                                                              sourceArea, source));
+        ANGLE_TRY(mImageArray[faceIndex][index.getLevelIndex()]->copyFromFramebuffer(
+            context, destOffset, sourceArea, source));
         mDirtyImages = true;
     }
     else
     {
         ANGLE_TRY(ensureRenderTarget(context));
-        if (isValidFaceLevel(faceIndex, index.mipIndex))
+        if (isValidFaceLevel(faceIndex, index.getLevelIndex()))
         {
-            ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, index.mipIndex));
+            ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, index.getLevelIndex()));
             ANGLE_TRY(mRenderer->copyImageCube(
                 context, source, sourceArea, gl::GetUnsizedFormat(getBaseLevelInternalFormat()),
-                destOffset, mTexStorage, index.target, index.mipIndex));
+                destOffset, mTexStorage, index.getTarget(), index.getLevelIndex()));
         }
     }
 
@@ -1808,7 +1802,7 @@
                                        bool unpackUnmultiplyAlpha,
                                        const gl::Texture *source)
 {
-    ASSERT(gl::TextureTargetToType(index.target) == gl::TextureType::CubeMap);
+    ASSERT(gl::TextureTargetToType(index.getTarget()) == gl::TextureType::CubeMap);
 
     gl::TextureTarget sourceTarget = NonCubeTextureTypeToTarget(source->getType());
 
@@ -1817,22 +1811,22 @@
     const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
     gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)),
                      static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1);
-    ANGLE_TRY(redefineImage(context, faceIndex, index.mipIndex,
+    ANGLE_TRY(redefineImage(context, faceIndex, index.getLevelIndex(),
                             internalFormatInfo.sizedInternalFormat, size, false));
 
     gl::Rectangle sourceRect(0, 0, size.width, size.height);
     gl::Offset destOffset(0, 0, 0);
 
-    if (!isSRGB(index.mipIndex, faceIndex) && canCreateRenderTargetForImage(index))
+    if (!isSRGB(index.getLevelIndex(), faceIndex) && canCreateRenderTargetForImage(index))
     {
         ANGLE_TRY(ensureRenderTarget(context));
-        ASSERT(isValidFaceLevel(faceIndex, index.mipIndex));
-        ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, index.mipIndex));
+        ASSERT(isValidFaceLevel(faceIndex, index.getLevelIndex()));
+        ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, index.getLevelIndex()));
 
         ANGLE_TRY(mRenderer->copyTexture(
             context, source, static_cast<GLint>(sourceLevel), sourceRect, internalFormatInfo.format,
-            internalFormatInfo.type, destOffset, mTexStorage, index.target, index.mipIndex,
-            unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+            internalFormatInfo.type, destOffset, mTexStorage, index.getTarget(),
+            index.getLevelIndex(), unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
     }
     else
     {
@@ -1866,22 +1860,22 @@
                                           bool unpackUnmultiplyAlpha,
                                           const gl::Texture *source)
 {
-    ASSERT(gl::TextureTargetToType(index.target) == gl::TextureType::CubeMap);
+    ASSERT(gl::TextureTargetToType(index.getTarget()) == gl::TextureType::CubeMap);
 
     GLint faceIndex = index.cubeMapFaceIndex();
 
-    if (!isSRGB(index.mipIndex, faceIndex) && canCreateRenderTargetForImage(index))
+    if (!isSRGB(index.getLevelIndex(), faceIndex) && canCreateRenderTargetForImage(index))
     {
         ANGLE_TRY(ensureRenderTarget(context));
-        ASSERT(isValidFaceLevel(faceIndex, index.mipIndex));
-        ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, index.mipIndex));
+        ASSERT(isValidFaceLevel(faceIndex, index.getLevelIndex()));
+        ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, index.getLevelIndex()));
 
         const gl::InternalFormat &internalFormatInfo =
-            gl::GetSizedInternalFormatInfo(getInternalFormat(index.mipIndex, faceIndex));
+            gl::GetSizedInternalFormatInfo(getInternalFormat(index.getLevelIndex(), faceIndex));
         ANGLE_TRY(mRenderer->copyTexture(
             context, source, static_cast<GLint>(sourceLevel), sourceArea, internalFormatInfo.format,
-            internalFormatInfo.type, destOffset, mTexStorage, index.target, index.mipIndex,
-            unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+            internalFormatInfo.type, destOffset, mTexStorage, index.getTarget(),
+            index.getLevelIndex(), unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
     }
     else
     {
@@ -2013,11 +2007,11 @@
                                            const gl::ImageIndex &index,
                                            RenderTargetD3D **outRT)
 {
-    ASSERT(gl::TextureTargetToType(index.target) == gl::TextureType::CubeMap);
+    ASSERT(gl::TextureTargetToType(index.getTarget()) == gl::TextureType::CubeMap);
 
     // ensure the underlying texture is created
     ANGLE_TRY(ensureRenderTarget(context));
-    ANGLE_TRY(updateStorageFaceLevel(context, index.cubeMapFaceIndex(), index.mipIndex));
+    ANGLE_TRY(updateStorageFaceLevel(context, index.cubeMapFaceIndex(), index.getLevelIndex()));
 
     return mTexStorage->getRenderTarget(context, index, outRT);
 }
@@ -2182,7 +2176,7 @@
 
 bool TextureD3D_Cube::isImageComplete(const gl::ImageIndex &index) const
 {
-    return isFaceLevelComplete(index.cubeMapFaceIndex(), index.mipIndex);
+    return isFaceLevelComplete(index.cubeMapFaceIndex(), index.getLevelIndex());
 }
 
 gl::Error TextureD3D_Cube::updateStorageFaceLevel(const gl::Context *context,
@@ -2249,9 +2243,9 @@
 
 bool TextureD3D_Cube::isValidIndex(const gl::ImageIndex &index) const
 {
-    return (mTexStorage && index.type == gl::TextureType::CubeMap &&
-            gl::TextureTargetToType(index.target) == gl::TextureType::CubeMap &&
-            index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount());
+    return (mTexStorage && index.getType() == gl::TextureType::CubeMap &&
+            gl::TextureTargetToType(index.getTarget()) == gl::TextureType::CubeMap &&
+            index.getLevelIndex() >= 0 && index.getLevelIndex() < mTexStorage->getLevelCount());
 }
 
 void TextureD3D_Cube::markAllImagesDirty()
@@ -2300,10 +2294,10 @@
 
 ImageD3D *TextureD3D_3D::getImage(const gl::ImageIndex &index) const
 {
-    ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    ASSERT(index.getLevelIndex() < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
     ASSERT(!index.hasLayer());
-    ASSERT(index.type == gl::TextureType::_3D);
-    return mImageArray[index.mipIndex].get();
+    ASSERT(index.getType() == gl::TextureType::_3D);
+    return mImageArray[index.getLevelIndex()].get();
 }
 
 GLsizei TextureD3D_3D::getLayerCount(int level) const
@@ -2366,11 +2360,11 @@
                                   const gl::PixelUnpackState &unpack,
                                   const uint8_t *pixels)
 {
-    ASSERT(index.target == gl::TextureTarget::_3D);
+    ASSERT(index.getTarget() == gl::TextureTarget::_3D);
     const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
 
-    ANGLE_TRY(redefineImage(context, index.mipIndex, internalFormatInfo.sizedInternalFormat, size,
-                            false));
+    ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormatInfo.sizedInternalFormat,
+                            size, false));
 
     bool fastUnpacked = false;
 
@@ -2378,20 +2372,20 @@
     gl::Buffer *unpackBuffer =
         context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
     if (isFastUnpackable(unpackBuffer, internalFormatInfo.sizedInternalFormat) && !size.empty() &&
-        isLevelComplete(index.mipIndex))
+        isLevelComplete(index.getLevelIndex()))
     {
         // Will try to create RT storage if it does not exist
         RenderTargetD3D *destRenderTarget = nullptr;
         ANGLE_TRY(getRenderTarget(context, index, &destRenderTarget));
 
-        gl::Box destArea(0, 0, 0, getWidth(index.mipIndex), getHeight(index.mipIndex),
-                         getDepth(index.mipIndex));
+        gl::Box destArea(0, 0, 0, getWidth(index.getLevelIndex()), getHeight(index.getLevelIndex()),
+                         getDepth(index.getLevelIndex()));
 
         ANGLE_TRY(fastUnpackPixels(context, unpack, pixels, destArea,
                                    internalFormatInfo.sizedInternalFormat, type, destRenderTarget));
 
         // Ensure we don't overwrite our newly initialized data
-        mImageArray[index.mipIndex]->markClean();
+        mImageArray[index.getLevelIndex()]->markClean();
 
         fastUnpacked = true;
     }
@@ -2412,17 +2406,17 @@
                                      const gl::PixelUnpackState &unpack,
                                      const uint8_t *pixels)
 {
-    ASSERT(index.target == gl::TextureTarget::_3D);
+    ASSERT(index.getTarget() == gl::TextureTarget::_3D);
 
     // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
     gl::Buffer *unpackBuffer =
         context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
-    GLenum mipFormat = getInternalFormat(index.mipIndex);
-    if (isFastUnpackable(unpackBuffer, mipFormat) && isLevelComplete(index.mipIndex))
+    GLenum mipFormat = getInternalFormat(index.getLevelIndex());
+    if (isFastUnpackable(unpackBuffer, mipFormat) && isLevelComplete(index.getLevelIndex()))
     {
         RenderTargetD3D *destRenderTarget = nullptr;
         ANGLE_TRY(getRenderTarget(context, index, &destRenderTarget));
-        ASSERT(!mImageArray[index.mipIndex]->isDirty());
+        ASSERT(!mImageArray[index.getLevelIndex()]->isDirty());
 
         return fastUnpackPixels(context, unpack, pixels, area, mipFormat, type, destRenderTarget);
     }
@@ -2440,10 +2434,10 @@
                                             size_t imageSize,
                                             const uint8_t *pixels)
 {
-    ASSERT(index.target == gl::TextureTarget::_3D);
+    ASSERT(index.getTarget() == gl::TextureTarget::_3D);
 
     // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
-    ANGLE_TRY(redefineImage(context, index.mipIndex, internalFormat, size, false));
+    ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormat, size, false));
 
     return setCompressedImageImpl(context, index, unpack, pixels, 0);
 }
@@ -2456,7 +2450,7 @@
                                                size_t imageSize,
                                                const uint8_t *pixels)
 {
-    ASSERT(index.target == gl::TextureTarget::_3D);
+    ASSERT(index.getTarget() == gl::TextureTarget::_3D);
 
     ANGLE_TRY(TextureD3D::subImageCompressed(context, index, area, format, unpack, pixels, 0));
     return commitRegion(context, index, area);
@@ -2478,7 +2472,7 @@
                                       const gl::Rectangle &sourceArea,
                                       gl::Framebuffer *source)
 {
-    ASSERT(index.target == gl::TextureTarget::_3D);
+    ASSERT(index.getTarget() == gl::TextureTarget::_3D);
 
     gl::Extents fbSize = source->getReadColorbuffer()->getSize();
     gl::Rectangle clippedSourceArea;
@@ -2496,18 +2490,19 @@
     // date before the copy and then copy back to the storage afterwards if needed.
     // TODO: Investigate 3D blits in D3D11.
 
-    bool syncTexStorage = mTexStorage && isLevelComplete(index.mipIndex);
+    bool syncTexStorage = mTexStorage && isLevelComplete(index.getLevelIndex());
     if (syncTexStorage)
     {
-        ANGLE_TRY(mImageArray[index.mipIndex]->copyFromTexStorage(context, index, mTexStorage));
+        ANGLE_TRY(
+            mImageArray[index.getLevelIndex()]->copyFromTexStorage(context, index, mTexStorage));
     }
-    ANGLE_TRY(mImageArray[index.mipIndex]->copyFromFramebuffer(context, clippedDestOffset,
-                                                               clippedSourceArea, source));
+    ANGLE_TRY(mImageArray[index.getLevelIndex()]->copyFromFramebuffer(context, clippedDestOffset,
+                                                                      clippedSourceArea, source));
     mDirtyImages = true;
 
     if (syncTexStorage)
     {
-        ANGLE_TRY(updateStorageLevel(context, index.mipIndex));
+        ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
     }
 
     return gl::NoError();
@@ -2593,7 +2588,7 @@
     }
     else
     {
-        ANGLE_TRY(updateStorageLevel(context, index.mipIndex));
+        ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
     }
 
     return mTexStorage->getRenderTarget(context, index, outRT);
@@ -2739,7 +2734,7 @@
 
 bool TextureD3D_3D::isImageComplete(const gl::ImageIndex &index) const
 {
-    return isLevelComplete(index.mipIndex);
+    return isLevelComplete(index.getLevelIndex());
 }
 
 gl::Error TextureD3D_3D::updateStorageLevel(const gl::Context *context, int level)
@@ -2792,7 +2787,8 @@
 gl::ImageIndexIterator TextureD3D_3D::imageIterator() const
 {
     return gl::ImageIndexIterator::Make3D(0, mTexStorage->getLevelCount(),
-                                          gl::ImageIndex::ENTIRE_LEVEL, gl::ImageIndex::ENTIRE_LEVEL);
+                                          gl::ImageIndex::kEntireLevel,
+                                          gl::ImageIndex::kEntireLevel);
 }
 
 gl::ImageIndex TextureD3D_3D::getImageIndex(GLint mip, GLint /*layer*/) const
@@ -2803,8 +2799,8 @@
 
 bool TextureD3D_3D::isValidIndex(const gl::ImageIndex &index) const
 {
-    return (mTexStorage && index.type == gl::TextureType::_3D && index.mipIndex >= 0 &&
-            index.mipIndex < mTexStorage->getLevelCount());
+    return (mTexStorage && index.getType() == gl::TextureType::_3D && index.getLevelIndex() >= 0 &&
+            index.getLevelIndex() < mTexStorage->getLevelCount());
 }
 
 void TextureD3D_3D::markAllImagesDirty()
@@ -2855,12 +2851,14 @@
 
 ImageD3D *TextureD3D_2DArray::getImage(const gl::ImageIndex &index) const
 {
-    ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
-    ASSERT(index.layerIndex != gl::ImageIndex::ENTIRE_LEVEL);
-    ASSERT((index.layerIndex == 0 && mLayerCounts[index.mipIndex] == 0) ||
-           index.layerIndex < mLayerCounts[index.mipIndex]);
-    ASSERT(index.type == gl::TextureType::_2DArray);
-    return (mImageArray[index.mipIndex] ? mImageArray[index.mipIndex][index.layerIndex] : nullptr);
+    ASSERT(index.getLevelIndex() < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+    ASSERT(index.hasLayer());
+    ASSERT((index.getLayerIndex() == 0 && mLayerCounts[index.getLevelIndex()] == 0) ||
+           index.getLayerIndex() < mLayerCounts[index.getLevelIndex()]);
+    ASSERT(index.getType() == gl::TextureType::_2DArray);
+    return (mImageArray[index.getLevelIndex()]
+                ? mImageArray[index.getLevelIndex()][index.getLayerIndex()]
+                : nullptr);
 }
 
 GLsizei TextureD3D_2DArray::getLayerCount(int level) const
@@ -2906,11 +2904,12 @@
                                        const gl::PixelUnpackState &unpack,
                                        const uint8_t *pixels)
 {
-    ASSERT(index.target == gl::TextureTarget::_2DArray);
+    ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);
 
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
 
-    ANGLE_TRY(redefineImage(context, index.mipIndex, formatInfo.sizedInternalFormat, size, false));
+    ANGLE_TRY(
+        redefineImage(context, index.getLevelIndex(), formatInfo.sizedInternalFormat, size, false));
 
     GLsizei inputDepthPitch              = 0;
     ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(type, size.width, size.height, unpack.alignment,
@@ -2920,7 +2919,7 @@
     for (int i = 0; i < size.depth; i++)
     {
         const ptrdiff_t layerOffset = (inputDepthPitch * i);
-        gl::ImageIndex layerIndex   = gl::ImageIndex::Make2DArray(index.mipIndex, i);
+        gl::ImageIndex layerIndex   = gl::ImageIndex::Make2DArray(index.getLevelIndex(), i);
         ANGLE_TRY(setImageImpl(context, layerIndex, type, unpack, pixels, layerOffset));
     }
 
@@ -2935,9 +2934,9 @@
                                           const gl::PixelUnpackState &unpack,
                                           const uint8_t *pixels)
 {
-    ASSERT(index.target == gl::TextureTarget::_2DArray);
+    ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);
     const gl::InternalFormat &formatInfo =
-        gl::GetInternalFormatInfo(getInternalFormat(index.mipIndex), type);
+        gl::GetInternalFormatInfo(getInternalFormat(index.getLevelIndex()), type);
     GLsizei inputDepthPitch              = 0;
     ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment,
                                                   unpack.rowLength, unpack.imageHeight),
@@ -2950,7 +2949,7 @@
 
         gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1);
 
-        gl::ImageIndex layerIndex = gl::ImageIndex::Make2DArray(index.mipIndex, layer);
+        gl::ImageIndex layerIndex = gl::ImageIndex::Make2DArray(index.getLevelIndex(), layer);
         ANGLE_TRY(TextureD3D::subImage(context, layerIndex, layerArea, format, type, unpack, pixels,
                                        layerOffset));
     }
@@ -2966,10 +2965,10 @@
                                                  size_t imageSize,
                                                  const uint8_t *pixels)
 {
-    ASSERT(index.target == gl::TextureTarget::_2DArray);
+    ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);
 
     // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
-    ANGLE_TRY(redefineImage(context, index.mipIndex, internalFormat, size, false));
+    ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormat, size, false));
 
     const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
     GLsizei inputDepthPitch              = 0;
@@ -2981,7 +2980,7 @@
     {
         const ptrdiff_t layerOffset = (inputDepthPitch * i);
 
-        gl::ImageIndex layerIndex = gl::ImageIndex::Make2DArray(index.mipIndex, i);
+        gl::ImageIndex layerIndex = gl::ImageIndex::Make2DArray(index.getLevelIndex(), i);
         ANGLE_TRY(setCompressedImageImpl(context, layerIndex, unpack, pixels, layerOffset));
     }
 
@@ -2996,7 +2995,7 @@
                                                     size_t imageSize,
                                                     const uint8_t *pixels)
 {
-    ASSERT(index.target == gl::TextureTarget::_2DArray);
+    ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);
 
     const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(format);
     GLsizei inputDepthPitch              = 0;
@@ -3011,7 +3010,7 @@
 
         gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1);
 
-        gl::ImageIndex layerIndex = gl::ImageIndex::Make2DArray(index.mipIndex, layer);
+        gl::ImageIndex layerIndex = gl::ImageIndex::Make2DArray(index.getLevelIndex(), layer);
         ANGLE_TRY(TextureD3D::subImageCompressed(context, layerIndex, layerArea, format, unpack,
                                                  pixels, layerOffset));
         ANGLE_TRY(commitRegion(context, layerIndex, layerArea));
@@ -3036,7 +3035,7 @@
                                            const gl::Rectangle &sourceArea,
                                            gl::Framebuffer *source)
 {
-    ASSERT(index.target == gl::TextureTarget::_2DArray);
+    ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);
 
     gl::Extents fbSize = source->getReadColorbuffer()->getSize();
     gl::Rectangle clippedSourceArea;
@@ -3052,7 +3051,7 @@
     if (!canCreateRenderTargetForImage(index))
     {
         gl::Offset destLayerOffset(clippedDestOffset.x, clippedDestOffset.y, 0);
-        ANGLE_TRY(mImageArray[index.mipIndex][clippedDestOffset.z]->copyFromFramebuffer(
+        ANGLE_TRY(mImageArray[index.getLevelIndex()][clippedDestOffset.z]->copyFromFramebuffer(
             context, destLayerOffset, clippedSourceArea, source));
         mDirtyImages = true;
     }
@@ -3060,13 +3059,13 @@
     {
         ANGLE_TRY(ensureRenderTarget(context));
 
-        if (isValidLevel(index.mipIndex))
+        if (isValidLevel(index.getLevelIndex()))
         {
-            ANGLE_TRY(updateStorageLevel(context, index.mipIndex));
+            ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
             ANGLE_TRY(
                 mRenderer->copyImage2DArray(context, source, clippedSourceArea,
                                             gl::GetUnsizedFormat(getInternalFormat(getBaseLevel())),
-                                            clippedDestOffset, mTexStorage, index.mipIndex));
+                                            clippedDestOffset, mTexStorage, index.getLevelIndex()));
         }
     }
     return gl::NoError();
@@ -3162,7 +3161,7 @@
 {
     // ensure the underlying texture is created
     ANGLE_TRY(ensureRenderTarget(context));
-    ANGLE_TRY(updateStorageLevel(context, index.mipIndex));
+    ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
     return mTexStorage->getRenderTarget(context, index, outRT);
 }
 
@@ -3311,7 +3310,7 @@
 
 bool TextureD3D_2DArray::isImageComplete(const gl::ImageIndex &index) const
 {
-    return isLevelComplete(index.mipIndex);
+    return isLevelComplete(index.getLevelIndex());
 }
 
 gl::Error TextureD3D_2DArray::updateStorageLevel(const gl::Context *context, int level)
@@ -3425,19 +3424,20 @@
 bool TextureD3D_2DArray::isValidIndex(const gl::ImageIndex &index) const
 {
     // Check for having a storage and the right type of index
-    if (!mTexStorage || index.type != gl::TextureType::_2DArray)
+    if (!mTexStorage || index.getType() != gl::TextureType::_2DArray)
     {
         return false;
     }
 
     // Check the mip index
-    if (index.mipIndex < 0 || index.mipIndex >= mTexStorage->getLevelCount())
+    if (index.getLevelIndex() < 0 || index.getLevelIndex() >= mTexStorage->getLevelCount())
     {
         return false;
     }
 
     // Check the layer index
-    return (!index.hasLayer() || (index.layerIndex >= 0 && index.layerIndex < mLayerCounts[index.mipIndex]));
+    return (!index.hasLayer() || (index.getLayerIndex() >= 0 &&
+                                  index.getLayerIndex() < mLayerCounts[index.getLevelIndex()]));
 }
 
 void TextureD3D_2DArray::markAllImagesDirty()
@@ -3614,7 +3614,7 @@
 
 bool TextureD3D_External::isImageComplete(const gl::ImageIndex &index) const
 {
-    return (index.mipIndex == 0) ? (mTexStorage != nullptr) : false;
+    return (index.getLevelIndex() == 0) ? (mTexStorage != nullptr) : false;
 }
 
 gl::Error TextureD3D_External::initializeStorage(const gl::Context *context, bool renderTarget)
@@ -3659,7 +3659,8 @@
 
 bool TextureD3D_External::isValidIndex(const gl::ImageIndex &index) const
 {
-    return (mTexStorage && index.type == gl::TextureType::External && index.mipIndex == 0);
+    return (mTexStorage && index.getType() == gl::TextureType::External &&
+            index.getLevelIndex() == 0);
 }
 
 void TextureD3D_External::markAllImagesDirty()
@@ -3819,7 +3820,8 @@
 
 bool TextureD3D_2DMultisample::isValidIndex(const gl::ImageIndex &index) const
 {
-    return (mTexStorage && index.type == gl::TextureType::_2DMultisample && index.mipIndex == 0);
+    return (mTexStorage && index.getType() == gl::TextureType::_2DMultisample &&
+            index.getLevelIndex() == 0);
 }
 
 GLsizei TextureD3D_2DMultisample::getLayerCount(int level) const
diff --git a/src/libANGLE/renderer/d3d/TextureD3D.h b/src/libANGLE/renderer/d3d/TextureD3D.h
index 5c0ee51..f0ec0e8 100644
--- a/src/libANGLE/renderer/d3d/TextureD3D.h
+++ b/src/libANGLE/renderer/d3d/TextureD3D.h
@@ -98,7 +98,8 @@
 
     gl::Error setBaseLevel(const gl::Context *context, GLuint baseLevel) override;
 
-    void syncState(const gl::Texture::DirtyBits &dirtyBits) override;
+    gl::Error syncState(const gl::Context *context,
+                        const gl::Texture::DirtyBits &dirtyBits) override;
 
     gl::Error initializeContents(const gl::Context *context,
                                  const gl::ImageIndex &imageIndex) override;
diff --git a/src/libANGLE/renderer/d3d/TextureStorage.h b/src/libANGLE/renderer/d3d/TextureStorage.h
index 1d743f7..c801645 100644
--- a/src/libANGLE/renderer/d3d/TextureStorage.h
+++ b/src/libANGLE/renderer/d3d/TextureStorage.h
@@ -18,7 +18,7 @@
 namespace gl
 {
 class Context;
-struct ImageIndex;
+class ImageIndex;
 struct Box;
 struct PixelUnpackState;
 }  // namespace gl
diff --git a/src/libANGLE/renderer/d3d/d3d11/Image11.cpp b/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
index 11c2756..527a29c 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
@@ -30,7 +30,7 @@
       mStagingSubresource(0),
       mRecoverFromStorage(false),
       mAssociatedStorage(nullptr),
-      mAssociatedImageIndex(gl::ImageIndex::MakeInvalid()),
+      mAssociatedImageIndex(),
       mRecoveredFromStorageCount(0)
 {
 }
@@ -224,7 +224,7 @@
 
         mRecoverFromStorage   = false;
         mAssociatedStorage    = nullptr;
-        mAssociatedImageIndex = gl::ImageIndex::MakeInvalid();
+        mAssociatedImageIndex = gl::ImageIndex();
     }
 }
 
diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
index 0af9963..cab05b6 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
@@ -2375,7 +2375,7 @@
         const TextureHelper11 *destResource = nullptr;
         ANGLE_TRY(destStorage11->getResource(context, &destResource));
 
-        gl::ImageIndex destIndex = gl::ImageIndex::MakeGeneric(destTarget, destLevel);
+        gl::ImageIndex destIndex = gl::ImageIndex::MakeFromTarget(destTarget, destLevel);
         UINT destSubresource     = destStorage11->getSubresourceIndex(destIndex);
 
         D3D11_BOX sourceBox{
@@ -2396,7 +2396,7 @@
         const d3d11::SharedSRV *sourceSRV = nullptr;
         ANGLE_TRY(sourceStorage11->getSRVLevels(context, sourceLevel, sourceLevel, &sourceSRV));
 
-        gl::ImageIndex destIndex             = gl::ImageIndex::MakeGeneric(destTarget, destLevel);
+        gl::ImageIndex destIndex = gl::ImageIndex::MakeFromTarget(destTarget, destLevel);
         RenderTargetD3D *destRenderTargetD3D = nullptr;
         ANGLE_TRY(destStorage11->getRenderTarget(context, destIndex, &destRenderTargetD3D));
 
diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
index d1b8bfd..78e2675 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
@@ -26,7 +26,7 @@
 namespace gl
 {
 class FramebufferAttachment;
-struct ImageIndex;
+class ImageIndex;
 }
 
 namespace rx
diff --git a/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
index fa4060e..7f5edb9 100644
--- a/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
@@ -34,8 +34,8 @@
 {
 bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOURCE_VIEW_DESC desc)
 {
-    unsigned mipLevel  = index.mipIndex;
-    gl::TextureType textureType = index.type;
+    unsigned mipLevel           = index.getLevelIndex();
+    gl::TextureType textureType = index.getType();
 
     switch (desc.ViewDimension)
     {
@@ -45,7 +45,7 @@
             unsigned int maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip;
             maxSrvMip              = allLevels ? INT_MAX : maxSrvMip;
 
-            unsigned mipMin = index.mipIndex;
+            unsigned mipMin = index.getLevelIndex();
             unsigned mipMax = INT_MAX;
 
             return textureType == gl::TextureType::_2D &&
@@ -55,7 +55,7 @@
 
         case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
         {
-            GLint layerIndex = index.layerIndex;
+            GLint layerIndex = index.getLayerIndex();
 
             bool allLevels = (desc.Texture2DArray.MipLevels == std::numeric_limits<UINT>::max());
             unsigned int maxSrvMip =
diff --git a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
index 02d83c4..7a14e7e 100644
--- a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
@@ -199,8 +199,8 @@
 
 UINT TextureStorage11::getSubresourceIndex(const gl::ImageIndex &index) const
 {
-    UINT mipSlice    = static_cast<UINT>(index.mipIndex + mTopLevel);
-    UINT arraySlice  = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
+    UINT mipSlice    = static_cast<UINT>(index.getLevelIndex() + mTopLevel);
+    UINT arraySlice  = static_cast<UINT>(index.hasLayer() ? index.getLayerIndex() : 0);
     UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
     ASSERT(subresource != std::numeric_limits<UINT>::max());
     return subresource;
@@ -511,7 +511,7 @@
 {
     ASSERT(srcTexture.valid());
 
-    const GLint level = index.mipIndex;
+    const GLint level = index.getLevelIndex();
 
     markLevelDirty(level);
 
@@ -578,7 +578,7 @@
 
     // If the zero-LOD workaround is active and we want to update a level greater than zero, then we
     // should update the mipmapped texture, even if mapmaps are currently disabled.
-    if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+    if (index.getLevelIndex() > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
     {
         ANGLE_TRY(getMippedResource(context, &srcTexture));
     }
@@ -630,9 +630,9 @@
                                            const gl::ImageIndex &sourceIndex,
                                            const gl::ImageIndex &destIndex)
 {
-    ASSERT(sourceIndex.layerIndex == destIndex.layerIndex);
+    ASSERT(sourceIndex.getLayerIndex() == destIndex.getLayerIndex());
 
-    markLevelDirty(destIndex.mipIndex);
+    markLevelDirty(destIndex.getLevelIndex());
 
     RenderTargetD3D *source = nullptr;
     ANGLE_TRY(getRenderTarget(context, sourceIndex, &source));
@@ -709,7 +709,7 @@
 {
     ASSERT(!image->isDirty());
 
-    markLevelDirty(index.mipIndex);
+    markLevelDirty(index.getLevelIndex());
 
     const TextureHelper11 *resource = nullptr;
     ANGLE_TRY(getResource(context, &resource));
@@ -720,8 +720,8 @@
     const gl::InternalFormat &internalFormatInfo =
         gl::GetInternalFormatInfo(image->getInternalFormat(), type);
 
-    gl::Box levelBox(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex),
-                     getLevelDepth(index.mipIndex));
+    gl::Box levelBox(0, 0, 0, getLevelWidth(index.getLevelIndex()),
+                     getLevelHeight(index.getLevelIndex()), getLevelDepth(index.getLevelIndex()));
     bool fullUpdate = (destBox == nullptr || *destBox == levelBox);
     ASSERT(internalFormatInfo.depthBits == 0 || fullUpdate);
 
@@ -743,7 +743,7 @@
                      srcDepthPitch);
     GLuint srcSkipBytes = 0;
     ANGLE_TRY_RESULT(
-        internalFormatInfo.computeSkipBytes(srcRowPitch, srcDepthPitch, unpack, index.is3D()),
+        internalFormatInfo.computeSkipBytes(srcRowPitch, srcDepthPitch, unpack, index.usesTex3D()),
         srcSkipBytes);
 
     const d3d11::Format &d3d11Format =
@@ -995,7 +995,7 @@
 
 void TextureStorage11_2D::associateImage(Image11 *image, const gl::ImageIndex &index)
 {
-    const GLint level = index.mipIndex;
+    const GLint level = index.getLevelIndex();
 
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
@@ -1007,7 +1007,7 @@
 void TextureStorage11_2D::verifyAssociatedImageValid(const gl::ImageIndex &index,
                                                      Image11 *expectedImage)
 {
-    const GLint level = index.mipIndex;
+    const GLint level = index.getLevelIndex();
 
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
     // This validation check should never return false. It means the Image/TextureStorage
@@ -1018,7 +1018,7 @@
 // disassociateImage allows an Image to end its association with a Storage.
 void TextureStorage11_2D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
 {
-    const GLint level = index.mipIndex;
+    const GLint level = index.getLevelIndex();
 
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
     ASSERT(mAssociatedImages[level] == expectedImage);
@@ -1031,7 +1031,7 @@
                                                       const gl::ImageIndex &index,
                                                       Image11 *incomingImage)
 {
-    const GLint level = index.mipIndex;
+    const GLint level = index.getLevelIndex();
 
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
 
@@ -1129,7 +1129,7 @@
 {
     ASSERT(!index.hasLayer());
 
-    const int level = index.mipIndex;
+    const int level = index.getLevelIndex();
     ASSERT(level >= 0 && level < getLevelCount());
 
     // In GL ES 2.0, the application can only render to level zero of the texture (Section 4.4.3 of
@@ -1433,20 +1433,20 @@
 
 void TextureStorage11_External::associateImage(Image11 *image, const gl::ImageIndex &index)
 {
-    ASSERT(index.mipIndex == 0);
+    ASSERT(index.getLevelIndex() == 0);
     mAssociatedImage = image;
 }
 
 void TextureStorage11_External::verifyAssociatedImageValid(const gl::ImageIndex &index,
                                                            Image11 *expectedImage)
 {
-    ASSERT(index.mipIndex == 0 && mAssociatedImage == expectedImage);
+    ASSERT(index.getLevelIndex() == 0 && mAssociatedImage == expectedImage);
 }
 
 void TextureStorage11_External::disassociateImage(const gl::ImageIndex &index,
                                                   Image11 *expectedImage)
 {
-    ASSERT(index.mipIndex == 0);
+    ASSERT(index.getLevelIndex() == 0);
     ASSERT(mAssociatedImage == expectedImage);
     mAssociatedImage = nullptr;
 }
@@ -1455,7 +1455,7 @@
                                                             const gl::ImageIndex &index,
                                                             Image11 *incomingImage)
 {
-    ASSERT(index.mipIndex == 0);
+    ASSERT(index.getLevelIndex() == 0);
 
     if (mAssociatedImage != nullptr && mAssociatedImage != incomingImage)
     {
@@ -1607,7 +1607,7 @@
                                                      RenderTargetD3D **outRT)
 {
     ASSERT(!index.hasLayer());
-    ASSERT(index.mipIndex == 0);
+    ASSERT(index.getLevelIndex() == 0);
 
     ANGLE_TRY(checkForUpdatedRenderTarget(context));
 
@@ -1866,7 +1866,7 @@
 {
     UINT arraySlice = index.cubeMapFaceIndex();
     if (mRenderer->getWorkarounds().zeroMaxLodWorkaround && mUseLevelZeroTexture &&
-        index.mipIndex == 0)
+        index.getLevelIndex() == 0)
     {
         UINT subresource = D3D11CalcSubresource(0, arraySlice, 1);
         ASSERT(subresource != std::numeric_limits<UINT>::max());
@@ -1874,7 +1874,7 @@
     }
     else
     {
-        UINT mipSlice    = static_cast<UINT>(index.mipIndex + mTopLevel);
+        UINT mipSlice    = static_cast<UINT>(index.getLevelIndex() + mTopLevel);
         UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
         ASSERT(subresource != std::numeric_limits<UINT>::max());
         return subresource;
@@ -1980,7 +1980,7 @@
 
 void TextureStorage11_Cube::associateImage(Image11 *image, const gl::ImageIndex &index)
 {
-    const GLint level       = index.mipIndex;
+    const GLint level       = index.getLevelIndex();
     const GLint layerTarget = index.cubeMapFaceIndex();
 
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
@@ -1998,7 +1998,7 @@
 void TextureStorage11_Cube::verifyAssociatedImageValid(const gl::ImageIndex &index,
                                                        Image11 *expectedImage)
 {
-    const GLint level       = index.mipIndex;
+    const GLint level       = index.getLevelIndex();
     const GLint layerTarget = index.cubeMapFaceIndex();
 
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
@@ -2011,7 +2011,7 @@
 // disassociateImage allows an Image to end its association with a Storage.
 void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
 {
-    const GLint level       = index.mipIndex;
+    const GLint level       = index.getLevelIndex();
     const GLint layerTarget = index.cubeMapFaceIndex();
 
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
@@ -2026,7 +2026,7 @@
                                                         const gl::ImageIndex &index,
                                                         Image11 *incomingImage)
 {
-    const GLint level       = index.mipIndex;
+    const GLint level       = index.getLevelIndex();
     const GLint layerTarget = index.cubeMapFaceIndex();
 
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
@@ -2123,7 +2123,7 @@
 {
     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
     srvDesc.Format                         = resourceFormat;
-    srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.mipIndex;
+    srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.getLevelIndex();
     srvDesc.Texture2DArray.MipLevels       = 1;
     srvDesc.Texture2DArray.FirstArraySlice = index.cubeMapFaceIndex();
     srvDesc.Texture2DArray.ArraySize       = 1;
@@ -2147,7 +2147,7 @@
                                                  RenderTargetD3D **outRT)
 {
     const int faceIndex = index.cubeMapFaceIndex();
-    const int level     = index.mipIndex;
+    const int level     = index.getLevelIndex();
 
     ASSERT(level >= 0 && level < getLevelCount());
     ASSERT(faceIndex >= 0 && faceIndex < static_cast<GLint>(gl::CUBE_FACE_COUNT));
@@ -2156,7 +2156,7 @@
     {
         if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
         {
-            ASSERT(index.mipIndex == 0);
+            ASSERT(index.getLevelIndex() == 0);
             ANGLE_TRY(useLevelZeroWorkaroundTexture(context, true));
         }
 
@@ -2411,8 +2411,8 @@
     while (itCopy.hasNext())
     {
         gl::ImageIndex index = itCopy.next();
-        gl::Box wholeArea(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex),
-                          1);
+        gl::Box wholeArea(0, 0, 0, getLevelWidth(index.getLevelIndex()),
+                          getLevelHeight(index.getLevelIndex()), 1);
         gl::Extents wholeSize(wholeArea.width, wholeArea.height, 1);
         UINT subresource = getSubresourceIndex(index);
         ANGLE_TRY(mRenderer->getBlitter()->copyDepthStencil(
@@ -2508,7 +2508,7 @@
 
 void TextureStorage11_3D::associateImage(Image11 *image, const gl::ImageIndex &index)
 {
-    const GLint level = index.mipIndex;
+    const GLint level = index.getLevelIndex();
 
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
 
@@ -2521,7 +2521,7 @@
 void TextureStorage11_3D::verifyAssociatedImageValid(const gl::ImageIndex &index,
                                                      Image11 *expectedImage)
 {
-    const GLint level = index.mipIndex;
+    const GLint level = index.getLevelIndex();
 
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
     // This validation check should never return false. It means the Image/TextureStorage
@@ -2532,7 +2532,7 @@
 // disassociateImage allows an Image to end its association with a Storage.
 void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
 {
-    const GLint level = index.mipIndex;
+    const GLint level = index.getLevelIndex();
 
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
     ASSERT(mAssociatedImages[level] == expectedImage);
@@ -2545,7 +2545,7 @@
                                                       const gl::ImageIndex &index,
                                                       Image11 *incomingImage)
 {
-    const GLint level = index.mipIndex;
+    const GLint level = index.getLevelIndex();
 
     ASSERT((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS));
 
@@ -2654,7 +2654,7 @@
                                                const gl::ImageIndex &index,
                                                RenderTargetD3D **outRT)
 {
-    const int mipLevel = index.mipIndex;
+    const int mipLevel = index.getLevelIndex();
     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
 
     ASSERT(mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
@@ -2694,7 +2694,7 @@
         return gl::NoError();
     }
 
-    const int layer = index.layerIndex;
+    const int layer = index.getLayerIndex();
 
     LevelLayerKey key(mipLevel, layer);
     if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
@@ -2831,9 +2831,9 @@
 
 void TextureStorage11_2DArray::associateImage(Image11 *image, const gl::ImageIndex &index)
 {
-    const GLint level       = index.mipIndex;
-    const GLint layerTarget = index.layerIndex;
-    const GLint numLayers   = index.numLayers;
+    const GLint level       = index.getLevelIndex();
+    const GLint layerTarget = index.getLayerIndex();
+    const GLint numLayers   = index.getLayerCount();
 
     ASSERT(0 <= level && level < getLevelCount());
 
@@ -2847,9 +2847,9 @@
 void TextureStorage11_2DArray::verifyAssociatedImageValid(const gl::ImageIndex &index,
                                                           Image11 *expectedImage)
 {
-    const GLint level       = index.mipIndex;
-    const GLint layerTarget = index.layerIndex;
-    const GLint numLayers   = index.numLayers;
+    const GLint level       = index.getLevelIndex();
+    const GLint layerTarget = index.getLayerIndex();
+    const GLint numLayers   = index.getLayerCount();
 
     LevelLayerRangeKey key(level, layerTarget, numLayers);
 
@@ -2864,9 +2864,9 @@
 void TextureStorage11_2DArray::disassociateImage(const gl::ImageIndex &index,
                                                  Image11 *expectedImage)
 {
-    const GLint level       = index.mipIndex;
-    const GLint layerTarget = index.layerIndex;
-    const GLint numLayers   = index.numLayers;
+    const GLint level       = index.getLevelIndex();
+    const GLint layerTarget = index.getLayerIndex();
+    const GLint numLayers   = index.getLayerCount();
 
     LevelLayerRangeKey key(level, layerTarget, numLayers);
 
@@ -2882,9 +2882,9 @@
                                                            const gl::ImageIndex &index,
                                                            Image11 *incomingImage)
 {
-    const GLint level       = index.mipIndex;
-    const GLint layerTarget = index.layerIndex;
-    const GLint numLayers   = index.numLayers;
+    const GLint level       = index.getLevelIndex();
+    const GLint layerTarget = index.getLayerIndex();
+    const GLint numLayers   = index.getLayerCount();
 
     LevelLayerRangeKey key(level, layerTarget, numLayers);
 
@@ -3000,10 +3000,10 @@
     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
     srvDesc.Format                         = resourceFormat;
     srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
-    srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.mipIndex;
+    srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.getLevelIndex();
     srvDesc.Texture2DArray.MipLevels       = 1;
-    srvDesc.Texture2DArray.FirstArraySlice = index.layerIndex;
-    srvDesc.Texture2DArray.ArraySize       = index.numLayers;
+    srvDesc.Texture2DArray.FirstArraySlice = index.getLayerIndex();
+    srvDesc.Texture2DArray.ArraySize       = index.getLayerCount();
 
     ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), srv));
 
@@ -3016,9 +3016,9 @@
 {
     ASSERT(index.hasLayer());
 
-    const int mipLevel  = index.mipIndex;
-    const int layer     = index.layerIndex;
-    const int numLayers = index.numLayers;
+    const int mipLevel  = index.getLevelIndex();
+    const int layer     = index.getLayerIndex();
+    const int numLayers = index.getLayerCount();
 
     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
 
@@ -3286,7 +3286,7 @@
 {
     ASSERT(!index.hasLayer());
 
-    const int level = index.mipIndex;
+    const int level = index.getLevelIndex();
     ASSERT(level == 0);
 
     ASSERT(outRT);
diff --git a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
index 7736a8f..e515557 100644
--- a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
@@ -22,8 +22,8 @@
 
 namespace gl
 {
-struct ImageIndex;
-}
+class ImageIndex;
+}  // namespace gl
 
 namespace rx
 {
diff --git a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
index 60e99d7..6af008a 100644
--- a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
@@ -37,6 +37,29 @@
 {
 }
 
+#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX)                          \
+    case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX:                  \
+        ASSERT(INDEX == mState.getBindingIndexFromAttribIndex(INDEX)); \
+        updateVertexAttribStorage(stateManager, dirtyBit, INDEX);      \
+        invalidateVertexBuffer = true;                                 \
+        break;
+
+#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX)                         \
+    case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX:                 \
+        ASSERT(INDEX == mState.getBindingIndexFromAttribIndex(INDEX)); \
+        updateVertexAttribStorage(stateManager, dirtyBit, INDEX);      \
+        invalidateVertexBuffer = true;                                 \
+        break;
+
+#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX)                      \
+    case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX:              \
+        if (mAttributeStorageTypes[INDEX] == VertexStorageType::STATIC) \
+        {                                                               \
+            invalidateVertexBuffer = true;                              \
+            mAttribsToTranslate.set(INDEX);                             \
+        }                                                               \
+        break;
+
 gl::Error VertexArray11::syncState(const gl::Context *context,
                                    const gl::VertexArray::DirtyBits &dirtyBits,
                                    const gl::VertexArray::DirtyAttribBitsArray &attribBits,
@@ -68,29 +91,13 @@
                 break;
             }
 
+                ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC);
+                ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC);
+                ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC);
+
             default:
-            {
-                size_t index = gl::VertexArray::GetVertexIndexFromDirtyBit(dirtyBit);
-
-                // TODO(jiawei.shao@intel.com): Vertex Attrib Bindings
-                ASSERT(index == mState.getBindingIndexFromAttribIndex(index));
-
-                if (dirtyBit < gl::VertexArray::DIRTY_BIT_BINDING_MAX)
-                {
-                    updateVertexAttribStorage(stateManager, dirtyBit, index);
-                }
-                else
-                {
-                    ASSERT(dirtyBit >= gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 &&
-                           dirtyBit < gl::VertexArray::DIRTY_BIT_BUFFER_DATA_MAX);
-                    if (mAttributeStorageTypes[index] == VertexStorageType::STATIC)
-                    {
-                        mAttribsToTranslate.set(index);
-                    }
-                }
-                invalidateVertexBuffer = true;
+                UNREACHABLE();
                 break;
-            }
         }
     }
 
diff --git a/src/libANGLE/renderer/d3d/d3d9/Blit9.h b/src/libANGLE/renderer/d3d/d3d9/Blit9.h
index 5913787..bae93ef 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Blit9.h
+++ b/src/libANGLE/renderer/d3d/d3d9/Blit9.h
@@ -11,7 +11,7 @@
 
 #include "common/angleutils.h"
 #include "libANGLE/Error.h"
-#include "libANGLE/PackedGLEnums.h"
+#include "libANGLE/PackedEnums.h"
 
 namespace gl
 {
diff --git a/src/libANGLE/renderer/d3d/d3d9/Image9.cpp b/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
index f3d71c7..56871be 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
@@ -470,7 +470,8 @@
 
     TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
     IDirect3DSurface9 *destSurface = nullptr;
-    ANGLE_TRY(storage9->getSurfaceLevel(context, index.target, index.mipIndex, true, &destSurface));
+    ANGLE_TRY(storage9->getSurfaceLevel(context, index.getTarget(), index.getLevelIndex(), true,
+                                        &destSurface));
 
     gl::Error error = copyToSurface(destSurface, region);
     SafeRelease(destSurface);
diff --git a/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp b/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp
index 12ffa0e..1b7d9fa 100644
--- a/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp
@@ -192,9 +192,9 @@
                                               const gl::ImageIndex &index,
                                               RenderTargetD3D **outRT)
 {
-    ASSERT(index.mipIndex < getLevelCount());
+    ASSERT(index.getLevelIndex() < getLevelCount());
 
-    if (!mRenderTargets[index.mipIndex] && isRenderTarget())
+    if (!mRenderTargets[index.getLevelIndex()] && isRenderTarget())
     {
         IDirect3DBaseTexture9 *baseTexture = nullptr;
         gl::Error error                    = getBaseTexture(context, &baseTexture);
@@ -204,24 +204,25 @@
         }
 
         IDirect3DSurface9 *surface = nullptr;
-        error = getSurfaceLevel(context, gl::TextureTarget::_2D, index.mipIndex, false, &surface);
+        error = getSurfaceLevel(context, gl::TextureTarget::_2D, index.getLevelIndex(), false,
+                                &surface);
         if (error.isError())
         {
             return error;
         }
 
-        size_t textureMipLevel = mTopLevel + index.mipIndex;
+        size_t textureMipLevel = mTopLevel + index.getLevelIndex();
         size_t mipWidth        = std::max<size_t>(mTextureWidth >> textureMipLevel, 1u);
         size_t mipHeight       = std::max<size_t>(mTextureHeight >> textureMipLevel, 1u);
 
         baseTexture->AddRef();
-        mRenderTargets[index.mipIndex] = new TextureRenderTarget9(
+        mRenderTargets[index.getLevelIndex()] = new TextureRenderTarget9(
             baseTexture, textureMipLevel, surface, mInternalFormat, static_cast<GLsizei>(mipWidth),
             static_cast<GLsizei>(mipHeight), 1, 0);
     }
 
     ASSERT(outRT);
-    *outRT = mRenderTargets[index.mipIndex];
+    *outRT = mRenderTargets[index.getLevelIndex()];
     return gl::NoError();
 }
 
@@ -230,15 +231,16 @@
                                              const gl::ImageIndex &destIndex)
 {
     IDirect3DSurface9 *upper = nullptr;
-    gl::Error error =
-        getSurfaceLevel(context, gl::TextureTarget::_2D, sourceIndex.mipIndex, false, &upper);
+    gl::Error error = getSurfaceLevel(context, gl::TextureTarget::_2D, sourceIndex.getLevelIndex(),
+                                      false, &upper);
     if (error.isError())
     {
         return error;
     }
 
     IDirect3DSurface9 *lower = nullptr;
-    error = getSurfaceLevel(context, gl::TextureTarget::_2D, destIndex.mipIndex, true, &lower);
+    error =
+        getSurfaceLevel(context, gl::TextureTarget::_2D, destIndex.getLevelIndex(), true, &lower);
     if (error.isError())
     {
         SafeRelease(upper);
@@ -363,7 +365,7 @@
                                                     RenderTargetD3D **outRT)
 {
     ASSERT(!index.hasLayer());
-    ASSERT(index.mipIndex == 0);
+    ASSERT(index.getLevelIndex() == 0);
 
     return mImage->getRenderTarget(context, outRT);
 }
@@ -516,10 +518,10 @@
                                                 RenderTargetD3D **outRT)
 {
     ASSERT(outRT);
-    ASSERT(index.mipIndex == 0);
+    ASSERT(index.getLevelIndex() == 0);
 
-    ASSERT(index.type == gl::TextureType::CubeMap &&
-           gl::TextureTargetToType(index.target) == gl::TextureType::CubeMap);
+    ASSERT(index.getType() == gl::TextureType::CubeMap &&
+           gl::TextureTargetToType(index.getTarget()) == gl::TextureType::CubeMap);
     const size_t renderTargetIndex = index.cubeMapFaceIndex();
 
     if (mRenderTarget[renderTargetIndex] == nullptr && isRenderTarget())
@@ -532,7 +534,8 @@
         }
 
         IDirect3DSurface9 *surface = nullptr;
-        error = getSurfaceLevel(context, index.target, mTopLevel + index.mipIndex, false, &surface);
+        error = getSurfaceLevel(context, index.getTarget(), mTopLevel + index.getLevelIndex(),
+                                false, &surface);
         if (error.isError())
         {
             return error;
@@ -540,7 +543,7 @@
 
         baseTexture->AddRef();
         mRenderTarget[renderTargetIndex] = new TextureRenderTarget9(
-            baseTexture, mTopLevel + index.mipIndex, surface, mInternalFormat,
+            baseTexture, mTopLevel + index.getLevelIndex(), surface, mInternalFormat,
             static_cast<GLsizei>(mTextureWidth), static_cast<GLsizei>(mTextureHeight), 1, 0);
     }
 
@@ -553,15 +556,16 @@
                                                const gl::ImageIndex &destIndex)
 {
     IDirect3DSurface9 *upper = nullptr;
-    gl::Error error =
-        getSurfaceLevel(context, sourceIndex.target, sourceIndex.mipIndex, false, &upper);
+    gl::Error error = getSurfaceLevel(context, sourceIndex.getTarget(), sourceIndex.getLevelIndex(),
+                                      false, &upper);
     if (error.isError())
     {
         return error;
     }
 
     IDirect3DSurface9 *lower = nullptr;
-    error = getSurfaceLevel(context, destIndex.target, destIndex.mipIndex, true, &lower);
+    error =
+        getSurfaceLevel(context, destIndex.getTarget(), destIndex.getLevelIndex(), true, &lower);
     if (error.isError())
     {
         SafeRelease(upper);
diff --git a/src/libANGLE/renderer/driver_utils.cpp b/src/libANGLE/renderer/driver_utils.cpp
index d97b8e7..9104895 100644
--- a/src/libANGLE/renderer/driver_utils.cpp
+++ b/src/libANGLE/renderer/driver_utils.cpp
@@ -117,4 +117,23 @@
     return std::find(std::begin(Kabylake), std::end(Kabylake), DeviceId) != std::end(Kabylake);
 }
 
+const char *GetVendorString(uint32_t vendorId)
+{
+    switch (vendorId)
+    {
+        case VENDOR_ID_AMD:
+            return "Advanced Micro Devices";
+        case VENDOR_ID_NVIDIA:
+            return "NVIDIA";
+        case VENDOR_ID_INTEL:
+            return "Intel";
+        case VENDOR_ID_QUALCOMM:
+            return "Qualcomm";
+        default:
+            // TODO(jmadill): More vendor IDs.
+            ASSERT(vendorId == 0xba5eba11);  // Mock vendor ID used for tests.
+            return "Unknown";
+    }
+}
+
 }  // namespace rx
\ No newline at end of file
diff --git a/src/libANGLE/renderer/driver_utils.h b/src/libANGLE/renderer/driver_utils.h
index 62bdc50..596f29c 100644
--- a/src/libANGLE/renderer/driver_utils.h
+++ b/src/libANGLE/renderer/driver_utils.h
@@ -45,6 +45,8 @@
     return vendor_id == VENDOR_ID_QUALCOMM;
 }
 
+const char *GetVendorString(uint32_t vendorId);
+
 // Intel
 class IntelDriverVersion
 {
diff --git a/src/libANGLE/renderer/gl/BlitGL.cpp b/src/libANGLE/renderer/gl/BlitGL.cpp
index b79348a..c3eddc7 100644
--- a/src/libANGLE/renderer/gl/BlitGL.cpp
+++ b/src/libANGLE/renderer/gl/BlitGL.cpp
@@ -633,9 +633,17 @@
                                             bool unpackPremultiplyAlpha,
                                             bool unpackUnmultiplyAlpha)
 {
+    ANGLE_TRY(initializeResources());
+
     ASSERT(source->getType() == gl::TextureType::_2D);
     const auto &destInternalFormatInfo = gl::GetInternalFormatInfo(destFormat, destType);
 
+    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
+    mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                                     source->getTextureID(), static_cast<GLint>(sourceLevel));
+    GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
+    ASSERT(status == GL_FRAMEBUFFER_COMPLETE);
+
     // Create a buffer for holding the source and destination memory
     const size_t sourcePixelSize = 4;
     size_t sourceBufferSize      = sourceArea.width * sourceArea.height * sourcePixelSize;
@@ -646,9 +654,6 @@
     uint8_t *sourceMemory = buffer->data();
     uint8_t *destMemory   = buffer->data() + sourceBufferSize;
 
-    mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
-    mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
-                                     source->getTextureID(), static_cast<GLint>(sourceLevel));
 
     GLenum readPixelsFormat        = GL_NONE;
     ColorReadFunction readFunction = nullptr;
@@ -689,6 +694,7 @@
     nativegl::TexSubImageFormat texSubImageFormat =
         nativegl::GetTexSubImageFormat(mFunctions, mWorkarounds, destFormat, destType);
 
+    mStateManager->bindTexture(dest->getType(), dest->getTextureID());
     mFunctions->texSubImage2D(ToGLenum(destTarget), static_cast<GLint>(destLevel), destOffset.x,
                               destOffset.y, sourceArea.width, sourceArea.height,
                               texSubImageFormat.format, texSubImageFormat.type, destMemory);
@@ -744,8 +750,8 @@
         for (GLenum bindTarget : bindTargets)
         {
             mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, bindTarget,
-                                             ToGLenum(imageIndex.target), source->getTextureID(),
-                                             imageIndex.mipIndex);
+                                             ToGLenum(imageIndex.getTarget()),
+                                             source->getTextureID(), imageIndex.getLevelIndex());
         }
 
         GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
@@ -769,7 +775,7 @@
             for (GLenum bindTarget : bindTargets)
             {
                 mFunctions->framebufferTexture(GL_FRAMEBUFFER, bindTarget, source->getTextureID(),
-                                               imageIndex.mipIndex);
+                                               imageIndex.getLevelIndex());
             }
 
             GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
@@ -789,17 +795,17 @@
             GLint layerCount = numTextureLayers;
             if (imageIndex.hasLayer())
             {
-                firstLayer = imageIndex.layerIndex;
-                layerCount = imageIndex.numLayers;
+                firstLayer = imageIndex.getLayerIndex();
+                layerCount = imageIndex.getLayerCount();
             }
 
             for (GLint layer = 0; layer < layerCount; layer++)
             {
                 for (GLenum bindTarget : bindTargets)
                 {
-                    mFunctions->framebufferTextureLayer(GL_FRAMEBUFFER, bindTarget,
-                                                        source->getTextureID(), imageIndex.mipIndex,
-                                                        layer + firstLayer);
+                    mFunctions->framebufferTextureLayer(
+                        GL_FRAMEBUFFER, bindTarget, source->getTextureID(),
+                        imageIndex.getLevelIndex(), layer + firstLayer);
                 }
 
                 GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
diff --git a/src/libANGLE/renderer/gl/BlitGL.h b/src/libANGLE/renderer/gl/BlitGL.h
index eed6d04..8b9f287 100644
--- a/src/libANGLE/renderer/gl/BlitGL.h
+++ b/src/libANGLE/renderer/gl/BlitGL.h
@@ -19,7 +19,7 @@
 namespace gl
 {
 class Framebuffer;
-struct ImageIndex;
+class ImageIndex;
 }
 
 namespace rx
diff --git a/src/libANGLE/renderer/gl/ClearMultiviewGL.cpp b/src/libANGLE/renderer/gl/ClearMultiviewGL.cpp
index 01f3d78..ad78da7 100644
--- a/src/libANGLE/renderer/gl/ClearMultiviewGL.cpp
+++ b/src/libANGLE/renderer/gl/ClearMultiviewGL.cpp
@@ -154,13 +154,14 @@
         }
 
         const auto &imageIndex = attachment->getTextureImageIndex();
-        ASSERT(imageIndex.type == gl::TextureType::_2DArray);
+        ASSERT(imageIndex.getType() == gl::TextureType::_2DArray);
 
         GLenum colorAttachment =
             static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + static_cast<int>(drawBufferId));
         const TextureGL *textureGL = GetImplAs<TextureGL>(attachment->getTexture());
         mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, colorAttachment,
-                                            textureGL->getTextureID(), imageIndex.mipIndex, layer);
+                                            textureGL->getTextureID(), imageIndex.getLevelIndex(),
+                                            layer);
     }
 
     const gl::FramebufferAttachment *depthStencilAttachment = state.getDepthStencilAttachment();
@@ -169,29 +170,32 @@
     if (depthStencilAttachment != nullptr)
     {
         const auto &imageIndex = depthStencilAttachment->getTextureImageIndex();
-        ASSERT(imageIndex.type == gl::TextureType::_2DArray);
+        ASSERT(imageIndex.getType() == gl::TextureType::_2DArray);
 
         const TextureGL *textureGL = GetImplAs<TextureGL>(depthStencilAttachment->getTexture());
         mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
-                                            textureGL->getTextureID(), imageIndex.mipIndex, layer);
+                                            textureGL->getTextureID(), imageIndex.getLevelIndex(),
+                                            layer);
     }
     else if (depthAttachment != nullptr)
     {
         const auto &imageIndex = depthAttachment->getTextureImageIndex();
-        ASSERT(imageIndex.type == gl::TextureType::_2DArray);
+        ASSERT(imageIndex.getType() == gl::TextureType::_2DArray);
 
         const TextureGL *textureGL = GetImplAs<TextureGL>(depthAttachment->getTexture());
         mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
-                                            textureGL->getTextureID(), imageIndex.mipIndex, layer);
+                                            textureGL->getTextureID(), imageIndex.getLevelIndex(),
+                                            layer);
     }
     else if (stencilAttachment != nullptr)
     {
         const auto &imageIndex = stencilAttachment->getTextureImageIndex();
-        ASSERT(imageIndex.type == gl::TextureType::_2DArray);
+        ASSERT(imageIndex.getType() == gl::TextureType::_2DArray);
 
         const TextureGL *textureGL = GetImplAs<TextureGL>(stencilAttachment->getTexture());
         mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
-                                            textureGL->getTextureID(), imageIndex.mipIndex, layer);
+                                            textureGL->getTextureID(), imageIndex.getLevelIndex(),
+                                            layer);
     }
 }
 
diff --git a/src/libANGLE/renderer/gl/FramebufferGL.cpp b/src/libANGLE/renderer/gl/FramebufferGL.cpp
index 914902a..5432e4a 100644
--- a/src/libANGLE/renderer/gl/FramebufferGL.cpp
+++ b/src/libANGLE/renderer/gl/FramebufferGL.cpp
@@ -113,8 +113,8 @@
         return false;
     }
     const ImageIndex &imageIndex = attachment.getTextureImageIndex();
-    int numLayers =
-        static_cast<int>(attachment.getTexture()->getDepth(imageIndex.target, imageIndex.mipIndex));
+    int numLayers                = static_cast<int>(
+        attachment.getTexture()->getDepth(imageIndex.getTarget(), imageIndex.getLevelIndex()));
     return (attachment.getNumViews() == numLayers);
 }
 
diff --git a/src/libANGLE/renderer/gl/TextureGL.cpp b/src/libANGLE/renderer/gl/TextureGL.cpp
index c0707c4..7681d32 100644
--- a/src/libANGLE/renderer/gl/TextureGL.cpp
+++ b/src/libANGLE/renderer/gl/TextureGL.cpp
@@ -152,8 +152,8 @@
     const gl::Buffer *unpackBuffer =
         context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
 
-    gl::TextureTarget target = index.target;
-    size_t level             = static_cast<size_t>(index.mipIndex);
+    gl::TextureTarget target = index.getTarget();
+    size_t level             = static_cast<size_t>(index.getLevelIndex());
 
     if (mWorkarounds.unpackOverlappingRowsSeparatelyUnpackBuffer && unpackBuffer &&
         unpack.rowLength != 0 && unpack.rowLength < size.width)
@@ -257,7 +257,7 @@
                                  const gl::PixelUnpackState &unpack,
                                  const uint8_t *pixels)
 {
-    ASSERT(TextureTargetToType(index.target) == getType());
+    ASSERT(TextureTargetToType(index.getTarget()) == getType());
 
     const gl::Buffer *unpackBuffer =
         context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
@@ -265,8 +265,8 @@
     nativegl::TexSubImageFormat texSubImageFormat =
         nativegl::GetTexSubImageFormat(mFunctions, mWorkarounds, format, type);
 
-    gl::TextureTarget target = index.target;
-    size_t level             = static_cast<size_t>(index.mipIndex);
+    gl::TextureTarget target = index.getTarget();
+    size_t level             = static_cast<size_t>(index.getLevelIndex());
 
     ASSERT(getLevelInfo(target, level).lumaWorkaround.enabled ==
            GetLevelInfo(format, texSubImageFormat.format).lumaWorkaround.enabled);
@@ -466,8 +466,8 @@
                                         size_t imageSize,
                                         const uint8_t *pixels)
 {
-    gl::TextureTarget target = index.target;
-    size_t level             = static_cast<size_t>(index.mipIndex);
+    gl::TextureTarget target = index.getTarget();
+    size_t level             = static_cast<size_t>(index.getLevelIndex());
     ASSERT(TextureTargetToType(target) == getType());
 
     nativegl::CompressedTexImageFormat compressedTexImageFormat =
@@ -507,8 +507,8 @@
                                            size_t imageSize,
                                            const uint8_t *pixels)
 {
-    gl::TextureTarget target = index.target;
-    size_t level             = static_cast<size_t>(index.mipIndex);
+    gl::TextureTarget target = index.getTarget();
+    size_t level             = static_cast<size_t>(index.getLevelIndex());
     ASSERT(TextureTargetToType(target) == getType());
 
     nativegl::CompressedTexSubImageFormat compressedTexSubImageFormat =
@@ -546,8 +546,8 @@
                                GLenum internalFormat,
                                gl::Framebuffer *source)
 {
-    gl::TextureTarget target = index.target;
-    size_t level             = static_cast<size_t>(index.mipIndex);
+    gl::TextureTarget target = index.getTarget();
+    size_t level             = static_cast<size_t>(index.getLevelIndex());
     GLenum type = GL_NONE;
     ANGLE_TRY(source->getImplementationColorReadType(context, &type));
     nativegl::CopyTexImageImageFormat copyTexImageFormat =
@@ -648,8 +648,8 @@
                                   const gl::Rectangle &origSourceArea,
                                   gl::Framebuffer *source)
 {
-    gl::TextureTarget target                 = index.target;
-    size_t level                             = static_cast<size_t>(index.mipIndex);
+    gl::TextureTarget target                 = index.getTarget();
+    size_t level                             = static_cast<size_t>(index.getLevelIndex());
     const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source);
 
     // Clip source area to framebuffer.
@@ -712,8 +712,8 @@
                                  bool unpackUnmultiplyAlpha,
                                  const gl::Texture *source)
 {
-    gl::TextureTarget target             = index.target;
-    size_t level                         = static_cast<size_t>(index.mipIndex);
+    gl::TextureTarget target             = index.getTarget();
+    size_t level                         = static_cast<size_t>(index.getLevelIndex());
     const TextureGL *sourceGL            = GetImplAs<TextureGL>(source);
     const gl::ImageDesc &sourceImageDesc =
         sourceGL->mState.getImageDesc(NonCubeTextureTypeToTarget(source->getType()), sourceLevel);
@@ -722,9 +722,10 @@
     reserveTexImageToBeFilled(target, level, internalFormat, sourceImageDesc.size,
                               gl::GetUnsizedFormat(internalFormat), type);
 
+    const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
     return copySubTextureHelper(context, target, level, gl::Offset(0, 0, 0), sourceLevel,
-                                sourceArea, gl::GetUnsizedFormat(internalFormat), type, unpackFlipY,
-                                unpackPremultiplyAlpha, unpackUnmultiplyAlpha, source);
+                                sourceArea, destFormatInfo, unpackFlipY, unpackPremultiplyAlpha,
+                                unpackUnmultiplyAlpha, source);
 }
 
 gl::Error TextureGL::copySubTexture(const gl::Context *context,
@@ -737,12 +738,12 @@
                                     bool unpackUnmultiplyAlpha,
                                     const gl::Texture *source)
 {
-    gl::TextureTarget target                 = index.target;
-    size_t level                             = static_cast<size_t>(index.mipIndex);
+    gl::TextureTarget target                 = index.getTarget();
+    size_t level                             = static_cast<size_t>(index.getLevelIndex());
     const gl::InternalFormat &destFormatInfo = *mState.getImageDesc(target, level).format.info;
     return copySubTextureHelper(context, target, level, destOffset, sourceLevel, sourceArea,
-                                destFormatInfo.format, destFormatInfo.type, unpackFlipY,
-                                unpackPremultiplyAlpha, unpackUnmultiplyAlpha, source);
+                                destFormatInfo, unpackFlipY, unpackPremultiplyAlpha,
+                                unpackUnmultiplyAlpha, source);
 }
 
 gl::Error TextureGL::copySubTextureHelper(const gl::Context *context,
@@ -751,8 +752,7 @@
                                           const gl::Offset &destOffset,
                                           size_t sourceLevel,
                                           const gl::Rectangle &sourceArea,
-                                          GLenum destFormat,
-                                          GLenum destType,
+                                          const gl::InternalFormat &destFormat,
                                           bool unpackFlipY,
                                           bool unpackPremultiplyAlpha,
                                           bool unpackUnmultiplyAlpha,
@@ -770,13 +770,12 @@
 
     GLenum sourceFormat = sourceImageDesc.format.info->format;
     bool sourceFormatContainSupersetOfDestFormat =
-        (sourceFormat == destFormat && sourceFormat != GL_BGRA_EXT) ||
-        (sourceFormat == GL_RGBA && destFormat == GL_RGB);
+        (sourceFormat == destFormat.format && sourceFormat != GL_BGRA_EXT) ||
+        (sourceFormat == GL_RGBA && destFormat.format == GL_RGB);
 
     GLenum sourceComponentType = sourceImageDesc.format.info->componentType;
-    const auto &destInternalFormatInfo = gl::GetInternalFormatInfo(destFormat, destType);
-    GLenum destComponentType           = destInternalFormatInfo.componentType;
-    bool destSRGB                      = destInternalFormatInfo.colorEncoding == GL_SRGB;
+    GLenum destComponentType   = destFormat.componentType;
+    bool destSRGB              = destFormat.colorEncoding == GL_SRGB;
     if (!unpackFlipY && unpackPremultiplyAlpha == unpackUnmultiplyAlpha && !needsLumaWorkaround &&
         sourceFormatContainSupersetOfDestFormat && sourceComponentType == destComponentType &&
         !destSRGB)
@@ -811,8 +810,8 @@
 
     // Fall back to CPU-readback
     return mBlitter->copySubTextureCPUReadback(context, sourceGL, sourceLevel, sourceComponentType,
-                                               this, target, level, destFormat, destType,
-                                               sourceArea, destOffset, unpackFlipY,
+                                               this, target, level, destFormat.format,
+                                               destFormat.type, sourceArea, destOffset, unpackFlipY,
                                                unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
 }
 
@@ -1062,11 +1061,11 @@
     return gl::InternalError();
 }
 
-void TextureGL::syncState(const gl::Texture::DirtyBits &dirtyBits)
+gl::Error TextureGL::syncState(const gl::Context *context, const gl::Texture::DirtyBits &dirtyBits)
 {
     if (dirtyBits.none() && mLocalDirtyBits.none())
     {
-        return;
+        return gl::NoError();
     }
 
     mStateManager->bindTexture(getType(), mTextureID);
@@ -1187,6 +1186,7 @@
     }
 
     mLocalDirtyBits.reset();
+    return gl::NoError();
 }
 
 bool TextureGL::hasAnyDirtyBit() const
@@ -1436,7 +1436,7 @@
                                         const gl::ImageIndex &imageIndex)
 {
     GLenum nativeInternalFormat =
-        getLevelInfo(imageIndex.target, imageIndex.mipIndex).nativeInternalFormat;
+        getLevelInfo(imageIndex.getTarget(), imageIndex.getLevelIndex()).nativeInternalFormat;
     if (nativegl::SupportsNativeRendering(mFunctions, mState.getType(), nativeInternalFormat))
     {
         int levelDepth = mState.getImageDesc(imageIndex).size.depth;
@@ -1477,16 +1477,16 @@
         if (nativegl::UseTexImage2D(getType()))
         {
             mFunctions->compressedTexSubImage2D(
-                ToGLenum(imageIndex.target), imageIndex.mipIndex, 0, 0, desc.size.width,
+                ToGLenum(imageIndex.getTarget()), imageIndex.getLevelIndex(), 0, 0, desc.size.width,
                 desc.size.height, nativeSubImageFormat.format, imageSize, zero->data());
         }
         else
         {
             ASSERT(nativegl::UseTexImage3D(getType()));
-            mFunctions->compressedTexSubImage3D(ToGLenum(imageIndex.target), imageIndex.mipIndex, 0,
-                                                0, 0, desc.size.width, desc.size.height,
-                                                desc.size.depth, nativeSubImageFormat.format,
-                                                imageSize, zero->data());
+            mFunctions->compressedTexSubImage3D(
+                ToGLenum(imageIndex.getTarget()), imageIndex.getLevelIndex(), 0, 0, 0,
+                desc.size.width, desc.size.height, desc.size.depth, nativeSubImageFormat.format,
+                imageSize, zero->data());
         }
     }
     else
@@ -1505,16 +1505,16 @@
 
         if (nativegl::UseTexImage2D(getType()))
         {
-            mFunctions->texSubImage2D(ToGLenum(imageIndex.target), imageIndex.mipIndex, 0, 0,
-                                      desc.size.width, desc.size.height,
+            mFunctions->texSubImage2D(ToGLenum(imageIndex.getTarget()), imageIndex.getLevelIndex(),
+                                      0, 0, desc.size.width, desc.size.height,
                                       nativeSubImageFormat.format, nativeSubImageFormat.type,
                                       zero->data());
         }
         else
         {
             ASSERT(nativegl::UseTexImage3D(getType()));
-            mFunctions->texSubImage3D(ToGLenum(imageIndex.target), imageIndex.mipIndex, 0, 0, 0,
-                                      desc.size.width, desc.size.height, desc.size.depth,
+            mFunctions->texSubImage3D(ToGLenum(imageIndex.getTarget()), imageIndex.getLevelIndex(),
+                                      0, 0, 0, desc.size.width, desc.size.height, desc.size.depth,
                                       nativeSubImageFormat.format, nativeSubImageFormat.type,
                                       zero->data());
         }
diff --git a/src/libANGLE/renderer/gl/TextureGL.h b/src/libANGLE/renderer/gl/TextureGL.h
index 85c3604..6c4b9cf 100644
--- a/src/libANGLE/renderer/gl/TextureGL.h
+++ b/src/libANGLE/renderer/gl/TextureGL.h
@@ -129,8 +129,7 @@
                                    const gl::Offset &destOffset,
                                    size_t sourceLevel,
                                    const gl::Rectangle &sourceArea,
-                                   GLenum destFormat,
-                                   GLenum destType,
+                                   const gl::InternalFormat &destFormat,
                                    bool unpackFlipY,
                                    bool unpackPremultiplyAlpha,
                                    bool unpackUnmultiplyAlpha,
@@ -166,7 +165,8 @@
     GLuint getTextureID() const;
     gl::TextureType getType() const;
 
-    void syncState(const gl::Texture::DirtyBits &dirtyBits) override;
+    gl::Error syncState(const gl::Context *context,
+                        const gl::Texture::DirtyBits &dirtyBits) override;
     bool hasAnyDirtyBit() const;
 
     gl::Error setBaseLevel(const gl::Context *context, GLuint baseLevel) override;
diff --git a/src/libANGLE/renderer/gl/VertexArrayGL.cpp b/src/libANGLE/renderer/gl/VertexArrayGL.cpp
index 4deb42a..2f617f2 100644
--- a/src/libANGLE/renderer/gl/VertexArrayGL.cpp
+++ b/src/libANGLE/renderer/gl/VertexArrayGL.cpp
@@ -26,12 +26,6 @@
 {
 namespace
 {
-// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
-bool AttributeNeedsStreaming(const VertexAttribute &attrib, const VertexBinding &binding)
-{
-    return (attrib.enabled && binding.getBuffer().get() == nullptr);
-}
-
 bool SameVertexAttribFormat(const VertexAttribute &a, const VertexAttribute &b)
 {
     return a.size == b.size && a.type == b.type && a.normalized == b.normalized &&
@@ -154,7 +148,8 @@
 {
     // Check if any attributes need to be streamed, determines if the index range needs to be
     // computed
-    bool attributesNeedStreaming = mAttributesNeedStreaming.any();
+    const gl::AttributesMask &needsStreamingAttribs =
+        (mState.getEnabledClientMemoryAttribsMask() & activeAttributesMask);
 
     // Determine if an index buffer needs to be streamed and the range of vertices that need to be
     // copied
@@ -162,7 +157,7 @@
     if (type != GL_NONE)
     {
         ANGLE_TRY(syncIndexData(context, count, type, indices, primitiveRestartEnabled,
-                                attributesNeedStreaming, &indexRange, outIndices));
+                                needsStreamingAttribs.any(), &indexRange, outIndices));
     }
     else
     {
@@ -171,9 +166,9 @@
         indexRange.end   = first + count - 1;
     }
 
-    if (attributesNeedStreaming)
+    if (needsStreamingAttribs.any())
     {
-        ANGLE_TRY(streamAttributes(activeAttributesMask, instanceCount, indexRange));
+        ANGLE_TRY(streamAttributes(needsStreamingAttribs, instanceCount, indexRange));
     }
 
     return gl::NoError();
@@ -261,7 +256,7 @@
     return gl::NoError();
 }
 
-void VertexArrayGL::computeStreamingAttributeSizes(const gl::AttributesMask &activeAttributesMask,
+void VertexArrayGL::computeStreamingAttributeSizes(const gl::AttributesMask &attribsToStream,
                                                    GLsizei instanceCount,
                                                    const gl::IndexRange &indexRange,
                                                    size_t *outStreamingDataSize,
@@ -270,18 +265,15 @@
     *outStreamingDataSize    = 0;
     *outMaxAttributeDataSize = 0;
 
-    ASSERT(mAttributesNeedStreaming.any());
+    ASSERT(attribsToStream.any());
 
     const auto &attribs  = mState.getVertexAttributes();
     const auto &bindings = mState.getVertexBindings();
 
-    gl::AttributesMask attribsToStream = (mAttributesNeedStreaming & activeAttributesMask);
-
     for (auto idx : attribsToStream)
     {
         const auto &attrib  = attribs[idx];
         const auto &binding = bindings[attrib.bindingIndex];
-        ASSERT(AttributeNeedsStreaming(attrib, binding));
 
         // If streaming is going to be required, compute the size of the required buffer
         // and how much slack space at the beginning of the buffer will be required by determining
@@ -295,7 +287,7 @@
     }
 }
 
-gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttributesMask,
+gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &attribsToStream,
                                           GLsizei instanceCount,
                                           const gl::IndexRange &indexRange) const
 {
@@ -303,8 +295,8 @@
     size_t streamingDataSize    = 0;
     size_t maxAttributeDataSize = 0;
 
-    computeStreamingAttributeSizes(activeAttributesMask, instanceCount, indexRange,
-                                   &streamingDataSize, &maxAttributeDataSize);
+    computeStreamingAttributeSizes(attribsToStream, instanceCount, indexRange, &streamingDataSize,
+                                   &maxAttributeDataSize);
 
     if (streamingDataSize == 0)
     {
@@ -345,15 +337,12 @@
         const auto &attribs  = mState.getVertexAttributes();
         const auto &bindings = mState.getVertexBindings();
 
-        gl::AttributesMask attribsToStream = (mAttributesNeedStreaming & activeAttributesMask);
-
         for (auto idx : attribsToStream)
         {
             const auto &attrib  = attribs[idx];
             ASSERT(IsVertexAttribPointerSupported(idx, attrib));
 
             const auto &binding = bindings[attrib.bindingIndex];
-            ASSERT(AttributeNeedsStreaming(attrib, binding));
 
             GLuint adjustedDivisor = GetAdjustedDivisor(mAppliedNumViews, binding.getDivisor());
             const size_t streamedVertexCount = ComputeVertexBindingElementCount(
@@ -425,13 +414,6 @@
     return GetImplAs<BufferGL>(mAppliedElementArrayBuffer.get())->getBufferID();
 }
 
-void VertexArrayGL::updateNeedsStreaming(size_t attribIndex)
-{
-    const auto &attrib  = mState.getVertexAttribute(attribIndex);
-    const auto &binding = mState.getBindingFromAttribIndex(attribIndex);
-    mAttributesNeedStreaming.set(attribIndex, AttributeNeedsStreaming(attrib, binding));
-}
-
 void VertexArrayGL::updateAttribEnabled(size_t attribIndex)
 {
     const bool enabled = mState.getVertexAttribute(attribIndex).enabled;
@@ -440,8 +422,6 @@
         return;
     }
 
-    updateNeedsStreaming(attribIndex);
-
     if (enabled)
     {
         mFunctions->enableVertexAttribArray(static_cast<GLuint>(attribIndex));
@@ -462,21 +442,12 @@
     // of the binding indexed attrib.bindingIndex (unless attribIndex == attrib.bindingIndex).
     const VertexBinding &binding = mState.getVertexBinding(attribIndex);
 
-    // Since mAttributesNeedStreaming[attribIndex] keeps the value set in the last draw, here we
-    // only need to update it when the buffer has been changed. e.g. When we set an attribute to be
-    // streamed in the last draw, and only change its format in this draw without calling
-    // updateNeedsStreaming, it will still be streamed because the flag is already on.
-    const auto &bindingBuffer = binding.getBuffer();
-    if (bindingBuffer != mAppliedBindings[attribIndex].getBuffer())
-    {
-        updateNeedsStreaming(attribIndex);
-    }
-
     // Early return when the vertex attribute isn't using a buffer object:
     // - If we need to stream, defer the attribPointer to the draw call.
     // - Skip the attribute that is disabled and uses a client memory pointer.
     // - Skip the attribute whose buffer is detached by BindVertexBuffer. Since it cannot have a
     //   client memory pointer either, it must be disabled and shouldn't affect the draw.
+    const auto &bindingBuffer = binding.getBuffer();
     const Buffer *arrayBuffer = bindingBuffer.get();
     if (arrayBuffer == nullptr)
     {
@@ -679,7 +650,7 @@
                                      size_t bindingIndex,
                                      const gl::VertexArray::DirtyBindingBits &dirtyBindingBits)
 {
-    ASSERT(dirtyBindingBits.any());
+    // Dependent state changes in buffers can trigger updates with no dirty bits set.
 
     for (size_t dirtyBit : dirtyBindingBits)
     {
@@ -701,6 +672,20 @@
     }
 }
 
+#define ANGLE_DIRTY_ATTRIB_FUNC(INDEX)                      \
+    case VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX:           \
+        syncDirtyAttrib(context, INDEX, attribBits[INDEX]); \
+        break;
+
+#define ANGLE_DIRTY_BINDING_FUNC(INDEX)                       \
+    case VertexArray::DIRTY_BIT_BINDING_0 + INDEX:            \
+        syncDirtyBinding(context, INDEX, bindingBits[INDEX]); \
+        break;
+
+#define ANGLE_DIRTY_BUFFER_DATA_FUNC(INDEX)            \
+    case VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
+        break;
+
 gl::Error VertexArrayGL::syncState(const gl::Context *context,
                                    const VertexArray::DirtyBits &dirtyBits,
                                    const gl::VertexArray::DirtyAttribBitsArray &attribBits,
@@ -719,26 +704,13 @@
             case VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
                 break;
 
+                ANGLE_VERTEX_INDEX_CASES(ANGLE_DIRTY_ATTRIB_FUNC);
+                ANGLE_VERTEX_INDEX_CASES(ANGLE_DIRTY_BINDING_FUNC);
+                ANGLE_VERTEX_INDEX_CASES(ANGLE_DIRTY_BUFFER_DATA_FUNC);
+
             default:
-            {
-                ASSERT(dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0);
-                size_t index = VertexArray::GetVertexIndexFromDirtyBit(dirtyBit);
-                if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX)
-                {
-                    syncDirtyAttrib(context, index, attribBits[index]);
-                }
-                else if (dirtyBit < VertexArray::DIRTY_BIT_BINDING_MAX)
-                {
-                    ASSERT(dirtyBit >= VertexArray::DIRTY_BIT_BINDING_0);
-                    syncDirtyBinding(context, index, bindingBits[index]);
-                }
-                else
-                {
-                    ASSERT(dirtyBit >= VertexArray::DIRTY_BIT_BUFFER_DATA_0 &&
-                           dirtyBit < VertexArray::DIRTY_BIT_BUFFER_DATA_MAX);
-                }
+                UNREACHABLE();
                 break;
-            }
         }
     }
 
diff --git a/src/libANGLE/renderer/gl/VertexArrayGL.h b/src/libANGLE/renderer/gl/VertexArrayGL.h
index 4755beb..2e209ce 100644
--- a/src/libANGLE/renderer/gl/VertexArrayGL.h
+++ b/src/libANGLE/renderer/gl/VertexArrayGL.h
@@ -74,14 +74,14 @@
 
     // Returns the amount of space needed to stream all attributes that need streaming
     // and the data size of the largest attribute
-    void computeStreamingAttributeSizes(const gl::AttributesMask &activeAttributesMask,
+    void computeStreamingAttributeSizes(const gl::AttributesMask &attribsToStream,
                                         GLsizei instanceCount,
                                         const gl::IndexRange &indexRange,
                                         size_t *outStreamingDataSize,
                                         size_t *outMaxAttributeDataSize) const;
 
     // Stream attributes that have client data
-    gl::Error streamAttributes(const gl::AttributesMask &activeAttributesMask,
+    gl::Error streamAttributes(const gl::AttributesMask &attribsToStream,
                                GLsizei instanceCount,
                                const gl::IndexRange &indexRange) const;
     void syncDirtyAttrib(const gl::Context *context,
@@ -125,9 +125,7 @@
 
     mutable size_t mStreamingArrayBufferSize;
     mutable GLuint mStreamingArrayBuffer;
-
-    gl::AttributesMask mAttributesNeedStreaming;
 };
-}
+}  // namespace rx
 
 #endif  // LIBANGLE_RENDERER_GL_VERTEXARRAYGL_H_
diff --git a/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp b/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp
index bb3839c..a3378fe 100644
--- a/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp
+++ b/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp
@@ -56,58 +56,84 @@
                        : EGL_OPENGL_ES2_BIT;
 
     // clang-format off
-    mConfigAttribList =
+    std::vector<EGLint> configAttribListBase =
     {
-        // Choose RGBA8888
         EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
-        EGL_RED_SIZE, 8,
-        EGL_GREEN_SIZE, 8,
-        EGL_BLUE_SIZE, 8,
-        EGL_ALPHA_SIZE, 8,
-        // EGL1.5 spec Section 2.2 says that depth, multisample and stencil buffer depths
-        // must match for contexts to be compatible.
-        EGL_DEPTH_SIZE, 24,
-        EGL_STENCIL_SIZE, 8,
-        EGL_SAMPLE_BUFFERS, 0,
         // Android doesn't support pixmaps
         EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
         EGL_CONFIG_CAVEAT, EGL_NONE,
         EGL_CONFORMANT, esBit,
         EGL_RENDERABLE_TYPE, esBit,
     };
+    // clang-format on
 
     if (mEGL->hasExtension("EGL_EXT_pixel_format_float"))
     {
         // Don't request floating point configs
-        mConfigAttribList.push_back(EGL_COLOR_COMPONENT_TYPE_EXT);
-        mConfigAttribList.push_back(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT);
+        configAttribListBase.push_back(EGL_COLOR_COMPONENT_TYPE_EXT);
+        configAttribListBase.push_back(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT);
     }
 
-    // Complete the attrib list
-    mConfigAttribList.push_back(EGL_NONE);
+    std::vector<EGLint> configAttribListWithFormat = configAttribListBase;
+    // EGL1.5 spec Section 2.2 says that depth, multisample and stencil buffer depths
+    // must match for contexts to be compatible.
+    // Choose RGBA8888
+    configAttribListWithFormat.push_back(EGL_RED_SIZE);
+    configAttribListWithFormat.push_back(8);
+    configAttribListWithFormat.push_back(EGL_GREEN_SIZE);
+    configAttribListWithFormat.push_back(8);
+    configAttribListWithFormat.push_back(EGL_BLUE_SIZE);
+    configAttribListWithFormat.push_back(8);
+    configAttribListWithFormat.push_back(EGL_ALPHA_SIZE);
+    configAttribListWithFormat.push_back(8);
+    // Choose DEPTH24_STENCIL8
+    configAttribListWithFormat.push_back(EGL_DEPTH_SIZE);
+    configAttribListWithFormat.push_back(24);
+    configAttribListWithFormat.push_back(EGL_STENCIL_SIZE);
+    configAttribListWithFormat.push_back(8);
+    // Choose no multisampling
+    configAttribListWithFormat.push_back(EGL_SAMPLE_BUFFERS);
+    configAttribListWithFormat.push_back(0);
 
-    // clang-format on
+    // Complete the attrib lists
+    configAttribListBase.push_back(EGL_NONE);
+    configAttribListWithFormat.push_back(EGL_NONE);
+
     EGLint numConfig;
+    EGLConfig configWithFormat;
 
-    EGLBoolean success = mEGL->chooseConfig(mConfigAttribList.data(), &mConfig, 1, &numConfig);
+    EGLBoolean success =
+        mEGL->chooseConfig(configAttribListWithFormat.data(), &configWithFormat, 1, &numConfig);
     if (success == EGL_FALSE)
     {
         return egl::EglNotInitialized()
                << "eglChooseConfig failed with " << egl::Error(mEGL->getError());
     }
 
-    ANGLE_TRY(initializeContext(display->getAttributeMap()));
-
     int dummyPbufferAttribs[] = {
         EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE,
     };
-    mDummyPbuffer = mEGL->createPbufferSurface(mConfig, dummyPbufferAttribs);
+    mDummyPbuffer = mEGL->createPbufferSurface(configWithFormat, dummyPbufferAttribs);
     if (mDummyPbuffer == EGL_NO_SURFACE)
     {
         return egl::EglNotInitialized()
                << "eglCreatePbufferSurface failed with " << egl::Error(mEGL->getError());
     }
 
+    // Create mDummyPbuffer with a normal config, but create a no_config mContext, if possible
+    if (mEGL->hasExtension("EGL_KHR_no_config_context"))
+    {
+        mConfigAttribList = configAttribListBase;
+        mConfig           = EGL_NO_CONFIG_KHR;
+    }
+    else
+    {
+        mConfigAttribList = configAttribListWithFormat;
+        mConfig           = configWithFormat;
+    }
+
+    ANGLE_TRY(initializeContext(display->getAttributeMap()));
+
     success = mEGL->makeCurrent(mDummyPbuffer, mContext);
     if (success == EGL_FALSE)
     {
@@ -316,8 +342,20 @@
             {
                 config.renderTargetFormat = GL_RGB565;
             }
+            else if (config.redSize == 5 && config.greenSize == 5 && config.blueSize == 5 &&
+                     config.alphaSize == 1)
+            {
+                config.renderTargetFormat = GL_RGB5_A1;
+            }
+            else if (config.redSize == 4 && config.greenSize == 4 && config.blueSize == 4 &&
+                     config.alphaSize == 4)
+            {
+                config.renderTargetFormat = GL_RGBA4;
+            }
             else
             {
+                ERR() << "RGBA(" << config.redSize << "," << config.greenSize << ","
+                      << config.blueSize << "," << config.alphaSize << ") not handled";
                 UNREACHABLE();
             }
         }
diff --git a/src/libANGLE/renderer/null/ContextNULL.cpp b/src/libANGLE/renderer/null/ContextNULL.cpp
index f7937a8..5a523d3 100644
--- a/src/libANGLE/renderer/null/ContextNULL.cpp
+++ b/src/libANGLE/renderer/null/ContextNULL.cpp
@@ -78,6 +78,7 @@
     mExtensions.debugMarker            = true;
     mExtensions.translatedShaderSource = true;
 
+    mExtensions.textureStorage             = true;
     mExtensions.rgb8rgba8 = true;
     mExtensions.textureCompressionDXT1     = true;
     mExtensions.textureCompressionDXT3     = true;
@@ -89,6 +90,11 @@
     mExtensions.lossyETCDecode             = true;
     mExtensions.geometryShader             = true;
 
+    mExtensions.eglImage                  = true;
+    mExtensions.eglImageExternal          = true;
+    mExtensions.eglImageExternalEssl3     = true;
+    mExtensions.eglStreamConsumerExternal = true;
+
     const gl::Version maxClientVersion(3, 1);
     mCaps = GenerateMinimumCaps(maxClientVersion, mExtensions);
 
diff --git a/src/libANGLE/renderer/null/ImageNULL.cpp b/src/libANGLE/renderer/null/ImageNULL.cpp
index d106bf6..bc5b6b4 100644
--- a/src/libANGLE/renderer/null/ImageNULL.cpp
+++ b/src/libANGLE/renderer/null/ImageNULL.cpp
@@ -24,14 +24,12 @@
 
 egl::Error ImageNULL::initialize()
 {
-    UNIMPLEMENTED();
-    return egl::EglBadAccess();
+    return egl::NoError();
 }
 
 gl::Error ImageNULL::orphan(const gl::Context *context, egl::ImageSibling *sibling)
 {
-    UNIMPLEMENTED();
-    return gl::InternalError();
+    return gl::NoError();
 }
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/null/TextureNULL.cpp b/src/libANGLE/renderer/null/TextureNULL.cpp
index 24dd7b1..dec6328 100644
--- a/src/libANGLE/renderer/null/TextureNULL.cpp
+++ b/src/libANGLE/renderer/null/TextureNULL.cpp
@@ -131,8 +131,10 @@
     return gl::NoError();
 }
 
-void TextureNULL::syncState(const gl::Texture::DirtyBits &dirtyBits)
+gl::Error TextureNULL::syncState(const gl::Context *context,
+                                 const gl::Texture::DirtyBits &dirtyBits)
 {
+    return gl::NoError();
 }
 
 gl::Error TextureNULL::setStorageMultisample(const gl::Context *context,
diff --git a/src/libANGLE/renderer/null/TextureNULL.h b/src/libANGLE/renderer/null/TextureNULL.h
index 465e4ae..a6789b8 100644
--- a/src/libANGLE/renderer/null/TextureNULL.h
+++ b/src/libANGLE/renderer/null/TextureNULL.h
@@ -85,7 +85,8 @@
     gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override;
     gl::Error releaseTexImage(const gl::Context *context) override;
 
-    void syncState(const gl::Texture::DirtyBits &dirtyBits) override;
+    gl::Error syncState(const gl::Context *context,
+                        const gl::Texture::DirtyBits &dirtyBits) override;
 
     gl::Error setStorageMultisample(const gl::Context *context,
                                     gl::TextureType type,
diff --git a/src/libANGLE/renderer/renderer_utils.cpp b/src/libANGLE/renderer/renderer_utils.cpp
index 2d74f66..8fa4a77 100644
--- a/src/libANGLE/renderer/renderer_utils.cpp
+++ b/src/libANGLE/renderer/renderer_utils.cpp
@@ -539,7 +539,7 @@
                                  area, GL_RGBA, GL_UNSIGNED_BYTE, color));
     }
 
-    t->syncState();
+    ANGLE_TRY(t->syncState(context));
 
     mIncompleteTextures[type].set(context, t.release());
     *textureOut = mIncompleteTextures[type].get();
diff --git a/src/libANGLE/renderer/vulkan/CommandGraph.cpp b/src/libANGLE/renderer/vulkan/CommandGraph.cpp
index ee4403a..106e21b 100644
--- a/src/libANGLE/renderer/vulkan/CommandGraph.cpp
+++ b/src/libANGLE/renderer/vulkan/CommandGraph.cpp
@@ -396,6 +396,11 @@
     return NoError();
 }
 
+const gl::Rectangle &CommandGraphNode::getRenderPassRenderArea() const
+{
+    return mRenderPassRenderArea;
+}
+
 // CommandGraph implementation.
 CommandGraph::CommandGraph()
 {
diff --git a/src/libANGLE/renderer/vulkan/CommandGraph.h b/src/libANGLE/renderer/vulkan/CommandGraph.h
index b51f929..235d9d5 100644
--- a/src/libANGLE/renderer/vulkan/CommandGraph.h
+++ b/src/libANGLE/renderer/vulkan/CommandGraph.h
@@ -132,6 +132,8 @@
                           RenderPassCache *renderPassCache,
                           CommandBuffer *primaryCommandBuffer);
 
+    const gl::Rectangle &getRenderPassRenderArea() const;
+
   private:
     void setHasChildren();
 
diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp
index 1040914..6ac3628 100644
--- a/src/libANGLE/renderer/vulkan/ContextVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp
@@ -37,6 +37,16 @@
 
 namespace rx
 {
+
+namespace
+{
+constexpr gl::Rectangle kMaxSizedScissor(0,
+                                         0,
+                                         std::numeric_limits<int>::max(),
+                                         std::numeric_limits<int>::max());
+
+}  // anonymous namespace
+
 ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
     : ContextImpl(state),
       mRenderer(renderer),
@@ -344,15 +354,14 @@
 {
     if (glState.isScissorTestEnabled())
     {
-        mPipelineDesc->updateScissor(glState.getScissor(),
-                                     glState.getDrawFramebuffer()->getDimensions());
+        mPipelineDesc->updateScissor(glState.getScissor());
     }
     else
     {
-        // If the scissor test isn't enabled, we have to also update the scissor to
-        // be equal to the framebuffer dimensions to make sure we keep rendering everything.
-        mPipelineDesc->updateScissor(glState.getViewport(),
-                                     glState.getDrawFramebuffer()->getDimensions());
+        // If the scissor test isn't enabled, we can simply use a really big scissor that's
+        // certainly larger than the current surface using the maximum size of a 2D texture
+        // for the width and height.
+        mPipelineDesc->updateScissor(kMaxSizedScissor);
     }
 }
 
@@ -373,23 +382,15 @@
         switch (dirtyBit)
         {
             case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
-                updateScissor(glState);
-                break;
             case gl::State::DIRTY_BIT_SCISSOR:
-                // Only modify the scissor region if the test is enabled, otherwise we want to keep
-                // the viewport size as the scissor region.
-                if (glState.isScissorTestEnabled())
-                {
-                    mPipelineDesc->updateScissor(glState.getScissor(),
-                                                 glState.getDrawFramebuffer()->getDimensions());
-                }
+                updateScissor(glState);
                 break;
             case gl::State::DIRTY_BIT_VIEWPORT:
                 mPipelineDesc->updateViewport(glState.getViewport(), glState.getNearPlane(),
                                               glState.getFarPlane());
                 break;
             case gl::State::DIRTY_BIT_DEPTH_RANGE:
-                WARN() << "DIRTY_BIT_DEPTH_RANGE unimplemented";
+                mPipelineDesc->updateDepthRange(glState.getNearPlane(), glState.getFarPlane());
                 break;
             case gl::State::DIRTY_BIT_BLEND_ENABLED:
                 mPipelineDesc->updateBlendEnabled(glState.isBlendEnabled());
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index ece646d..d447564 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -454,6 +454,26 @@
         ANGLE_TRY(node->beginInsideRenderPassRecording(renderer, &commandBuffer));
     }
 
+    // TODO(jmadill): Cube map attachments. http://anglebug.com/2470
+    // We assume for now that we always need to clear only 1 layer starting at the
+    // baseArrayLayer 0, this might need to change depending how we'll implement
+    // cube maps, 3d textures and array textures.
+    VkClearRect clearRect;
+    clearRect.baseArrayLayer = 0;
+    clearRect.layerCount     = 1;
+
+    // When clearing, the scissor region must be clipped to the renderArea per the validation rules
+    // in Vulkan.
+    gl::Rectangle intersection;
+    if (!ClipRectangle(contextVk->getGLState().getScissor(), node->getRenderPassRenderArea(),
+                       &intersection))
+    {
+        // There is nothing to clear since the scissor is outside of the render area.
+        return gl::NoError();
+    }
+
+    clearRect.rect = gl_vk::GetRect(intersection);
+
     gl::AttachmentArray<VkClearAttachment> clearAttachments;
     int clearAttachmentIndex = 0;
 
@@ -501,14 +521,6 @@
         }
     }
 
-    // We assume for now that we always need to clear only 1 layer starting at the
-    // baseArrayLayer 0, this might need to change depending how we'll implement
-    // cube maps, 3d textures and array textures.
-    VkClearRect clearRect;
-    clearRect.baseArrayLayer = 0;
-    clearRect.layerCount     = 1;
-    clearRect.rect           = contextVk->getScissor();
-
     commandBuffer->clearAttachments(static_cast<uint32_t>(clearAttachmentIndex),
                                     clearAttachments.data(), 1, &clearRect);
     return gl::NoError();
diff --git a/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp b/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp
index ff3d986..c5c3bcb 100644
--- a/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp
+++ b/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp
@@ -28,15 +28,37 @@
 namespace
 {
 
+constexpr char kQualifierMarkerBegin[] = "@@ QUALIFIER-";
+constexpr char kLayoutMarkerBegin[]    = "@@ LAYOUT-";
+constexpr char kMarkerEnd[]            = " @@";
+constexpr char kUniformQualifier[]     = "uniform";
+
 void InsertLayoutSpecifierString(std::string *shaderString,
                                  const std::string &variableName,
                                  const std::string &layoutString)
 {
     std::stringstream searchStringBuilder;
-    searchStringBuilder << "@@ LAYOUT-" << variableName << " @@";
+    searchStringBuilder << kLayoutMarkerBegin << variableName << kMarkerEnd;
     std::string searchString = searchStringBuilder.str();
 
-    angle::ReplaceSubstring(shaderString, searchString, layoutString);
+    if (layoutString != "")
+    {
+        angle::ReplaceSubstring(shaderString, searchString, "layout(" + layoutString + ")");
+    }
+    else
+    {
+        angle::ReplaceSubstring(shaderString, searchString, layoutString);
+    }
+}
+
+void InsertQualifierSpecifierString(std::string *shaderString,
+                                    const std::string &variableName,
+                                    const std::string &replacementString)
+{
+    std::stringstream searchStringBuilder;
+    searchStringBuilder << kQualifierMarkerBegin << variableName << kMarkerEnd;
+    std::string searchString = searchStringBuilder.str();
+    angle::ReplaceSubstring(shaderString, searchString, replacementString);
 }
 
 }  // anonymous namespace
@@ -98,23 +120,53 @@
     // Parse attribute locations and replace them in the vertex shader.
     // See corresponding code in OutputVulkanGLSL.cpp.
     // TODO(jmadill): Also do the same for ESSL 3 fragment outputs.
-    for (const auto &attribute : programState.getAttributes())
+    for (const sh::Attribute &attribute : programState.getAttributes())
     {
-        if (!attribute.staticUse)
-            continue;
+        // Warning: If we endup supporting ES 3.0 shaders and up, Program::linkAttributes is going
+        // to bring us all attributes in this list instead of only the active ones.
+        ASSERT(attribute.active);
 
         std::string locationString = "location = " + Str(attribute.location);
         InsertLayoutSpecifierString(&vertexSource, attribute.name, locationString);
+        InsertQualifierSpecifierString(&vertexSource, attribute.name, "in");
+    }
+
+    // The attributes in the programState could have been filled with active attributes only
+    // depending on the shader version. If there is inactive attributes left, we have to remove
+    // their @@ QUALIFIER and @@ LAYOUT markers.
+    for (const sh::Attribute &attribute : glVertexShader->getAllAttributes(glContext))
+    {
+        if (attribute.active)
+        {
+            continue;
+        }
+
+        InsertLayoutSpecifierString(&vertexSource, attribute.name, "");
+        InsertQualifierSpecifierString(&vertexSource, attribute.name, "");
     }
 
     // Assign varying locations.
-    // TODO(jmadill): This might need to be redone.
-    for (const auto &varyingReg : resources.varyingPacking.getRegisterList())
+    for (const gl::PackedVaryingRegister &varyingReg : resources.varyingPacking.getRegisterList())
     {
         const auto &varying        = *varyingReg.packedVarying;
-        std::string locationString = "location = " + Str(varyingReg.registerRow);
+
+        std::string locationString = "location = " + Str(varyingReg.registerRow) +
+                                     ", component = " + Str(varyingReg.registerColumn);
         InsertLayoutSpecifierString(&vertexSource, varying.varying->name, locationString);
         InsertLayoutSpecifierString(&fragmentSource, varying.varying->name, locationString);
+
+        ASSERT(varying.interpolation == sh::INTERPOLATION_SMOOTH);
+        InsertQualifierSpecifierString(&vertexSource, varying.varying->name, "out");
+        InsertQualifierSpecifierString(&fragmentSource, varying.varying->name, "in");
+    }
+
+    // Remove all the markers for unused varyings.
+    for (const std::string &varyingName : resources.varyingPacking.getInactiveVaryingNames())
+    {
+        InsertLayoutSpecifierString(&vertexSource, varyingName, "");
+        InsertLayoutSpecifierString(&fragmentSource, varyingName, "");
+        InsertQualifierSpecifierString(&vertexSource, varyingName, "");
+        InsertQualifierSpecifierString(&fragmentSource, varyingName, "");
     }
 
     // Bind the default uniforms for vertex and fragment shaders.
@@ -143,18 +195,27 @@
         if (samplerUniform.isActive(gl::ShaderType::Vertex))
         {
             InsertLayoutSpecifierString(&vertexSource, samplerUniform.name, setBindingString);
+            InsertQualifierSpecifierString(&vertexSource, samplerUniform.name, kUniformQualifier);
+        }
+        else
+        {
+            InsertQualifierSpecifierString(&vertexSource, samplerUniform.name, "");
         }
 
         if (samplerUniform.isActive(gl::ShaderType::Fragment))
         {
             InsertLayoutSpecifierString(&fragmentSource, samplerUniform.name, setBindingString);
+            InsertQualifierSpecifierString(&fragmentSource, samplerUniform.name, kUniformQualifier);
+        }
+        else
+        {
+            InsertQualifierSpecifierString(&fragmentSource, samplerUniform.name, "");
         }
 
         textureCount += samplerUniform.getBasicTypeElementCount();
     }
 
     std::array<const char *, 2> strings = {{vertexSource.c_str(), fragmentSource.c_str()}};
-
     std::array<int, 2> lengths = {
         {static_cast<int>(vertexSource.length()), static_cast<int>(fragmentSource.length())}};
 
diff --git a/src/libANGLE/renderer/vulkan/ProgramVk.cpp b/src/libANGLE/renderer/vulkan/ProgramVk.cpp
index 6fb33e0..989232f 100644
--- a/src/libANGLE/renderer/vulkan/ProgramVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ProgramVk.cpp
@@ -431,7 +431,8 @@
 
     if (linkedUniform.isSampler())
     {
-        UNIMPLEMENTED();
+        // We could potentially cache some indexing here. For now this is a no-op since the mapping
+        // is handled entirely in ContextVk.
         return;
     }
 
diff --git a/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp b/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
index b7e363e..d23994e 100644
--- a/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
@@ -81,7 +81,7 @@
             (isDepthOrStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0);
 
         gl::Extents extents(static_cast<int>(width), static_cast<int>(height), 1);
-        ANGLE_TRY(mImage.init2D(device, extents, vkFormat, 1, usage));
+        ANGLE_TRY(mImage.init(device, gl::TextureType::_2D, extents, vkFormat, 1, usage));
 
         VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
         ANGLE_TRY(mImage.initMemory(device, renderer->getMemoryProperties(), flags));
@@ -91,7 +91,8 @@
             (textureFormat.stencilBits > 0 ? VK_IMAGE_ASPECT_STENCIL_BIT : 0) |
             (textureFormat.redBits > 0 ? VK_IMAGE_ASPECT_COLOR_BIT : 0);
 
-        ANGLE_TRY(mImage.initImageView(device, aspect, gl::SwizzleState(), &mImageView));
+        ANGLE_TRY(mImage.initImageView(device, gl::TextureType::_2D, aspect, gl::SwizzleState(),
+                                       &mImageView));
 
         // TODO(jmadill): Fold this into the RenderPass load/store ops. http://anglebug.com/2361
         vk::CommandBuffer *commandBuffer = nullptr;
diff --git a/src/libANGLE/renderer/vulkan/RendererVk.cpp b/src/libANGLE/renderer/vulkan/RendererVk.cpp
index 1c732cb..be8747a 100644
--- a/src/libANGLE/renderer/vulkan/RendererVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RendererVk.cpp
@@ -579,22 +579,7 @@
 
 std::string RendererVk::getVendorString() const
 {
-    switch (mPhysicalDeviceProperties.vendorID)
-    {
-        case VENDOR_ID_AMD:
-            return "Advanced Micro Devices";
-        case VENDOR_ID_NVIDIA:
-            return "NVIDIA";
-        case VENDOR_ID_INTEL:
-            return "Intel";
-        default:
-        {
-            // TODO(jmadill): More vendor IDs.
-            std::stringstream strstr;
-            strstr << "Vendor ID: " << mPhysicalDeviceProperties.vendorID;
-            return strstr.str();
-        }
-    }
+    return GetVendorString(mPhysicalDeviceProperties.vendorID);
 }
 
 std::string RendererVk::getRendererDescription() const
@@ -608,7 +593,18 @@
     strstr << VK_VERSION_MINOR(apiVersion) << ".";
     strstr << VK_VERSION_PATCH(apiVersion);
 
-    strstr << "(" << mPhysicalDeviceProperties.deviceName << ")";
+    strstr << "(";
+
+    // In the case of NVIDIA, deviceName does not necessarily contain "NVIDIA". Add "NVIDIA" so that
+    // Vulkan end2end tests can be selectively disabled on NVIDIA. TODO(jmadill): should not be
+    // needed after http://anglebug.com/1874 is fixed and end2end_tests use more sophisticated
+    // driver detection.
+    if (mPhysicalDeviceProperties.vendorID == VENDOR_ID_NVIDIA)
+    {
+        strstr << GetVendorString(mPhysicalDeviceProperties.vendorID) << " ";
+    }
+
+    strstr << mPhysicalDeviceProperties.deviceName << ")";
 
     return strstr.str();
 }
diff --git a/src/libANGLE/renderer/vulkan/ShaderVk.cpp b/src/libANGLE/renderer/vulkan/ShaderVk.cpp
index 78024a6..fb43c21 100644
--- a/src/libANGLE/renderer/vulkan/ShaderVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ShaderVk.cpp
@@ -26,7 +26,7 @@
                                                          std::string *sourcePath)
 {
     *sourceStream << mData.getSource();
-    return 0;
+    return SH_INITIALIZE_UNINITIALIZED_LOCALS;
 }
 
 bool ShaderVk::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog)
diff --git a/src/libANGLE/renderer/vulkan/SurfaceVk.cpp b/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
index d736782..faa6988 100644
--- a/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
+++ b/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
@@ -396,8 +396,8 @@
     {
         SwapchainImage &member = mSwapchainImages[imageIndex];
         member.image.init2DWeakReference(swapchainImages[imageIndex], extents, format, 1);
-        member.image.initImageView(device, VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(),
-                                   &member.imageView);
+        member.image.initImageView(device, gl::TextureType::_2D, VK_IMAGE_ASPECT_COLOR_BIT,
+                                   gl::SwizzleState(), &member.imageView);
 
         // Set transfer dest layout, and clear the image to black.
         member.image.clearColor(transparentBlack, commandBuffer);
@@ -418,7 +418,8 @@
             (VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
              VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
 
-        ANGLE_TRY(mDepthStencilImage.init2D(device, extents, dsFormat, 1, usage));
+        ANGLE_TRY(
+            mDepthStencilImage.init(device, gl::TextureType::_2D, extents, dsFormat, 1, usage));
         ANGLE_TRY(mDepthStencilImage.initMemory(device, renderer->getMemoryProperties(),
                                                 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
 
@@ -431,8 +432,8 @@
         // Set transfer dest layout, and clear the image.
         mDepthStencilImage.clearDepthStencil(aspect, depthStencilClearValue, commandBuffer);
 
-        ANGLE_TRY(mDepthStencilImage.initImageView(device, aspect, gl::SwizzleState(),
-                                                   &mDepthStencilImageView));
+        ANGLE_TRY(mDepthStencilImage.initImageView(device, gl::TextureType::_2D, aspect,
+                                                   gl::SwizzleState(), &mDepthStencilImageView));
 
         mDepthStencilRenderTarget.resource  = this;
         mDepthStencilRenderTarget.image     = &mDepthStencilImage;
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
index 6cda5d5..0582e30 100644
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
@@ -55,27 +55,29 @@
 }  // anonymous namespace
 
 // StagingStorage implementation.
-StagingStorage::StagingStorage()
-    : mStagingBuffer(kStagingBufferFlags, kStagingBufferSize), mCurrentBufferHandle(VK_NULL_HANDLE)
+PixelBuffer::PixelBuffer() : mStagingBuffer(kStagingBufferFlags, kStagingBufferSize)
 {
-    mStagingBuffer.init(1);
+    // vkCmdCopyBufferToImage must have an offset that is a multiple of 4.
+    // https://www.khronos.org/registry/vulkan/specs/1.0/man/html/VkBufferImageCopy.html
+    mStagingBuffer.init(4);
 }
 
-StagingStorage::~StagingStorage()
+PixelBuffer::~PixelBuffer()
 {
 }
 
-void StagingStorage::release(RendererVk *renderer)
+void PixelBuffer::release(RendererVk *renderer)
 {
     mStagingBuffer.release(renderer);
 }
 
-gl::Error StagingStorage::stageSubresourceUpdate(ContextVk *contextVk,
-                                                 const gl::Extents &extents,
-                                                 const gl::InternalFormat &formatInfo,
-                                                 const gl::PixelUnpackState &unpack,
-                                                 GLenum type,
-                                                 const uint8_t *pixels)
+gl::Error PixelBuffer::stageSubresourceUpdate(ContextVk *contextVk,
+                                              const gl::ImageIndex &index,
+                                              const gl::Extents &extents,
+                                              const gl::InternalFormat &formatInfo,
+                                              const gl::PixelUnpackState &unpack,
+                                              GLenum type,
+                                              const uint8_t *pixels)
 {
     GLuint inputRowPitch = 0;
     ANGLE_TRY_RESULT(
@@ -103,11 +105,13 @@
     size_t outputRowPitch   = storageFormat.pixelBytes * extents.width;
     size_t outputDepthPitch = outputRowPitch * extents.height;
 
+    VkBuffer bufferHandle = VK_NULL_HANDLE;
+
     uint8_t *stagingPointer = nullptr;
     bool newBufferAllocated = false;
     uint32_t stagingOffset  = 0;
     size_t allocationSize   = outputDepthPitch * extents.depth;
-    mStagingBuffer.allocate(renderer, allocationSize, &stagingPointer, &mCurrentBufferHandle,
+    mStagingBuffer.allocate(renderer, allocationSize, &stagingPointer, &bufferHandle,
                             &stagingOffset, &newBufferAllocated);
 
     const uint8_t *source = pixels + inputSkipBytes;
@@ -117,40 +121,64 @@
     loadFunction.loadFunction(extents.width, extents.height, extents.depth, source, inputRowPitch,
                               inputDepthPitch, stagingPointer, outputRowPitch, outputDepthPitch);
 
-    mCurrentCopyRegion.bufferOffset                    = static_cast<VkDeviceSize>(stagingOffset);
-    mCurrentCopyRegion.bufferRowLength                 = extents.width;
-    mCurrentCopyRegion.bufferImageHeight               = extents.height;
-    mCurrentCopyRegion.imageSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
-    mCurrentCopyRegion.imageSubresource.mipLevel       = 0;
-    mCurrentCopyRegion.imageSubresource.baseArrayLayer = 0;
-    mCurrentCopyRegion.imageSubresource.layerCount     = 1;
+    VkBufferImageCopy copy;
 
-    gl_vk::GetOffset(gl::Offset(), &mCurrentCopyRegion.imageOffset);
-    gl_vk::GetExtent(extents, &mCurrentCopyRegion.imageExtent);
+    copy.bufferOffset                    = static_cast<VkDeviceSize>(stagingOffset);
+    copy.bufferRowLength                 = extents.width;
+    copy.bufferImageHeight               = extents.height;
+    copy.imageSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
+    copy.imageSubresource.mipLevel       = index.getLevelIndex();
+    copy.imageSubresource.baseArrayLayer = index.hasLayer() ? index.getLayerIndex() : 0;
+    copy.imageSubresource.layerCount     = index.getLayerCount();
+
+    gl_vk::GetOffset(gl::Offset(), &copy.imageOffset);
+    gl_vk::GetExtent(extents, &copy.imageExtent);
+
+    mSubresourceUpdates.emplace_back(bufferHandle, copy);
 
     return gl::NoError();
 }
 
-vk::Error StagingStorage::flushUpdatesToImage(RendererVk *renderer,
-                                              vk::ImageHelper *image,
-                                              vk::CommandBuffer *commandBuffer)
+vk::Error PixelBuffer::flushUpdatesToImage(RendererVk *renderer,
+                                           vk::ImageHelper *image,
+                                           vk::CommandBuffer *commandBuffer)
 {
-    if (mCurrentBufferHandle != VK_NULL_HANDLE)
+    if (mSubresourceUpdates.empty())
     {
-        // Conservatively flush all writes to the image. We could use a more restricted barrier.
-        image->changeLayoutWithStages(
-            VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-            VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, commandBuffer);
-
-        ANGLE_TRY(mStagingBuffer.flush(renderer->getDevice()));
-        commandBuffer->copyBufferToImage(mCurrentBufferHandle, image->getImage(),
-                                         image->getCurrentLayout(), 1, &mCurrentCopyRegion);
-        mCurrentBufferHandle = VK_NULL_HANDLE;
+        return vk::NoError();
     }
 
+    // Conservatively flush all writes to the image. We could use a more restricted barrier.
+    image->changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                                  VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+                                  VK_PIPELINE_STAGE_TRANSFER_BIT, commandBuffer);
+
+    ANGLE_TRY(mStagingBuffer.flush(renderer->getDevice()));
+
+    for (const SubresourceUpdate &update : mSubresourceUpdates)
+    {
+        ASSERT(update.bufferHandle != VK_NULL_HANDLE);
+        commandBuffer->copyBufferToImage(update.bufferHandle, image->getImage(),
+                                         image->getCurrentLayout(), 1, &update.copyRegion);
+    }
+
+    mSubresourceUpdates.clear();
+
     return vk::NoError();
 }
 
+PixelBuffer::SubresourceUpdate::SubresourceUpdate() : bufferHandle(VK_NULL_HANDLE)
+{
+}
+
+PixelBuffer::SubresourceUpdate::SubresourceUpdate(VkBuffer bufferHandleIn,
+                                                  const VkBufferImageCopy &copyRegionIn)
+    : bufferHandle(bufferHandleIn), copyRegion(copyRegionIn)
+{
+}
+
+PixelBuffer::SubresourceUpdate::SubresourceUpdate(const SubresourceUpdate &other) = default;
+
 // TextureVk implementation.
 TextureVk::TextureVk(const gl::TextureState &state) : TextureImpl(state)
 {
@@ -171,7 +199,7 @@
     releaseImage(context, renderer);
     renderer->releaseResource(*this, &mSampler);
 
-    mStagingStorage.release(renderer);
+    mPixelBuffer.release(renderer);
 
     return gl::NoError();
 }
@@ -187,10 +215,13 @@
 {
     ContextVk *contextVk = vk::GetImpl(context);
     RendererVk *renderer = contextVk->getRenderer();
-    VkDevice device      = contextVk->getDevice();
 
     // TODO(jmadill): support multi-level textures.
-    ASSERT(index.mipIndex == 0);
+    if (index.getLevelIndex() != 0)
+    {
+        UNIMPLEMENTED();
+        return gl::InternalError();
+    }
 
     // Convert internalFormat to sized internal format.
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
@@ -211,48 +242,14 @@
         return gl::NoError();
     }
 
-    // TODO(jmadill): Cube map textures. http://anglebug.com/2318
-    if (index.target != gl::TextureTarget::_2D)
-    {
-        UNIMPLEMENTED();
-        return gl::InternalError();
-    }
-
-    if (!mSampler.valid())
-    {
-        // Create a simple sampler. Force basic parameter settings.
-        // TODO(jmadill): Sampler parameters.
-        VkSamplerCreateInfo samplerInfo;
-        samplerInfo.sType                   = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
-        samplerInfo.pNext                   = nullptr;
-        samplerInfo.flags                   = 0;
-        samplerInfo.magFilter               = VK_FILTER_NEAREST;
-        samplerInfo.minFilter               = VK_FILTER_NEAREST;
-        samplerInfo.mipmapMode              = VK_SAMPLER_MIPMAP_MODE_NEAREST;
-        samplerInfo.addressModeU            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
-        samplerInfo.addressModeV            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
-        samplerInfo.addressModeW            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
-        samplerInfo.mipLodBias              = 0.0f;
-        samplerInfo.anisotropyEnable        = VK_FALSE;
-        samplerInfo.maxAnisotropy           = 1.0f;
-        samplerInfo.compareEnable           = VK_FALSE;
-        samplerInfo.compareOp               = VK_COMPARE_OP_ALWAYS;
-        samplerInfo.minLod                  = 0.0f;
-        samplerInfo.maxLod                  = 1.0f;
-        samplerInfo.borderColor             = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
-        samplerInfo.unnormalizedCoordinates = VK_FALSE;
-
-        ANGLE_TRY(mSampler.init(device, samplerInfo));
-    }
-
     // Create a new graph node to store image initialization commands.
     getNewWritingNode(renderer);
 
     // Handle initial data.
     if (pixels)
     {
-        ANGLE_TRY(mStagingStorage.stageSubresourceUpdate(contextVk, size, formatInfo, unpack, type,
-                                                         pixels));
+        ANGLE_TRY(mPixelBuffer.stageSubresourceUpdate(contextVk, index, size, formatInfo, unpack,
+                                                      type, pixels));
     }
 
     return gl::NoError();
@@ -268,9 +265,9 @@
 {
     ContextVk *contextVk                 = vk::GetImpl(context);
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
-    ANGLE_TRY(mStagingStorage.stageSubresourceUpdate(
-        contextVk, gl::Extents(area.width, area.height, area.depth), formatInfo, unpack, type,
-        pixels));
+    ANGLE_TRY(mPixelBuffer.stageSubresourceUpdate(contextVk, index,
+                                                  gl::Extents(area.width, area.height, area.depth),
+                                                  formatInfo, unpack, type, pixels));
     return gl::NoError();
 }
 
@@ -375,10 +372,10 @@
                                                FramebufferAttachmentRenderTarget **rtOut)
 {
     // TODO(jmadill): Handle cube textures. http://anglebug.com/2318
-    ASSERT(imageIndex.type == gl::TextureType::_2D);
+    ASSERT(imageIndex.getType() == gl::TextureType::_2D);
 
     // Non-zero mip level attachments are an ES 3.0 feature.
-    ASSERT(imageIndex.mipIndex == 0 && imageIndex.layerIndex == gl::ImageIndex::ENTIRE_LEVEL);
+    ASSERT(imageIndex.getLevelIndex() == 0 && !imageIndex.hasLayer());
 
     ContextVk *contextVk = vk::GetImpl(context);
     RendererVk *renderer = contextVk->getRenderer();
@@ -420,7 +417,8 @@
         VkImageUsageFlags usage =
             (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
              VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
-        ANGLE_TRY(mImage.init2D(device, extents, format, 1, usage));
+
+        ANGLE_TRY(mImage.init(device, mState.getType(), extents, format, 1, usage));
 
         VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
         ANGLE_TRY(mImage.initMemory(device, renderer->getMemoryProperties(), flags));
@@ -428,8 +426,9 @@
         gl::SwizzleState mappedSwizzle;
         MapSwizzleState(format.internalFormat, mState.getSwizzleState(), &mappedSwizzle);
 
-        ANGLE_TRY(
-            mImage.initImageView(device, VK_IMAGE_ASPECT_COLOR_BIT, mappedSwizzle, &mImageView));
+        // TODO(jmadill): Separate imageviews for RenderTargets and Sampling.
+        ANGLE_TRY(mImage.initImageView(device, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT,
+                                       mappedSwizzle, &mImageView));
 
         // TODO(jmadill): Fold this into the RenderPass load/store ops. http://anglebug.com/2361
 
@@ -437,13 +436,49 @@
         mImage.clearColor(black, commandBuffer);
     }
 
-    ANGLE_TRY(mStagingStorage.flushUpdatesToImage(renderer, &mImage, commandBuffer));
+    ANGLE_TRY(mPixelBuffer.flushUpdatesToImage(renderer, &mImage, commandBuffer));
     return vk::NoError();
 }
 
-void TextureVk::syncState(const gl::Texture::DirtyBits &dirtyBits)
+gl::Error TextureVk::syncState(const gl::Context *context, const gl::Texture::DirtyBits &dirtyBits)
 {
-    // TODO(jmadill): Texture sync state.
+    if (dirtyBits.none() && mSampler.valid())
+    {
+        return gl::NoError();
+    }
+
+    ContextVk *contextVk = vk::GetImpl(context);
+    if (mSampler.valid())
+    {
+        RendererVk *renderer = contextVk->getRenderer();
+        renderer->releaseResource(*this, &mSampler);
+    }
+
+    const gl::SamplerState &samplerState = mState.getSamplerState();
+
+    // Create a simple sampler. Force basic parameter settings.
+    VkSamplerCreateInfo samplerInfo;
+    samplerInfo.sType                   = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
+    samplerInfo.pNext                   = nullptr;
+    samplerInfo.flags                   = 0;
+    samplerInfo.magFilter               = gl_vk::GetFilter(samplerState.magFilter);
+    samplerInfo.minFilter               = gl_vk::GetFilter(samplerState.minFilter);
+    samplerInfo.mipmapMode              = VK_SAMPLER_MIPMAP_MODE_NEAREST;
+    samplerInfo.addressModeU            = gl_vk::GetSamplerAddressMode(samplerState.wrapS);
+    samplerInfo.addressModeV            = gl_vk::GetSamplerAddressMode(samplerState.wrapT);
+    samplerInfo.addressModeW            = gl_vk::GetSamplerAddressMode(samplerState.wrapR);
+    samplerInfo.mipLodBias              = 0.0f;
+    samplerInfo.anisotropyEnable        = VK_FALSE;
+    samplerInfo.maxAnisotropy           = 1.0f;
+    samplerInfo.compareEnable           = VK_FALSE;
+    samplerInfo.compareOp               = VK_COMPARE_OP_ALWAYS;
+    samplerInfo.minLod                  = 0.0f;
+    samplerInfo.maxLod                  = 1.0f;
+    samplerInfo.borderColor             = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
+    samplerInfo.unnormalizedCoordinates = VK_FALSE;
+
+    ANGLE_TRY(mSampler.init(contextVk->getDevice(), samplerInfo));
+    return gl::NoError();
 }
 
 gl::Error TextureVk::setStorageMultisample(const gl::Context *context,
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.h b/src/libANGLE/renderer/vulkan/TextureVk.h
index 1e082bc..456f140 100644
--- a/src/libANGLE/renderer/vulkan/TextureVk.h
+++ b/src/libANGLE/renderer/vulkan/TextureVk.h
@@ -18,15 +18,16 @@
 namespace rx
 {
 
-class StagingStorage final : angle::NonCopyable
+class PixelBuffer final : angle::NonCopyable
 {
   public:
-    StagingStorage();
-    ~StagingStorage();
+    PixelBuffer();
+    ~PixelBuffer();
 
     void release(RendererVk *renderer);
 
     gl::Error stageSubresourceUpdate(ContextVk *contextVk,
+                                     const gl::ImageIndex &index,
                                      const gl::Extents &extents,
                                      const gl::InternalFormat &formatInfo,
                                      const gl::PixelUnpackState &unpack,
@@ -38,9 +39,18 @@
                                   vk::CommandBuffer *commandBuffer);
 
   private:
+    struct SubresourceUpdate
+    {
+        SubresourceUpdate();
+        SubresourceUpdate(VkBuffer bufferHandle, const VkBufferImageCopy &copyRegion);
+        SubresourceUpdate(const SubresourceUpdate &other);
+
+        VkBuffer bufferHandle;
+        VkBufferImageCopy copyRegion;
+    };
+
     vk::DynamicBuffer mStagingBuffer;
-    VkBuffer mCurrentBufferHandle;
-    VkBufferImageCopy mCurrentCopyRegion;
+    std::vector<SubresourceUpdate> mSubresourceUpdates;
 };
 
 class TextureVk : public TextureImpl, public vk::CommandGraphResource
@@ -119,7 +129,8 @@
                                         const gl::ImageIndex &imageIndex,
                                         FramebufferAttachmentRenderTarget **rtOut) override;
 
-    void syncState(const gl::Texture::DirtyBits &dirtyBits) override;
+    gl::Error syncState(const gl::Context *context,
+                        const gl::Texture::DirtyBits &dirtyBits) override;
 
     gl::Error setStorageMultisample(const gl::Context *context,
                                     gl::TextureType type,
@@ -146,7 +157,7 @@
 
     RenderTargetVk mRenderTarget;
 
-    StagingStorage mStagingStorage;
+    PixelBuffer mPixelBuffer;
 };
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
index aa573fe..81919a7 100644
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
@@ -70,8 +70,8 @@
 {
     ASSERT(!attribsToStream.none());
 
-    const auto &attribs          = mState.getVertexAttributes();
-    const auto &bindings         = mState.getVertexBindings();
+    const auto &attribs  = mState.getVertexAttributes();
+    const auto &bindings = mState.getVertexBindings();
 
     const size_t lastVertex = drawCallParams.firstVertex() + drawCallParams.vertexCount();
 
@@ -144,6 +144,22 @@
     return gl::NoError();
 }
 
+#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX)                                          \
+    case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX:                                  \
+        syncDirtyAttrib(attribs[INDEX], bindings[attribs[INDEX].bindingIndex], INDEX); \
+        invalidatePipeline = true;                                                     \
+        break;
+
+#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX)                                         \
+    case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX:                                 \
+        syncDirtyAttrib(attribs[INDEX], bindings[attribs[INDEX].bindingIndex], INDEX); \
+        invalidatePipeline = true;                                                     \
+        break;
+
+#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX)         \
+    case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
+        break;
+
 gl::Error VertexArrayVk::syncState(const gl::Context *context,
                                    const gl::VertexArray::DirtyBits &dirtyBits,
                                    const gl::VertexArray::DirtyAttribBitsArray &attribBits,
@@ -192,46 +208,13 @@
                 mDirtyLineLoopTranslation = true;
                 break;
 
+                ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC);
+                ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC);
+                ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC);
+
             default:
-            {
-                size_t attribIndex = gl::VertexArray::GetVertexIndexFromDirtyBit(dirtyBit);
-
-                // Invalidate the input description for pipelines.
-                mDirtyPackedInputs.set(attribIndex);
-
-                const auto &attrib  = attribs[attribIndex];
-                const auto &binding = bindings[attrib.bindingIndex];
-
-                if (attrib.enabled)
-                {
-                    gl::Buffer *bufferGL = binding.getBuffer().get();
-
-                    if (bufferGL)
-                    {
-                        BufferVk *bufferVk                        = vk::GetImpl(bufferGL);
-                        mCurrentArrayBufferResources[attribIndex] = bufferVk;
-                        mCurrentArrayBufferHandles[attribIndex] =
-                            bufferVk->getVkBuffer().getHandle();
-                        mClientMemoryAttribs.reset(attribIndex);
-                    }
-                    else
-                    {
-                        mCurrentArrayBufferResources[attribIndex] = nullptr;
-                        mCurrentArrayBufferHandles[attribIndex]   = VK_NULL_HANDLE;
-                        mClientMemoryAttribs.set(attribIndex);
-                    }
-                    // TODO(jmadill): Offset handling.  Assume zero for now.
-                    mCurrentArrayBufferOffsets[attribIndex] = 0;
-                }
-                else
-                {
-                    mClientMemoryAttribs.reset(attribIndex);
-                    UNIMPLEMENTED();
-                }
-
-                invalidatePipeline = true;
+                UNREACHABLE();
                 break;
-            }
         }
     }
 
@@ -244,6 +227,37 @@
     return gl::NoError();
 }
 
+void VertexArrayVk::syncDirtyAttrib(const gl::VertexAttribute &attrib,
+                                    const gl::VertexBinding &binding,
+                                    size_t attribIndex)
+{
+    // Invalidate the input description for pipelines.
+    mDirtyPackedInputs.set(attribIndex);
+
+    if (attrib.enabled)
+    {
+        gl::Buffer *bufferGL = binding.getBuffer().get();
+
+        if (bufferGL)
+        {
+            BufferVk *bufferVk                        = vk::GetImpl(bufferGL);
+            mCurrentArrayBufferResources[attribIndex] = bufferVk;
+            mCurrentArrayBufferHandles[attribIndex]   = bufferVk->getVkBuffer().getHandle();
+        }
+        else
+        {
+            mCurrentArrayBufferResources[attribIndex] = nullptr;
+            mCurrentArrayBufferHandles[attribIndex]   = VK_NULL_HANDLE;
+        }
+        // TODO(jmadill): Offset handling.  Assume zero for now.
+        mCurrentArrayBufferOffsets[attribIndex] = 0;
+    }
+    else
+    {
+        UNIMPLEMENTED();
+    }
+}
+
 const gl::AttribArray<VkBuffer> &VertexArrayVk::getCurrentArrayBufferHandles() const
 {
     return mCurrentArrayBufferHandles;
@@ -350,7 +364,6 @@
     }
 
     // Handle GL_LINE_LOOP drawArrays.
-    // This test may be incorrect if the draw call switches from DrawArrays/DrawElements.
     int lastVertex = drawCallParams.firstVertex() + drawCallParams.vertexCount();
     if (!mLineLoopBufferFirstIndex.valid() || !mLineLoopBufferLastIndex.valid() ||
         mLineLoopBufferFirstIndex != drawCallParams.firstVertex() ||
@@ -389,23 +402,26 @@
     }
 
     // Handle GL_LINE_LOOP drawElements.
-    gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer().get();
-    if (!elementArrayBuffer)
-    {
-        UNIMPLEMENTED();
-        return gl::InternalError() << "Line loop indices in client memory not supported";
-    }
-
-    BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
-
-    VkIndexType indexType = gl_vk::GetIndexType(drawCallParams.type());
-
-    // This also doesn't check if the element type changed, which should trigger translation.
     if (mDirtyLineLoopTranslation)
     {
-        ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
-            renderer, elementArrayBufferVk, indexType, drawCallParams.indexCount(),
-            &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
+        gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer().get();
+        VkIndexType indexType          = gl_vk::GetIndexType(drawCallParams.type());
+
+        if (!elementArrayBuffer)
+        {
+            ANGLE_TRY(mLineLoopHelper.getIndexBufferForClientElementArray(
+                renderer, drawCallParams.indices(), indexType, drawCallParams.indexCount(),
+                &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
+        }
+        else
+        {
+            // When using an element array buffer, 'indices' is an offset to the first element.
+            intptr_t offset                = reinterpret_cast<intptr_t>(drawCallParams.indices());
+            BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
+            ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
+                renderer, elementArrayBufferVk, indexType, drawCallParams.indexCount(), offset,
+                &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
+        }
     }
 
     ANGLE_TRY(onIndexedDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
@@ -422,12 +438,13 @@
 {
     const gl::State &state                  = context->getGLState();
     const gl::Program *programGL            = state.getProgram();
+    const gl::AttributesMask &clientAttribs = mState.getEnabledClientMemoryAttribsMask();
     const gl::AttributesMask &activeAttribs = programGL->getActiveAttribLocationsMask();
     uint32_t maxAttrib                      = programGL->getState().getMaxActiveAttribLocation();
 
-    if (mClientMemoryAttribs.any())
+    if (clientAttribs.any())
     {
-        const gl::AttributesMask &attribsToStream = (mClientMemoryAttribs & activeAttribs);
+        const gl::AttributesMask &attribsToStream = (clientAttribs & activeAttribs);
         if (attribsToStream.any())
         {
             ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
@@ -447,7 +464,16 @@
             updateArrayBufferReadDependencies(drawNode, activeAttribs,
                                               renderer->getCurrentQueueSerial());
         }
+
         mVertexBuffersDirty = false;
+
+        // This forces the binding to happen if we follow a drawElement call from a drawArrays call.
+        mIndexBufferDirty = true;
+
+        // If we've had a drawElements call with a line loop before, we want to make sure this is
+        // invalidated the next time drawElements is called since we use the same index buffer for
+        // both calls.
+        mDirtyLineLoopTranslation = true;
     }
 
     return gl::NoError();
@@ -461,7 +487,7 @@
 {
     ANGLE_TRY(onDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
 
-    if (!mState.getElementArrayBuffer().get())
+    if (!mState.getElementArrayBuffer().get() && drawCallParams.mode() != GL_LINE_LOOP)
     {
         ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
         ANGLE_TRY(streamIndexData(renderer, drawCallParams));
@@ -486,6 +512,12 @@
                                        gl_vk::GetIndexType(drawCallParams.type()));
         updateElementArrayBufferReadDependency(drawNode, renderer->getCurrentQueueSerial());
         mIndexBufferDirty = false;
+
+        // If we've had a drawArrays call with a line loop before, we want to make sure this is
+        // invalidated the next time drawArrays is called since we use the same index buffer for
+        // both calls.
+        mLineLoopBufferFirstIndex.reset();
+        mLineLoopBufferLastIndex.reset();
     }
 
     return gl::NoError();
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.h b/src/libANGLE/renderer/vulkan/VertexArrayVk.h
index fe26f73..4c4cec3 100644
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.h
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.h
@@ -99,6 +99,10 @@
                             vk::CommandGraphNode *drawNode,
                             bool newCommandBuffer);
 
+    void syncDirtyAttrib(const gl::VertexAttribute &attrib,
+                         const gl::VertexBinding &binding,
+                         size_t attribIndex);
+
     gl::AttribArray<VkBuffer> mCurrentArrayBufferHandles;
     gl::AttribArray<VkDeviceSize> mCurrentArrayBufferOffsets;
     gl::AttribArray<vk::CommandGraphResource *> mCurrentArrayBufferResources;
@@ -112,10 +116,6 @@
     vk::VertexInputBindings mPackedInputBindings;
     vk::VertexInputAttributes mPackedInputAttributes;
 
-    // Which attributes need to be copied from client memory.
-    // TODO(jmadill): Move this to VertexArrayState. http://anglebug.com/2389
-    gl::AttributesMask mClientMemoryAttribs;
-
     vk::DynamicBuffer mDynamicVertexData;
     vk::DynamicBuffer mDynamicIndexData;
 
diff --git a/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp b/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp
index 79dda22..f680a0e 100644
--- a/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp
@@ -647,13 +647,15 @@
     mViewport.y        = static_cast<float>(viewport.y);
     mViewport.width    = static_cast<float>(viewport.width);
     mViewport.height   = static_cast<float>(viewport.height);
-    mViewport.minDepth = nearPlane;
-    mViewport.maxDepth = farPlane;
+    updateDepthRange(nearPlane, farPlane);
+}
 
-    mScissor.offset.x      = viewport.x;
-    mScissor.offset.y      = viewport.y;
-    mScissor.extent.width  = viewport.width;
-    mScissor.extent.height = viewport.height;
+void PipelineDesc::updateDepthRange(float nearPlane, float farPlane)
+{
+    // GLES2.0 Section 2.12.1: Each of n and f are clamped to lie within [0, 1], as are all
+    // arguments of type clampf.
+    mViewport.minDepth = gl::clamp01(nearPlane);
+    mViewport.maxDepth = gl::clamp01(farPlane);
 }
 
 void PipelineDesc::updateVertexInputInfo(const VertexInputBindings &bindings,
@@ -808,22 +810,9 @@
     mRenderPassDesc = renderPassDesc;
 }
 
-void PipelineDesc::updateScissor(const gl::Rectangle &rect, gl::Box framebufferDimensions)
+void PipelineDesc::updateScissor(const gl::Rectangle &rect)
 {
-    gl::Rectangle intersection;
-    gl::Rectangle clipRect(static_cast<GLuint>(0), static_cast<GLuint>(0),
-                           static_cast<GLuint>(framebufferDimensions.width),
-                           static_cast<GLuint>(framebufferDimensions.height));
-    // Coordinates outside the framebuffer aren't valid in Vulkan but not error is returned, the
-    // scissor is just ignored.
-    if (ClipRectangle(rect, clipRect, &intersection))
-    {
-        mScissor = gl_vk::GetRect(intersection);
-    }
-    else
-    {
-        mScissor = gl_vk::GetRect(rect);
-    }
+    mScissor = gl_vk::GetRect(rect);
 }
 
 // AttachmentOpsArray implementation.
diff --git a/src/libANGLE/renderer/vulkan/vk_cache_utils.h b/src/libANGLE/renderer/vulkan/vk_cache_utils.h
index b8d1418..9b230a7 100644
--- a/src/libANGLE/renderer/vulkan/vk_cache_utils.h
+++ b/src/libANGLE/renderer/vulkan/vk_cache_utils.h
@@ -269,6 +269,7 @@
                              Pipeline *pipelineOut) const;
 
     void updateViewport(const gl::Rectangle &viewport, float nearPlane, float farPlane);
+    void updateDepthRange(float nearPlane, float farPlane);
 
     // Shader stage info
     const ShaderStageInfo &getShaderStageInfo() const;
@@ -292,7 +293,7 @@
 
     // Scissor support
     const VkRect2D &getScissor() const { return mScissor; }
-    void updateScissor(const gl::Rectangle &rect, gl::Box surfaceDimensions);
+    void updateScissor(const gl::Rectangle &rect);
 
     // Blend states
     void updateBlendEnabled(bool isBlendEnabled);
diff --git a/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp b/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
index e1c3b3a..14e970c 100644
--- a/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
@@ -93,8 +93,12 @@
     // we'll defer the implementation until we tackle the next version.
     // outCaps->maxServerWaitTimeout
 
-    const GLuint maxUniformVectors = physicalDeviceProperties.limits.maxUniformBufferRange /
-                                     (sizeof(GLfloat) * kComponentsPerVector);
+    GLuint maxUniformVectors = physicalDeviceProperties.limits.maxUniformBufferRange /
+                               (sizeof(GLfloat) * kComponentsPerVector);
+
+    // Clamp the maxUniformVectors to 1024u, on AMD the maxUniformBufferRange is way too high.
+    maxUniformVectors = std::min(1024u, maxUniformVectors);
+
     const GLuint maxUniformComponents = maxUniformVectors * kComponentsPerVector;
 
     // Uniforms are implemented using a uniform buffer, so the max number of uniforms we can
@@ -110,8 +114,6 @@
     // and likely one per shader stage for ANGLE internal variables.
     // outCaps->maxVertexUniformBlocks = ...
 
-    outCaps->maxVertexOutputComponents = physicalDeviceProperties.limits.maxVertexOutputComponents;
-
     // we use the same bindings on each stage, so the limitation is the same combined or not.
     outCaps->maxCombinedTextureImageUnits =
         physicalDeviceProperties.limits.maxPerStageDescriptorSamplers;
@@ -119,8 +121,17 @@
     outCaps->maxVertexTextureImageUnits =
         physicalDeviceProperties.limits.maxPerStageDescriptorSamplers;
 
-    // TODO(jmadill): count reserved varyings
-    outCaps->maxVaryingVectors = physicalDeviceProperties.limits.maxVertexOutputComponents / 4;
+    // The max vertex output components should not include gl_Position.
+    // The gles2.0 section 2.10 states that "gl_Position is not a varying variable and does
+    // not count against this limit.", but the Vulkan spec has no such mention in its Built-in
+    // vars section. It is implicit that we need to actually reserve it for Vulkan in that case.
+    // TODO(lucferron): AMD has a weird behavior when we edge toward the maximum number of varyings
+    // and can often crash. Reserving an additional varying just for them bringing the total to 2.
+    // http://anglebug.com/2483
+    constexpr GLint kReservedVaryingCount = 2;
+    outCaps->maxVaryingVectors =
+        (physicalDeviceProperties.limits.maxVertexOutputComponents / 4) - kReservedVaryingCount;
+    outCaps->maxVertexOutputComponents = outCaps->maxVaryingVectors * 4;
 }
 }  // namespace vk
 }  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.cpp b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
index 98774fd..4261879 100644
--- a/src/libANGLE/renderer/vulkan/vk_helpers.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
@@ -19,7 +19,7 @@
 namespace
 {
 // TODO(jmadill): Pick non-arbitrary max.
-constexpr uint32_t kDynamicDescriptorPoolMaxSets = 2048;
+constexpr uint32_t kDefaultDynamicDescriptorPoolMaxSets = 2048;
 
 constexpr VkBufferUsageFlags kLineLoopDynamicBufferUsage =
     (VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
@@ -66,6 +66,30 @@
             return 0;
     }
 }
+
+VkImageCreateFlags GetImageCreateFlags(gl::TextureType textureType)
+{
+    if (textureType == gl::TextureType::CubeMap)
+    {
+        return VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+uint32_t GetImageLayerCount(gl::TextureType textureType)
+{
+    if (textureType == gl::TextureType::CubeMap)
+    {
+        return gl::CUBE_FACE_COUNT;
+    }
+    else
+    {
+        return 1;
+    }
+}
 }  // anonymous namespace
 
 // DynamicBuffer implementation.
@@ -215,7 +239,8 @@
 
 // DynamicDescriptorPool implementation.
 DynamicDescriptorPool::DynamicDescriptorPool()
-    : mCurrentAllocatedDescriptorSetCount(0),
+    : mMaxSetsPerPool(kDefaultDynamicDescriptorPoolMaxSets),
+      mCurrentAllocatedDescriptorSetCount(0),
       mUniformBufferDescriptorsPerSet(0),
       mCombinedImageSamplerDescriptorsPerSet(0)
 {
@@ -250,7 +275,7 @@
     uint32_t descriptorSetCount,
     VkDescriptorSet *descriptorSetsOut)
 {
-    if (descriptorSetCount + mCurrentAllocatedDescriptorSetCount > kDynamicDescriptorPoolMaxSets)
+    if (descriptorSetCount + mCurrentAllocatedDescriptorSetCount > mMaxSetsPerPool)
     {
         RendererVk *renderer = contextVk->getRenderer();
         Serial currentSerial = renderer->getCurrentQueueSerial();
@@ -279,17 +304,16 @@
     VkDescriptorPoolSize poolSizes[DescriptorPoolIndexCount];
     poolSizes[UniformBufferIndex].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
     poolSizes[UniformBufferIndex].descriptorCount =
-        mUniformBufferDescriptorsPerSet * kDynamicDescriptorPoolMaxSets / DescriptorPoolIndexCount;
+        mUniformBufferDescriptorsPerSet * mMaxSetsPerPool;
     poolSizes[TextureIndex].type            = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
-    poolSizes[TextureIndex].descriptorCount = mCombinedImageSamplerDescriptorsPerSet *
-                                              kDynamicDescriptorPoolMaxSets /
-                                              DescriptorPoolIndexCount;
+    poolSizes[TextureIndex].descriptorCount =
+        mCombinedImageSamplerDescriptorsPerSet * mMaxSetsPerPool;
 
     VkDescriptorPoolCreateInfo descriptorPoolInfo;
     descriptorPoolInfo.sType   = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
     descriptorPoolInfo.pNext   = nullptr;
     descriptorPoolInfo.flags   = 0;
-    descriptorPoolInfo.maxSets = kDynamicDescriptorPoolMaxSets;
+    descriptorPoolInfo.maxSets = mMaxSetsPerPool;
 
     // Reserve pools for uniform blocks and textures.
     descriptorPoolInfo.poolSizeCount = DescriptorPoolIndexCount;
@@ -300,10 +324,21 @@
     return NoError();
 }
 
+void DynamicDescriptorPool::setMaxSetsPerPoolForTesting(uint32_t maxSetsPerPool)
+{
+    mMaxSetsPerPool = maxSetsPerPool;
+}
+
+// LineLoopHelper implementation.
 LineLoopHelper::LineLoopHelper()
     : mDynamicIndexBuffer(kLineLoopDynamicBufferUsage, kLineLoopDynamicBufferMinSize)
 {
-    mDynamicIndexBuffer.init(1);
+    // We need to use an alignment of the maximum size we're going to allocate, which is
+    // VK_INDEX_TYPE_UINT32. When we switch from a drawElement to a drawArray call, the allocations
+    // can vary in size. According to the Vulkan spec, when calling vkCmdBindIndexBuffer: 'The
+    // sum of offset and the address of the range of VkDeviceMemory object that is backing buffer,
+    // must be a multiple of the type indicated by indexType'.
+    mDynamicIndexBuffer.init(sizeof(uint32_t));
 }
 
 LineLoopHelper::~LineLoopHelper() = default;
@@ -341,23 +376,26 @@
                                                               BufferVk *elementArrayBufferVk,
                                                               VkIndexType indexType,
                                                               int indexCount,
+                                                              intptr_t elementArrayOffset,
                                                               VkBuffer *bufferHandleOut,
                                                               VkDeviceSize *bufferOffsetOut)
 {
     ASSERT(indexType == VK_INDEX_TYPE_UINT16 || indexType == VK_INDEX_TYPE_UINT32);
 
     uint32_t *indices = nullptr;
-    uint32_t offset   = 0;
+    uint32_t destinationOffset = 0;
 
     auto unitSize = (indexType == VK_INDEX_TYPE_UINT16 ? sizeof(uint16_t) : sizeof(uint32_t));
     size_t allocateBytes = unitSize * (indexCount + 1);
     ANGLE_TRY(mDynamicIndexBuffer.allocate(renderer, allocateBytes,
                                            reinterpret_cast<uint8_t **>(&indices), bufferHandleOut,
-                                           &offset, nullptr));
-    *bufferOffsetOut = static_cast<VkDeviceSize>(offset);
+                                           &destinationOffset, nullptr));
+    *bufferOffsetOut = static_cast<VkDeviceSize>(destinationOffset);
 
-    VkBufferCopy copy1 = {0, offset, static_cast<VkDeviceSize>(indexCount) * unitSize};
-    VkBufferCopy copy2 = {0, offset + static_cast<VkDeviceSize>(indexCount) * unitSize, unitSize};
+    VkDeviceSize sourceOffset = static_cast<VkDeviceSize>(elementArrayOffset);
+    uint64_t unitCount        = static_cast<VkDeviceSize>(indexCount);
+    VkBufferCopy copy1        = {sourceOffset, destinationOffset, unitCount * unitSize};
+    VkBufferCopy copy2        = {sourceOffset, destinationOffset + unitCount * unitSize, unitSize};
     std::array<VkBufferCopy, 2> copies = {{copy1, copy2}};
 
     vk::CommandBuffer *commandBuffer;
@@ -372,6 +410,34 @@
     return gl::NoError();
 }
 
+gl::Error LineLoopHelper::getIndexBufferForClientElementArray(RendererVk *renderer,
+                                                              const void *indicesInput,
+                                                              VkIndexType indexType,
+                                                              int indexCount,
+                                                              VkBuffer *bufferHandleOut,
+                                                              VkDeviceSize *bufferOffsetOut)
+{
+    // TODO(lucferron): we'll eventually need to support uint8, emulated on 16 since Vulkan only
+    // supports 16 / 32.
+    ASSERT(indexType == VK_INDEX_TYPE_UINT16 || indexType == VK_INDEX_TYPE_UINT32);
+
+    uint8_t *indices = nullptr;
+    uint32_t offset  = 0;
+
+    auto unitSize = (indexType == VK_INDEX_TYPE_UINT16 ? sizeof(uint16_t) : sizeof(uint32_t));
+    size_t allocateBytes = unitSize * (indexCount + 1);
+    ANGLE_TRY(mDynamicIndexBuffer.allocate(renderer, allocateBytes,
+                                           reinterpret_cast<uint8_t **>(&indices), bufferHandleOut,
+                                           &offset, nullptr));
+    *bufferOffsetOut = static_cast<VkDeviceSize>(offset);
+
+    memcpy(indices, indicesInput, unitSize * indexCount);
+    memcpy(indices + unitSize * indexCount, indicesInput, unitSize);
+
+    ANGLE_TRY(mDynamicIndexBuffer.flush(renderer->getDevice()));
+    return gl::NoError();
+}
+
 void LineLoopHelper::destroy(VkDevice device)
 {
     mDynamicIndexBuffer.destroy(device);
@@ -389,7 +455,8 @@
     : mFormat(nullptr),
       mSamples(0),
       mAllocatedMemorySize(0),
-      mCurrentLayout(VK_IMAGE_LAYOUT_UNDEFINED)
+      mCurrentLayout(VK_IMAGE_LAYOUT_UNDEFINED),
+      mLayerCount(0)
 {
 }
 
@@ -400,8 +467,11 @@
       mFormat(other.mFormat),
       mSamples(other.mSamples),
       mAllocatedMemorySize(other.mAllocatedMemorySize),
-      mCurrentLayout(other.mCurrentLayout)
+      mCurrentLayout(other.mCurrentLayout),
+      mLayerCount(other.mLayerCount)
 {
+    other.mCurrentLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+    other.mLayerCount    = 0;
 }
 
 ImageHelper::~ImageHelper()
@@ -414,29 +484,31 @@
     return mImage.valid();
 }
 
-Error ImageHelper::init2D(VkDevice device,
-                          const gl::Extents &extents,
-                          const Format &format,
-                          GLint samples,
-                          VkImageUsageFlags usage)
+Error ImageHelper::init(VkDevice device,
+                        gl::TextureType textureType,
+                        const gl::Extents &extents,
+                        const Format &format,
+                        GLint samples,
+                        VkImageUsageFlags usage)
 {
     ASSERT(!valid());
 
-    mExtents = extents;
-    mFormat  = &format;
-    mSamples = samples;
+    mExtents    = extents;
+    mFormat     = &format;
+    mSamples    = samples;
+    mLayerCount = GetImageLayerCount(textureType);
 
     VkImageCreateInfo imageInfo;
     imageInfo.sType                 = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
     imageInfo.pNext                 = nullptr;
-    imageInfo.flags                 = 0;
-    imageInfo.imageType             = VK_IMAGE_TYPE_2D;
+    imageInfo.flags                 = GetImageCreateFlags(textureType);
+    imageInfo.imageType             = gl_vk::GetImageType(textureType);
     imageInfo.format                = format.vkTextureFormat;
     imageInfo.extent.width          = static_cast<uint32_t>(extents.width);
     imageInfo.extent.height         = static_cast<uint32_t>(extents.height);
     imageInfo.extent.depth          = 1;
     imageInfo.mipLevels             = 1;
-    imageInfo.arrayLayers           = 1;
+    imageInfo.arrayLayers           = mLayerCount;
     imageInfo.samples               = gl_vk::GetSamples(samples);
     imageInfo.tiling                = VK_IMAGE_TILING_OPTIMAL;
     imageInfo.usage                 = usage;
@@ -473,6 +545,7 @@
 }
 
 Error ImageHelper::initImageView(VkDevice device,
+                                 gl::TextureType textureType,
                                  VkImageAspectFlags aspectMask,
                                  const gl::SwizzleState &swizzleMap,
                                  ImageView *imageViewOut)
@@ -482,7 +555,7 @@
     viewInfo.pNext                           = nullptr;
     viewInfo.flags                           = 0;
     viewInfo.image                           = mImage.getHandle();
-    viewInfo.viewType                        = VK_IMAGE_VIEW_TYPE_2D;
+    viewInfo.viewType                        = gl_vk::GetImageViewType(textureType);
     viewInfo.format                          = mFormat->vkTextureFormat;
     viewInfo.components.r                    = gl_vk::GetSwizzle(swizzleMap.swizzleRed);
     viewInfo.components.g                    = gl_vk::GetSwizzle(swizzleMap.swizzleGreen);
@@ -492,7 +565,7 @@
     viewInfo.subresourceRange.baseMipLevel   = 0;
     viewInfo.subresourceRange.levelCount     = 1;
     viewInfo.subresourceRange.baseArrayLayer = 0;
-    viewInfo.subresourceRange.layerCount     = 1;
+    viewInfo.subresourceRange.layerCount     = mLayerCount;
 
     ANGLE_TRY(imageViewOut->init(device, viewInfo));
     return NoError();
@@ -502,6 +575,8 @@
 {
     mImage.destroy(device);
     mDeviceMemory.destroy(device);
+    mCurrentLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+    mLayerCount    = 0;
 }
 
 void ImageHelper::init2DWeakReference(VkImage handle,
@@ -511,9 +586,10 @@
 {
     ASSERT(!valid());
 
-    mExtents = extents;
-    mFormat  = &format;
-    mSamples = samples;
+    mExtents    = extents;
+    mFormat     = &format;
+    mSamples    = samples;
+    mLayerCount = 1;
 
     mImage.setHandle(handle);
 }
@@ -526,9 +602,10 @@
 {
     ASSERT(!valid());
 
-    mExtents = extents;
-    mFormat  = &format;
-    mSamples = 1;
+    mExtents    = extents;
+    mFormat     = &format;
+    mSamples    = 1;
+    mLayerCount = 1;
 
     // Use Preinitialized for writable staging images - in these cases we want to map the memory
     // before we do a copy. For readback images, use an undefined layout.
@@ -626,7 +703,7 @@
     imageMemoryBarrier.subresourceRange.baseMipLevel   = 0;
     imageMemoryBarrier.subresourceRange.levelCount     = 1;
     imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
-    imageMemoryBarrier.subresourceRange.layerCount     = 1;
+    imageMemoryBarrier.subresourceRange.layerCount     = mLayerCount;
 
     // TODO(jmadill): Test all the permutations of the access flags.
     imageMemoryBarrier.srcAccessMask = GetBasicLayoutAccessFlags(mCurrentLayout);
@@ -668,7 +745,7 @@
     range.baseMipLevel   = 0;
     range.levelCount     = 1;
     range.baseArrayLayer = 0;
-    range.layerCount     = 1;
+    range.layerCount     = mLayerCount;
 
     commandBuffer->clearColorImage(mImage, mCurrentLayout, color, 1, &range);
 }
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.h b/src/libANGLE/renderer/vulkan/vk_helpers.h
index 237c85c..09cf845 100644
--- a/src/libANGLE/renderer/vulkan/vk_helpers.h
+++ b/src/libANGLE/renderer/vulkan/vk_helpers.h
@@ -12,6 +12,11 @@
 #include "libANGLE/renderer/vulkan/CommandGraph.h"
 #include "libANGLE/renderer/vulkan/vk_utils.h"
 
+namespace gl
+{
+class ImageIndex;
+}  // namespace gl;
+
 namespace rx
 {
 namespace vk
@@ -96,9 +101,13 @@
                                  uint32_t descriptorSetCount,
                                  VkDescriptorSet *descriptorSetsOut);
 
+    // For testing only!
+    void setMaxSetsPerPoolForTesting(uint32_t maxSetsPerPool);
+
   private:
     Error allocateNewPool(const VkDevice &device);
 
+    uint32_t mMaxSetsPerPool;
     DescriptorPool mCurrentDescriptorSetPool;
     size_t mCurrentAllocatedDescriptorSetCount;
     uint32_t mUniformBufferDescriptorsPerSet;
@@ -126,8 +135,16 @@
                                                   BufferVk *elementArrayBufferVk,
                                                   VkIndexType indexType,
                                                   int indexCount,
+                                                  intptr_t elementArrayOffset,
                                                   VkBuffer *bufferHandleOut,
                                                   VkDeviceSize *bufferOffsetOut);
+    gl::Error getIndexBufferForClientElementArray(RendererVk *renderer,
+                                                  const void *indicesInput,
+                                                  VkIndexType indexType,
+                                                  int indexCount,
+                                                  VkBuffer *bufferHandleOut,
+                                                  VkDeviceSize *bufferOffsetOut);
+
     void destroy(VkDevice device);
 
     static void Draw(int count, CommandBuffer *commandBuffer);
@@ -145,15 +162,17 @@
 
     bool valid() const;
 
-    Error init2D(VkDevice device,
-                 const gl::Extents &extents,
-                 const Format &format,
-                 GLint samples,
-                 VkImageUsageFlags usage);
+    Error init(VkDevice device,
+               gl::TextureType textureType,
+               const gl::Extents &extents,
+               const Format &format,
+               GLint samples,
+               VkImageUsageFlags usage);
     Error initMemory(VkDevice device,
                      const MemoryProperties &memoryProperties,
                      VkMemoryPropertyFlags flags);
     Error initImageView(VkDevice device,
+                        gl::TextureType textureType,
                         VkImageAspectFlags aspectMask,
                         const gl::SwizzleState &swizzleMap,
                         ImageView *imageViewOut);
@@ -217,6 +236,9 @@
 
     // Current state.
     VkImageLayout mCurrentLayout;
+
+    // Cached properties.
+    uint32_t mLayerCount;
 };
 
 }  // namespace vk
diff --git a/src/libANGLE/renderer/vulkan/vk_utils.cpp b/src/libANGLE/renderer/vulkan/vk_utils.cpp
index fa9b4bf..75dcd67 100644
--- a/src/libANGLE/renderer/vulkan/vk_utils.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_utils.cpp
@@ -1139,6 +1139,43 @@
 
 namespace gl_vk
 {
+
+VkFilter GetFilter(const GLenum filter)
+{
+    switch (filter)
+    {
+        case GL_LINEAR_MIPMAP_LINEAR:
+        case GL_LINEAR_MIPMAP_NEAREST:
+        case GL_LINEAR:
+            return VK_FILTER_LINEAR;
+        case GL_NEAREST_MIPMAP_LINEAR:
+        case GL_NEAREST_MIPMAP_NEAREST:
+        case GL_NEAREST:
+            return VK_FILTER_NEAREST;
+        default:
+            UNIMPLEMENTED();
+            return VK_FILTER_MAX_ENUM;
+    }
+}
+
+VkSamplerAddressMode GetSamplerAddressMode(const GLenum wrap)
+{
+    switch (wrap)
+    {
+        case GL_REPEAT:
+            return VK_SAMPLER_ADDRESS_MODE_REPEAT;
+        case GL_MIRRORED_REPEAT:
+            return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
+        case GL_CLAMP_TO_BORDER:
+            return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
+        case GL_CLAMP_TO_EDGE:
+            return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+        default:
+            UNIMPLEMENTED();
+            return VK_SAMPLER_ADDRESS_MODE_MAX_ENUM;
+    }
+}
+
 VkRect2D GetRect(const gl::Rectangle &source)
 {
     return {{source.x, source.y},
@@ -1278,6 +1315,36 @@
     vkExtent->height = glExtent.height;
     vkExtent->depth  = glExtent.depth;
 }
+
+VkImageType GetImageType(gl::TextureType textureType)
+{
+    switch (textureType)
+    {
+        case gl::TextureType::_2D:
+            return VK_IMAGE_TYPE_2D;
+        case gl::TextureType::CubeMap:
+            return VK_IMAGE_TYPE_2D;
+        default:
+            // We will need to implement all the texture types for ES3+.
+            UNIMPLEMENTED();
+            return VK_IMAGE_TYPE_MAX_ENUM;
+    }
+}
+
+VkImageViewType GetImageViewType(gl::TextureType textureType)
+{
+    switch (textureType)
+    {
+        case gl::TextureType::_2D:
+            return VK_IMAGE_VIEW_TYPE_2D;
+        case gl::TextureType::CubeMap:
+            return VK_IMAGE_VIEW_TYPE_CUBE;
+        default:
+            // We will need to implement all the texture types for ES3+.
+            UNIMPLEMENTED();
+            return VK_IMAGE_VIEW_TYPE_MAX_ENUM;
+    }
+}
 }  // namespace gl_vk
 }  // namespace rx
 
diff --git a/src/libANGLE/renderer/vulkan/vk_utils.h b/src/libANGLE/renderer/vulkan/vk_utils.h
index bb0d77e..c860e20 100644
--- a/src/libANGLE/renderer/vulkan/vk_utils.h
+++ b/src/libANGLE/renderer/vulkan/vk_utils.h
@@ -650,6 +650,8 @@
 namespace gl_vk
 {
 VkRect2D GetRect(const gl::Rectangle &source);
+VkFilter GetFilter(const GLenum filter);
+VkSamplerAddressMode GetSamplerAddressMode(const GLenum wrap);
 VkPrimitiveTopology GetPrimitiveTopology(GLenum mode);
 VkCullModeFlags GetCullMode(const gl::RasterizerState &rasterState);
 VkFrontFace GetFrontFace(GLenum frontFace);
@@ -658,6 +660,8 @@
 VkIndexType GetIndexType(GLenum elementType);
 void GetOffset(const gl::Offset &glOffset, VkOffset3D *vkOffset);
 void GetExtent(const gl::Extents &glExtent, VkExtent3D *vkExtent);
+VkImageType GetImageType(gl::TextureType textureType);
+VkImageViewType GetImageViewType(gl::TextureType textureType);
 }  // namespace gl_vk
 
 }  // namespace rx
@@ -665,7 +669,7 @@
 #define ANGLE_VK_TRY(command)                                          \
     {                                                                  \
         auto ANGLE_LOCAL_VAR = command;                                \
-        if (ANGLE_LOCAL_VAR != VK_SUCCESS)                             \
+        if (ANGLE_UNLIKELY(ANGLE_LOCAL_VAR != VK_SUCCESS))             \
         {                                                              \
             return rx::vk::Error(ANGLE_LOCAL_VAR, __FILE__, __LINE__); \
         }                                                              \
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index 1e53415..22c47a0 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -75,65 +75,52 @@
 
     bool webglCompatibility = context->getExtensions().webglCompatibility;
 
-    const VertexArray *vao     = state.getVertexArray();
+    const VertexArray *vao              = state.getVertexArray();
+    const AttributesMask &clientAttribs = vao->getEnabledClientMemoryAttribsMask();
+
+    if (clientAttribs.any())
+    {
+        if (webglCompatibility || !state.areClientArraysEnabled())
+        {
+            // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
+            // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
+            // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
+            // to drawArrays or drawElements will generate an INVALID_OPERATION error.
+            ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
+            return false;
+        }
+        else if (vao->hasEnabledNullPointerClientArray())
+        {
+            // This is an application error that would normally result in a crash, but we catch it
+            // and return an error
+            ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
+            return false;
+        }
+    }
+
+    // If we're drawing zero vertices, we have enough data.
+    if (vertexCount <= 0 || primcount <= 0)
+    {
+        return true;
+    }
+
     const auto &vertexAttribs  = vao->getVertexAttributes();
     const auto &vertexBindings = vao->getVertexBindings();
-    for (size_t attributeIndex : vao->getEnabledAttributesMask())
+
+    const AttributesMask &activeAttribs = (program->getActiveAttribLocationsMask() &
+                                           vao->getEnabledAttributesMask() & ~clientAttribs);
+
+    for (size_t attributeIndex : activeAttribs)
     {
         const VertexAttribute &attrib = vertexAttribs[attributeIndex];
+        ASSERT(attrib.enabled);
 
-        // No need to range check for disabled attribs.
-        if (!attrib.enabled)
-        {
-            continue;
-        }
-
-        // If we have no buffer, then we either get an error, or there are no more checks to be
-        // done.
         const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
-        gl::Buffer *buffer           = binding.getBuffer().get();
-        if (!buffer)
-        {
-            if (webglCompatibility || !state.areClientArraysEnabled())
-            {
-                // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
-                // If a vertex attribute is enabled as an array via enableVertexAttribArray but
-                // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
-                // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
-                // error.
-                ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
-                return false;
-            }
-            else if (attrib.pointer == nullptr)
-            {
-                // This is an application error that would normally result in a crash,
-                // but we catch it and return an error
-                ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
-                return false;
-            }
-            continue;
-        }
+        ASSERT(program->isAttribLocationActive(attributeIndex));
 
-        // This needs to come after the check for client arrays as even unused attributes cannot use
-        // client-side arrays
-        if (!program->isAttribLocationActive(attributeIndex))
-        {
-            continue;
-        }
-
-        // If we're drawing zero vertices, we have enough data.
-        if (vertexCount <= 0 || primcount <= 0)
-        {
-            continue;
-        }
-
-        GLint maxVertexElement = 0;
+        GLint maxVertexElement = maxVertex;
         GLuint divisor         = binding.getDivisor();
-        if (divisor == 0)
-        {
-            maxVertexElement = maxVertex;
-        }
-        else
+        if (divisor != 0)
         {
             maxVertexElement = (primcount - 1) / divisor;
         }
@@ -149,39 +136,49 @@
 
         // We know attribStride is given as a GLsizei which is typedefed to int.
         // We also know an upper bound for attribSize.
-        static_assert(std::is_same<int, GLsizei>::value, "");
-        uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
-        uint64_t attribSize   = ComputeVertexAttributeTypeSize(attrib);
-        ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
+        static_assert(std::is_same<int, GLsizei>::value, "Unexpected type");
+        ASSERT(ComputeVertexAttributeStride(attrib, binding) == binding.getStride());
+        uint64_t attribStride = binding.getStride();
+        ASSERT(attribStride <= kIntMax && ComputeVertexAttributeTypeSize(attrib) <= kMaxAttribSize);
 
-        // Computing the max offset using uint64_t without attrib.offset is overflow
-        // safe. Note: Last vertex element does not take the full stride!
-        static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
-        uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
+        // Computing the product of two 32-bit ints will fit in 64 bits without overflow.
+        static_assert(kIntMax * kIntMax < kUint64Max, "Unexpected overflow");
+        uint64_t attribDataSizeMinusAttribSize = maxVertexElement * attribStride;
 
         // An overflow can happen when adding the offset, check for it.
-        uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
-        if (attribDataSizeNoOffset > kUint64Max - attribOffset)
+        if (attribDataSizeMinusAttribSize > kUint64Max - attrib.cachedSizePlusRelativeOffset)
         {
             ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
             return false;
         }
-        uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
 
         // [OpenGL ES 3.0.2] section 2.9.4 page 40:
-        // We can return INVALID_OPERATION if our vertex attribute does not have
-        // enough backing data.
-        if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
+        // We can return INVALID_OPERATION if our array buffer does not have enough backing data.
+        if (attribDataSizeMinusAttribSize + attrib.cachedSizePlusRelativeOffset >
+            binding.getCachedBufferSizeMinusOffset())
         {
             ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
             return false;
         }
+    }
 
-        if (webglCompatibility && buffer->isBoundForTransformFeedbackAndOtherUse())
+    // TODO(jmadill): Cache this. http://anglebug.com/1391
+    if (webglCompatibility)
+    {
+        for (size_t attributeIndex : activeAttribs)
         {
-            ANGLE_VALIDATION_ERR(context, InvalidOperation(),
-                                 VertexBufferBoundForTransformFeedback);
-            return false;
+            const VertexAttribute &attrib = vertexAttribs[attributeIndex];
+            ASSERT(attrib.enabled);
+
+            const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
+
+            gl::Buffer *buffer = binding.getBuffer().get();
+            if (buffer && buffer->isBoundForTransformFeedbackAndOtherUse())
+            {
+                ANGLE_VALIDATION_ERR(context, InvalidOperation(),
+                                     VertexBufferBoundForTransformFeedback);
+                return false;
+            }
         }
     }
 
@@ -1280,12 +1277,12 @@
         return false;
     }
 
-    if (!ValidateFramebufferComplete(context, readFramebuffer, true))
+    if (!ValidateFramebufferComplete(context, readFramebuffer))
     {
         return false;
     }
 
-    if (!ValidateFramebufferComplete(context, drawFramebuffer, true))
+    if (!ValidateFramebufferComplete(context, drawFramebuffer))
     {
         return false;
     }
@@ -2254,7 +2251,7 @@
             Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
             ASSERT(readFramebuffer);
 
-            if (!ValidateFramebufferComplete(context, readFramebuffer, false))
+            if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
             {
                 return false;
             }
@@ -2442,7 +2439,7 @@
 
     const gl::State &state       = context->getGLState();
     Framebuffer *readFramebuffer = state.getReadFramebuffer();
-    if (!ValidateFramebufferComplete(context, readFramebuffer, true))
+    if (!ValidateFramebufferComplete(context, readFramebuffer))
     {
         return false;
     }
@@ -2673,7 +2670,7 @@
         }
     }
 
-    if (!ValidateFramebufferComplete(context, framebuffer, true))
+    if (!ValidateFramebufferComplete(context, framebuffer))
     {
         return false;
     }
@@ -4992,7 +4989,7 @@
     return true;
 }
 
-bool ValidateGetInternalFormativRobustANGLE(Context *context,
+bool ValidateGetInternalformativRobustANGLE(Context *context,
                                             GLenum target,
                                             GLenum internalformat,
                                             GLenum pname,
@@ -5579,7 +5576,7 @@
 
     Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
 
-    if (!ValidateFramebufferComplete(context, readFramebuffer, true))
+    if (!ValidateFramebufferComplete(context, readFramebuffer))
     {
         return false;
     }
@@ -6336,33 +6333,9 @@
     return true;
 }
 
-// We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
-// implementation format info for incomplete framebuffers. It seems like these queries are
-// incongruent with the other errors.
-bool ValidateFramebufferComplete(Context *context, Framebuffer *framebuffer, bool isFramebufferOp)
-{
-    bool complete = false;
-    ANGLE_VALIDATION_TRY(framebuffer->isComplete(context, &complete));
-    if (!complete)
-    {
-        if (isFramebufferOp)
-        {
-            context->handleError(InvalidFramebufferOperation());
-        }
-        else
-        {
-            context->handleError(InvalidOperation());
-        }
-        return false;
-    }
-    return true;
-}
-
 bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
 {
-    GLint samples = 0;
-    ANGLE_VALIDATION_TRY(framebuffer->getSamples(context, &samples));
-    if (samples != 0)
+    if (framebuffer->getSamples(context) != 0)
     {
         context->handleError(InvalidOperation());
         return false;
diff --git a/src/libANGLE/validationES.h b/src/libANGLE/validationES.h
index 2532455..f4e4538 100644
--- a/src/libANGLE/validationES.h
+++ b/src/libANGLE/validationES.h
@@ -10,7 +10,9 @@
 #define LIBANGLE_VALIDATION_ES_H_
 
 #include "common/mathutil.h"
-#include "libANGLE/PackedGLEnums.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/PackedEnums.h"
 
 #include <GLES2/gl2.h>
 #include <GLES3/gl3.h>
@@ -628,7 +630,7 @@
                                                 GLsizei *length,
                                                 GLint *params);
 
-bool ValidateGetInternalFormativRobustANGLE(Context *context,
+bool ValidateGetInternalformativRobustANGLE(Context *context,
                                             GLenum target,
                                             GLenum internalformat,
                                             GLenum pname,
@@ -676,7 +678,6 @@
                                      GLsizei bufSize,
                                      GLsizei *numParams);
 
-bool ValidateFramebufferComplete(Context *context, Framebuffer *framebuffer, bool isFramebufferOp);
 bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer);
 
 bool ValidateMultitextureUnit(Context *context, GLenum texture);
@@ -687,6 +688,21 @@
     return false;
 #define ANGLE_VALIDATION_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_HANDLE_VALIDATION_ERR);
 
+// We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
+// implementation format info for incomplete framebuffers. It seems like these queries are
+// incongruent with the other errors.
+// Inlined for speed.
+template <typename ErrorStream = InvalidFramebufferOperation>
+ANGLE_INLINE bool ValidateFramebufferComplete(Context *context, Framebuffer *framebuffer)
+{
+    if (!framebuffer->isComplete(context))
+    {
+        context->handleError(ErrorStream());
+        return false;
+    }
+
+    return true;
+}
 }  // namespace gl
 
 #endif  // LIBANGLE_VALIDATION_ES_H_
diff --git a/src/libANGLE/validationES1.cpp b/src/libANGLE/validationES1.cpp
index 160c31f..7b0a80b 100644
--- a/src/libANGLE/validationES1.cpp
+++ b/src/libANGLE/validationES1.cpp
@@ -20,29 +20,134 @@
         return false;                                                 \
     }
 
-namespace
+namespace gl
 {
 
-bool ValidateAlphaFuncCommon(gl::Context *context, gl::AlphaTestFunc func)
+bool ValidateAlphaFuncCommon(Context *context, AlphaTestFunc func)
 {
     switch (func)
     {
-        case gl::AlphaTestFunc::AlwaysPass:
-        case gl::AlphaTestFunc::Equal:
-        case gl::AlphaTestFunc::Gequal:
-        case gl::AlphaTestFunc::Greater:
-        case gl::AlphaTestFunc::Lequal:
-        case gl::AlphaTestFunc::Less:
-        case gl::AlphaTestFunc::Never:
-        case gl::AlphaTestFunc::NotEqual:
+        case AlphaTestFunc::AlwaysPass:
+        case AlphaTestFunc::Equal:
+        case AlphaTestFunc::Gequal:
+        case AlphaTestFunc::Greater:
+        case AlphaTestFunc::Lequal:
+        case AlphaTestFunc::Less:
+        case AlphaTestFunc::Never:
+        case AlphaTestFunc::NotEqual:
             return true;
         default:
-            context->handleError(gl::InvalidEnum() << gl::kErrorEnumNotSupported);
+            ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
             return false;
     }
 }
 
-}  // anonymous namespace
+bool ValidateClientStateCommon(Context *context, ClientVertexArrayType arrayType)
+{
+    ANGLE_VALIDATE_IS_GLES1(context);
+    switch (arrayType)
+    {
+        case ClientVertexArrayType::Vertex:
+        case ClientVertexArrayType::Normal:
+        case ClientVertexArrayType::Color:
+        case ClientVertexArrayType::TextureCoord:
+            return true;
+        case ClientVertexArrayType::PointSize:
+            if (!context->getExtensions().pointSizeArray)
+            {
+                ANGLE_VALIDATION_ERR(context, InvalidEnum(), PointSizeArrayExtensionNotEnabled);
+                return false;
+            }
+            return true;
+        default:
+            ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidClientState);
+            return false;
+    }
+}
+
+bool ValidateBuiltinVertexAttributeCommon(Context *context,
+                                          ClientVertexArrayType arrayType,
+                                          GLint size,
+                                          GLenum type,
+                                          GLsizei stride,
+                                          const void *pointer)
+{
+    ANGLE_VALIDATE_IS_GLES1(context);
+
+    if (stride < 0)
+    {
+        ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexPointerStride);
+        return false;
+    }
+
+    int minSize = 1;
+    int maxSize = 4;
+
+    switch (arrayType)
+    {
+        case ClientVertexArrayType::Vertex:
+        case ClientVertexArrayType::TextureCoord:
+            minSize = 2;
+            maxSize = 4;
+            break;
+        case ClientVertexArrayType::Normal:
+            minSize = 3;
+            maxSize = 3;
+            break;
+        case ClientVertexArrayType::Color:
+            minSize = 4;
+            maxSize = 4;
+            break;
+        case ClientVertexArrayType::PointSize:
+            if (!context->getExtensions().pointSizeArray)
+            {
+                ANGLE_VALIDATION_ERR(context, InvalidEnum(), PointSizeArrayExtensionNotEnabled);
+                return false;
+            }
+
+            minSize = 1;
+            maxSize = 1;
+            break;
+        default:
+            UNREACHABLE();
+            return false;
+    }
+
+    if (size < minSize || size > maxSize)
+    {
+        ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexPointerSize);
+        return false;
+    }
+
+    switch (type)
+    {
+        case GL_BYTE:
+            if (arrayType == ClientVertexArrayType::PointSize)
+            {
+                ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidVertexPointerType);
+                return false;
+            }
+            break;
+        case GL_SHORT:
+            if (arrayType == ClientVertexArrayType::PointSize ||
+                arrayType == ClientVertexArrayType::Color)
+            {
+                ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidVertexPointerType);
+                return false;
+            }
+            break;
+        case GL_FIXED:
+        case GL_FLOAT:
+            break;
+        default:
+            ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidVertexPointerType);
+            return false;
+    }
+
+    return true;
+}
+
+}  // namespace gl
 
 namespace gl
 {
@@ -113,8 +218,8 @@
                           GLsizei stride,
                           const void *pointer)
 {
-    UNIMPLEMENTED();
-    return true;
+    return ValidateBuiltinVertexAttributeCommon(context, ClientVertexArrayType::Color, size, type,
+                                                stride, pointer);
 }
 
 bool ValidateCullFace(Context *context, GLenum mode)
@@ -129,16 +234,14 @@
     return true;
 }
 
-bool ValidateDisableClientState(Context *context, GLenum array)
+bool ValidateDisableClientState(Context *context, ClientVertexArrayType arrayType)
 {
-    UNIMPLEMENTED();
-    return true;
+    return ValidateClientStateCommon(context, arrayType);
 }
 
-bool ValidateEnableClientState(Context *context, GLenum array)
+bool ValidateEnableClientState(Context *context, ClientVertexArrayType arrayType)
 {
-    UNIMPLEMENTED();
-    return true;
+    return ValidateClientStateCommon(context, arrayType);
 }
 
 bool ValidateFogf(Context *context, GLenum pname, GLfloat param)
@@ -173,7 +276,11 @@
                       GLfloat n,
                       GLfloat f)
 {
-    UNIMPLEMENTED();
+    ANGLE_VALIDATE_IS_GLES1(context);
+    if (l == r || b == t || n == f || n <= 0.0f || f <= 0.0f)
+    {
+        ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProjectionMatrix);
+    }
     return true;
 }
 
@@ -185,7 +292,11 @@
                       GLfixed n,
                       GLfixed f)
 {
-    UNIMPLEMENTED();
+    ANGLE_VALIDATE_IS_GLES1(context);
+    if (l == r || b == t || n == f || n <= 0 || f <= 0)
+    {
+        ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProjectionMatrix);
+    }
     return true;
 }
 
@@ -239,8 +350,19 @@
 
 bool ValidateGetPointerv(Context *context, GLenum pname, void **params)
 {
-    UNIMPLEMENTED();
-    return true;
+    ANGLE_VALIDATE_IS_GLES1(context);
+    switch (pname)
+    {
+        case GL_VERTEX_ARRAY_POINTER:
+        case GL_NORMAL_ARRAY_POINTER:
+        case GL_COLOR_ARRAY_POINTER:
+        case GL_TEXTURE_COORD_ARRAY_POINTER:
+        case GL_POINT_SIZE_ARRAY_POINTER_OES:
+            return true;
+        default:
+            ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPointerQuery);
+            return false;
+    }
 }
 
 bool ValidateGetTexEnvfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
@@ -432,8 +554,8 @@
 
 bool ValidateNormalPointer(Context *context, GLenum type, GLsizei stride, const void *pointer)
 {
-    UNIMPLEMENTED();
-    return true;
+    return ValidateBuiltinVertexAttributeCommon(context, ClientVertexArrayType::Normal, 3, type,
+                                                stride, pointer);
 }
 
 bool ValidateOrthof(Context *context,
@@ -444,7 +566,11 @@
                     GLfloat n,
                     GLfloat f)
 {
-    UNIMPLEMENTED();
+    ANGLE_VALIDATE_IS_GLES1(context);
+    if (l == r || b == t || n == f || n <= 0.0f || f <= 0.0f)
+    {
+        ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProjectionMatrix);
+    }
     return true;
 }
 
@@ -456,7 +582,11 @@
                     GLfixed n,
                     GLfixed f)
 {
-    UNIMPLEMENTED();
+    ANGLE_VALIDATE_IS_GLES1(context);
+    if (l == r || b == t || n == f || n <= 0 || f <= 0)
+    {
+        ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProjectionMatrix);
+    }
     return true;
 }
 
@@ -528,13 +658,13 @@
 
 bool ValidateRotatef(Context *context, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
 {
-    UNIMPLEMENTED();
+    ANGLE_VALIDATE_IS_GLES1(context);
     return true;
 }
 
 bool ValidateRotatex(Context *context, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
 {
-    UNIMPLEMENTED();
+    ANGLE_VALIDATE_IS_GLES1(context);
     return true;
 }
 
@@ -546,13 +676,13 @@
 
 bool ValidateScalef(Context *context, GLfloat x, GLfloat y, GLfloat z)
 {
-    UNIMPLEMENTED();
+    ANGLE_VALIDATE_IS_GLES1(context);
     return true;
 }
 
 bool ValidateScalex(Context *context, GLfixed x, GLfixed y, GLfixed z)
 {
-    UNIMPLEMENTED();
+    ANGLE_VALIDATE_IS_GLES1(context);
     return true;
 }
 
@@ -568,8 +698,8 @@
                              GLsizei stride,
                              const void *pointer)
 {
-    UNIMPLEMENTED();
-    return true;
+    return ValidateBuiltinVertexAttributeCommon(context, ClientVertexArrayType::TextureCoord, size,
+                                                type, stride, pointer);
 }
 
 bool ValidateTexEnvf(Context *context, GLenum target, GLenum pname, GLfloat param)
@@ -625,13 +755,13 @@
 
 bool ValidateTranslatef(Context *context, GLfloat x, GLfloat y, GLfloat z)
 {
-    UNIMPLEMENTED();
+    ANGLE_VALIDATE_IS_GLES1(context);
     return true;
 }
 
 bool ValidateTranslatex(Context *context, GLfixed x, GLfixed y, GLfixed z)
 {
-    UNIMPLEMENTED();
+    ANGLE_VALIDATE_IS_GLES1(context);
     return true;
 }
 
@@ -641,8 +771,8 @@
                            GLsizei stride,
                            const void *pointer)
 {
-    UNIMPLEMENTED();
-    return true;
+    return ValidateBuiltinVertexAttributeCommon(context, ClientVertexArrayType::Vertex, size, type,
+                                                stride, pointer);
 }
 
 bool ValidateDrawTexfOES(Context *context,
@@ -742,8 +872,8 @@
 
 bool ValidatePointSizePointerOES(Context *context, GLenum type, GLsizei stride, const void *pointer)
 {
-    UNIMPLEMENTED();
-    return true;
+    return ValidateBuiltinVertexAttributeCommon(context, ClientVertexArrayType::PointSize, 1, type,
+                                                stride, pointer);
 }
 
 bool ValidateQueryMatrixxOES(Context *context, GLfixed *mantissa, GLint *exponent)
@@ -917,4 +1047,5 @@
     UNIMPLEMENTED();
     return true;
 }
-}
+
+}  // namespace gl
diff --git a/src/libANGLE/validationES1.h b/src/libANGLE/validationES1.h
index be871e7..a549d8b 100644
--- a/src/libANGLE/validationES1.h
+++ b/src/libANGLE/validationES1.h
@@ -35,8 +35,8 @@
                           const void *pointer);
 bool ValidateCullFace(Context *context, GLenum mode);
 bool ValidateDepthRangex(Context *context, GLfixed n, GLfixed f);
-bool ValidateDisableClientState(Context *context, GLenum array);
-bool ValidateEnableClientState(Context *context, GLenum array);
+bool ValidateDisableClientState(Context *context, ClientVertexArrayType array);
+bool ValidateEnableClientState(Context *context, ClientVertexArrayType array);
 bool ValidateFogf(Context *context, GLenum pname, GLfloat param);
 bool ValidateFogfv(Context *context, GLenum pname, const GLfloat *params);
 bool ValidateFogx(Context *context, GLenum pname, GLfixed param);
diff --git a/src/libANGLE/validationES2.cpp b/src/libANGLE/validationES2.cpp
index bb164ef..364de0c 100644
--- a/src/libANGLE/validationES2.cpp
+++ b/src/libANGLE/validationES2.cpp
@@ -794,7 +794,14 @@
 
         // GLES1 emulation: GLES1-specific caps
         case GL_ALPHA_TEST:
+        case GL_VERTEX_ARRAY:
+        case GL_NORMAL_ARRAY:
+        case GL_COLOR_ARRAY:
+        case GL_TEXTURE_COORD_ARRAY:
             return context->getClientVersion() < Version(2, 0);
+        case GL_POINT_SIZE_ARRAY_OES:
+            return context->getClientVersion() < Version(2, 0) &&
+                   context->getExtensions().pointSizeArray;
 
         default:
             return false;
@@ -2473,7 +2480,7 @@
         if (readColorAttachment && drawColorAttachment)
         {
             if (!(readColorAttachment->type() == GL_TEXTURE &&
-                  readColorAttachment->getTextureImageIndex().type == TextureType::_2D) &&
+                  readColorAttachment->getTextureImageIndex().getType() == TextureType::_2D) &&
                 readColorAttachment->type() != GL_RENDERBUFFER &&
                 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
             {
@@ -2489,7 +2496,7 @@
                 if (attachment)
                 {
                     if (!(attachment->type() == GL_TEXTURE &&
-                          attachment->getTextureImageIndex().type == TextureType::_2D) &&
+                          attachment->getTextureImageIndex().getType() == TextureType::_2D) &&
                         attachment->type() != GL_RENDERBUFFER &&
                         attachment->type() != GL_FRAMEBUFFER_DEFAULT)
                     {
@@ -2507,8 +2514,7 @@
                 }
             }
 
-            GLint samples = 0;
-            ANGLE_VALIDATION_TRY(readFramebuffer->getSamples(context, &samples));
+            GLint samples = readFramebuffer->getSamples(context);
             if (samples != 0 &&
                 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
                               srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
@@ -2559,7 +2565,7 @@
 {
     Framebuffer *fbo = context->getGLState().getDrawFramebuffer();
 
-    if (!ValidateFramebufferComplete(context, fbo, true))
+    if (!ValidateFramebufferComplete(context, fbo))
     {
         return false;
     }
@@ -2623,17 +2629,17 @@
                                            pixels);
 }
 
-bool ValidateTexImage2DRobust(Context *context,
-                              TextureTarget target,
-                              GLint level,
-                              GLint internalformat,
-                              GLsizei width,
-                              GLsizei height,
-                              GLint border,
-                              GLenum format,
-                              GLenum type,
-                              GLsizei bufSize,
-                              const void *pixels)
+bool ValidateTexImage2DRobustANGLE(Context *context,
+                                   TextureTarget target,
+                                   GLint level,
+                                   GLint internalformat,
+                                   GLsizei width,
+                                   GLsizei height,
+                                   GLint border,
+                                   GLenum format,
+                                   GLenum type,
+                                   GLsizei bufSize,
+                                   const void *pixels)
 {
     if (!ValidateRobustEntryPoint(context, bufSize))
     {
@@ -6133,10 +6139,10 @@
     }
 
     // ES3 and WebGL grant mipmap generation for sRGBA (with alpha) textures but GL_EXT_sRGB does
-    // not.
-    bool supportsSRGBMipmapGeneration =
-        context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
-    if (!supportsSRGBMipmapGeneration && format.colorEncoding == GL_SRGB)
+    // not.  Differentiate the ES3 format from the extension format by checking if the format is
+    // sized, GL_EXT_sRGB does not add any sized formats.
+    bool supportsSRGBMipmapGeneration = context->getExtensions().webglCompatibility;
+    if (!supportsSRGBMipmapGeneration && !format.sized && format.colorEncoding == GL_SRGB)
     {
         ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
         return false;
diff --git a/src/libANGLE/validationES2.h b/src/libANGLE/validationES2.h
index 52bedfb..74f2080 100644
--- a/src/libANGLE/validationES2.h
+++ b/src/libANGLE/validationES2.h
@@ -9,7 +9,7 @@
 #ifndef LIBANGLE_VALIDATION_ES2_H_
 #define LIBANGLE_VALIDATION_ES2_H_
 
-#include "libANGLE/PackedGLEnums.h"
+#include "libANGLE/PackedEnums.h"
 
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
@@ -131,17 +131,17 @@
                         GLenum format,
                         GLenum type,
                         const void *pixels);
-bool ValidateTexImage2DRobust(Context *context,
-                              TextureTarget target,
-                              GLint level,
-                              GLint internalformat,
-                              GLsizei width,
-                              GLsizei height,
-                              GLint border,
-                              GLenum format,
-                              GLenum type,
-                              GLsizei bufSize,
-                              const void *pixels);
+bool ValidateTexImage2DRobustANGLE(Context *context,
+                                   TextureTarget target,
+                                   GLint level,
+                                   GLint internalformat,
+                                   GLsizei width,
+                                   GLsizei height,
+                                   GLint border,
+                                   GLenum format,
+                                   GLenum type,
+                                   GLsizei bufSize,
+                                   const void *pixels);
 bool ValidateTexSubImage2D(Context *context,
                            TextureTarget target,
                            GLint level,
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp
index 42f9df6..a7f522c 100644
--- a/src/libANGLE/validationES3.cpp
+++ b/src/libANGLE/validationES3.cpp
@@ -808,7 +808,7 @@
     gl::Framebuffer *framebuffer = state.getReadFramebuffer();
     GLuint readFramebufferID     = framebuffer->id();
 
-    if (!ValidateFramebufferComplete(context, framebuffer, true))
+    if (!ValidateFramebufferComplete(context, framebuffer))
     {
         return false;
     }
@@ -1244,7 +1244,7 @@
         return false;
     }
 
-    if (!ValidateFramebufferComplete(context, context->getGLState().getDrawFramebuffer(), true))
+    if (!ValidateFramebufferComplete(context, context->getGLState().getDrawFramebuffer()))
     {
         return false;
     }
diff --git a/src/libANGLE/validationES3.h b/src/libANGLE/validationES3.h
index e61d96f..bdce129 100644
--- a/src/libANGLE/validationES3.h
+++ b/src/libANGLE/validationES3.h
@@ -9,7 +9,7 @@
 #ifndef LIBANGLE_VALIDATION_ES3_H_
 #define LIBANGLE_VALIDATION_ES3_H_
 
-#include "libANGLE/PackedGLEnums.h"
+#include "libANGLE/PackedEnums.h"
 
 #include <GLES3/gl3.h>
 
diff --git a/src/libANGLE/validationES31.cpp b/src/libANGLE/validationES31.cpp
index 097e463..8681136 100644
--- a/src/libANGLE/validationES31.cpp
+++ b/src/libANGLE/validationES31.cpp
@@ -1075,8 +1075,7 @@
     }
 
     Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
-    GLint samples            = 0;
-    ANGLE_VALIDATION_TRY(framebuffer->getSamples(context, &samples));
+    GLint samples            = framebuffer->getSamples(context);
 
     if (index >= static_cast<GLuint>(samples))
     {
diff --git a/src/libANGLE/validationES31.h b/src/libANGLE/validationES31.h
index e24f6d9..70a396f 100644
--- a/src/libANGLE/validationES31.h
+++ b/src/libANGLE/validationES31.h
@@ -9,7 +9,7 @@
 #ifndef LIBANGLE_VALIDATION_ES31_H_
 #define LIBANGLE_VALIDATION_ES31_H_
 
-#include "libANGLE/PackedGLEnums.h"
+#include "libANGLE/PackedEnums.h"
 
 #include <GLES3/gl31.h>
 
diff --git a/src/libGLESv2.gypi b/src/libGLESv2.gypi
index ccecbda..2435ad8 100644
--- a/src/libGLESv2.gypi
+++ b/src/libGLESv2.gypi
@@ -184,8 +184,10 @@
             'libANGLE/MemoryProgramCache.h',
             'libANGLE/Observer.cpp',
             'libANGLE/Observer.h',
-            'libANGLE/PackedGLEnums.cpp',
-            'libANGLE/PackedGLEnums.h',
+            'libANGLE/PackedEGLEnums_autogen.cpp',
+            'libANGLE/PackedEGLEnums_autogen.h',
+            'libANGLE/PackedEnums.cpp',
+            'libANGLE/PackedEnums.h',
             'libANGLE/PackedGLEnums_autogen.cpp',
             'libANGLE/PackedGLEnums_autogen.h',
             'libANGLE/Path.h',
@@ -881,8 +883,6 @@
             'libGLESv2/entry_points_gles_1_0_autogen.h',
             'libGLESv2/entry_points_gles_2_0_autogen.cpp',
             'libGLESv2/entry_points_gles_2_0_autogen.h',
-            'libGLESv2/entry_points_gles_2_0_ext.cpp',
-            'libGLESv2/entry_points_gles_2_0_ext.h',
             'libGLESv2/entry_points_gles_3_0_autogen.cpp',
             'libGLESv2/entry_points_gles_3_0_autogen.h',
             'libGLESv2/entry_points_gles_3_1_autogen.cpp',
diff --git a/src/libGLESv2/entry_points_egl.cpp b/src/libGLESv2/entry_points_egl.cpp
index 2afbe07..1420a9d 100644
--- a/src/libGLESv2/entry_points_egl.cpp
+++ b/src/libGLESv2/entry_points_egl.cpp
@@ -752,7 +752,7 @@
         return EGL_FALSE;
     }
 
-    if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
+    if (eglSurface->getTextureFormat() == TextureFormat::NoTexture)
     {
         thread->setError(EglBadMatch());
         return EGL_FALSE;
@@ -839,7 +839,7 @@
         return EGL_FALSE;
     }
 
-    if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
+    if (eglSurface->getTextureFormat() == TextureFormat::NoTexture)
     {
         thread->setError(EglBadMatch());
         return EGL_FALSE;
diff --git a/src/libGLESv2/entry_points_gles_1_0_autogen.cpp b/src/libGLESv2/entry_points_gles_1_0_autogen.cpp
index beada99..e606904 100644
--- a/src/libGLESv2/entry_points_gles_1_0_autogen.cpp
+++ b/src/libGLESv2/entry_points_gles_1_0_autogen.cpp
@@ -223,11 +223,12 @@
     Context *context = GetValidGlobalContext();
     if (context)
     {
-        context->gatherParams<EntryPoint::DisableClientState>(array);
+        ClientVertexArrayType arrayPacked = FromGLenum<ClientVertexArrayType>(array);
+        context->gatherParams<EntryPoint::DisableClientState>(arrayPacked);
 
-        if (context->skipValidation() || ValidateDisableClientState(context, array))
+        if (context->skipValidation() || ValidateDisableClientState(context, arrayPacked))
         {
-            context->disableClientState(array);
+            context->disableClientState(arrayPacked);
         }
     }
 }
@@ -239,11 +240,12 @@
     Context *context = GetValidGlobalContext();
     if (context)
     {
-        context->gatherParams<EntryPoint::EnableClientState>(array);
+        ClientVertexArrayType arrayPacked = FromGLenum<ClientVertexArrayType>(array);
+        context->gatherParams<EntryPoint::EnableClientState>(arrayPacked);
 
-        if (context->skipValidation() || ValidateEnableClientState(context, array))
+        if (context->skipValidation() || ValidateEnableClientState(context, arrayPacked))
         {
-            context->enableClientState(array);
+            context->enableClientState(arrayPacked);
         }
     }
 }
diff --git a/src/libGLESv2/entry_points_gles_2_0_ext.cpp b/src/libGLESv2/entry_points_gles_2_0_ext.cpp
deleted file mode 100644
index 42ed4a7..0000000
--- a/src/libGLESv2/entry_points_gles_2_0_ext.cpp
+++ /dev/null
@@ -1,2158 +0,0 @@
-//
-// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// entry_points_gles_2_0_ext.cpp : Implements the GLES 2.0 extension entry points.
-
-#include "libGLESv2/entry_points_gles_2_0_ext.h"
-#include "libGLESv2/global_state.h"
-
-#include "libANGLE/Buffer.h"
-#include "libANGLE/Context.h"
-#include "libANGLE/Error.h"
-#include "libANGLE/ErrorStrings.h"
-#include "libANGLE/Fence.h"
-#include "libANGLE/Framebuffer.h"
-#include "libANGLE/Query.h"
-#include "libANGLE/Shader.h"
-#include "libANGLE/Thread.h"
-#include "libANGLE/VertexArray.h"
-#include "libANGLE/queryconversions.h"
-#include "libANGLE/queryutils.h"
-
-#include "libANGLE/validationES.h"
-#include "libANGLE/validationES2.h"
-#include "libANGLE/validationES3.h"
-#include "libANGLE/validationES31.h"
-
-#include "common/debug.h"
-#include "common/utilities.h"
-
-namespace gl
-{
-
-ANGLE_EXPORT void GL_APIENTRY BindUniformLocationCHROMIUM(GLuint program,
-                                                          GLint location,
-                                                          const GLchar *name)
-{
-    EVENT("(GLuint program = %u, GLint location = %d, const GLchar *name = 0x%0.8p)", program,
-          location, name);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidateBindUniformLocationCHROMIUM(context, program, location, name))
-        {
-            return;
-        }
-
-        context->bindUniformLocation(program, location, name);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY CoverageModulationCHROMIUM(GLenum components)
-{
-    EVENT("(GLenum components = %u)", components);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() && !ValidateCoverageModulationCHROMIUM(context, components))
-        {
-            return;
-        }
-        context->coverageModulation(components);
-    }
-}
-
-// CHROMIUM_path_rendering
-ANGLE_EXPORT void GL_APIENTRY MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *matrix)
-{
-    EVENT("(GLenum matrixMode = %u)", matrixMode);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() && !ValidateMatrixLoadfCHROMIUM(context, matrixMode, matrix))
-        {
-            return;
-        }
-        context->matrixLoadf(matrixMode, matrix);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY MatrixLoadIdentityCHROMIUM(GLenum matrixMode)
-{
-    EVENT("(GLenum matrixMode = %u)", matrixMode);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() && !ValidateMatrixLoadIdentityCHROMIUM(context, matrixMode))
-        {
-            return;
-        }
-        context->matrixLoadIdentity(matrixMode);
-    }
-}
-
-ANGLE_EXPORT GLuint GL_APIENTRY GenPathsCHROMIUM(GLsizei range)
-{
-    EVENT("(GLsizei range = %d)", range);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() && !ValidateGenPathsCHROMIUM(context, range))
-        {
-            return 0;
-        }
-        return context->genPaths(range);
-    }
-    return 0;
-}
-
-ANGLE_EXPORT void GL_APIENTRY DeletePathsCHROMIUM(GLuint first, GLsizei range)
-{
-    EVENT("(GLuint first = %u, GLsizei range = %d)", first, range);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() && !ValidateDeletePathsCHROMIUM(context, first, range))
-        {
-            return;
-        }
-        context->deletePaths(first, range);
-    }
-}
-
-ANGLE_EXPORT GLboolean GL_APIENTRY IsPathCHROMIUM(GLuint path)
-{
-    EVENT("(GLuint path = %u)", path);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() && !ValidateIsPathCHROMIUM(context, path))
-        {
-            return GL_FALSE;
-        }
-        return context->isPath(path);
-    }
-    return GL_FALSE;
-}
-
-ANGLE_EXPORT void GL_APIENTRY PathCommandsCHROMIUM(GLuint path,
-                                                   GLsizei numCommands,
-                                                   const GLubyte *commands,
-                                                   GLsizei numCoords,
-                                                   GLenum coordType,
-                                                   const void *coords)
-{
-    EVENT(
-        "(GLuint path = %u, GLsizei numCommands = %d, commands = %p, "
-        "GLsizei numCoords = %d, GLenum coordType = %u, void* coords = %p)",
-        path, numCommands, commands, numCoords, coordType, coords);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidatePathCommandsCHROMIUM(context, path, numCommands, commands, numCoords,
-                                          coordType, coords))
-        {
-            return;
-        }
-        context->pathCommands(path, numCommands, commands, numCoords, coordType, coords);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY PathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value)
-{
-    EVENT("(GLuint path = %u, GLenum pname = %u, GLfloat value = %f)", path, pname, value);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidatePathParameterfCHROMIUM(context, path, pname, value))
-        {
-            return;
-        }
-
-        context->pathParameterf(path, pname, value);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY PathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value)
-{
-    EVENT("(GLuint path = %u, GLenum pname = %u, GLint value = %d)", path, pname, value);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidatePathParameteriCHROMIUM(context, path, pname, value))
-        {
-            return;
-        }
-
-        context->pathParameteri(path, pname, value);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetPathParameterfvCHROMIUM(GLuint path, GLenum pname, GLfloat *value)
-{
-    EVENT("(GLuint path = %u, GLenum pname = %u, GLfloat *value = %p)", path, pname, value);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidateGetPathParameterfvCHROMIUM(context, path, pname, value))
-        {
-            return;
-        }
-        context->getPathParameterfv(path, pname, value);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetPathParameterivCHROMIUM(GLuint path, GLenum pname, GLint *value)
-{
-    EVENT("(GLuint path = %u, GLenum pname = %u, GLint *value = %p)", path, pname, value);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidateGetPathParameterivCHROMIUM(context, path, pname, value))
-        {
-            return;
-        }
-        context->getPathParameteriv(path, pname, value);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY PathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask)
-{
-    EVENT("(GLenum func = %u, GLint ref = %d, GLuint mask = %u)", func, ref, mask);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidatePathStencilFuncCHROMIUM(context, func, ref, mask))
-        {
-            return;
-        }
-        context->pathStencilFunc(func, ref, mask);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY StencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask)
-{
-    EVENT("(GLuint path = %u, GLenum fillMode = %u, GLuint mask = %u)", path, fillMode, mask);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidateStencilFillPathCHROMIUM(context, path, fillMode, mask))
-        {
-            return;
-        }
-        context->stencilFillPath(path, fillMode, mask);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY StencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask)
-{
-    EVENT("(GLuint path = %u, GLint ference = %d, GLuint mask = %u)", path, reference, mask);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidateStencilStrokePathCHROMIUM(context, path, reference, mask))
-        {
-            return;
-        }
-        context->stencilStrokePath(path, reference, mask);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY CoverFillPathCHROMIUM(GLuint path, GLenum coverMode)
-{
-    EVENT("(GLuint path = %u, GLenum coverMode = %u)", path, coverMode);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() && !ValidateCoverFillPathCHROMIUM(context, path, coverMode))
-        {
-            return;
-        }
-        context->coverFillPath(path, coverMode);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY CoverStrokePathCHROMIUM(GLuint path, GLenum coverMode)
-{
-    EVENT("(GLuint path = %u, GLenum coverMode = %u)", path, coverMode);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidateCoverStrokePathCHROMIUM(context, path, coverMode))
-        {
-            return;
-        }
-        context->coverStrokePath(path, coverMode);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY StencilThenCoverFillPathCHROMIUM(GLuint path,
-                                                               GLenum fillMode,
-                                                               GLuint mask,
-                                                               GLenum coverMode)
-{
-    EVENT("(GLuint path = %u, GLenum fillMode = %u, GLuint mask = %u, GLenum coverMode = %u)", path,
-          fillMode, mask, coverMode);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidateStencilThenCoverFillPathCHROMIUM(context, path, fillMode, mask, coverMode))
-        {
-            return;
-        }
-        context->stencilThenCoverFillPath(path, fillMode, mask, coverMode);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY StencilThenCoverStrokePathCHROMIUM(GLuint path,
-                                                                 GLint reference,
-                                                                 GLuint mask,
-                                                                 GLenum coverMode)
-{
-    EVENT("(GLuint path = %u, GLint reference = %d, GLuint mask = %u, GLenum coverMode = %u)", path,
-          reference, mask, coverMode);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidateStencilThenCoverStrokePathCHROMIUM(context, path, reference, mask, coverMode))
-        {
-            return;
-        }
-        context->stencilThenCoverStrokePath(path, reference, mask, coverMode);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY CoverFillPathInstancedCHROMIUM(GLsizei numPaths,
-                                                             GLenum pathNameType,
-                                                             const void *paths,
-                                                             GLuint pathBase,
-                                                             GLenum coverMode,
-                                                             GLenum transformType,
-                                                             const GLfloat *transformValues)
-{
-    EVENT(
-        "(GLsizei numPaths = %d, GLenum pathNameType = %u, const void *paths = %p "
-        "GLuint pathBase = %u, GLenum coverMode = %u, GLenum transformType = %u "
-        "const GLfloat *transformValues = %p)",
-        numPaths, pathNameType, paths, pathBase, coverMode, transformType, transformValues);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() && !ValidateCoverFillPathInstancedCHROMIUM(
-                                              context, numPaths, pathNameType, paths, pathBase,
-                                              coverMode, transformType, transformValues))
-        {
-            return;
-        }
-        context->coverFillPathInstanced(numPaths, pathNameType, paths, pathBase, coverMode,
-                                        transformType, transformValues);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY CoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
-                                                               GLenum pathNameType,
-                                                               const void *paths,
-                                                               GLuint pathBase,
-                                                               GLenum coverMode,
-                                                               GLenum transformType,
-                                                               const GLfloat *transformValues)
-{
-    EVENT(
-        "(GLsizei numPaths = %d, GLenum pathNameType = %u, const void *paths = %p "
-        "GLuint pathBase = %u, GLenum coverMode = %u, GLenum transformType = %u "
-        "const GLfloat *transformValues = %p)",
-        numPaths, pathNameType, paths, pathBase, coverMode, transformType, transformValues);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() && !ValidateCoverStrokePathInstancedCHROMIUM(
-                                              context, numPaths, pathNameType, paths, pathBase,
-                                              coverMode, transformType, transformValues))
-        {
-            return;
-        }
-        context->coverStrokePathInstanced(numPaths, pathNameType, paths, pathBase, coverMode,
-                                          transformType, transformValues);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY StencilStrokePathInstancedCHROMIUM(GLsizei numPaths,
-                                                                 GLenum pathNameType,
-                                                                 const void *paths,
-                                                                 GLuint pathBase,
-                                                                 GLint reference,
-                                                                 GLuint mask,
-                                                                 GLenum transformType,
-                                                                 const GLfloat *transformValues)
-{
-    EVENT(
-        "(GLsizei numPaths = %u, GLenum pathNameType = %u, const void *paths = %p "
-        "GLuint pathBase = %u, GLint reference = %d GLuint mask = %u GLenum transformType = %u "
-        "const GLfloat *transformValues = %p)",
-        numPaths, pathNameType, paths, pathBase, reference, mask, transformType, transformValues);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() && !ValidateStencilStrokePathInstancedCHROMIUM(
-                                              context, numPaths, pathNameType, paths, pathBase,
-                                              reference, mask, transformType, transformValues))
-        {
-            return;
-        }
-        context->stencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase, reference,
-                                            mask, transformType, transformValues);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY StencilFillPathInstancedCHROMIUM(GLsizei numPaths,
-                                                               GLenum pathNameType,
-                                                               const void *paths,
-                                                               GLuint pathBase,
-                                                               GLenum fillMode,
-                                                               GLuint mask,
-                                                               GLenum transformType,
-                                                               const GLfloat *transformValues)
-{
-    EVENT(
-        "(GLsizei numPaths = %u, GLenum pathNameType = %u const void *paths = %p "
-        "GLuint pathBase = %u, GLenum fillMode = %u, GLuint mask = %u, GLenum transformType = %u "
-        "const GLfloat *transformValues = %p)",
-        numPaths, pathNameType, paths, pathBase, fillMode, mask, transformType, transformValues);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() && !ValidateStencilFillPathInstancedCHROMIUM(
-                                              context, numPaths, pathNameType, paths, pathBase,
-                                              fillMode, mask, transformType, transformValues))
-        {
-            return;
-        }
-        context->stencilFillPathInstanced(numPaths, pathNameType, paths, pathBase, fillMode, mask,
-                                          transformType, transformValues);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY
-StencilThenCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
-                                          GLenum pathNameType,
-                                          const void *paths,
-                                          GLuint pathBase,
-                                          GLenum fillMode,
-                                          GLuint mask,
-                                          GLenum coverMode,
-                                          GLenum transformType,
-                                          const GLfloat *transformValues)
-{
-    EVENT(
-        "(GLsizei numPaths = %u, GLenum pathNameType = %u const void *paths = %p "
-        "GLuint pathBase = %u, GLenum coverMode = %u, GLuint mask = %u, GLenum transformType = %u "
-        "const GLfloat *transformValues = %p)",
-        numPaths, pathNameType, paths, pathBase, coverMode, mask, transformType, transformValues);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidateStencilThenCoverFillPathInstancedCHROMIUM(
-                context, numPaths, pathNameType, paths, pathBase, fillMode, mask, coverMode,
-                transformType, transformValues))
-        {
-            return;
-        }
-        context->stencilThenCoverFillPathInstanced(numPaths, pathNameType, paths, pathBase,
-                                                   fillMode, mask, coverMode, transformType,
-                                                   transformValues);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY
-StencilThenCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
-                                            GLenum pathNameType,
-                                            const void *paths,
-                                            GLuint pathBase,
-                                            GLint reference,
-                                            GLuint mask,
-                                            GLenum coverMode,
-                                            GLenum transformType,
-                                            const GLfloat *transformValues)
-{
-    EVENT(
-        "(GLsizei numPaths = %u, GLenum pathNameType = %u, const void *paths = %p "
-        "GLuint pathBase = %u GLenum coverMode = %u GLint reference = %d GLuint mask = %u GLenum "
-        "transformType = %u "
-        "const GLfloat *transformValues = %p)",
-        numPaths, pathNameType, paths, pathBase, coverMode, reference, mask, transformType,
-        transformValues);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidateStencilThenCoverStrokePathInstancedCHROMIUM(
-                context, numPaths, pathNameType, paths, pathBase, reference, mask, coverMode,
-                transformType, transformValues))
-        {
-            return;
-        }
-        context->stencilThenCoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
-                                                     reference, mask, coverMode, transformType,
-                                                     transformValues);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY BindFragmentInputLocationCHROMIUM(GLuint program,
-                                                                GLint location,
-                                                                const GLchar *name)
-{
-    EVENT("(GLuint program = %u, GLint location = %d, const GLchar *name = %p)", program, location,
-          name);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidateBindFragmentInputLocationCHROMIUM(context, program, location, name))
-        {
-            return;
-        }
-        context->bindFragmentInputLocation(program, location, name);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY ProgramPathFragmentInputGenCHROMIUM(GLuint program,
-                                                                  GLint location,
-                                                                  GLenum genMode,
-                                                                  GLint components,
-                                                                  const GLfloat *coeffs)
-{
-    EVENT(
-        "(GLuint program = %u, GLint location %d, GLenum genMode = %u, GLint components = %d, "
-        "const GLfloat * coeffs = %p)",
-        program, location, genMode, components, coeffs);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidateProgramPathFragmentInputGenCHROMIUM(context, program, location, genMode,
-                                                         components, coeffs))
-        {
-            return;
-        }
-        context->programPathFragmentInputGen(program, location, genMode, components, coeffs);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY CopyTextureCHROMIUM(GLuint sourceId,
-                                                  GLint sourceLevel,
-                                                  GLenum destTarget,
-                                                  GLuint destId,
-                                                  GLint destLevel,
-                                                  GLint internalFormat,
-                                                  GLenum destType,
-                                                  GLboolean unpackFlipY,
-                                                  GLboolean unpackPremultiplyAlpha,
-                                                  GLboolean unpackUnmultiplyAlpha)
-{
-    EVENT(
-        "(GLuint sourceId = %u, GLint sourceLevel = %d, GLenum destTarget = 0x%X, GLuint destId = "
-        "%u, GLint destLevel = %d, GLint internalFormat = 0x%X, GLenum destType = "
-        "0x%X, GLboolean unpackFlipY = %u, GLboolean unpackPremultiplyAlpha = %u, GLboolean "
-        "unpackUnmultiplyAlpha = %u)",
-        sourceId, sourceLevel, destTarget, destId, destLevel, internalFormat, destType, unpackFlipY,
-        unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        TextureTarget destTargetPacked = FromGLenum<TextureTarget>(destTarget);
-        if (!context->skipValidation() &&
-            !ValidateCopyTextureCHROMIUM(context, sourceId, sourceLevel, destTargetPacked, destId,
-                                         destLevel, internalFormat, destType, unpackFlipY,
-                                         unpackPremultiplyAlpha, unpackUnmultiplyAlpha))
-        {
-            return;
-        }
-
-        context->copyTexture(sourceId, sourceLevel, destTargetPacked, destId, destLevel,
-                             internalFormat, destType, unpackFlipY, unpackPremultiplyAlpha,
-                             unpackUnmultiplyAlpha);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY CopySubTextureCHROMIUM(GLuint sourceId,
-                                                     GLint sourceLevel,
-                                                     GLenum destTarget,
-                                                     GLuint destId,
-                                                     GLint destLevel,
-                                                     GLint xoffset,
-                                                     GLint yoffset,
-                                                     GLint x,
-                                                     GLint y,
-                                                     GLsizei width,
-                                                     GLsizei height,
-                                                     GLboolean unpackFlipY,
-                                                     GLboolean unpackPremultiplyAlpha,
-                                                     GLboolean unpackUnmultiplyAlpha)
-{
-    EVENT(
-        "(GLuint sourceId = %u, GLint sourceLevel = %d, GLenum destTarget = 0x%X, GLuint destId = "
-        "%u, GLint destLevel = %d, GLint xoffset = "
-        "%d, GLint yoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = "
-        "%d, GLboolean unpackPremultiplyAlpha = %u, GLboolean unpackUnmultiplyAlpha = %u)",
-        sourceId, sourceLevel, destTarget, destId, destLevel, xoffset, yoffset, x, y, width, height,
-        unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        TextureTarget destTargetPacked = FromGLenum<TextureTarget>(destTarget);
-        if (!context->skipValidation() &&
-            !ValidateCopySubTextureCHROMIUM(context, sourceId, sourceLevel, destTargetPacked,
-                                            destId, destLevel, xoffset, yoffset, x, y, width,
-                                            height, unpackFlipY, unpackPremultiplyAlpha,
-                                            unpackUnmultiplyAlpha))
-        {
-            return;
-        }
-
-        context->copySubTexture(sourceId, sourceLevel, destTargetPacked, destId, destLevel, xoffset,
-                                yoffset, x, y, width, height, unpackFlipY, unpackPremultiplyAlpha,
-                                unpackUnmultiplyAlpha);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY CompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId)
-{
-    EVENT("(GLuint sourceId = %u, GLuint destId = %u)", sourceId, destId);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidateCompressedCopyTextureCHROMIUM(context, sourceId, destId))
-        {
-            return;
-        }
-
-        context->compressedCopyTexture(sourceId, destId);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY RequestExtensionANGLE(const GLchar *name)
-{
-    EVENT("(const GLchar *name = %p)", name);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() && !ValidateRequestExtensionANGLE(context, name))
-        {
-            return;
-        }
-
-        context->requestExtension(name);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetBooleanvRobustANGLE(GLenum pname,
-                                                     GLsizei bufSize,
-                                                     GLsizei *length,
-                                                     GLboolean *params)
-{
-    EVENT(
-        "(GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLboolean* params "
-        "= 0x%0.8p)",
-        pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetBooleanvRobustANGLE(context, pname, bufSize, length, params))
-        {
-            return;
-        }
-
-        context->getBooleanvRobust(pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetBufferParameterivRobustANGLE(GLenum target,
-                                                              GLenum pname,
-                                                              GLsizei bufSize,
-                                                              GLsizei *length,
-                                                              GLint *params)
-{
-    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname,
-          params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
-
-        if (!ValidateGetBufferParameterivRobustANGLE(context, targetPacked, pname, bufSize, length,
-                                                     params))
-        {
-            return;
-        }
-
-        context->getBufferParameterivRobust(targetPacked, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetFloatvRobustANGLE(GLenum pname,
-                                                   GLsizei bufSize,
-                                                   GLsizei *length,
-                                                   GLfloat *params)
-{
-    EVENT(
-        "(GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLfloat* params = "
-        "0x%0.8p)",
-        pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetFloatvRobustANGLE(context, pname, bufSize, length, params))
-        {
-            return;
-        }
-
-        context->getFloatvRobust(pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetFramebufferAttachmentParameterivRobustANGLE(GLenum target,
-                                                                             GLenum attachment,
-                                                                             GLenum pname,
-                                                                             GLsizei bufSize,
-                                                                             GLsizei *length,
-                                                                             GLint *params)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X,  GLsizei bufsize = "
-        "%d, GLsizei* length = 0x%0.8p, GLint* params = 0x%0.8p)",
-        target, attachment, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetFramebufferAttachmentParameterivRobustANGLE(context, target, attachment,
-                                                                    pname, bufSize, length, params))
-        {
-            return;
-        }
-
-        context->getFramebufferAttachmentParameterivRobust(target, attachment, pname, bufSize,
-                                                           length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetIntegervRobustANGLE(GLenum pname,
-                                                     GLsizei bufSize,
-                                                     GLsizei *length,
-                                                     GLint *data)
-{
-    EVENT(
-        "(GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLint* params = "
-        "0x%0.8p)",
-        pname, bufSize, length, data);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetIntegervRobustANGLE(context, pname, bufSize, length, data))
-        {
-            return;
-        }
-
-        context->getIntegervRobust(pname, bufSize, length, data);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetProgramivRobustANGLE(GLuint program,
-                                                      GLenum pname,
-                                                      GLsizei bufSize,
-                                                      GLsizei *length,
-                                                      GLint *params)
-{
-    EVENT(
-        "(GLuint program = %d, GLenum pname = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
-        "GLint* params = 0x%0.8p)",
-        program, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetProgramivRobustANGLE(context, program, pname, bufSize, length, params))
-        {
-            return;
-        }
-
-        context->getProgramivRobust(program, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetRenderbufferParameterivRobustANGLE(GLenum target,
-                                                                    GLenum pname,
-                                                                    GLsizei bufSize,
-                                                                    GLsizei *length,
-                                                                    GLint *params)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLint* params = 0x%0.8p)",
-        target, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetRenderbufferParameterivRobustANGLE(context, target, pname, bufSize, length,
-                                                           params))
-        {
-            return;
-        }
-
-        context->getRenderbufferParameterivRobust(target, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY
-GetShaderivRobustANGLE(GLuint shader, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params)
-{
-    EVENT(
-        "(GLuint shader = %d, GLenum pname = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
-        "GLint* params = 0x%0.8p)",
-        shader, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetShaderivRobustANGLE(context, shader, pname, bufSize, length, params))
-        {
-            return;
-        }
-
-        context->getShaderivRobust(shader, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetTexParameterfvRobustANGLE(GLenum target,
-                                                           GLenum pname,
-                                                           GLsizei bufSize,
-                                                           GLsizei *length,
-                                                           GLfloat *params)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLfloat* params = 0x%0.8p)",
-        target, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        TextureType targetPacked = FromGLenum<TextureType>(target);
-        if (!ValidateGetTexParameterfvRobustANGLE(context, targetPacked, pname, bufSize, length,
-                                                  params))
-        {
-            return;
-        }
-
-        context->getTexParameterfvRobust(targetPacked, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetTexParameterivRobustANGLE(GLenum target,
-                                                           GLenum pname,
-                                                           GLsizei bufSize,
-                                                           GLsizei *length,
-                                                           GLint *params)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLfloat* params = 0x%0.8p)",
-        target, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        TextureType targetPacked = FromGLenum<TextureType>(target);
-        if (!ValidateGetTexParameterivRobustANGLE(context, targetPacked, pname, bufSize, length,
-                                                  params))
-        {
-            return;
-        }
-
-        context->getTexParameterivRobust(targetPacked, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetUniformfvRobustANGLE(GLuint program,
-                                                      GLint location,
-                                                      GLsizei bufSize,
-                                                      GLsizei *length,
-                                                      GLfloat *params)
-{
-    EVENT(
-        "(GLuint program = %d, GLint location = %d, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLfloat* params = 0x%0.8p)",
-        program, location, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetUniformfvRobustANGLE(context, program, location, bufSize, length, params))
-        {
-            return;
-        }
-
-        context->getUniformfvRobust(program, location, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetUniformivRobustANGLE(GLuint program,
-                                                      GLint location,
-                                                      GLsizei bufSize,
-                                                      GLsizei *length,
-                                                      GLint *params)
-{
-    EVENT(
-        "(GLuint program = %d, GLint location = %d, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLint* params = 0x%0.8p)",
-        program, location, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetUniformivRobustANGLE(context, program, location, bufSize, length, params))
-        {
-            return;
-        }
-
-        context->getUniformivRobust(program, location, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetVertexAttribfvRobustANGLE(GLuint index,
-                                                           GLenum pname,
-                                                           GLsizei bufSize,
-                                                           GLsizei *length,
-                                                           GLfloat *params)
-{
-    EVENT(
-        "(GLuint index = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
-        "GLfloat* params = 0x%0.8p)",
-        index, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetVertexAttribfvRobustANGLE(context, index, pname, bufSize, length, params))
-        {
-            return;
-        }
-
-        context->getVertexAttribfvRobust(index, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetVertexAttribivRobustANGLE(GLuint index,
-                                                           GLenum pname,
-                                                           GLsizei bufSize,
-                                                           GLsizei *length,
-                                                           GLint *params)
-{
-    EVENT(
-        "(GLuint index = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
-        "GLint* params = 0x%0.8p)",
-        index, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetVertexAttribivRobustANGLE(context, index, pname, bufSize, length, params))
-        {
-            return;
-        }
-
-        context->getVertexAttribivRobust(index, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetVertexAttribPointervRobustANGLE(GLuint index,
-                                                                 GLenum pname,
-                                                                 GLsizei bufSize,
-                                                                 GLsizei *length,
-                                                                 void **pointer)
-{
-    EVENT(
-        "(GLuint index = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
-        "void** pointer = 0x%0.8p)",
-        index, pname, bufSize, length, pointer);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetVertexAttribPointervRobustANGLE(context, index, pname, bufSize, length,
-                                                        pointer))
-        {
-            return;
-        }
-
-        context->getVertexAttribPointervRobust(index, pname, bufSize, length, pointer);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY ReadPixelsRobustANGLE(GLint x,
-                                                    GLint y,
-                                                    GLsizei width,
-                                                    GLsizei height,
-                                                    GLenum format,
-                                                    GLenum type,
-                                                    GLsizei bufSize,
-                                                    GLsizei *length,
-                                                    GLsizei *columns,
-                                                    GLsizei *rows,
-                                                    void *pixels)
-{
-    EVENT(
-        "(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
-        "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLsizei* columns = 0x%0.8p, GLsizei* rows = 0x%0.8p, void* pixels = 0x%0.8p)",
-        x, y, width, height, format, type, bufSize, length, columns, rows, pixels);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateReadPixelsRobustANGLE(context, x, y, width, height, format, type, bufSize,
-                                           length, columns, rows, pixels))
-        {
-            return;
-        }
-
-        context->readPixelsRobust(x, y, width, height, format, type, bufSize, length, columns, rows,
-                                  pixels);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY TexImage2DRobustANGLE(GLenum target,
-                                                    GLint level,
-                                                    GLint internalformat,
-                                                    GLsizei width,
-                                                    GLsizei height,
-                                                    GLint border,
-                                                    GLenum format,
-                                                    GLenum type,
-                                                    GLsizei bufSize,
-                                                    const void *pixels)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
-        "GLsizei height = %d, GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, GLsizei "
-        "bufSize = %d, const void* pixels = 0x%0.8p)",
-        target, level, internalformat, width, height, border, format, type, bufSize, pixels);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        TextureTarget targetPacked = FromGLenum<TextureTarget>(target);
-        if (!ValidateTexImage2DRobust(context, targetPacked, level, internalformat, width, height,
-                                      border, format, type, bufSize, pixels))
-        {
-            return;
-        }
-
-        context->texImage2DRobust(targetPacked, level, internalformat, width, height, border,
-                                  format, type, bufSize, pixels);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY TexParameterfvRobustANGLE(GLenum target,
-                                                        GLenum pname,
-                                                        GLsizei bufSize,
-                                                        const GLfloat *params)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLfloat* params = "
-        "0x%0.8p)",
-        target, pname, bufSize, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        TextureType targetPacked = FromGLenum<TextureType>(target);
-        if (!ValidateTexParameterfvRobustANGLE(context, targetPacked, pname, bufSize, params))
-        {
-            return;
-        }
-
-        context->texParameterfvRobust(targetPacked, pname, bufSize, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY TexParameterivRobustANGLE(GLenum target,
-                                                        GLenum pname,
-                                                        GLsizei bufSize,
-                                                        const GLint *params)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLfloat* params = "
-        "0x%0.8p)",
-        target, pname, bufSize, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        TextureType targetPacked = FromGLenum<TextureType>(target);
-        if (!ValidateTexParameterivRobustANGLE(context, targetPacked, pname, bufSize, params))
-        {
-            return;
-        }
-
-        context->texParameterivRobust(targetPacked, pname, bufSize, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY TexSubImage2DRobustANGLE(GLenum target,
-                                                       GLint level,
-                                                       GLint xoffset,
-                                                       GLint yoffset,
-                                                       GLsizei width,
-                                                       GLsizei height,
-                                                       GLenum format,
-                                                       GLenum type,
-                                                       GLsizei bufSize,
-                                                       const void *pixels)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
-        "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
-        "GLsizei bufsize = %d, const void* pixels = 0x%0.8p)",
-        target, level, xoffset, yoffset, width, height, format, type, bufSize, pixels);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        TextureTarget targetPacked = FromGLenum<TextureTarget>(target);
-        if (!ValidateTexSubImage2DRobustANGLE(context, targetPacked, level, xoffset, yoffset, width,
-                                              height, format, type, bufSize, pixels))
-        {
-            return;
-        }
-
-        context->texSubImage2DRobust(targetPacked, level, xoffset, yoffset, width, height, format,
-                                     type, bufSize, pixels);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY TexImage3DRobustANGLE(GLenum target,
-                                                    GLint level,
-                                                    GLint internalformat,
-                                                    GLsizei width,
-                                                    GLsizei height,
-                                                    GLsizei depth,
-                                                    GLint border,
-                                                    GLenum format,
-                                                    GLenum type,
-                                                    GLsizei bufSize,
-                                                    const void *pixels)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
-        "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, "
-        "GLenum type = 0x%X, GLsizei bufsize = %d, const void* pixels = 0x%0.8p)",
-        target, level, internalformat, width, height, depth, border, format, type, bufSize, pixels);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        TextureType targetPacked = FromGLenum<TextureType>(target);
-        if (!ValidateTexImage3DRobustANGLE(context, targetPacked, level, internalformat, width,
-                                           height, depth, border, format, type, bufSize, pixels))
-        {
-            return;
-        }
-
-        context->texImage3DRobust(targetPacked, level, internalformat, width, height, depth, border,
-                                  format, type, bufSize, pixels);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY TexSubImage3DRobustANGLE(GLenum target,
-                                                       GLint level,
-                                                       GLint xoffset,
-                                                       GLint yoffset,
-                                                       GLint zoffset,
-                                                       GLsizei width,
-                                                       GLsizei height,
-                                                       GLsizei depth,
-                                                       GLenum format,
-                                                       GLenum type,
-                                                       GLsizei bufSize,
-                                                       const void *pixels)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
-        "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
-        "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufsize = %d, const void* pixels = "
-        "0x%0.8p)",
-        target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, bufSize,
-        pixels);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        TextureType targetPacked = FromGLenum<TextureType>(target);
-        if (!ValidateTexSubImage3DRobustANGLE(context, targetPacked, level, xoffset, yoffset,
-                                              zoffset, width, height, depth, format, type, bufSize,
-                                              pixels))
-        {
-            return;
-        }
-
-        context->texSubImage3DRobust(targetPacked, level, xoffset, yoffset, zoffset, width, height,
-                                     depth, format, type, bufSize, pixels);
-    }
-}
-
-void GL_APIENTRY CompressedTexImage2DRobustANGLE(GLenum target,
-                                                 GLint level,
-                                                 GLenum internalformat,
-                                                 GLsizei width,
-                                                 GLsizei height,
-                                                 GLint border,
-                                                 GLsizei imageSize,
-                                                 GLsizei dataSize,
-                                                 const GLvoid *data)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = "
-        "%d, "
-        "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, GLsizei dataSize = %d, "
-        "const GLvoid* data = 0x%0.8p)",
-        target, level, internalformat, width, height, border, imageSize, dataSize, data);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        TextureTarget targetPacked = FromGLenum<TextureTarget>(target);
-        if (!context->skipValidation() && !ValidateCompressedTexImage2DRobustANGLE(
-                                              context, targetPacked, level, internalformat, width,
-                                              height, border, imageSize, dataSize, data))
-        {
-            return;
-        }
-
-        context->compressedTexImage2DRobust(targetPacked, level, internalformat, width, height,
-                                            border, imageSize, dataSize, data);
-    }
-}
-
-void GL_APIENTRY CompressedTexSubImage2DRobustANGLE(GLenum target,
-                                                    GLint level,
-                                                    GLint xoffset,
-                                                    GLint yoffset,
-                                                    GLsizei width,
-                                                    GLsizei height,
-                                                    GLenum format,
-                                                    GLsizei imageSize,
-                                                    GLsizei dataSize,
-                                                    const GLvoid *data)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
-        "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
-        "GLsizei imageSize = %d, GLsizei dataSize = %d, const GLvoid* data = 0x%0.8p)",
-        target, level, xoffset, yoffset, width, height, format, imageSize, dataSize, data);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        TextureTarget targetPacked = FromGLenum<TextureTarget>(target);
-        if (!context->skipValidation() && !ValidateCompressedTexSubImage2DRobustANGLE(
-                                              context, targetPacked, level, xoffset, yoffset, width,
-                                              height, format, imageSize, dataSize, data))
-        {
-            return;
-        }
-
-        context->compressedTexSubImage2DRobust(targetPacked, level, xoffset, yoffset, width, height,
-                                               format, imageSize, dataSize, data);
-    }
-}
-
-void GL_APIENTRY CompressedTexImage3DRobustANGLE(GLenum target,
-                                                 GLint level,
-                                                 GLenum internalformat,
-                                                 GLsizei width,
-                                                 GLsizei height,
-                                                 GLsizei depth,
-                                                 GLint border,
-                                                 GLsizei imageSize,
-                                                 GLsizei dataSize,
-                                                 const GLvoid *data)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = "
-        "%d, "
-        "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, "
-        "GLsizei dataSize = %d, const GLvoid* data = 0x%0.8p)",
-        target, level, internalformat, width, height, depth, border, imageSize, dataSize, data);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        TextureType targetPacked = FromGLenum<TextureType>(target);
-        if (!context->skipValidation() && !ValidateCompressedTexImage3DRobustANGLE(
-                                              context, targetPacked, level, internalformat, width,
-                                              height, depth, border, imageSize, dataSize, data))
-        {
-            return;
-        }
-
-        context->compressedTexImage3DRobust(targetPacked, level, internalformat, width, height,
-                                            depth, border, imageSize, dataSize, data);
-    }
-}
-
-void GL_APIENTRY CompressedTexSubImage3DRobustANGLE(GLenum target,
-                                                    GLint level,
-                                                    GLint xoffset,
-                                                    GLint yoffset,
-                                                    GLint zoffset,
-                                                    GLsizei width,
-                                                    GLsizei height,
-                                                    GLsizei depth,
-                                                    GLenum format,
-                                                    GLsizei imageSize,
-                                                    GLsizei dataSize,
-                                                    const GLvoid *data)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
-        "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
-        "GLenum format = 0x%X, GLsizei imageSize = %d, GLsizei dataSize = %d, const GLvoid* data = "
-        "0x%0.8p)",
-        target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, dataSize,
-        data);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        TextureType targetPacked = FromGLenum<TextureType>(target);
-        if (!context->skipValidation() &&
-            !ValidateCompressedTexSubImage3DRobustANGLE(context, targetPacked, level, xoffset,
-                                                        yoffset, zoffset, width, height, depth,
-                                                        format, imageSize, dataSize, data))
-        {
-            return;
-        }
-
-        context->compressedTexSubImage3DRobust(targetPacked, level, xoffset, yoffset, zoffset,
-                                               width, height, depth, format, imageSize, dataSize,
-                                               data);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY
-GetQueryivRobustANGLE(GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLint* params = 0x%0.8p)",
-        target, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetQueryivRobustANGLE(context, target, pname, bufSize, length, params))
-        {
-            return;
-        }
-
-        context->getQueryivRobust(target, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetQueryObjectuivRobustANGLE(GLuint id,
-                                                           GLenum pname,
-                                                           GLsizei bufSize,
-                                                           GLsizei *length,
-                                                           GLuint *params)
-{
-    EVENT(
-        "(GLuint id = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
-        "GLint* params = 0x%0.8p)",
-        id, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetQueryObjectuivRobustANGLE(context, id, pname, bufSize, length, params))
-        {
-            return;
-        }
-
-        context->getQueryObjectuivRobust(id, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetBufferPointervRobustANGLE(GLenum target,
-                                                           GLenum pname,
-                                                           GLsizei bufSize,
-                                                           GLsizei *length,
-                                                           void **params)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLenum pname = 0x%X,  GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, void** params = 0x%0.8p)",
-        target, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
-
-        if (!ValidateGetBufferPointervRobustANGLE(context, targetPacked, pname, bufSize, length,
-                                                  params))
-        {
-            return;
-        }
-
-        context->getBufferPointervRobust(targetPacked, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY
-GetIntegeri_vRobustANGLE(GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLint *data)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLuint index = %u, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLint* data = 0x%0.8p)",
-        target, index, bufSize, length, data);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetIntegeri_vRobustANGLE(context, target, index, bufSize, length, data))
-        {
-            return;
-        }
-
-        context->getIntegeri_vRobust(target, index, bufSize, length, data);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetInternalformativRobustANGLE(GLenum target,
-                                                             GLenum internalformat,
-                                                             GLenum pname,
-                                                             GLsizei bufSize,
-                                                             GLsizei *length,
-                                                             GLint *params)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize "
-        "= %d, GLsizei* length = 0x%0.8p, GLint* params = 0x%0.8p)",
-        target, internalformat, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetInternalFormativRobustANGLE(context, target, internalformat, pname, bufSize,
-                                                    length, params))
-        {
-            return;
-        }
-
-        context->getInternalformativRobust(target, internalformat, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIivRobustANGLE(GLuint index,
-                                                            GLenum pname,
-                                                            GLsizei bufSize,
-                                                            GLsizei *length,
-                                                            GLint *params)
-{
-    EVENT(
-        "(GLuint index = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
-        "GLint* params = 0x%0.8p)",
-        index, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetVertexAttribIivRobustANGLE(context, index, pname, bufSize, length, params))
-        {
-            return;
-        }
-
-        context->getVertexAttribIivRobust(index, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIuivRobustANGLE(GLuint index,
-                                                             GLenum pname,
-                                                             GLsizei bufSize,
-                                                             GLsizei *length,
-                                                             GLuint *params)
-{
-    EVENT(
-        "(GLuint index = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
-        "GLuint* params = 0x%0.8p)",
-        index, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetVertexAttribIuivRobustANGLE(context, index, pname, bufSize, length, params))
-        {
-            return;
-        }
-
-        context->getVertexAttribIuivRobust(index, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetUniformuivRobustANGLE(GLuint program,
-                                                       GLint location,
-                                                       GLsizei bufSize,
-                                                       GLsizei *length,
-                                                       GLuint *params)
-{
-    EVENT(
-        "(GLuint program = %u, GLint location = %d, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLuint* params = 0x%0.8p)",
-        program, location, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetUniformuivRobustANGLE(context, program, location, bufSize, length, params))
-        {
-            return;
-        }
-
-        context->getUniformuivRobust(program, location, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockivRobustANGLE(GLuint program,
-                                                                 GLuint uniformBlockIndex,
-                                                                 GLenum pname,
-                                                                 GLsizei bufSize,
-                                                                 GLsizei *length,
-                                                                 GLint *params)
-{
-    EVENT(
-        "(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLsizei bufsize "
-        "= %d, GLsizei* length = 0x%0.8p, GLint* params = 0x%0.8p)",
-        program, uniformBlockIndex, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetActiveUniformBlockivRobustANGLE(context, program, uniformBlockIndex, pname,
-                                                        bufSize, length, params))
-        {
-            return;
-        }
-
-        context->getActiveUniformBlockivRobust(program, uniformBlockIndex, pname, bufSize, length,
-                                               params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetInteger64vRobustANGLE(GLenum pname,
-                                                       GLsizei bufSize,
-                                                       GLsizei *length,
-                                                       GLint64 *data)
-{
-    EVENT(
-        "(GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLint64* params = "
-        "0x%0.8p)",
-        pname, bufSize, length, data);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetInteger64vRobustANGLE(context, pname, bufSize, length, data))
-        {
-            return;
-        }
-
-        context->getInteger64vRobust(pname, bufSize, length, data);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetInteger64i_vRobustANGLE(GLenum target,
-                                                         GLuint index,
-                                                         GLsizei bufSize,
-                                                         GLsizei *length,
-                                                         GLint64 *data)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLuint index = %u, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLint64* data = 0x%0.8p)",
-        target, index, bufSize, length, data);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetInteger64i_vRobustANGLE(context, target, index, bufSize, length, data))
-        {
-            return;
-        }
-
-        context->getInteger64i_vRobust(target, index, bufSize, length, data);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetBufferParameteri64vRobustANGLE(GLenum target,
-                                                                GLenum pname,
-                                                                GLsizei bufSize,
-                                                                GLsizei *length,
-                                                                GLint64 *params)
-{
-    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", target, pname,
-          bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
-
-        if (!ValidateGetBufferParameteri64vRobustANGLE(context, targetPacked, pname, bufSize,
-                                                       length, params))
-        {
-            return;
-        }
-
-        context->getBufferParameteri64vRobust(targetPacked, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY SamplerParameterivRobustANGLE(GLuint sampler,
-                                                            GLenum pname,
-                                                            GLsizei bufSize,
-                                                            const GLint *param)
-{
-    EVENT(
-        "(GLuint sampler = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, const GLint* params = "
-        "0x%0.8p)",
-        sampler, pname, bufSize, param);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateSamplerParameterivRobustANGLE(context, sampler, pname, bufSize, param))
-        {
-            return;
-        }
-
-        context->samplerParameterivRobust(sampler, pname, bufSize, param);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY SamplerParameterfvRobustANGLE(GLuint sampler,
-                                                            GLenum pname,
-                                                            GLsizei bufSize,
-                                                            const GLfloat *param)
-{
-    EVENT(
-        "(GLuint sampler = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, const GLfloat* params = "
-        "0x%0.8p)",
-        sampler, pname, bufSize, param);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateSamplerParameterfvRobustANGLE(context, sampler, pname, bufSize, param))
-        {
-            return;
-        }
-
-        context->samplerParameterfvRobust(sampler, pname, bufSize, param);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterivRobustANGLE(GLuint sampler,
-                                                               GLenum pname,
-                                                               GLsizei bufSize,
-                                                               GLsizei *length,
-                                                               GLint *params)
-{
-    EVENT(
-        "(GLuint sampler = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLint* params = 0x%0.8p)",
-        sampler, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetSamplerParameterivRobustANGLE(context, sampler, pname, bufSize, length,
-                                                      params))
-        {
-            return;
-        }
-
-        context->getSamplerParameterivRobust(sampler, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterfvRobustANGLE(GLuint sampler,
-                                                               GLenum pname,
-                                                               GLsizei bufSize,
-                                                               GLsizei *length,
-                                                               GLfloat *params)
-{
-    EVENT(
-        "(GLuint sample = %ur, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLfloat* params = 0x%0.8p)",
-        sampler, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetSamplerParameterfvRobustANGLE(context, sampler, pname, bufSize, length,
-                                                      params))
-        {
-            return;
-        }
-
-        context->getSamplerParameterfvRobust(sampler, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetFramebufferParameterivRobustANGLE(GLenum target,
-                                                                   GLenum pname,
-                                                                   GLsizei bufSize,
-                                                                   GLsizei *length,
-                                                                   GLint *params)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLint* params = 0x%0.8p)",
-        target, pname, bufSize, length, params);
-    UNIMPLEMENTED();
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetProgramInterfaceivRobustANGLE(GLuint program,
-                                                               GLenum programInterface,
-                                                               GLenum pname,
-                                                               GLsizei bufSize,
-                                                               GLsizei *length,
-                                                               GLint *params)
-{
-    EVENT(
-        "(GLuint program = %u, GLenum programInterface = 0x%X, GLenum pname = 0x%X, GLsizei "
-        "bufsize = %d, GLsizei* length = 0x%0.8p, GLint* params = 0x%0.8p)",
-        program, programInterface, pname, bufSize, length, params);
-    UNIMPLEMENTED();
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetBooleani_vRobustANGLE(GLenum target,
-                                                       GLuint index,
-                                                       GLsizei bufSize,
-                                                       GLsizei *length,
-                                                       GLboolean *data)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLuint index = %u, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLboolean* data = 0x%0.8p)",
-        target, index, bufSize, length, data);
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetBooleani_vRobustANGLE(context, target, index, bufSize, length, data))
-        {
-            return;
-        }
-
-        context->getBooleani_vRobust(target, index, bufSize, length, data);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetMultisamplefvRobustANGLE(GLenum pname,
-                                                          GLuint index,
-                                                          GLsizei bufSize,
-                                                          GLsizei *length,
-                                                          GLfloat *val)
-{
-    EVENT(
-        "(GLenum pname = 0x%X, GLuint index = %u, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
-        "GLfloat* val = 0x%0.8p)",
-        pname, index, bufSize, length, val);
-    UNIMPLEMENTED();
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameterivRobustANGLE(GLenum target,
-                                                                GLint level,
-                                                                GLenum pname,
-                                                                GLsizei bufSize,
-                                                                GLsizei *length,
-                                                                GLint *params)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLint level = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, "
-        "GLsizei* length = 0x%0.8p, GLint* params = 0x%0.8p)",
-        target, level, pname, bufSize, length, params);
-    UNIMPLEMENTED();
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameterfvRobustANGLE(GLenum target,
-                                                                GLint level,
-                                                                GLenum pname,
-                                                                GLsizei bufSize,
-                                                                GLsizei *length,
-                                                                GLfloat *params)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLint level = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, "
-        "GLsizei* length = 0x%0.8p, GLfloat* params = 0x%0.8p)",
-        target, level, pname, bufSize, length, params);
-    UNIMPLEMENTED();
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetPointervRobustANGLERobustANGLE(GLenum pname,
-                                                                GLsizei bufSize,
-                                                                GLsizei *length,
-                                                                void **params)
-{
-    EVENT(
-        "(GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, void **params = "
-        "0x%0.8p)",
-        pname, bufSize, length, params);
-    UNIMPLEMENTED();
-}
-
-ANGLE_EXPORT void GL_APIENTRY ReadnPixelsRobustANGLE(GLint x,
-                                                     GLint y,
-                                                     GLsizei width,
-                                                     GLsizei height,
-                                                     GLenum format,
-                                                     GLenum type,
-                                                     GLsizei bufSize,
-                                                     GLsizei *length,
-                                                     GLsizei *columns,
-                                                     GLsizei *rows,
-                                                     void *data)
-{
-    EVENT(
-        "(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
-        "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLsizei* columns = 0x%0.8p, GLsizei* rows = 0x%0.8p, void *data = 0x%0.8p)",
-        x, y, width, height, format, type, bufSize, length, columns, rows, data);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateReadnPixelsRobustANGLE(context, x, y, width, height, format, type, bufSize,
-                                            length, columns, rows, data))
-        {
-            return;
-        }
-
-        context->readnPixelsRobust(x, y, width, height, format, type, bufSize, length, columns,
-                                   rows, data);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetnUniformfvRobustANGLE(GLuint program,
-                                                       GLint location,
-                                                       GLsizei bufSize,
-                                                       GLsizei *length,
-                                                       GLfloat *params)
-{
-    EVENT(
-        "(GLuint program = %d, GLint location = %d, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLfloat* params = 0x%0.8p)",
-        program, location, bufSize, length, params);
-    UNIMPLEMENTED();
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetnUniformivRobustANGLE(GLuint program,
-                                                       GLint location,
-                                                       GLsizei bufSize,
-                                                       GLsizei *length,
-                                                       GLint *params)
-{
-    EVENT(
-        "(GLuint program = %d, GLint location = %d, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLint* params = 0x%0.8p)",
-        program, location, bufSize, length, params);
-    UNIMPLEMENTED();
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetnUniformuivRobustANGLE(GLuint program,
-                                                        GLint location,
-                                                        GLsizei bufSize,
-                                                        GLsizei *length,
-                                                        GLuint *params)
-{
-    EVENT(
-        "(GLuint program = %u, GLint location = %d, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLuint* params = 0x%0.8p)",
-        program, location, bufSize, length, params);
-    UNIMPLEMENTED();
-}
-
-ANGLE_EXPORT void GL_APIENTRY TexParameterIivRobustANGLE(GLenum target,
-                                                         GLenum pname,
-                                                         GLsizei bufSize,
-                                                         const GLint *params)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, const GLint *params = "
-        "0x%0.8p)",
-        target, pname, bufSize, params);
-    UNIMPLEMENTED();
-}
-
-ANGLE_EXPORT void GL_APIENTRY TexParameterIuivRobustANGLE(GLenum target,
-                                                          GLenum pname,
-                                                          GLsizei bufSize,
-                                                          const GLuint *params)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, const GLuint *params = "
-        "0x%0.8p)",
-        target, pname, bufSize, params);
-    UNIMPLEMENTED();
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetTexParameterIivRobustANGLE(GLenum target,
-                                                            GLenum pname,
-                                                            GLsizei bufSize,
-                                                            GLsizei *length,
-                                                            GLint *params)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLint *params = 0x%0.8p)",
-        target, pname, bufSize, length, params);
-    UNIMPLEMENTED();
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetTexParameterIuivRobustANGLE(GLenum target,
-                                                             GLenum pname,
-                                                             GLsizei bufSize,
-                                                             GLsizei *length,
-                                                             GLuint *params)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLuint *params = 0x%0.8p)",
-        target, pname, bufSize, length, params);
-    UNIMPLEMENTED();
-}
-
-ANGLE_EXPORT void GL_APIENTRY SamplerParameterIivRobustANGLE(GLuint sampler,
-                                                             GLenum pname,
-                                                             GLsizei bufSize,
-                                                             const GLint *param)
-{
-    EVENT(
-        "(GLuint sampler = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, const GLint *param = "
-        "0x%0.8p)",
-        sampler, pname, bufSize, param);
-    UNIMPLEMENTED();
-}
-
-ANGLE_EXPORT void GL_APIENTRY SamplerParameterIuivRobustANGLE(GLuint sampler,
-                                                              GLenum pname,
-                                                              GLsizei bufSize,
-                                                              const GLuint *param)
-{
-    EVENT(
-        "(GLuint sampler = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, const GLuint *param = "
-        "0x%0.8p)",
-        sampler, pname, bufSize, param);
-    UNIMPLEMENTED();
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterIivRobustANGLE(GLuint sampler,
-                                                                GLenum pname,
-                                                                GLsizei bufSize,
-                                                                GLsizei *length,
-                                                                GLint *params)
-{
-    EVENT(
-        "(GLuint sampler = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLint *params = 0x%0.8p)",
-        sampler, pname, bufSize, length, params);
-    UNIMPLEMENTED();
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterIuivRobustANGLE(GLuint sampler,
-                                                                 GLenum pname,
-                                                                 GLsizei bufSize,
-                                                                 GLsizei *length,
-                                                                 GLuint *params)
-{
-    EVENT(
-        "(GLuint sampler = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
-        "0x%0.8p, GLuint *params = 0x%0.8p)",
-        sampler, pname, bufSize, length, params);
-    UNIMPLEMENTED();
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetQueryObjectivRobustANGLE(GLuint id,
-                                                          GLenum pname,
-                                                          GLsizei bufSize,
-                                                          GLsizei *length,
-                                                          GLint *params)
-{
-    EVENT(
-        "(GLuint id = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
-        "GLuint *params = 0x%0.8p)",
-        id, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetQueryObjectivRobustANGLE(context, id, pname, bufSize, length, params))
-        {
-            return;
-        }
-
-        context->getQueryObjectivRobust(id, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetQueryObjecti64vRobustANGLE(GLuint id,
-                                                            GLenum pname,
-                                                            GLsizei bufSize,
-                                                            GLsizei *length,
-                                                            GLint64 *params)
-{
-    EVENT(
-        "(GLuint id = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
-        "GLint64 *params = 0x%0.8p)",
-        id, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetQueryObjecti64vRobustANGLE(context, id, pname, bufSize, length, params))
-        {
-            return;
-        }
-
-        context->getQueryObjecti64vRobust(id, pname, bufSize, length, params);
-    }
-}
-
-ANGLE_EXPORT void GL_APIENTRY GetQueryObjectui64vRobustANGLE(GLuint id,
-                                                             GLenum pname,
-                                                             GLsizei bufSize,
-                                                             GLsizei *length,
-                                                             GLuint64 *params)
-{
-    EVENT(
-        "(GLuint id = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
-        "GLuint64 *params = 0x%0.8p)",
-        id, pname, bufSize, length, params);
-
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!ValidateGetQueryObjectui64vRobustANGLE(context, id, pname, bufSize, length, params))
-        {
-            return;
-        }
-
-        context->getQueryObjectui64vRobust(id, pname, bufSize, length, params);
-    }
-}
-
-GL_APICALL void GL_APIENTRY FramebufferTextureMultiviewLayeredANGLE(GLenum target,
-                                                                    GLenum attachment,
-                                                                    GLuint texture,
-                                                                    GLint level,
-                                                                    GLint baseViewIndex,
-                                                                    GLsizei numViews)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, "
-        "GLint baseViewIndex = %d, GLsizei numViews = %d)",
-        target, attachment, texture, level, baseViewIndex, numViews);
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidateFramebufferTextureMultiviewLayeredANGLE(context, target, attachment, texture,
-                                                             level, baseViewIndex, numViews))
-        {
-            return;
-        }
-        context->framebufferTextureMultiviewLayered(target, attachment, texture, level,
-                                                    baseViewIndex, numViews);
-    }
-}
-
-GL_APICALL void GL_APIENTRY FramebufferTextureMultiviewSideBySideANGLE(GLenum target,
-                                                                       GLenum attachment,
-                                                                       GLuint texture,
-                                                                       GLint level,
-                                                                       GLsizei numViews,
-                                                                       const GLint *viewportOffsets)
-{
-    EVENT(
-        "(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, "
-        "GLsizei numViews = %d, GLsizei* viewportOffsets = 0x%0.8p)",
-        target, attachment, texture, level, numViews, viewportOffsets);
-    Context *context = GetValidGlobalContext();
-    if (context)
-    {
-        if (!context->skipValidation() &&
-            !ValidateFramebufferTextureMultiviewSideBySideANGLE(
-                context, target, attachment, texture, level, numViews, viewportOffsets))
-        {
-            return;
-        }
-        context->framebufferTextureMultiviewSideBySide(target, attachment, texture, level, numViews,
-                                                       viewportOffsets);
-    }
-}
-
-}  // gl
diff --git a/src/libGLESv2/entry_points_gles_2_0_ext.h b/src/libGLESv2/entry_points_gles_2_0_ext.h
deleted file mode 100644
index 6ce643b..0000000
--- a/src/libGLESv2/entry_points_gles_2_0_ext.h
+++ /dev/null
@@ -1,538 +0,0 @@
-//
-// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// entry_points_gles_2_0_ext.h : Defines the GLES 2.0 extension entry points.
-
-#ifndef LIBGLESV2_ENTRYPOINTGLES20EXT_H_
-#define LIBGLESV2_ENTRYPOINTGLES20EXT_H_
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <export.h>
-
-namespace gl
-{
-
-// GL_CHROMIUM_bind_uniform_location
-ANGLE_EXPORT void GL_APIENTRY BindUniformLocationCHROMIUM(GLuint program,
-                                                          GLint location,
-                                                          const GLchar *name);
-
-// GL_CHROMIUM_framebuffer_mixed_samples
-ANGLE_EXPORT void GL_APIENTRY MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *matrix);
-ANGLE_EXPORT void GL_APIENTRY MatrixLoadIdentityCHROMIUM(GLenum matrixMode);
-
-ANGLE_EXPORT void GL_APIENTRY CoverageModulationCHROMIUM(GLenum components);
-
-// GL_CHROMIUM_path_rendering
-ANGLE_EXPORT GLuint GL_APIENTRY GenPathsCHROMIUM(GLsizei chromium);
-ANGLE_EXPORT void GL_APIENTRY DeletePathsCHROMIUM(GLuint first, GLsizei range);
-ANGLE_EXPORT GLboolean GL_APIENTRY IsPathCHROMIUM(GLuint path);
-ANGLE_EXPORT void GL_APIENTRY PathCommandsCHROMIUM(GLuint path,
-                                                   GLsizei numCommands,
-                                                   const GLubyte *commands,
-                                                   GLsizei numCoords,
-                                                   GLenum coordType,
-                                                   const void *coords);
-ANGLE_EXPORT void GL_APIENTRY PathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value);
-ANGLE_EXPORT void GL_APIENTRY PathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value);
-ANGLE_EXPORT void GL_APIENTRY GetPathParameterfvCHROMIUM(GLuint path, GLenum pname, GLfloat *value);
-ANGLE_EXPORT void GL_APIENTRY GetPathParameterivCHROMIUM(GLuint path, GLenum pname, GLint *value);
-ANGLE_EXPORT void GL_APIENTRY PathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask);
-ANGLE_EXPORT void GL_APIENTRY StencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask);
-ANGLE_EXPORT void GL_APIENTRY StencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask);
-ANGLE_EXPORT void GL_APIENTRY CoverFillPathCHROMIUM(GLuint path, GLenum coverMode);
-ANGLE_EXPORT void GL_APIENTRY CoverStrokePathCHROMIUM(GLuint path, GLenum coverMode);
-ANGLE_EXPORT void GL_APIENTRY StencilThenCoverFillPathCHROMIUM(GLuint path,
-                                                               GLenum fillMode,
-                                                               GLuint mask,
-                                                               GLenum coverMode);
-ANGLE_EXPORT void GL_APIENTRY StencilThenCoverStrokePathCHROMIUM(GLuint path,
-                                                                 GLint reference,
-                                                                 GLuint mask,
-                                                                 GLenum coverMode);
-ANGLE_EXPORT void GL_APIENTRY CoverFillPathInstancedCHROMIUM(GLsizei numPaths,
-                                                             GLenum pathNameType,
-                                                             const void *paths,
-                                                             GLuint pathBase,
-                                                             GLenum coverMode,
-                                                             GLenum transformType,
-                                                             const GLfloat *transformValues);
-ANGLE_EXPORT void GL_APIENTRY CoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
-                                                               GLenum pathNameType,
-                                                               const void *paths,
-                                                               GLuint pathBase,
-                                                               GLenum coverMode,
-                                                               GLenum transformType,
-                                                               const GLfloat *transformValues);
-ANGLE_EXPORT void GL_APIENTRY StencilFillPathInstancedCHROMIUM(GLsizei numPaths,
-                                                               GLenum pathNameType,
-                                                               const void *paths,
-                                                               GLuint pathBAse,
-                                                               GLenum fillMode,
-                                                               GLuint mask,
-                                                               GLenum transformType,
-                                                               const GLfloat *transformValues);
-ANGLE_EXPORT void GL_APIENTRY StencilStrokePathInstancedCHROMIUM(GLsizei numPaths,
-                                                                 GLenum pathNameType,
-                                                                 const void *paths,
-                                                                 GLuint pathBase,
-                                                                 GLint reference,
-                                                                 GLuint mask,
-                                                                 GLenum transformType,
-                                                                 const GLfloat *transformValues);
-ANGLE_EXPORT void GL_APIENTRY
-StencilThenCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
-                                          GLenum pathNameType,
-                                          const void *paths,
-                                          GLuint pathBase,
-                                          GLenum fillMode,
-                                          GLuint mask,
-                                          GLenum coverMode,
-                                          GLenum transformType,
-                                          const GLfloat *transformValues);
-ANGLE_EXPORT void GL_APIENTRY
-StencilThenCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
-                                            GLenum pathNameType,
-                                            const void *paths,
-                                            GLuint pathBase,
-                                            GLint reference,
-                                            GLuint mask,
-                                            GLenum coverMode,
-                                            GLenum transformType,
-                                            const GLfloat *transformValues);
-ANGLE_EXPORT void GL_APIENTRY BindFragmentInputLocationCHROMIUM(GLuint program,
-                                                                GLint location,
-                                                                const GLchar *name);
-ANGLE_EXPORT void GL_APIENTRY ProgramPathFragmentInputGenCHROMIUM(GLuint program,
-                                                                  GLint location,
-                                                                  GLenum genMode,
-                                                                  GLint components,
-                                                                  const GLfloat *coeffs);
-
-// GL_CHROMIUM_copy_texture
-ANGLE_EXPORT void GL_APIENTRY CopyTextureCHROMIUM(GLuint sourceId,
-                                                  GLint sourceLevel,
-                                                  GLenum destTarget,
-                                                  GLuint destId,
-                                                  GLint destLevel,
-                                                  GLint internalFormat,
-                                                  GLenum destType,
-                                                  GLboolean unpackFlipY,
-                                                  GLboolean unpackPremultiplyAlpha,
-                                                  GLboolean unpackUnmultiplyAlpha);
-
-ANGLE_EXPORT void GL_APIENTRY CopySubTextureCHROMIUM(GLuint sourceId,
-                                                     GLint sourceLevel,
-                                                     GLenum destTarget,
-                                                     GLuint destId,
-                                                     GLint destLevel,
-                                                     GLint xoffset,
-                                                     GLint yoffset,
-                                                     GLint x,
-                                                     GLint y,
-                                                     GLsizei width,
-                                                     GLsizei height,
-                                                     GLboolean unpackFlipY,
-                                                     GLboolean unpackPremultiplyAlpha,
-                                                     GLboolean unpackUnmultiplyAlpha);
-
-// GL_CHROMIUM_copy_compressed_texture
-ANGLE_EXPORT void GL_APIENTRY CompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId);
-
-// GL_ANGLE_request_extension
-ANGLE_EXPORT void GL_APIENTRY RequestExtensionANGLE(const GLchar *name);
-
-// GL_ANGLE_robust_client_memory
-ANGLE_EXPORT void GL_APIENTRY GetBooleanvRobustANGLE(GLenum pname,
-                                                     GLsizei bufSize,
-                                                     GLsizei *length,
-                                                     GLboolean *data);
-ANGLE_EXPORT void GL_APIENTRY GetBufferParameterivRobustANGLE(GLenum target,
-                                                              GLenum pname,
-                                                              GLsizei bufSize,
-                                                              GLsizei *length,
-                                                              GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetFloatvRobustANGLE(GLenum pname,
-                                                   GLsizei bufSize,
-                                                   GLsizei *length,
-                                                   GLfloat *data);
-ANGLE_EXPORT void GL_APIENTRY GetFramebufferAttachmentParameterivRobustANGLE(GLenum target,
-                                                                             GLenum attachment,
-                                                                             GLenum pname,
-                                                                             GLsizei bufSize,
-                                                                             GLsizei *length,
-                                                                             GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetIntegervRobustANGLE(GLenum pname,
-                                                     GLsizei bufSize,
-                                                     GLsizei *length,
-                                                     GLint *data);
-ANGLE_EXPORT void GL_APIENTRY GetProgramivRobustANGLE(GLuint program,
-                                                      GLenum pname,
-                                                      GLsizei bufSize,
-                                                      GLsizei *length,
-                                                      GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetRenderbufferParameterivRobustANGLE(GLenum target,
-                                                                    GLenum pname,
-                                                                    GLsizei bufSize,
-                                                                    GLsizei *length,
-                                                                    GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetShaderivRobustANGLE(GLuint shader,
-                                                     GLenum pname,
-                                                     GLsizei bufSize,
-                                                     GLsizei *length,
-                                                     GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetTexParameterfvRobustANGLE(GLenum target,
-                                                           GLenum pname,
-                                                           GLsizei bufSize,
-                                                           GLsizei *length,
-                                                           GLfloat *params);
-ANGLE_EXPORT void GL_APIENTRY GetTexParameterivRobustANGLE(GLenum target,
-                                                           GLenum pname,
-                                                           GLsizei bufSize,
-                                                           GLsizei *length,
-                                                           GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetUniformfvRobustANGLE(GLuint program,
-                                                      GLint location,
-                                                      GLsizei bufSize,
-                                                      GLsizei *length,
-                                                      GLfloat *params);
-ANGLE_EXPORT void GL_APIENTRY GetUniformivRobustANGLE(GLuint program,
-                                                      GLint location,
-                                                      GLsizei bufSize,
-                                                      GLsizei *length,
-                                                      GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetVertexAttribfvRobustANGLE(GLuint index,
-                                                           GLenum pname,
-                                                           GLsizei bufSize,
-                                                           GLsizei *length,
-                                                           GLfloat *params);
-ANGLE_EXPORT void GL_APIENTRY GetVertexAttribivRobustANGLE(GLuint index,
-                                                           GLenum pname,
-                                                           GLsizei bufSize,
-                                                           GLsizei *length,
-                                                           GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetVertexAttribPointervRobustANGLE(GLuint index,
-                                                                 GLenum pname,
-                                                                 GLsizei bufSize,
-                                                                 GLsizei *length,
-                                                                 void **pointer);
-ANGLE_EXPORT void GL_APIENTRY ReadPixelsRobustANGLE(GLint x,
-                                                    GLint y,
-                                                    GLsizei width,
-                                                    GLsizei height,
-                                                    GLenum format,
-                                                    GLenum type,
-                                                    GLsizei bufSize,
-                                                    GLsizei *length,
-                                                    GLsizei *columns,
-                                                    GLsizei *rows,
-                                                    void *pixels);
-ANGLE_EXPORT void GL_APIENTRY TexImage2DRobustANGLE(GLenum target,
-                                                    GLint level,
-                                                    GLint internalformat,
-                                                    GLsizei width,
-                                                    GLsizei height,
-                                                    GLint border,
-                                                    GLenum format,
-                                                    GLenum type,
-                                                    GLsizei bufSize,
-                                                    const void *pixels);
-ANGLE_EXPORT void GL_APIENTRY TexParameterfvRobustANGLE(GLenum target,
-                                                        GLenum pname,
-                                                        GLsizei bufSize,
-                                                        const GLfloat *params);
-ANGLE_EXPORT void GL_APIENTRY TexParameterivRobustANGLE(GLenum target,
-                                                        GLenum pname,
-                                                        GLsizei bufSize,
-                                                        const GLint *params);
-ANGLE_EXPORT void GL_APIENTRY TexSubImage2DRobustANGLE(GLenum target,
-                                                       GLint level,
-                                                       GLint xoffset,
-                                                       GLint yoffset,
-                                                       GLsizei width,
-                                                       GLsizei height,
-                                                       GLenum format,
-                                                       GLenum type,
-                                                       GLsizei bufSize,
-                                                       const void *pixels);
-
-ANGLE_EXPORT void GL_APIENTRY TexImage3DRobustANGLE(GLenum target,
-                                                    GLint level,
-                                                    GLint internalformat,
-                                                    GLsizei width,
-                                                    GLsizei height,
-                                                    GLsizei depth,
-                                                    GLint border,
-                                                    GLenum format,
-                                                    GLenum type,
-                                                    GLsizei bufSize,
-                                                    const void *pixels);
-ANGLE_EXPORT void GL_APIENTRY TexSubImage3DRobustANGLE(GLenum target,
-                                                       GLint level,
-                                                       GLint xoffset,
-                                                       GLint yoffset,
-                                                       GLint zoffset,
-                                                       GLsizei width,
-                                                       GLsizei height,
-                                                       GLsizei depth,
-                                                       GLenum format,
-                                                       GLenum type,
-                                                       GLsizei bufSize,
-                                                       const void *pixels);
-
-ANGLE_EXPORT void GL_APIENTRY CompressedTexImage2DRobustANGLE(GLenum target,
-                                                              GLint level,
-                                                              GLenum internalformat,
-                                                              GLsizei width,
-                                                              GLsizei height,
-                                                              GLint border,
-                                                              GLsizei imageSize,
-                                                              GLsizei dataSize,
-                                                              const GLvoid *data);
-ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage2DRobustANGLE(GLenum target,
-                                                                 GLint level,
-                                                                 GLint xoffset,
-                                                                 GLint yoffset,
-                                                                 GLsizei width,
-                                                                 GLsizei height,
-                                                                 GLenum format,
-                                                                 GLsizei imageSize,
-                                                                 GLsizei dataSize,
-                                                                 const GLvoid *data);
-ANGLE_EXPORT void GL_APIENTRY CompressedTexImage3DRobustANGLE(GLenum target,
-                                                              GLint level,
-                                                              GLenum internalformat,
-                                                              GLsizei width,
-                                                              GLsizei height,
-                                                              GLsizei depth,
-                                                              GLint border,
-                                                              GLsizei imageSize,
-                                                              GLsizei dataSize,
-                                                              const GLvoid *data);
-ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage3DRobustANGLE(GLenum target,
-                                                                 GLint level,
-                                                                 GLint xoffset,
-                                                                 GLint yoffset,
-                                                                 GLint zoffset,
-                                                                 GLsizei width,
-                                                                 GLsizei height,
-                                                                 GLsizei depth,
-                                                                 GLenum format,
-                                                                 GLsizei imageSize,
-                                                                 GLsizei dataSize,
-                                                                 const GLvoid *data);
-
-ANGLE_EXPORT void GL_APIENTRY
-GetQueryivRobustANGLE(GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetQueryObjectuivRobustANGLE(GLuint id,
-                                                           GLenum pname,
-                                                           GLsizei bufSize,
-                                                           GLsizei *length,
-                                                           GLuint *params);
-ANGLE_EXPORT void GL_APIENTRY GetBufferPointervRobustANGLE(GLenum target,
-                                                           GLenum pname,
-                                                           GLsizei bufSize,
-                                                           GLsizei *length,
-                                                           void **params);
-ANGLE_EXPORT void GL_APIENTRY GetIntegeri_vRobustANGLE(GLenum target,
-                                                       GLuint index,
-                                                       GLsizei bufSize,
-                                                       GLsizei *length,
-                                                       GLint *data);
-ANGLE_EXPORT void GL_APIENTRY GetInternalformativRobustANGLE(GLenum target,
-                                                             GLenum internalformat,
-                                                             GLenum pname,
-                                                             GLsizei bufSize,
-                                                             GLsizei *length,
-                                                             GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIivRobustANGLE(GLuint index,
-                                                            GLenum pname,
-                                                            GLsizei bufSize,
-                                                            GLsizei *length,
-                                                            GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIuivRobustANGLE(GLuint index,
-                                                             GLenum pname,
-                                                             GLsizei bufSize,
-                                                             GLsizei *length,
-                                                             GLuint *params);
-ANGLE_EXPORT void GL_APIENTRY GetUniformuivRobustANGLE(GLuint program,
-                                                       GLint location,
-                                                       GLsizei bufSize,
-                                                       GLsizei *length,
-                                                       GLuint *params);
-ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockivRobustANGLE(GLuint program,
-                                                                 GLuint uniformBlockIndex,
-                                                                 GLenum pname,
-                                                                 GLsizei bufSize,
-                                                                 GLsizei *length,
-                                                                 GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetInteger64vRobustANGLE(GLenum pname,
-                                                       GLsizei bufSize,
-                                                       GLsizei *length,
-                                                       GLint64 *data);
-ANGLE_EXPORT void GL_APIENTRY GetInteger64i_vRobustANGLE(GLenum target,
-                                                         GLuint index,
-                                                         GLsizei bufSize,
-                                                         GLsizei *length,
-                                                         GLint64 *data);
-ANGLE_EXPORT void GL_APIENTRY GetBufferParameteri64vRobustANGLE(GLenum target,
-                                                                GLenum pname,
-                                                                GLsizei bufSize,
-                                                                GLsizei *length,
-                                                                GLint64 *params);
-ANGLE_EXPORT void GL_APIENTRY SamplerParameterivRobustANGLE(GLuint sampler,
-                                                            GLenum pname,
-                                                            GLsizei bufSize,
-                                                            const GLint *param);
-ANGLE_EXPORT void GL_APIENTRY SamplerParameterfvRobustANGLE(GLuint sampler,
-                                                            GLenum pname,
-                                                            GLsizei bufSize,
-                                                            const GLfloat *param);
-ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterivRobustANGLE(GLuint sampler,
-                                                               GLenum pname,
-                                                               GLsizei bufSize,
-                                                               GLsizei *length,
-                                                               GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterfvRobustANGLE(GLuint sampler,
-                                                               GLenum pname,
-                                                               GLsizei bufSize,
-                                                               GLsizei *length,
-                                                               GLfloat *params);
-
-ANGLE_EXPORT void GL_APIENTRY GetFramebufferParameterivRobustANGLE(GLenum target,
-                                                                   GLenum pname,
-                                                                   GLsizei bufSize,
-                                                                   GLsizei *length,
-                                                                   GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetProgramInterfaceivRobustANGLE(GLuint program,
-                                                               GLenum programInterface,
-                                                               GLenum pname,
-                                                               GLsizei bufSize,
-                                                               GLsizei *length,
-                                                               GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetBooleani_vRobustANGLE(GLenum target,
-                                                       GLuint index,
-                                                       GLsizei bufSize,
-                                                       GLsizei *length,
-                                                       GLboolean *data);
-ANGLE_EXPORT void GL_APIENTRY GetMultisamplefvRobustANGLE(GLenum pname,
-                                                          GLuint index,
-                                                          GLsizei bufSize,
-                                                          GLsizei *length,
-                                                          GLfloat *val);
-ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameterivRobustANGLE(GLenum target,
-                                                                GLint level,
-                                                                GLenum pname,
-                                                                GLsizei bufSize,
-                                                                GLsizei *length,
-                                                                GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameterfvRobustANGLE(GLenum target,
-                                                                GLint level,
-                                                                GLenum pname,
-                                                                GLsizei bufSize,
-                                                                GLsizei *length,
-                                                                GLfloat *params);
-
-ANGLE_EXPORT void GL_APIENTRY GetPointervRobustANGLERobustANGLE(GLenum pname,
-                                                                GLsizei bufSize,
-                                                                GLsizei *length,
-                                                                void **params);
-ANGLE_EXPORT void GL_APIENTRY ReadnPixelsRobustANGLE(GLint x,
-                                                     GLint y,
-                                                     GLsizei width,
-                                                     GLsizei height,
-                                                     GLenum format,
-                                                     GLenum type,
-                                                     GLsizei bufSize,
-                                                     GLsizei *length,
-                                                     GLsizei *columns,
-                                                     GLsizei *rows,
-                                                     void *data);
-ANGLE_EXPORT void GL_APIENTRY GetnUniformfvRobustANGLE(GLuint program,
-                                                       GLint location,
-                                                       GLsizei bufSize,
-                                                       GLsizei *length,
-                                                       GLfloat *params);
-ANGLE_EXPORT void GL_APIENTRY GetnUniformivRobustANGLE(GLuint program,
-                                                       GLint location,
-                                                       GLsizei bufSize,
-                                                       GLsizei *length,
-                                                       GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetnUniformuivRobustANGLE(GLuint program,
-                                                        GLint location,
-                                                        GLsizei bufSize,
-                                                        GLsizei *length,
-                                                        GLuint *params);
-ANGLE_EXPORT void GL_APIENTRY TexParameterIivRobustANGLE(GLenum target,
-                                                         GLenum pname,
-                                                         GLsizei bufSize,
-                                                         const GLint *params);
-ANGLE_EXPORT void GL_APIENTRY TexParameterIuivRobustANGLE(GLenum target,
-                                                          GLenum pname,
-                                                          GLsizei bufSize,
-                                                          const GLuint *params);
-ANGLE_EXPORT void GL_APIENTRY GetTexParameterIivRobustANGLE(GLenum target,
-                                                            GLenum pname,
-                                                            GLsizei bufSize,
-                                                            GLsizei *length,
-                                                            GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetTexParameterIuivRobustANGLE(GLenum target,
-                                                             GLenum pname,
-                                                             GLsizei bufSize,
-                                                             GLsizei *length,
-                                                             GLuint *params);
-ANGLE_EXPORT void GL_APIENTRY SamplerParameterIivRobustANGLE(GLuint sampler,
-                                                             GLenum pname,
-                                                             GLsizei bufSize,
-                                                             const GLint *param);
-ANGLE_EXPORT void GL_APIENTRY SamplerParameterIuivRobustANGLE(GLuint sampler,
-                                                              GLenum pname,
-                                                              GLsizei bufSize,
-                                                              const GLuint *param);
-ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterIivRobustANGLE(GLuint sampler,
-                                                                GLenum pname,
-                                                                GLsizei bufSize,
-                                                                GLsizei *length,
-                                                                GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterIuivRobustANGLE(GLuint sampler,
-                                                                 GLenum pname,
-                                                                 GLsizei bufSize,
-                                                                 GLsizei *length,
-                                                                 GLuint *params);
-ANGLE_EXPORT void GL_APIENTRY GetQueryObjectivRobustANGLE(GLuint id,
-                                                          GLenum pname,
-                                                          GLsizei bufSize,
-                                                          GLsizei *length,
-                                                          GLint *params);
-ANGLE_EXPORT void GL_APIENTRY GetQueryObjecti64vRobustANGLE(GLuint id,
-                                                            GLenum pname,
-                                                            GLsizei bufSize,
-                                                            GLsizei *length,
-                                                            GLint64 *params);
-ANGLE_EXPORT void GL_APIENTRY GetQueryObjectui64vRobustANGLE(GLuint id,
-                                                             GLenum pname,
-                                                             GLsizei bufSize,
-                                                             GLsizei *length,
-                                                             GLuint64 *params);
-
-// GL_ANGLE_multiview
-ANGLE_EXPORT void GL_APIENTRY FramebufferTextureMultiviewLayeredANGLE(GLenum target,
-                                                                      GLenum attachment,
-                                                                      GLuint texture,
-                                                                      GLint level,
-                                                                      GLint baseViewIndex,
-                                                                      GLsizei numViews);
-ANGLE_EXPORT void GL_APIENTRY
-FramebufferTextureMultiviewSideBySideANGLE(GLenum target,
-                                           GLenum attachment,
-                                           GLuint texture,
-                                           GLint level,
-                                           GLsizei numViews,
-                                           const GLint *viewportOffsets);
-}  // namespace gl
-
-#endif  // LIBGLESV2_ENTRYPOINTGLES20EXT_H_
diff --git a/src/libGLESv2/entry_points_gles_ext_autogen.cpp b/src/libGLESv2/entry_points_gles_ext_autogen.cpp
index ba240dd..69f4e6c 100644
--- a/src/libGLESv2/entry_points_gles_ext_autogen.cpp
+++ b/src/libGLESv2/entry_points_gles_ext_autogen.cpp
@@ -1,5 +1,5 @@
 // GENERATED FILE - DO NOT EDIT.
-// Generated by generate_entry_points.py using data from gl.xml.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
 //
 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
@@ -146,6 +146,1788 @@
     }
 }
 
+// GL_ANGLE_multiview
+void GL_APIENTRY FramebufferTextureMultiviewLayeredANGLE(GLenum target,
+                                                         GLenum attachment,
+                                                         GLuint texture,
+                                                         GLint level,
+                                                         GLint baseViewIndex,
+                                                         GLsizei numViews)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, "
+        "GLint baseViewIndex = %d, GLsizei numViews = %d)",
+        target, attachment, texture, level, baseViewIndex, numViews);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::FramebufferTextureMultiviewLayeredANGLE>(
+            target, attachment, texture, level, baseViewIndex, numViews);
+
+        if (context->skipValidation() ||
+            ValidateFramebufferTextureMultiviewLayeredANGLE(context, target, attachment, texture,
+                                                            level, baseViewIndex, numViews))
+        {
+            context->framebufferTextureMultiviewLayered(target, attachment, texture, level,
+                                                        baseViewIndex, numViews);
+        }
+    }
+}
+
+void GL_APIENTRY FramebufferTextureMultiviewSideBySideANGLE(GLenum target,
+                                                            GLenum attachment,
+                                                            GLuint texture,
+                                                            GLint level,
+                                                            GLsizei numViews,
+                                                            const GLint *viewportOffsets)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, "
+        "GLsizei numViews = %d, const GLint * viewportOffsets = 0x%0.8p)",
+        target, attachment, texture, level, numViews, viewportOffsets);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::FramebufferTextureMultiviewSideBySideANGLE>(
+            target, attachment, texture, level, numViews, viewportOffsets);
+
+        if (context->skipValidation() ||
+            ValidateFramebufferTextureMultiviewSideBySideANGLE(context, target, attachment, texture,
+                                                               level, numViews, viewportOffsets))
+        {
+            context->framebufferTextureMultiviewSideBySide(target, attachment, texture, level,
+                                                           numViews, viewportOffsets);
+        }
+    }
+}
+
+// GL_ANGLE_request_extension
+void GL_APIENTRY RequestExtensionANGLE(const GLchar *name)
+{
+    EVENT("(const GLchar * name = 0x%0.8p)", name);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::RequestExtensionANGLE>(name);
+
+        if (context->skipValidation() || ValidateRequestExtensionANGLE(context, name))
+        {
+            context->requestExtension(name);
+        }
+    }
+}
+
+// GL_ANGLE_robust_client_memory
+void GL_APIENTRY GetBooleanvRobustANGLE(GLenum pname,
+                                        GLsizei bufSize,
+                                        GLsizei *length,
+                                        GLboolean *params)
+{
+    EVENT(
+        "(GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = 0x%0.8p, GLboolean * "
+        "params = 0x%0.8p)",
+        pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetBooleanvRobustANGLE>(pname, bufSize, length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetBooleanvRobustANGLE(context, pname, bufSize, length, params))
+        {
+            context->getBooleanvRobust(pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetBufferParameterivRobustANGLE(GLenum target,
+                                                 GLenum pname,
+                                                 GLsizei bufSize,
+                                                 GLsizei *length,
+                                                 GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLint * params = 0x%0.8p)",
+        target, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
+        context->gatherParams<EntryPoint::GetBufferParameterivRobustANGLE>(targetPacked, pname,
+                                                                           bufSize, length, params);
+
+        if (context->skipValidation() || ValidateGetBufferParameterivRobustANGLE(
+                                             context, targetPacked, pname, bufSize, length, params))
+        {
+            context->getBufferParameterivRobust(targetPacked, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetFloatvRobustANGLE(GLenum pname,
+                                      GLsizei bufSize,
+                                      GLsizei *length,
+                                      GLfloat *params)
+{
+    EVENT(
+        "(GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = 0x%0.8p, GLfloat * params "
+        "= 0x%0.8p)",
+        pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetFloatvRobustANGLE>(pname, bufSize, length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetFloatvRobustANGLE(context, pname, bufSize, length, params))
+        {
+            context->getFloatvRobust(pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetFramebufferAttachmentParameterivRobustANGLE(GLenum target,
+                                                                GLenum attachment,
+                                                                GLenum pname,
+                                                                GLsizei bufSize,
+                                                                GLsizei *length,
+                                                                GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = "
+        "%d, GLsizei * length = 0x%0.8p, GLint * params = 0x%0.8p)",
+        target, attachment, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetFramebufferAttachmentParameterivRobustANGLE>(
+            target, attachment, pname, bufSize, length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetFramebufferAttachmentParameterivRobustANGLE(context, target, attachment,
+                                                                   pname, bufSize, length, params))
+        {
+            context->getFramebufferAttachmentParameterivRobust(target, attachment, pname, bufSize,
+                                                               length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetIntegervRobustANGLE(GLenum pname, GLsizei bufSize, GLsizei *length, GLint *data)
+{
+    EVENT(
+        "(GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = 0x%0.8p, GLint * data = "
+        "0x%0.8p)",
+        pname, bufSize, length, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetIntegervRobustANGLE>(pname, bufSize, length, data);
+
+        if (context->skipValidation() ||
+            ValidateGetIntegervRobustANGLE(context, pname, bufSize, length, data))
+        {
+            context->getIntegervRobust(pname, bufSize, length, data);
+        }
+    }
+}
+
+void GL_APIENTRY GetProgramivRobustANGLE(GLuint program,
+                                         GLenum pname,
+                                         GLsizei bufSize,
+                                         GLsizei *length,
+                                         GLint *params)
+{
+    EVENT(
+        "(GLuint program = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLint * params = 0x%0.8p)",
+        program, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetProgramivRobustANGLE>(program, pname, bufSize, length,
+                                                                   params);
+
+        if (context->skipValidation() ||
+            ValidateGetProgramivRobustANGLE(context, program, pname, bufSize, length, params))
+        {
+            context->getProgramivRobust(program, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetRenderbufferParameterivRobustANGLE(GLenum target,
+                                                       GLenum pname,
+                                                       GLsizei bufSize,
+                                                       GLsizei *length,
+                                                       GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLint * params = 0x%0.8p)",
+        target, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetRenderbufferParameterivRobustANGLE>(
+            target, pname, bufSize, length, params);
+
+        if (context->skipValidation() || ValidateGetRenderbufferParameterivRobustANGLE(
+                                             context, target, pname, bufSize, length, params))
+        {
+            context->getRenderbufferParameterivRobust(target, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY
+GetShaderivRobustANGLE(GLuint shader, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params)
+{
+    EVENT(
+        "(GLuint shader = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLint * params = 0x%0.8p)",
+        shader, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetShaderivRobustANGLE>(shader, pname, bufSize, length,
+                                                                  params);
+
+        if (context->skipValidation() ||
+            ValidateGetShaderivRobustANGLE(context, shader, pname, bufSize, length, params))
+        {
+            context->getShaderivRobust(shader, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetTexParameterfvRobustANGLE(GLenum target,
+                                              GLenum pname,
+                                              GLsizei bufSize,
+                                              GLsizei *length,
+                                              GLfloat *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLfloat * params = 0x%0.8p)",
+        target, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureType targetPacked = FromGLenum<TextureType>(target);
+        context->gatherParams<EntryPoint::GetTexParameterfvRobustANGLE>(targetPacked, pname,
+                                                                        bufSize, length, params);
+
+        if (context->skipValidation() || ValidateGetTexParameterfvRobustANGLE(
+                                             context, targetPacked, pname, bufSize, length, params))
+        {
+            context->getTexParameterfvRobust(targetPacked, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetTexParameterivRobustANGLE(GLenum target,
+                                              GLenum pname,
+                                              GLsizei bufSize,
+                                              GLsizei *length,
+                                              GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLint * params = 0x%0.8p)",
+        target, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureType targetPacked = FromGLenum<TextureType>(target);
+        context->gatherParams<EntryPoint::GetTexParameterivRobustANGLE>(targetPacked, pname,
+                                                                        bufSize, length, params);
+
+        if (context->skipValidation() || ValidateGetTexParameterivRobustANGLE(
+                                             context, targetPacked, pname, bufSize, length, params))
+        {
+            context->getTexParameterivRobust(targetPacked, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetUniformfvRobustANGLE(GLuint program,
+                                         GLint location,
+                                         GLsizei bufSize,
+                                         GLsizei *length,
+                                         GLfloat *params)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLfloat * params = 0x%0.8p)",
+        program, location, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetUniformfvRobustANGLE>(program, location, bufSize,
+                                                                   length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetUniformfvRobustANGLE(context, program, location, bufSize, length, params))
+        {
+            context->getUniformfvRobust(program, location, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetUniformivRobustANGLE(GLuint program,
+                                         GLint location,
+                                         GLsizei bufSize,
+                                         GLsizei *length,
+                                         GLint *params)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLint * params = 0x%0.8p)",
+        program, location, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetUniformivRobustANGLE>(program, location, bufSize,
+                                                                   length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetUniformivRobustANGLE(context, program, location, bufSize, length, params))
+        {
+            context->getUniformivRobust(program, location, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetVertexAttribfvRobustANGLE(GLuint index,
+                                              GLenum pname,
+                                              GLsizei bufSize,
+                                              GLsizei *length,
+                                              GLfloat *params)
+{
+    EVENT(
+        "(GLuint index = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLfloat * params = 0x%0.8p)",
+        index, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetVertexAttribfvRobustANGLE>(index, pname, bufSize,
+                                                                        length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetVertexAttribfvRobustANGLE(context, index, pname, bufSize, length, params))
+        {
+            context->getVertexAttribfvRobust(index, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetVertexAttribivRobustANGLE(GLuint index,
+                                              GLenum pname,
+                                              GLsizei bufSize,
+                                              GLsizei *length,
+                                              GLint *params)
+{
+    EVENT(
+        "(GLuint index = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLint * params = 0x%0.8p)",
+        index, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetVertexAttribivRobustANGLE>(index, pname, bufSize,
+                                                                        length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetVertexAttribivRobustANGLE(context, index, pname, bufSize, length, params))
+        {
+            context->getVertexAttribivRobust(index, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetVertexAttribPointervRobustANGLE(GLuint index,
+                                                    GLenum pname,
+                                                    GLsizei bufSize,
+                                                    GLsizei *length,
+                                                    void **pointer)
+{
+    EVENT(
+        "(GLuint index = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, void ** pointer = 0x%0.8p)",
+        index, pname, bufSize, length, pointer);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetVertexAttribPointervRobustANGLE>(index, pname, bufSize,
+                                                                              length, pointer);
+
+        if (context->skipValidation() || ValidateGetVertexAttribPointervRobustANGLE(
+                                             context, index, pname, bufSize, length, pointer))
+        {
+            context->getVertexAttribPointervRobust(index, pname, bufSize, length, pointer);
+        }
+    }
+}
+
+void GL_APIENTRY ReadPixelsRobustANGLE(GLint x,
+                                       GLint y,
+                                       GLsizei width,
+                                       GLsizei height,
+                                       GLenum format,
+                                       GLenum type,
+                                       GLsizei bufSize,
+                                       GLsizei *length,
+                                       GLsizei *columns,
+                                       GLsizei *rows,
+                                       void *pixels)
+{
+    EVENT(
+        "(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLenum format = "
+        "0x%X, GLenum type = 0x%X, GLsizei bufSize = %d, GLsizei * length = 0x%0.8p, GLsizei * "
+        "columns = 0x%0.8p, GLsizei * rows = 0x%0.8p, void * pixels = 0x%0.8p)",
+        x, y, width, height, format, type, bufSize, length, columns, rows, pixels);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::ReadPixelsRobustANGLE>(
+            x, y, width, height, format, type, bufSize, length, columns, rows, pixels);
+
+        if (context->skipValidation() ||
+            ValidateReadPixelsRobustANGLE(context, x, y, width, height, format, type, bufSize,
+                                          length, columns, rows, pixels))
+        {
+            context->readPixelsRobust(x, y, width, height, format, type, bufSize, length, columns,
+                                      rows, pixels);
+        }
+    }
+}
+
+void GL_APIENTRY TexImage2DRobustANGLE(GLenum target,
+                                       GLint level,
+                                       GLint internalformat,
+                                       GLsizei width,
+                                       GLsizei height,
+                                       GLint border,
+                                       GLenum format,
+                                       GLenum type,
+                                       GLsizei bufSize,
+                                       const void *pixels)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
+        "GLsizei height = %d, GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, GLsizei "
+        "bufSize = %d, const void * pixels = 0x%0.8p)",
+        target, level, internalformat, width, height, border, format, type, bufSize, pixels);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureTarget targetPacked = FromGLenum<TextureTarget>(target);
+        context->gatherParams<EntryPoint::TexImage2DRobustANGLE>(
+            targetPacked, level, internalformat, width, height, border, format, type, bufSize,
+            pixels);
+
+        if (context->skipValidation() ||
+            ValidateTexImage2DRobustANGLE(context, targetPacked, level, internalformat, width,
+                                          height, border, format, type, bufSize, pixels))
+        {
+            context->texImage2DRobust(targetPacked, level, internalformat, width, height, border,
+                                      format, type, bufSize, pixels);
+        }
+    }
+}
+
+void GL_APIENTRY TexParameterfvRobustANGLE(GLenum target,
+                                           GLenum pname,
+                                           GLsizei bufSize,
+                                           const GLfloat *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, const GLfloat * params "
+        "= 0x%0.8p)",
+        target, pname, bufSize, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureType targetPacked = FromGLenum<TextureType>(target);
+        context->gatherParams<EntryPoint::TexParameterfvRobustANGLE>(targetPacked, pname, bufSize,
+                                                                     params);
+
+        if (context->skipValidation() ||
+            ValidateTexParameterfvRobustANGLE(context, targetPacked, pname, bufSize, params))
+        {
+            context->texParameterfvRobust(targetPacked, pname, bufSize, params);
+        }
+    }
+}
+
+void GL_APIENTRY TexParameterivRobustANGLE(GLenum target,
+                                           GLenum pname,
+                                           GLsizei bufSize,
+                                           const GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, const GLint * params = "
+        "0x%0.8p)",
+        target, pname, bufSize, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureType targetPacked = FromGLenum<TextureType>(target);
+        context->gatherParams<EntryPoint::TexParameterivRobustANGLE>(targetPacked, pname, bufSize,
+                                                                     params);
+
+        if (context->skipValidation() ||
+            ValidateTexParameterivRobustANGLE(context, targetPacked, pname, bufSize, params))
+        {
+            context->texParameterivRobust(targetPacked, pname, bufSize, params);
+        }
+    }
+}
+
+void GL_APIENTRY TexSubImage2DRobustANGLE(GLenum target,
+                                          GLint level,
+                                          GLint xoffset,
+                                          GLint yoffset,
+                                          GLsizei width,
+                                          GLsizei height,
+                                          GLenum format,
+                                          GLenum type,
+                                          GLsizei bufSize,
+                                          const void *pixels)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, GLsizei "
+        "width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, GLsizei "
+        "bufSize = %d, const void * pixels = 0x%0.8p)",
+        target, level, xoffset, yoffset, width, height, format, type, bufSize, pixels);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureTarget targetPacked = FromGLenum<TextureTarget>(target);
+        context->gatherParams<EntryPoint::TexSubImage2DRobustANGLE>(
+            targetPacked, level, xoffset, yoffset, width, height, format, type, bufSize, pixels);
+
+        if (context->skipValidation() ||
+            ValidateTexSubImage2DRobustANGLE(context, targetPacked, level, xoffset, yoffset, width,
+                                             height, format, type, bufSize, pixels))
+        {
+            context->texSubImage2DRobust(targetPacked, level, xoffset, yoffset, width, height,
+                                         format, type, bufSize, pixels);
+        }
+    }
+}
+
+void GL_APIENTRY TexImage3DRobustANGLE(GLenum target,
+                                       GLint level,
+                                       GLint internalformat,
+                                       GLsizei width,
+                                       GLsizei height,
+                                       GLsizei depth,
+                                       GLint border,
+                                       GLenum format,
+                                       GLenum type,
+                                       GLsizei bufSize,
+                                       const void *pixels)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
+        "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, GLenum "
+        "type = 0x%X, GLsizei bufSize = %d, const void * pixels = 0x%0.8p)",
+        target, level, internalformat, width, height, depth, border, format, type, bufSize, pixels);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureType targetPacked = FromGLenum<TextureType>(target);
+        context->gatherParams<EntryPoint::TexImage3DRobustANGLE>(
+            targetPacked, level, internalformat, width, height, depth, border, format, type,
+            bufSize, pixels);
+
+        if (context->skipValidation() ||
+            ValidateTexImage3DRobustANGLE(context, targetPacked, level, internalformat, width,
+                                          height, depth, border, format, type, bufSize, pixels))
+        {
+            context->texImage3DRobust(targetPacked, level, internalformat, width, height, depth,
+                                      border, format, type, bufSize, pixels);
+        }
+    }
+}
+
+void GL_APIENTRY TexSubImage3DRobustANGLE(GLenum target,
+                                          GLint level,
+                                          GLint xoffset,
+                                          GLint yoffset,
+                                          GLint zoffset,
+                                          GLsizei width,
+                                          GLsizei height,
+                                          GLsizei depth,
+                                          GLenum format,
+                                          GLenum type,
+                                          GLsizei bufSize,
+                                          const void *pixels)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, GLint "
+        "zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLenum format "
+        "= 0x%X, GLenum type = 0x%X, GLsizei bufSize = %d, const void * pixels = 0x%0.8p)",
+        target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, bufSize,
+        pixels);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureType targetPacked = FromGLenum<TextureType>(target);
+        context->gatherParams<EntryPoint::TexSubImage3DRobustANGLE>(
+            targetPacked, level, xoffset, yoffset, zoffset, width, height, depth, format, type,
+            bufSize, pixels);
+
+        if (context->skipValidation() ||
+            ValidateTexSubImage3DRobustANGLE(context, targetPacked, level, xoffset, yoffset,
+                                             zoffset, width, height, depth, format, type, bufSize,
+                                             pixels))
+        {
+            context->texSubImage3DRobust(targetPacked, level, xoffset, yoffset, zoffset, width,
+                                         height, depth, format, type, bufSize, pixels);
+        }
+    }
+}
+
+void GL_APIENTRY CompressedTexImage2DRobustANGLE(GLenum target,
+                                                 GLint level,
+                                                 GLenum internalformat,
+                                                 GLsizei width,
+                                                 GLsizei height,
+                                                 GLint border,
+                                                 GLsizei imageSize,
+                                                 GLsizei dataSize,
+                                                 const GLvoid *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = "
+        "%d, GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, GLsizei dataSize = "
+        "%d, const GLvoid * data = 0x%0.8p)",
+        target, level, internalformat, width, height, border, imageSize, dataSize, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureTarget targetPacked = FromGLenum<TextureTarget>(target);
+        context->gatherParams<EntryPoint::CompressedTexImage2DRobustANGLE>(
+            targetPacked, level, internalformat, width, height, border, imageSize, dataSize, data);
+
+        if (context->skipValidation() || ValidateCompressedTexImage2DRobustANGLE(
+                                             context, targetPacked, level, internalformat, width,
+                                             height, border, imageSize, dataSize, data))
+        {
+            context->compressedTexImage2DRobust(targetPacked, level, internalformat, width, height,
+                                                border, imageSize, dataSize, data);
+        }
+    }
+}
+
+void GL_APIENTRY CompressedTexSubImage2DRobustANGLE(GLenum target,
+                                                    GLint level,
+                                                    GLsizei xoffset,
+                                                    GLsizei yoffset,
+                                                    GLsizei width,
+                                                    GLsizei height,
+                                                    GLenum format,
+                                                    GLsizei imageSize,
+                                                    GLsizei dataSize,
+                                                    const GLvoid *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLsizei xoffset = %d, GLsizei yoffset = %d, "
+        "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLsizei imageSize = %d, "
+        "GLsizei dataSize = %d, const GLvoid * data = 0x%0.8p)",
+        target, level, xoffset, yoffset, width, height, format, imageSize, dataSize, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureTarget targetPacked = FromGLenum<TextureTarget>(target);
+        context->gatherParams<EntryPoint::CompressedTexSubImage2DRobustANGLE>(
+            targetPacked, level, xoffset, yoffset, width, height, format, imageSize, dataSize,
+            data);
+
+        if (context->skipValidation() || ValidateCompressedTexSubImage2DRobustANGLE(
+                                             context, targetPacked, level, xoffset, yoffset, width,
+                                             height, format, imageSize, dataSize, data))
+        {
+            context->compressedTexSubImage2DRobust(targetPacked, level, xoffset, yoffset, width,
+                                                   height, format, imageSize, dataSize, data);
+        }
+    }
+}
+
+void GL_APIENTRY CompressedTexImage3DRobustANGLE(GLenum target,
+                                                 GLint level,
+                                                 GLenum internalformat,
+                                                 GLsizei width,
+                                                 GLsizei height,
+                                                 GLsizei depth,
+                                                 GLint border,
+                                                 GLsizei imageSize,
+                                                 GLsizei dataSize,
+                                                 const GLvoid *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = "
+        "%d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, "
+        "GLsizei dataSize = %d, const GLvoid * data = 0x%0.8p)",
+        target, level, internalformat, width, height, depth, border, imageSize, dataSize, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureType targetPacked = FromGLenum<TextureType>(target);
+        context->gatherParams<EntryPoint::CompressedTexImage3DRobustANGLE>(
+            targetPacked, level, internalformat, width, height, depth, border, imageSize, dataSize,
+            data);
+
+        if (context->skipValidation() || ValidateCompressedTexImage3DRobustANGLE(
+                                             context, targetPacked, level, internalformat, width,
+                                             height, depth, border, imageSize, dataSize, data))
+        {
+            context->compressedTexImage3DRobust(targetPacked, level, internalformat, width, height,
+                                                depth, border, imageSize, dataSize, data);
+        }
+    }
+}
+
+void GL_APIENTRY CompressedTexSubImage3DRobustANGLE(GLenum target,
+                                                    GLint level,
+                                                    GLint xoffset,
+                                                    GLint yoffset,
+                                                    GLint zoffset,
+                                                    GLsizei width,
+                                                    GLsizei height,
+                                                    GLsizei depth,
+                                                    GLenum format,
+                                                    GLsizei imageSize,
+                                                    GLsizei dataSize,
+                                                    const GLvoid *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, GLint "
+        "zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLenum format "
+        "= 0x%X, GLsizei imageSize = %d, GLsizei dataSize = %d, const GLvoid * data = 0x%0.8p)",
+        target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, dataSize,
+        data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureType targetPacked = FromGLenum<TextureType>(target);
+        context->gatherParams<EntryPoint::CompressedTexSubImage3DRobustANGLE>(
+            targetPacked, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize,
+            dataSize, data);
+
+        if (context->skipValidation() ||
+            ValidateCompressedTexSubImage3DRobustANGLE(context, targetPacked, level, xoffset,
+                                                       yoffset, zoffset, width, height, depth,
+                                                       format, imageSize, dataSize, data))
+        {
+            context->compressedTexSubImage3DRobust(targetPacked, level, xoffset, yoffset, zoffset,
+                                                   width, height, depth, format, imageSize,
+                                                   dataSize, data);
+        }
+    }
+}
+
+void GL_APIENTRY
+GetQueryivRobustANGLE(GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLint * params = 0x%0.8p)",
+        target, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetQueryivRobustANGLE>(target, pname, bufSize, length,
+                                                                 params);
+
+        if (context->skipValidation() ||
+            ValidateGetQueryivRobustANGLE(context, target, pname, bufSize, length, params))
+        {
+            context->getQueryivRobust(target, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetQueryObjectuivRobustANGLE(GLuint id,
+                                              GLenum pname,
+                                              GLsizei bufSize,
+                                              GLsizei *length,
+                                              GLuint *params)
+{
+    EVENT(
+        "(GLuint id = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = 0x%0.8p, "
+        "GLuint * params = 0x%0.8p)",
+        id, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetQueryObjectuivRobustANGLE>(id, pname, bufSize, length,
+                                                                        params);
+
+        if (context->skipValidation() ||
+            ValidateGetQueryObjectuivRobustANGLE(context, id, pname, bufSize, length, params))
+        {
+            context->getQueryObjectuivRobust(id, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetBufferPointervRobustANGLE(GLenum target,
+                                              GLenum pname,
+                                              GLsizei bufSize,
+                                              GLsizei *length,
+                                              void **params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, void ** params = 0x%0.8p)",
+        target, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
+        context->gatherParams<EntryPoint::GetBufferPointervRobustANGLE>(targetPacked, pname,
+                                                                        bufSize, length, params);
+
+        if (context->skipValidation() || ValidateGetBufferPointervRobustANGLE(
+                                             context, targetPacked, pname, bufSize, length, params))
+        {
+            context->getBufferPointervRobust(targetPacked, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY
+GetIntegeri_vRobustANGLE(GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLint *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLuint index = %u, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLint * data = 0x%0.8p)",
+        target, index, bufSize, length, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetIntegeri_vRobustANGLE>(target, index, bufSize, length,
+                                                                    data);
+
+        if (context->skipValidation() ||
+            ValidateGetIntegeri_vRobustANGLE(context, target, index, bufSize, length, data))
+        {
+            context->getIntegeri_vRobust(target, index, bufSize, length, data);
+        }
+    }
+}
+
+void GL_APIENTRY GetInternalformativRobustANGLE(GLenum target,
+                                                GLenum internalformat,
+                                                GLenum pname,
+                                                GLsizei bufSize,
+                                                GLsizei *length,
+                                                GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize "
+        "= %d, GLsizei * length = 0x%0.8p, GLint * params = 0x%0.8p)",
+        target, internalformat, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetInternalformativRobustANGLE>(
+            target, internalformat, pname, bufSize, length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetInternalformativRobustANGLE(context, target, internalformat, pname, bufSize,
+                                                   length, params))
+        {
+            context->getInternalformativRobust(target, internalformat, pname, bufSize, length,
+                                               params);
+        }
+    }
+}
+
+void GL_APIENTRY GetVertexAttribIivRobustANGLE(GLuint index,
+                                               GLenum pname,
+                                               GLsizei bufSize,
+                                               GLsizei *length,
+                                               GLint *params)
+{
+    EVENT(
+        "(GLuint index = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLint * params = 0x%0.8p)",
+        index, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetVertexAttribIivRobustANGLE>(index, pname, bufSize,
+                                                                         length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetVertexAttribIivRobustANGLE(context, index, pname, bufSize, length, params))
+        {
+            context->getVertexAttribIivRobust(index, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetVertexAttribIuivRobustANGLE(GLuint index,
+                                                GLenum pname,
+                                                GLsizei bufSize,
+                                                GLsizei *length,
+                                                GLuint *params)
+{
+    EVENT(
+        "(GLuint index = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLuint * params = 0x%0.8p)",
+        index, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetVertexAttribIuivRobustANGLE>(index, pname, bufSize,
+                                                                          length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetVertexAttribIuivRobustANGLE(context, index, pname, bufSize, length, params))
+        {
+            context->getVertexAttribIuivRobust(index, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetUniformuivRobustANGLE(GLuint program,
+                                          GLint location,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          GLuint *params)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLuint * params = 0x%0.8p)",
+        program, location, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetUniformuivRobustANGLE>(program, location, bufSize,
+                                                                    length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetUniformuivRobustANGLE(context, program, location, bufSize, length, params))
+        {
+            context->getUniformuivRobust(program, location, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetActiveUniformBlockivRobustANGLE(GLuint program,
+                                                    GLuint uniformBlockIndex,
+                                                    GLenum pname,
+                                                    GLsizei bufSize,
+                                                    GLsizei *length,
+                                                    GLint *params)
+{
+    EVENT(
+        "(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLsizei bufSize "
+        "= %d, GLsizei * length = 0x%0.8p, GLint * params = 0x%0.8p)",
+        program, uniformBlockIndex, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetActiveUniformBlockivRobustANGLE>(
+            program, uniformBlockIndex, pname, bufSize, length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetActiveUniformBlockivRobustANGLE(context, program, uniformBlockIndex, pname,
+                                                       bufSize, length, params))
+        {
+            context->getActiveUniformBlockivRobust(program, uniformBlockIndex, pname, bufSize,
+                                                   length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetInteger64vRobustANGLE(GLenum pname,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          GLint64 *data)
+{
+    EVENT(
+        "(GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = 0x%0.8p, GLint64 * data = "
+        "0x%0.8p)",
+        pname, bufSize, length, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetInteger64vRobustANGLE>(pname, bufSize, length, data);
+
+        if (context->skipValidation() ||
+            ValidateGetInteger64vRobustANGLE(context, pname, bufSize, length, data))
+        {
+            context->getInteger64vRobust(pname, bufSize, length, data);
+        }
+    }
+}
+
+void GL_APIENTRY GetInteger64i_vRobustANGLE(GLenum target,
+                                            GLuint index,
+                                            GLsizei bufSize,
+                                            GLsizei *length,
+                                            GLint64 *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLuint index = %u, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLint64 * data = 0x%0.8p)",
+        target, index, bufSize, length, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetInteger64i_vRobustANGLE>(target, index, bufSize,
+                                                                      length, data);
+
+        if (context->skipValidation() ||
+            ValidateGetInteger64i_vRobustANGLE(context, target, index, bufSize, length, data))
+        {
+            context->getInteger64i_vRobust(target, index, bufSize, length, data);
+        }
+    }
+}
+
+void GL_APIENTRY GetBufferParameteri64vRobustANGLE(GLenum target,
+                                                   GLenum pname,
+                                                   GLsizei bufSize,
+                                                   GLsizei *length,
+                                                   GLint64 *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLint64 * params = 0x%0.8p)",
+        target, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
+        context->gatherParams<EntryPoint::GetBufferParameteri64vRobustANGLE>(
+            targetPacked, pname, bufSize, length, params);
+
+        if (context->skipValidation() || ValidateGetBufferParameteri64vRobustANGLE(
+                                             context, targetPacked, pname, bufSize, length, params))
+        {
+            context->getBufferParameteri64vRobust(targetPacked, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY SamplerParameterivRobustANGLE(GLuint sampler,
+                                               GLuint pname,
+                                               GLsizei bufSize,
+                                               const GLint *param)
+{
+    EVENT(
+        "(GLuint sampler = %u, GLuint pname = %u, GLsizei bufSize = %d, const GLint * param = "
+        "0x%0.8p)",
+        sampler, pname, bufSize, param);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::SamplerParameterivRobustANGLE>(sampler, pname, bufSize,
+                                                                         param);
+
+        if (context->skipValidation() ||
+            ValidateSamplerParameterivRobustANGLE(context, sampler, pname, bufSize, param))
+        {
+            context->samplerParameterivRobust(sampler, pname, bufSize, param);
+        }
+    }
+}
+
+void GL_APIENTRY SamplerParameterfvRobustANGLE(GLuint sampler,
+                                               GLenum pname,
+                                               GLsizei bufSize,
+                                               const GLfloat *param)
+{
+    EVENT(
+        "(GLuint sampler = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, const GLfloat * param = "
+        "0x%0.8p)",
+        sampler, pname, bufSize, param);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::SamplerParameterfvRobustANGLE>(sampler, pname, bufSize,
+                                                                         param);
+
+        if (context->skipValidation() ||
+            ValidateSamplerParameterfvRobustANGLE(context, sampler, pname, bufSize, param))
+        {
+            context->samplerParameterfvRobust(sampler, pname, bufSize, param);
+        }
+    }
+}
+
+void GL_APIENTRY GetSamplerParameterivRobustANGLE(GLuint sampler,
+                                                  GLenum pname,
+                                                  GLsizei bufSize,
+                                                  GLsizei *length,
+                                                  GLint *params)
+{
+    EVENT(
+        "(GLuint sampler = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLint * params = 0x%0.8p)",
+        sampler, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetSamplerParameterivRobustANGLE>(sampler, pname, bufSize,
+                                                                            length, params);
+
+        if (context->skipValidation() || ValidateGetSamplerParameterivRobustANGLE(
+                                             context, sampler, pname, bufSize, length, params))
+        {
+            context->getSamplerParameterivRobust(sampler, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetSamplerParameterfvRobustANGLE(GLuint sampler,
+                                                  GLenum pname,
+                                                  GLsizei bufSize,
+                                                  GLsizei *length,
+                                                  GLfloat *params)
+{
+    EVENT(
+        "(GLuint sampler = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLfloat * params = 0x%0.8p)",
+        sampler, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetSamplerParameterfvRobustANGLE>(sampler, pname, bufSize,
+                                                                            length, params);
+
+        if (context->skipValidation() || ValidateGetSamplerParameterfvRobustANGLE(
+                                             context, sampler, pname, bufSize, length, params))
+        {
+            context->getSamplerParameterfvRobust(sampler, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetFramebufferParameterivRobustANGLE(GLuint sampler,
+                                                      GLenum pname,
+                                                      GLsizei bufSize,
+                                                      GLsizei *length,
+                                                      GLint *params)
+{
+    EVENT(
+        "(GLuint sampler = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLint * params = 0x%0.8p)",
+        sampler, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetFramebufferParameterivRobustANGLE>(
+            sampler, pname, bufSize, length, params);
+
+        if (context->skipValidation() || ValidateGetFramebufferParameterivRobustANGLE(
+                                             context, sampler, pname, bufSize, length, params))
+        {
+            context->getFramebufferParameterivRobust(sampler, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetProgramInterfaceivRobustANGLE(GLuint program,
+                                                  GLenum programInterface,
+                                                  GLenum pname,
+                                                  GLsizei bufSize,
+                                                  GLsizei *length,
+                                                  GLint *params)
+{
+    EVENT(
+        "(GLuint program = %u, GLenum programInterface = 0x%X, GLenum pname = 0x%X, GLsizei "
+        "bufSize = %d, GLsizei * length = 0x%0.8p, GLint * params = 0x%0.8p)",
+        program, programInterface, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetProgramInterfaceivRobustANGLE>(
+            program, programInterface, pname, bufSize, length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetProgramInterfaceivRobustANGLE(context, program, programInterface, pname,
+                                                     bufSize, length, params))
+        {
+            context->getProgramInterfaceivRobust(program, programInterface, pname, bufSize, length,
+                                                 params);
+        }
+    }
+}
+
+void GL_APIENTRY GetBooleani_vRobustANGLE(GLenum target,
+                                          GLuint index,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          GLboolean *data)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLuint index = %u, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLboolean * data = 0x%0.8p)",
+        target, index, bufSize, length, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetBooleani_vRobustANGLE>(target, index, bufSize, length,
+                                                                    data);
+
+        if (context->skipValidation() ||
+            ValidateGetBooleani_vRobustANGLE(context, target, index, bufSize, length, data))
+        {
+            context->getBooleani_vRobust(target, index, bufSize, length, data);
+        }
+    }
+}
+
+void GL_APIENTRY GetMultisamplefvRobustANGLE(GLenum pname,
+                                             GLuint index,
+                                             GLsizei bufSize,
+                                             GLsizei *length,
+                                             GLfloat *val)
+{
+    EVENT(
+        "(GLenum pname = 0x%X, GLuint index = %u, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLfloat * val = 0x%0.8p)",
+        pname, index, bufSize, length, val);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetMultisamplefvRobustANGLE>(pname, index, bufSize,
+                                                                       length, val);
+
+        if (context->skipValidation() ||
+            ValidateGetMultisamplefvRobustANGLE(context, pname, index, bufSize, length, val))
+        {
+            context->getMultisamplefvRobust(pname, index, bufSize, length, val);
+        }
+    }
+}
+
+void GL_APIENTRY GetTexLevelParameterivRobustANGLE(GLenum target,
+                                                   GLint level,
+                                                   GLenum pname,
+                                                   GLsizei bufSize,
+                                                   GLsizei *length,
+                                                   GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLenum pname = 0x%X, GLsizei bufSize = %d, "
+        "GLsizei * length = 0x%0.8p, GLint * params = 0x%0.8p)",
+        target, level, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureTarget targetPacked = FromGLenum<TextureTarget>(target);
+        context->gatherParams<EntryPoint::GetTexLevelParameterivRobustANGLE>(
+            targetPacked, level, pname, bufSize, length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetTexLevelParameterivRobustANGLE(context, targetPacked, level, pname, bufSize,
+                                                      length, params))
+        {
+            context->getTexLevelParameterivRobust(targetPacked, level, pname, bufSize, length,
+                                                  params);
+        }
+    }
+}
+
+void GL_APIENTRY GetTexLevelParameterfvRobustANGLE(GLenum target,
+                                                   GLint level,
+                                                   GLenum pname,
+                                                   GLsizei bufSize,
+                                                   GLsizei *length,
+                                                   GLfloat *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLint level = %d, GLenum pname = 0x%X, GLsizei bufSize = %d, "
+        "GLsizei * length = 0x%0.8p, GLfloat * params = 0x%0.8p)",
+        target, level, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureTarget targetPacked = FromGLenum<TextureTarget>(target);
+        context->gatherParams<EntryPoint::GetTexLevelParameterfvRobustANGLE>(
+            targetPacked, level, pname, bufSize, length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetTexLevelParameterfvRobustANGLE(context, targetPacked, level, pname, bufSize,
+                                                      length, params))
+        {
+            context->getTexLevelParameterfvRobust(targetPacked, level, pname, bufSize, length,
+                                                  params);
+        }
+    }
+}
+
+void GL_APIENTRY GetPointervRobustANGLERobustANGLE(GLenum pname,
+                                                   GLsizei bufSize,
+                                                   GLsizei *length,
+                                                   void **params)
+{
+    EVENT(
+        "(GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = 0x%0.8p, void ** params = "
+        "0x%0.8p)",
+        pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetPointervRobustANGLERobustANGLE>(pname, bufSize, length,
+                                                                             params);
+
+        if (context->skipValidation() ||
+            ValidateGetPointervRobustANGLERobustANGLE(context, pname, bufSize, length, params))
+        {
+            context->getPointervRobustANGLERobust(pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY ReadnPixelsRobustANGLE(GLint x,
+                                        GLint y,
+                                        GLsizei width,
+                                        GLsizei height,
+                                        GLenum format,
+                                        GLenum type,
+                                        GLsizei bufSize,
+                                        GLsizei *length,
+                                        GLsizei *columns,
+                                        GLsizei *rows,
+                                        void *data)
+{
+    EVENT(
+        "(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLenum format = "
+        "0x%X, GLenum type = 0x%X, GLsizei bufSize = %d, GLsizei * length = 0x%0.8p, GLsizei * "
+        "columns = 0x%0.8p, GLsizei * rows = 0x%0.8p, void * data = 0x%0.8p)",
+        x, y, width, height, format, type, bufSize, length, columns, rows, data);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::ReadnPixelsRobustANGLE>(
+            x, y, width, height, format, type, bufSize, length, columns, rows, data);
+
+        if (context->skipValidation() ||
+            ValidateReadnPixelsRobustANGLE(context, x, y, width, height, format, type, bufSize,
+                                           length, columns, rows, data))
+        {
+            context->readnPixelsRobust(x, y, width, height, format, type, bufSize, length, columns,
+                                       rows, data);
+        }
+    }
+}
+
+void GL_APIENTRY GetnUniformfvRobustANGLE(GLuint program,
+                                          GLint location,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          GLfloat *params)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLfloat * params = 0x%0.8p)",
+        program, location, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetnUniformfvRobustANGLE>(program, location, bufSize,
+                                                                    length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetnUniformfvRobustANGLE(context, program, location, bufSize, length, params))
+        {
+            context->getnUniformfvRobust(program, location, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetnUniformivRobustANGLE(GLuint program,
+                                          GLint location,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          GLint *params)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLint * params = 0x%0.8p)",
+        program, location, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetnUniformivRobustANGLE>(program, location, bufSize,
+                                                                    length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetnUniformivRobustANGLE(context, program, location, bufSize, length, params))
+        {
+            context->getnUniformivRobust(program, location, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetnUniformuivRobustANGLE(GLuint program,
+                                           GLint location,
+                                           GLsizei bufSize,
+                                           GLsizei *length,
+                                           GLuint *params)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLuint * params = 0x%0.8p)",
+        program, location, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetnUniformuivRobustANGLE>(program, location, bufSize,
+                                                                     length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetnUniformuivRobustANGLE(context, program, location, bufSize, length, params))
+        {
+            context->getnUniformuivRobust(program, location, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY TexParameterIivRobustANGLE(GLenum target,
+                                            GLenum pname,
+                                            GLsizei bufSize,
+                                            const GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, const GLint * params = "
+        "0x%0.8p)",
+        target, pname, bufSize, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureType targetPacked = FromGLenum<TextureType>(target);
+        context->gatherParams<EntryPoint::TexParameterIivRobustANGLE>(targetPacked, pname, bufSize,
+                                                                      params);
+
+        if (context->skipValidation() ||
+            ValidateTexParameterIivRobustANGLE(context, targetPacked, pname, bufSize, params))
+        {
+            context->texParameterIivRobust(targetPacked, pname, bufSize, params);
+        }
+    }
+}
+
+void GL_APIENTRY TexParameterIuivRobustANGLE(GLenum target,
+                                             GLenum pname,
+                                             GLsizei bufSize,
+                                             const GLuint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, const GLuint * params = "
+        "0x%0.8p)",
+        target, pname, bufSize, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureType targetPacked = FromGLenum<TextureType>(target);
+        context->gatherParams<EntryPoint::TexParameterIuivRobustANGLE>(targetPacked, pname, bufSize,
+                                                                       params);
+
+        if (context->skipValidation() ||
+            ValidateTexParameterIuivRobustANGLE(context, targetPacked, pname, bufSize, params))
+        {
+            context->texParameterIuivRobust(targetPacked, pname, bufSize, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetTexParameterIivRobustANGLE(GLenum target,
+                                               GLenum pname,
+                                               GLsizei bufSize,
+                                               GLsizei *length,
+                                               GLint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLint * params = 0x%0.8p)",
+        target, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureType targetPacked = FromGLenum<TextureType>(target);
+        context->gatherParams<EntryPoint::GetTexParameterIivRobustANGLE>(targetPacked, pname,
+                                                                         bufSize, length, params);
+
+        if (context->skipValidation() || ValidateGetTexParameterIivRobustANGLE(
+                                             context, targetPacked, pname, bufSize, length, params))
+        {
+            context->getTexParameterIivRobust(targetPacked, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetTexParameterIuivRobustANGLE(GLenum target,
+                                                GLenum pname,
+                                                GLsizei bufSize,
+                                                GLsizei *length,
+                                                GLuint *params)
+{
+    EVENT(
+        "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLuint * params = 0x%0.8p)",
+        target, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureType targetPacked = FromGLenum<TextureType>(target);
+        context->gatherParams<EntryPoint::GetTexParameterIuivRobustANGLE>(targetPacked, pname,
+                                                                          bufSize, length, params);
+
+        if (context->skipValidation() || ValidateGetTexParameterIuivRobustANGLE(
+                                             context, targetPacked, pname, bufSize, length, params))
+        {
+            context->getTexParameterIuivRobust(targetPacked, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY SamplerParameterIivRobustANGLE(GLuint sampler,
+                                                GLenum pname,
+                                                GLsizei bufSize,
+                                                const GLint *param)
+{
+    EVENT(
+        "(GLuint sampler = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, const GLint * param = "
+        "0x%0.8p)",
+        sampler, pname, bufSize, param);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::SamplerParameterIivRobustANGLE>(sampler, pname, bufSize,
+                                                                          param);
+
+        if (context->skipValidation() ||
+            ValidateSamplerParameterIivRobustANGLE(context, sampler, pname, bufSize, param))
+        {
+            context->samplerParameterIivRobust(sampler, pname, bufSize, param);
+        }
+    }
+}
+
+void GL_APIENTRY SamplerParameterIuivRobustANGLE(GLuint sampler,
+                                                 GLenum pname,
+                                                 GLsizei bufSize,
+                                                 const GLuint *param)
+{
+    EVENT(
+        "(GLuint sampler = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, const GLuint * param = "
+        "0x%0.8p)",
+        sampler, pname, bufSize, param);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::SamplerParameterIuivRobustANGLE>(sampler, pname, bufSize,
+                                                                           param);
+
+        if (context->skipValidation() ||
+            ValidateSamplerParameterIuivRobustANGLE(context, sampler, pname, bufSize, param))
+        {
+            context->samplerParameterIuivRobust(sampler, pname, bufSize, param);
+        }
+    }
+}
+
+void GL_APIENTRY GetSamplerParameterIivRobustANGLE(GLuint sampler,
+                                                   GLenum pname,
+                                                   GLsizei bufSize,
+                                                   GLsizei *length,
+                                                   GLint *params)
+{
+    EVENT(
+        "(GLuint sampler = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLint * params = 0x%0.8p)",
+        sampler, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetSamplerParameterIivRobustANGLE>(
+            sampler, pname, bufSize, length, params);
+
+        if (context->skipValidation() || ValidateGetSamplerParameterIivRobustANGLE(
+                                             context, sampler, pname, bufSize, length, params))
+        {
+            context->getSamplerParameterIivRobust(sampler, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetSamplerParameterIuivRobustANGLE(GLuint sampler,
+                                                    GLenum pname,
+                                                    GLsizei bufSize,
+                                                    GLsizei *length,
+                                                    GLuint *params)
+{
+    EVENT(
+        "(GLuint sampler = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = "
+        "0x%0.8p, GLuint * params = 0x%0.8p)",
+        sampler, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetSamplerParameterIuivRobustANGLE>(
+            sampler, pname, bufSize, length, params);
+
+        if (context->skipValidation() || ValidateGetSamplerParameterIuivRobustANGLE(
+                                             context, sampler, pname, bufSize, length, params))
+        {
+            context->getSamplerParameterIuivRobust(sampler, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetQueryObjectivRobustANGLE(GLuint id,
+                                             GLenum pname,
+                                             GLsizei bufSize,
+                                             GLsizei *length,
+                                             GLint *params)
+{
+    EVENT(
+        "(GLuint id = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = 0x%0.8p, "
+        "GLint * params = 0x%0.8p)",
+        id, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetQueryObjectivRobustANGLE>(id, pname, bufSize, length,
+                                                                       params);
+
+        if (context->skipValidation() ||
+            ValidateGetQueryObjectivRobustANGLE(context, id, pname, bufSize, length, params))
+        {
+            context->getQueryObjectivRobust(id, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetQueryObjecti64vRobustANGLE(GLuint id,
+                                               GLenum pname,
+                                               GLsizei bufSize,
+                                               GLsizei *length,
+                                               GLint64 *params)
+{
+    EVENT(
+        "(GLuint id = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = 0x%0.8p, "
+        "GLint64 * params = 0x%0.8p)",
+        id, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetQueryObjecti64vRobustANGLE>(id, pname, bufSize, length,
+                                                                         params);
+
+        if (context->skipValidation() ||
+            ValidateGetQueryObjecti64vRobustANGLE(context, id, pname, bufSize, length, params))
+        {
+            context->getQueryObjecti64vRobust(id, pname, bufSize, length, params);
+        }
+    }
+}
+
+void GL_APIENTRY GetQueryObjectui64vRobustANGLE(GLuint id,
+                                                GLenum pname,
+                                                GLsizei bufSize,
+                                                GLsizei *length,
+                                                GLuint64 *params)
+{
+    EVENT(
+        "(GLuint id = %u, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei * length = 0x%0.8p, "
+        "GLuint64 * params = 0x%0.8p)",
+        id, pname, bufSize, length, params);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetQueryObjectui64vRobustANGLE>(id, pname, bufSize,
+                                                                          length, params);
+
+        if (context->skipValidation() ||
+            ValidateGetQueryObjectui64vRobustANGLE(context, id, pname, bufSize, length, params))
+        {
+            context->getQueryObjectui64vRobust(id, pname, bufSize, length, params);
+        }
+    }
+}
+
 // GL_ANGLE_translated_shader_source
 void GL_APIENTRY GetTranslatedShaderSourceANGLE(GLuint shader,
                                                 GLsizei bufsize,
@@ -171,6 +1953,693 @@
     }
 }
 
+// GL_CHROMIUM_bind_uniform_location
+void GL_APIENTRY BindUniformLocationCHROMIUM(GLuint program, GLint location, const GLchar *name)
+{
+    EVENT("(GLuint program = %u, GLint location = %d, const GLchar* name = 0x%0.8p)", program,
+          location, name);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::BindUniformLocationCHROMIUM>(program, location, name);
+
+        if (context->skipValidation() ||
+            ValidateBindUniformLocationCHROMIUM(context, program, location, name))
+        {
+            context->bindUniformLocation(program, location, name);
+        }
+    }
+}
+
+// GL_CHROMIUM_copy_compressed_texture
+void GL_APIENTRY CompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId)
+{
+    EVENT("(GLuint sourceId = %u, GLuint destId = %u)", sourceId, destId);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::CompressedCopyTextureCHROMIUM>(sourceId, destId);
+
+        if (context->skipValidation() ||
+            ValidateCompressedCopyTextureCHROMIUM(context, sourceId, destId))
+        {
+            context->compressedCopyTexture(sourceId, destId);
+        }
+    }
+}
+
+// GL_CHROMIUM_copy_texture
+void GL_APIENTRY CopyTextureCHROMIUM(GLuint sourceId,
+                                     GLint sourceLevel,
+                                     GLenum destTarget,
+                                     GLuint destId,
+                                     GLint destLevel,
+                                     GLint internalFormat,
+                                     GLenum destType,
+                                     GLboolean unpackFlipY,
+                                     GLboolean unpackPremultiplyAlpha,
+                                     GLboolean unpackUnmultiplyAlpha)
+{
+    EVENT(
+        "(GLuint sourceId = %u, GLint sourceLevel = %d, GLenum destTarget = 0x%X, GLuint destId = "
+        "%u, GLint destLevel = %d, GLint internalFormat = %d, GLenum destType = 0x%X, GLboolean "
+        "unpackFlipY = %u, GLboolean unpackPremultiplyAlpha = %u, GLboolean unpackUnmultiplyAlpha "
+        "= %u)",
+        sourceId, sourceLevel, destTarget, destId, destLevel, internalFormat, destType, unpackFlipY,
+        unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureTarget destTargetPacked = FromGLenum<TextureTarget>(destTarget);
+        context->gatherParams<EntryPoint::CopyTextureCHROMIUM>(
+            sourceId, sourceLevel, destTargetPacked, destId, destLevel, internalFormat, destType,
+            unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
+
+        if (context->skipValidation() ||
+            ValidateCopyTextureCHROMIUM(context, sourceId, sourceLevel, destTargetPacked, destId,
+                                        destLevel, internalFormat, destType, unpackFlipY,
+                                        unpackPremultiplyAlpha, unpackUnmultiplyAlpha))
+        {
+            context->copyTexture(sourceId, sourceLevel, destTargetPacked, destId, destLevel,
+                                 internalFormat, destType, unpackFlipY, unpackPremultiplyAlpha,
+                                 unpackUnmultiplyAlpha);
+        }
+    }
+}
+
+void GL_APIENTRY CopySubTextureCHROMIUM(GLuint sourceId,
+                                        GLint sourceLevel,
+                                        GLenum destTarget,
+                                        GLuint destId,
+                                        GLint destLevel,
+                                        GLint xoffset,
+                                        GLint yoffset,
+                                        GLint x,
+                                        GLint y,
+                                        GLint width,
+                                        GLint height,
+                                        GLboolean unpackFlipY,
+                                        GLboolean unpackPremultiplyAlpha,
+                                        GLboolean unpackUnmultiplyAlpha)
+{
+    EVENT(
+        "(GLuint sourceId = %u, GLint sourceLevel = %d, GLenum destTarget = 0x%X, GLuint destId = "
+        "%u, GLint destLevel = %d, GLint xoffset = %d, GLint yoffset = %d, GLint x = %d, GLint y = "
+        "%d, GLint width = %d, GLint height = %d, GLboolean unpackFlipY = %u, GLboolean "
+        "unpackPremultiplyAlpha = %u, GLboolean unpackUnmultiplyAlpha = %u)",
+        sourceId, sourceLevel, destTarget, destId, destLevel, xoffset, yoffset, x, y, width, height,
+        unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        TextureTarget destTargetPacked = FromGLenum<TextureTarget>(destTarget);
+        context->gatherParams<EntryPoint::CopySubTextureCHROMIUM>(
+            sourceId, sourceLevel, destTargetPacked, destId, destLevel, xoffset, yoffset, x, y,
+            width, height, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
+
+        if (context->skipValidation() ||
+            ValidateCopySubTextureCHROMIUM(context, sourceId, sourceLevel, destTargetPacked, destId,
+                                           destLevel, xoffset, yoffset, x, y, width, height,
+                                           unpackFlipY, unpackPremultiplyAlpha,
+                                           unpackUnmultiplyAlpha))
+        {
+            context->copySubTexture(sourceId, sourceLevel, destTargetPacked, destId, destLevel,
+                                    xoffset, yoffset, x, y, width, height, unpackFlipY,
+                                    unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
+        }
+    }
+}
+
+// GL_CHROMIUM_framebuffer_mixed_samples
+void GL_APIENTRY CoverageModulationCHROMIUM(GLenum components)
+{
+    EVENT("(GLenum components = 0x%X)", components);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::CoverageModulationCHROMIUM>(components);
+
+        if (context->skipValidation() || ValidateCoverageModulationCHROMIUM(context, components))
+        {
+            context->coverageModulation(components);
+        }
+    }
+}
+
+void GL_APIENTRY MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *matrix)
+{
+    EVENT("(GLenum matrixMode = 0x%X, const GLfloat * matrix = 0x%0.8p)", matrixMode, matrix);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::MatrixLoadfCHROMIUM>(matrixMode, matrix);
+
+        if (context->skipValidation() || ValidateMatrixLoadfCHROMIUM(context, matrixMode, matrix))
+        {
+            context->matrixLoadf(matrixMode, matrix);
+        }
+    }
+}
+
+void GL_APIENTRY MatrixLoadIdentityCHROMIUM(GLenum matrixMode)
+{
+    EVENT("(GLenum matrixMode = 0x%X)", matrixMode);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::MatrixLoadIdentityCHROMIUM>(matrixMode);
+
+        if (context->skipValidation() || ValidateMatrixLoadIdentityCHROMIUM(context, matrixMode))
+        {
+            context->matrixLoadIdentity(matrixMode);
+        }
+    }
+}
+
+// GL_CHROMIUM_path_rendering
+GLuint GL_APIENTRY GenPathsCHROMIUM(GLsizei range)
+{
+    EVENT("(GLsizei range = %d)", range);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GenPathsCHROMIUM>(range);
+
+        if (context->skipValidation() || ValidateGenPathsCHROMIUM(context, range))
+        {
+            return context->genPaths(range);
+        }
+    }
+
+    return GetDefaultReturnValue<EntryPoint::GenPathsCHROMIUM, GLuint>();
+}
+
+void GL_APIENTRY DeletePathsCHROMIUM(GLuint first, GLsizei range)
+{
+    EVENT("(GLuint first = %u, GLsizei range = %d)", first, range);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::DeletePathsCHROMIUM>(first, range);
+
+        if (context->skipValidation() || ValidateDeletePathsCHROMIUM(context, first, range))
+        {
+            context->deletePaths(first, range);
+        }
+    }
+}
+
+GLboolean GL_APIENTRY IsPathCHROMIUM(GLuint path)
+{
+    EVENT("(GLuint path = %u)", path);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::IsPathCHROMIUM>(path);
+
+        if (context->skipValidation() || ValidateIsPathCHROMIUM(context, path))
+        {
+            return context->isPath(path);
+        }
+    }
+
+    return GetDefaultReturnValue<EntryPoint::IsPathCHROMIUM, GLboolean>();
+}
+
+void GL_APIENTRY PathCommandsCHROMIUM(GLuint path,
+                                      GLsizei numCommands,
+                                      const GLubyte *commands,
+                                      GLsizei numCoords,
+                                      GLenum coordType,
+                                      const void *coords)
+{
+    EVENT(
+        "(GLuint path = %u, GLsizei numCommands = %d, const GLubyte * commands = 0x%0.8p, GLsizei "
+        "numCoords = %d, GLenum coordType = 0x%X, const void* coords = 0x%0.8p)",
+        path, numCommands, commands, numCoords, coordType, coords);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::PathCommandsCHROMIUM>(path, numCommands, commands,
+                                                                numCoords, coordType, coords);
+
+        if (context->skipValidation() ||
+            ValidatePathCommandsCHROMIUM(context, path, numCommands, commands, numCoords, coordType,
+                                         coords))
+        {
+            context->pathCommands(path, numCommands, commands, numCoords, coordType, coords);
+        }
+    }
+}
+
+void GL_APIENTRY PathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value)
+{
+    EVENT("(GLuint path = %u, GLenum pname = 0x%X, GLfloat value = %f)", path, pname, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::PathParameterfCHROMIUM>(path, pname, value);
+
+        if (context->skipValidation() ||
+            ValidatePathParameterfCHROMIUM(context, path, pname, value))
+        {
+            context->pathParameterf(path, pname, value);
+        }
+    }
+}
+
+void GL_APIENTRY PathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value)
+{
+    EVENT("(GLuint path = %u, GLenum pname = 0x%X, GLint value = %d)", path, pname, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::PathParameteriCHROMIUM>(path, pname, value);
+
+        if (context->skipValidation() ||
+            ValidatePathParameteriCHROMIUM(context, path, pname, value))
+        {
+            context->pathParameteri(path, pname, value);
+        }
+    }
+}
+
+void GL_APIENTRY GetPathParameterfvCHROMIUM(GLuint path, GLenum pname, GLfloat *value)
+{
+    EVENT("(GLuint path = %u, GLenum pname = 0x%X, GLfloat * value = 0x%0.8p)", path, pname, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetPathParameterfvCHROMIUM>(path, pname, value);
+
+        if (context->skipValidation() ||
+            ValidateGetPathParameterfvCHROMIUM(context, path, pname, value))
+        {
+            context->getPathParameterfv(path, pname, value);
+        }
+    }
+}
+
+void GL_APIENTRY GetPathParameterivCHROMIUM(GLuint path, GLenum pname, GLint *value)
+{
+    EVENT("(GLuint path = %u, GLenum pname = 0x%X, GLint * value = 0x%0.8p)", path, pname, value);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::GetPathParameterivCHROMIUM>(path, pname, value);
+
+        if (context->skipValidation() ||
+            ValidateGetPathParameterivCHROMIUM(context, path, pname, value))
+        {
+            context->getPathParameteriv(path, pname, value);
+        }
+    }
+}
+
+void GL_APIENTRY PathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask)
+{
+    EVENT("(GLenum func = 0x%X, GLint ref = %d, GLuint mask = %u)", func, ref, mask);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::PathStencilFuncCHROMIUM>(func, ref, mask);
+
+        if (context->skipValidation() || ValidatePathStencilFuncCHROMIUM(context, func, ref, mask))
+        {
+            context->pathStencilFunc(func, ref, mask);
+        }
+    }
+}
+
+void GL_APIENTRY StencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask)
+{
+    EVENT("(GLuint path = %u, GLenum fillMode = 0x%X, GLuint mask = %u)", path, fillMode, mask);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::StencilFillPathCHROMIUM>(path, fillMode, mask);
+
+        if (context->skipValidation() ||
+            ValidateStencilFillPathCHROMIUM(context, path, fillMode, mask))
+        {
+            context->stencilFillPath(path, fillMode, mask);
+        }
+    }
+}
+
+void GL_APIENTRY StencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask)
+{
+    EVENT("(GLuint path = %u, GLint reference = %d, GLuint mask = %u)", path, reference, mask);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::StencilStrokePathCHROMIUM>(path, reference, mask);
+
+        if (context->skipValidation() ||
+            ValidateStencilStrokePathCHROMIUM(context, path, reference, mask))
+        {
+            context->stencilStrokePath(path, reference, mask);
+        }
+    }
+}
+
+void GL_APIENTRY CoverFillPathCHROMIUM(GLuint path, GLenum coverMode)
+{
+    EVENT("(GLuint path = %u, GLenum coverMode = 0x%X)", path, coverMode);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::CoverFillPathCHROMIUM>(path, coverMode);
+
+        if (context->skipValidation() || ValidateCoverFillPathCHROMIUM(context, path, coverMode))
+        {
+            context->coverFillPath(path, coverMode);
+        }
+    }
+}
+
+void GL_APIENTRY CoverStrokePathCHROMIUM(GLuint path, GLenum coverMode)
+{
+    EVENT("(GLuint path = %u, GLenum coverMode = 0x%X)", path, coverMode);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::CoverStrokePathCHROMIUM>(path, coverMode);
+
+        if (context->skipValidation() || ValidateCoverStrokePathCHROMIUM(context, path, coverMode))
+        {
+            context->coverStrokePath(path, coverMode);
+        }
+    }
+}
+
+void GL_APIENTRY StencilThenCoverFillPathCHROMIUM(GLuint path,
+                                                  GLenum fillMode,
+                                                  GLuint mask,
+                                                  GLenum coverMode)
+{
+    EVENT("(GLuint path = %u, GLenum fillMode = 0x%X, GLuint mask = %u, GLenum coverMode = 0x%X)",
+          path, fillMode, mask, coverMode);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::StencilThenCoverFillPathCHROMIUM>(path, fillMode, mask,
+                                                                            coverMode);
+
+        if (context->skipValidation() ||
+            ValidateStencilThenCoverFillPathCHROMIUM(context, path, fillMode, mask, coverMode))
+        {
+            context->stencilThenCoverFillPath(path, fillMode, mask, coverMode);
+        }
+    }
+}
+
+void GL_APIENTRY StencilThenCoverStrokePathCHROMIUM(GLuint path,
+                                                    GLint reference,
+                                                    GLuint mask,
+                                                    GLenum coverMode)
+{
+    EVENT("(GLuint path = %u, GLint reference = %d, GLuint mask = %u, GLenum coverMode = 0x%X)",
+          path, reference, mask, coverMode);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::StencilThenCoverStrokePathCHROMIUM>(path, reference, mask,
+                                                                              coverMode);
+
+        if (context->skipValidation() ||
+            ValidateStencilThenCoverStrokePathCHROMIUM(context, path, reference, mask, coverMode))
+        {
+            context->stencilThenCoverStrokePath(path, reference, mask, coverMode);
+        }
+    }
+}
+
+void GL_APIENTRY CoverFillPathInstancedCHROMIUM(GLsizei numPath,
+                                                GLenum pathNameType,
+                                                const void *paths,
+                                                GLuint pathBase,
+                                                GLenum coverMode,
+                                                GLenum transformType,
+                                                const GLfloat *transformValues)
+{
+    EVENT(
+        "(GLsizei numPath = %d, GLenum pathNameType = 0x%X, const void * paths = 0x%0.8p, GLuint "
+        "pathBase = %u, GLenum coverMode = 0x%X, GLenum transformType = 0x%X, const GLfloat * "
+        "transformValues = 0x%0.8p)",
+        numPath, pathNameType, paths, pathBase, coverMode, transformType, transformValues);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::CoverFillPathInstancedCHROMIUM>(
+            numPath, pathNameType, paths, pathBase, coverMode, transformType, transformValues);
+
+        if (context->skipValidation() ||
+            ValidateCoverFillPathInstancedCHROMIUM(context, numPath, pathNameType, paths, pathBase,
+                                                   coverMode, transformType, transformValues))
+        {
+            context->coverFillPathInstanced(numPath, pathNameType, paths, pathBase, coverMode,
+                                            transformType, transformValues);
+        }
+    }
+}
+
+void GL_APIENTRY CoverStrokePathInstancedCHROMIUM(GLsizei numPath,
+                                                  GLenum pathNameType,
+                                                  const void *paths,
+                                                  GLuint pathBase,
+                                                  GLenum coverMode,
+                                                  GLenum transformType,
+                                                  const GLfloat *transformValues)
+{
+    EVENT(
+        "(GLsizei numPath = %d, GLenum pathNameType = 0x%X, const void * paths = 0x%0.8p, GLuint "
+        "pathBase = %u, GLenum coverMode = 0x%X, GLenum transformType = 0x%X, const GLfloat * "
+        "transformValues = 0x%0.8p)",
+        numPath, pathNameType, paths, pathBase, coverMode, transformType, transformValues);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::CoverStrokePathInstancedCHROMIUM>(
+            numPath, pathNameType, paths, pathBase, coverMode, transformType, transformValues);
+
+        if (context->skipValidation() || ValidateCoverStrokePathInstancedCHROMIUM(
+                                             context, numPath, pathNameType, paths, pathBase,
+                                             coverMode, transformType, transformValues))
+        {
+            context->coverStrokePathInstanced(numPath, pathNameType, paths, pathBase, coverMode,
+                                              transformType, transformValues);
+        }
+    }
+}
+
+void GL_APIENTRY StencilStrokePathInstancedCHROMIUM(GLsizei numPath,
+                                                    GLenum pathNameType,
+                                                    const void *paths,
+                                                    GLuint pathBase,
+                                                    GLint reference,
+                                                    GLuint mask,
+                                                    GLenum transformType,
+                                                    const GLfloat *transformValues)
+{
+    EVENT(
+        "(GLsizei numPath = %d, GLenum pathNameType = 0x%X, const void * paths = 0x%0.8p, GLuint "
+        "pathBase = %u, GLint reference = %d, GLuint mask = %u, GLenum transformType = 0x%X, const "
+        "GLfloat * transformValues = 0x%0.8p)",
+        numPath, pathNameType, paths, pathBase, reference, mask, transformType, transformValues);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::StencilStrokePathInstancedCHROMIUM>(
+            numPath, pathNameType, paths, pathBase, reference, mask, transformType,
+            transformValues);
+
+        if (context->skipValidation() || ValidateStencilStrokePathInstancedCHROMIUM(
+                                             context, numPath, pathNameType, paths, pathBase,
+                                             reference, mask, transformType, transformValues))
+        {
+            context->stencilStrokePathInstanced(numPath, pathNameType, paths, pathBase, reference,
+                                                mask, transformType, transformValues);
+        }
+    }
+}
+
+void GL_APIENTRY StencilFillPathInstancedCHROMIUM(GLsizei numPaths,
+                                                  GLenum pathNameType,
+                                                  const void *paths,
+                                                  GLuint pathBase,
+                                                  GLenum fillMode,
+                                                  GLuint mask,
+                                                  GLenum transformType,
+                                                  const GLfloat *transformValues)
+{
+    EVENT(
+        "(GLsizei numPaths = %d, GLenum pathNameType = 0x%X, const void * paths = 0x%0.8p, GLuint "
+        "pathBase = %u, GLenum fillMode = 0x%X, GLuint mask = %u, GLenum transformType = 0x%X, "
+        "const GLfloat * transformValues = 0x%0.8p)",
+        numPaths, pathNameType, paths, pathBase, fillMode, mask, transformType, transformValues);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::StencilFillPathInstancedCHROMIUM>(
+            numPaths, pathNameType, paths, pathBase, fillMode, mask, transformType,
+            transformValues);
+
+        if (context->skipValidation() || ValidateStencilFillPathInstancedCHROMIUM(
+                                             context, numPaths, pathNameType, paths, pathBase,
+                                             fillMode, mask, transformType, transformValues))
+        {
+            context->stencilFillPathInstanced(numPaths, pathNameType, paths, pathBase, fillMode,
+                                              mask, transformType, transformValues);
+        }
+    }
+}
+
+void GL_APIENTRY StencilThenCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
+                                                           GLenum pathNameType,
+                                                           const void *paths,
+                                                           GLuint pathBase,
+                                                           GLenum fillMode,
+                                                           GLuint mask,
+                                                           GLenum coverMode,
+                                                           GLenum transformType,
+                                                           const GLfloat *transformValues)
+{
+    EVENT(
+        "(GLsizei numPaths = %d, GLenum pathNameType = 0x%X, const void * paths = 0x%0.8p, GLuint "
+        "pathBase = %u, GLenum fillMode = 0x%X, GLuint mask = %u, GLenum coverMode = 0x%X, GLenum "
+        "transformType = 0x%X, const GLfloat * transformValues = 0x%0.8p)",
+        numPaths, pathNameType, paths, pathBase, fillMode, mask, coverMode, transformType,
+        transformValues);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::StencilThenCoverFillPathInstancedCHROMIUM>(
+            numPaths, pathNameType, paths, pathBase, fillMode, mask, coverMode, transformType,
+            transformValues);
+
+        if (context->skipValidation() ||
+            ValidateStencilThenCoverFillPathInstancedCHROMIUM(
+                context, numPaths, pathNameType, paths, pathBase, fillMode, mask, coverMode,
+                transformType, transformValues))
+        {
+            context->stencilThenCoverFillPathInstanced(numPaths, pathNameType, paths, pathBase,
+                                                       fillMode, mask, coverMode, transformType,
+                                                       transformValues);
+        }
+    }
+}
+
+void GL_APIENTRY StencilThenCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
+                                                             GLenum pathNameType,
+                                                             const void *paths,
+                                                             GLuint pathBase,
+                                                             GLint reference,
+                                                             GLuint mask,
+                                                             GLenum coverMode,
+                                                             GLenum transformType,
+                                                             const GLfloat *transformValues)
+{
+    EVENT(
+        "(GLsizei numPaths = %d, GLenum pathNameType = 0x%X, const void * paths = 0x%0.8p, GLuint "
+        "pathBase = %u, GLint reference = %d, GLuint mask = %u, GLenum coverMode = 0x%X, GLenum "
+        "transformType = 0x%X, const GLfloat * transformValues = 0x%0.8p)",
+        numPaths, pathNameType, paths, pathBase, reference, mask, coverMode, transformType,
+        transformValues);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::StencilThenCoverStrokePathInstancedCHROMIUM>(
+            numPaths, pathNameType, paths, pathBase, reference, mask, coverMode, transformType,
+            transformValues);
+
+        if (context->skipValidation() ||
+            ValidateStencilThenCoverStrokePathInstancedCHROMIUM(
+                context, numPaths, pathNameType, paths, pathBase, reference, mask, coverMode,
+                transformType, transformValues))
+        {
+            context->stencilThenCoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
+                                                         reference, mask, coverMode, transformType,
+                                                         transformValues);
+        }
+    }
+}
+
+void GL_APIENTRY BindFragmentInputLocationCHROMIUM(GLuint programs,
+                                                   GLint location,
+                                                   const GLchar *name)
+{
+    EVENT("(GLuint programs = %u, GLint location = %d, const GLchar * name = 0x%0.8p)", programs,
+          location, name);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::BindFragmentInputLocationCHROMIUM>(programs, location,
+                                                                             name);
+
+        if (context->skipValidation() ||
+            ValidateBindFragmentInputLocationCHROMIUM(context, programs, location, name))
+        {
+            context->bindFragmentInputLocation(programs, location, name);
+        }
+    }
+}
+
+void GL_APIENTRY ProgramPathFragmentInputGenCHROMIUM(GLuint program,
+                                                     GLint location,
+                                                     GLenum genMode,
+                                                     GLint components,
+                                                     const GLfloat *coeffs)
+{
+    EVENT(
+        "(GLuint program = %u, GLint location = %d, GLenum genMode = 0x%X, GLint components = %d, "
+        "const GLfloat * coeffs = 0x%0.8p)",
+        program, location, genMode, components, coeffs);
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        context->gatherParams<EntryPoint::ProgramPathFragmentInputGenCHROMIUM>(
+            program, location, genMode, components, coeffs);
+
+        if (context->skipValidation() ||
+            ValidateProgramPathFragmentInputGenCHROMIUM(context, program, location, genMode,
+                                                        components, coeffs))
+        {
+            context->programPathFragmentInputGen(program, location, genMode, components, coeffs);
+        }
+    }
+}
+
 // GL_EXT_debug_marker
 void GL_APIENTRY InsertEventMarkerEXT(GLsizei length, const GLchar *marker)
 {
diff --git a/src/libGLESv2/entry_points_gles_ext_autogen.h b/src/libGLESv2/entry_points_gles_ext_autogen.h
index 2e287d9..380bb20 100644
--- a/src/libGLESv2/entry_points_gles_ext_autogen.h
+++ b/src/libGLESv2/entry_points_gles_ext_autogen.h
@@ -1,5 +1,5 @@
 // GENERATED FILE - DO NOT EDIT.
-// Generated by generate_entry_points.py using data from gl.xml.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
 //
 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
@@ -51,12 +51,523 @@
                                                          GLsizei primcount);
 ANGLE_EXPORT void GL_APIENTRY VertexAttribDivisorANGLE(GLuint index, GLuint divisor);
 
+// GL_ANGLE_multiview
+ANGLE_EXPORT void GL_APIENTRY FramebufferTextureMultiviewLayeredANGLE(GLenum target,
+                                                                      GLenum attachment,
+                                                                      GLuint texture,
+                                                                      GLint level,
+                                                                      GLint baseViewIndex,
+                                                                      GLsizei numViews);
+ANGLE_EXPORT void GL_APIENTRY
+FramebufferTextureMultiviewSideBySideANGLE(GLenum target,
+                                           GLenum attachment,
+                                           GLuint texture,
+                                           GLint level,
+                                           GLsizei numViews,
+                                           const GLint *viewportOffsets);
+
+// GL_ANGLE_request_extension
+ANGLE_EXPORT void GL_APIENTRY RequestExtensionANGLE(const GLchar *name);
+
+// GL_ANGLE_robust_client_memory
+ANGLE_EXPORT void GL_APIENTRY GetBooleanvRobustANGLE(GLenum pname,
+                                                     GLsizei bufSize,
+                                                     GLsizei *length,
+                                                     GLboolean *params);
+ANGLE_EXPORT void GL_APIENTRY GetBufferParameterivRobustANGLE(GLenum target,
+                                                              GLenum pname,
+                                                              GLsizei bufSize,
+                                                              GLsizei *length,
+                                                              GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetFloatvRobustANGLE(GLenum pname,
+                                                   GLsizei bufSize,
+                                                   GLsizei *length,
+                                                   GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetFramebufferAttachmentParameterivRobustANGLE(GLenum target,
+                                                                             GLenum attachment,
+                                                                             GLenum pname,
+                                                                             GLsizei bufSize,
+                                                                             GLsizei *length,
+                                                                             GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetIntegervRobustANGLE(GLenum pname,
+                                                     GLsizei bufSize,
+                                                     GLsizei *length,
+                                                     GLint *data);
+ANGLE_EXPORT void GL_APIENTRY GetProgramivRobustANGLE(GLuint program,
+                                                      GLenum pname,
+                                                      GLsizei bufSize,
+                                                      GLsizei *length,
+                                                      GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetRenderbufferParameterivRobustANGLE(GLenum target,
+                                                                    GLenum pname,
+                                                                    GLsizei bufSize,
+                                                                    GLsizei *length,
+                                                                    GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetShaderivRobustANGLE(GLuint shader,
+                                                     GLenum pname,
+                                                     GLsizei bufSize,
+                                                     GLsizei *length,
+                                                     GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterfvRobustANGLE(GLenum target,
+                                                           GLenum pname,
+                                                           GLsizei bufSize,
+                                                           GLsizei *length,
+                                                           GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterivRobustANGLE(GLenum target,
+                                                           GLenum pname,
+                                                           GLsizei bufSize,
+                                                           GLsizei *length,
+                                                           GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetUniformfvRobustANGLE(GLuint program,
+                                                      GLint location,
+                                                      GLsizei bufSize,
+                                                      GLsizei *length,
+                                                      GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetUniformivRobustANGLE(GLuint program,
+                                                      GLint location,
+                                                      GLsizei bufSize,
+                                                      GLsizei *length,
+                                                      GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribfvRobustANGLE(GLuint index,
+                                                           GLenum pname,
+                                                           GLsizei bufSize,
+                                                           GLsizei *length,
+                                                           GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribivRobustANGLE(GLuint index,
+                                                           GLenum pname,
+                                                           GLsizei bufSize,
+                                                           GLsizei *length,
+                                                           GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribPointervRobustANGLE(GLuint index,
+                                                                 GLenum pname,
+                                                                 GLsizei bufSize,
+                                                                 GLsizei *length,
+                                                                 void **pointer);
+ANGLE_EXPORT void GL_APIENTRY ReadPixelsRobustANGLE(GLint x,
+                                                    GLint y,
+                                                    GLsizei width,
+                                                    GLsizei height,
+                                                    GLenum format,
+                                                    GLenum type,
+                                                    GLsizei bufSize,
+                                                    GLsizei *length,
+                                                    GLsizei *columns,
+                                                    GLsizei *rows,
+                                                    void *pixels);
+ANGLE_EXPORT void GL_APIENTRY TexImage2DRobustANGLE(GLenum target,
+                                                    GLint level,
+                                                    GLint internalformat,
+                                                    GLsizei width,
+                                                    GLsizei height,
+                                                    GLint border,
+                                                    GLenum format,
+                                                    GLenum type,
+                                                    GLsizei bufSize,
+                                                    const void *pixels);
+ANGLE_EXPORT void GL_APIENTRY TexParameterfvRobustANGLE(GLenum target,
+                                                        GLenum pname,
+                                                        GLsizei bufSize,
+                                                        const GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY TexParameterivRobustANGLE(GLenum target,
+                                                        GLenum pname,
+                                                        GLsizei bufSize,
+                                                        const GLint *params);
+ANGLE_EXPORT void GL_APIENTRY TexSubImage2DRobustANGLE(GLenum target,
+                                                       GLint level,
+                                                       GLint xoffset,
+                                                       GLint yoffset,
+                                                       GLsizei width,
+                                                       GLsizei height,
+                                                       GLenum format,
+                                                       GLenum type,
+                                                       GLsizei bufSize,
+                                                       const void *pixels);
+ANGLE_EXPORT void GL_APIENTRY TexImage3DRobustANGLE(GLenum target,
+                                                    GLint level,
+                                                    GLint internalformat,
+                                                    GLsizei width,
+                                                    GLsizei height,
+                                                    GLsizei depth,
+                                                    GLint border,
+                                                    GLenum format,
+                                                    GLenum type,
+                                                    GLsizei bufSize,
+                                                    const void *pixels);
+ANGLE_EXPORT void GL_APIENTRY TexSubImage3DRobustANGLE(GLenum target,
+                                                       GLint level,
+                                                       GLint xoffset,
+                                                       GLint yoffset,
+                                                       GLint zoffset,
+                                                       GLsizei width,
+                                                       GLsizei height,
+                                                       GLsizei depth,
+                                                       GLenum format,
+                                                       GLenum type,
+                                                       GLsizei bufSize,
+                                                       const void *pixels);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexImage2DRobustANGLE(GLenum target,
+                                                              GLint level,
+                                                              GLenum internalformat,
+                                                              GLsizei width,
+                                                              GLsizei height,
+                                                              GLint border,
+                                                              GLsizei imageSize,
+                                                              GLsizei dataSize,
+                                                              const GLvoid *data);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage2DRobustANGLE(GLenum target,
+                                                                 GLint level,
+                                                                 GLsizei xoffset,
+                                                                 GLsizei yoffset,
+                                                                 GLsizei width,
+                                                                 GLsizei height,
+                                                                 GLenum format,
+                                                                 GLsizei imageSize,
+                                                                 GLsizei dataSize,
+                                                                 const GLvoid *data);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexImage3DRobustANGLE(GLenum target,
+                                                              GLint level,
+                                                              GLenum internalformat,
+                                                              GLsizei width,
+                                                              GLsizei height,
+                                                              GLsizei depth,
+                                                              GLint border,
+                                                              GLsizei imageSize,
+                                                              GLsizei dataSize,
+                                                              const GLvoid *data);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage3DRobustANGLE(GLenum target,
+                                                                 GLint level,
+                                                                 GLint xoffset,
+                                                                 GLint yoffset,
+                                                                 GLint zoffset,
+                                                                 GLsizei width,
+                                                                 GLsizei height,
+                                                                 GLsizei depth,
+                                                                 GLenum format,
+                                                                 GLsizei imageSize,
+                                                                 GLsizei dataSize,
+                                                                 const GLvoid *data);
+ANGLE_EXPORT void GL_APIENTRY
+GetQueryivRobustANGLE(GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectuivRobustANGLE(GLuint id,
+                                                           GLenum pname,
+                                                           GLsizei bufSize,
+                                                           GLsizei *length,
+                                                           GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY GetBufferPointervRobustANGLE(GLenum target,
+                                                           GLenum pname,
+                                                           GLsizei bufSize,
+                                                           GLsizei *length,
+                                                           void **params);
+ANGLE_EXPORT void GL_APIENTRY GetIntegeri_vRobustANGLE(GLenum target,
+                                                       GLuint index,
+                                                       GLsizei bufSize,
+                                                       GLsizei *length,
+                                                       GLint *data);
+ANGLE_EXPORT void GL_APIENTRY GetInternalformativRobustANGLE(GLenum target,
+                                                             GLenum internalformat,
+                                                             GLenum pname,
+                                                             GLsizei bufSize,
+                                                             GLsizei *length,
+                                                             GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIivRobustANGLE(GLuint index,
+                                                            GLenum pname,
+                                                            GLsizei bufSize,
+                                                            GLsizei *length,
+                                                            GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIuivRobustANGLE(GLuint index,
+                                                             GLenum pname,
+                                                             GLsizei bufSize,
+                                                             GLsizei *length,
+                                                             GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY GetUniformuivRobustANGLE(GLuint program,
+                                                       GLint location,
+                                                       GLsizei bufSize,
+                                                       GLsizei *length,
+                                                       GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockivRobustANGLE(GLuint program,
+                                                                 GLuint uniformBlockIndex,
+                                                                 GLenum pname,
+                                                                 GLsizei bufSize,
+                                                                 GLsizei *length,
+                                                                 GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetInteger64vRobustANGLE(GLenum pname,
+                                                       GLsizei bufSize,
+                                                       GLsizei *length,
+                                                       GLint64 *data);
+ANGLE_EXPORT void GL_APIENTRY GetInteger64i_vRobustANGLE(GLenum target,
+                                                         GLuint index,
+                                                         GLsizei bufSize,
+                                                         GLsizei *length,
+                                                         GLint64 *data);
+ANGLE_EXPORT void GL_APIENTRY GetBufferParameteri64vRobustANGLE(GLenum target,
+                                                                GLenum pname,
+                                                                GLsizei bufSize,
+                                                                GLsizei *length,
+                                                                GLint64 *params);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterivRobustANGLE(GLuint sampler,
+                                                            GLuint pname,
+                                                            GLsizei bufSize,
+                                                            const GLint *param);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterfvRobustANGLE(GLuint sampler,
+                                                            GLenum pname,
+                                                            GLsizei bufSize,
+                                                            const GLfloat *param);
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterivRobustANGLE(GLuint sampler,
+                                                               GLenum pname,
+                                                               GLsizei bufSize,
+                                                               GLsizei *length,
+                                                               GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterfvRobustANGLE(GLuint sampler,
+                                                               GLenum pname,
+                                                               GLsizei bufSize,
+                                                               GLsizei *length,
+                                                               GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetFramebufferParameterivRobustANGLE(GLuint sampler,
+                                                                   GLenum pname,
+                                                                   GLsizei bufSize,
+                                                                   GLsizei *length,
+                                                                   GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetProgramInterfaceivRobustANGLE(GLuint program,
+                                                               GLenum programInterface,
+                                                               GLenum pname,
+                                                               GLsizei bufSize,
+                                                               GLsizei *length,
+                                                               GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetBooleani_vRobustANGLE(GLenum target,
+                                                       GLuint index,
+                                                       GLsizei bufSize,
+                                                       GLsizei *length,
+                                                       GLboolean *data);
+ANGLE_EXPORT void GL_APIENTRY GetMultisamplefvRobustANGLE(GLenum pname,
+                                                          GLuint index,
+                                                          GLsizei bufSize,
+                                                          GLsizei *length,
+                                                          GLfloat *val);
+ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameterivRobustANGLE(GLenum target,
+                                                                GLint level,
+                                                                GLenum pname,
+                                                                GLsizei bufSize,
+                                                                GLsizei *length,
+                                                                GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameterfvRobustANGLE(GLenum target,
+                                                                GLint level,
+                                                                GLenum pname,
+                                                                GLsizei bufSize,
+                                                                GLsizei *length,
+                                                                GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetPointervRobustANGLERobustANGLE(GLenum pname,
+                                                                GLsizei bufSize,
+                                                                GLsizei *length,
+                                                                void **params);
+ANGLE_EXPORT void GL_APIENTRY ReadnPixelsRobustANGLE(GLint x,
+                                                     GLint y,
+                                                     GLsizei width,
+                                                     GLsizei height,
+                                                     GLenum format,
+                                                     GLenum type,
+                                                     GLsizei bufSize,
+                                                     GLsizei *length,
+                                                     GLsizei *columns,
+                                                     GLsizei *rows,
+                                                     void *data);
+ANGLE_EXPORT void GL_APIENTRY GetnUniformfvRobustANGLE(GLuint program,
+                                                       GLint location,
+                                                       GLsizei bufSize,
+                                                       GLsizei *length,
+                                                       GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetnUniformivRobustANGLE(GLuint program,
+                                                       GLint location,
+                                                       GLsizei bufSize,
+                                                       GLsizei *length,
+                                                       GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetnUniformuivRobustANGLE(GLuint program,
+                                                        GLint location,
+                                                        GLsizei bufSize,
+                                                        GLsizei *length,
+                                                        GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY TexParameterIivRobustANGLE(GLenum target,
+                                                         GLenum pname,
+                                                         GLsizei bufSize,
+                                                         const GLint *params);
+ANGLE_EXPORT void GL_APIENTRY TexParameterIuivRobustANGLE(GLenum target,
+                                                          GLenum pname,
+                                                          GLsizei bufSize,
+                                                          const GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterIivRobustANGLE(GLenum target,
+                                                            GLenum pname,
+                                                            GLsizei bufSize,
+                                                            GLsizei *length,
+                                                            GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterIuivRobustANGLE(GLenum target,
+                                                             GLenum pname,
+                                                             GLsizei bufSize,
+                                                             GLsizei *length,
+                                                             GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterIivRobustANGLE(GLuint sampler,
+                                                             GLenum pname,
+                                                             GLsizei bufSize,
+                                                             const GLint *param);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterIuivRobustANGLE(GLuint sampler,
+                                                              GLenum pname,
+                                                              GLsizei bufSize,
+                                                              const GLuint *param);
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterIivRobustANGLE(GLuint sampler,
+                                                                GLenum pname,
+                                                                GLsizei bufSize,
+                                                                GLsizei *length,
+                                                                GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterIuivRobustANGLE(GLuint sampler,
+                                                                 GLenum pname,
+                                                                 GLsizei bufSize,
+                                                                 GLsizei *length,
+                                                                 GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectivRobustANGLE(GLuint id,
+                                                          GLenum pname,
+                                                          GLsizei bufSize,
+                                                          GLsizei *length,
+                                                          GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjecti64vRobustANGLE(GLuint id,
+                                                            GLenum pname,
+                                                            GLsizei bufSize,
+                                                            GLsizei *length,
+                                                            GLint64 *params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectui64vRobustANGLE(GLuint id,
+                                                             GLenum pname,
+                                                             GLsizei bufSize,
+                                                             GLsizei *length,
+                                                             GLuint64 *params);
+
 // GL_ANGLE_translated_shader_source
 ANGLE_EXPORT void GL_APIENTRY GetTranslatedShaderSourceANGLE(GLuint shader,
                                                              GLsizei bufsize,
                                                              GLsizei *length,
                                                              GLchar *source);
 
+// GL_CHROMIUM_bind_uniform_location
+ANGLE_EXPORT void GL_APIENTRY BindUniformLocationCHROMIUM(GLuint program,
+                                                          GLint location,
+                                                          const GLchar *name);
+
+// GL_CHROMIUM_copy_compressed_texture
+ANGLE_EXPORT void GL_APIENTRY CompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId);
+
+// GL_CHROMIUM_copy_texture
+ANGLE_EXPORT void GL_APIENTRY CopyTextureCHROMIUM(GLuint sourceId,
+                                                  GLint sourceLevel,
+                                                  GLenum destTarget,
+                                                  GLuint destId,
+                                                  GLint destLevel,
+                                                  GLint internalFormat,
+                                                  GLenum destType,
+                                                  GLboolean unpackFlipY,
+                                                  GLboolean unpackPremultiplyAlpha,
+                                                  GLboolean unpackUnmultiplyAlpha);
+ANGLE_EXPORT void GL_APIENTRY CopySubTextureCHROMIUM(GLuint sourceId,
+                                                     GLint sourceLevel,
+                                                     GLenum destTarget,
+                                                     GLuint destId,
+                                                     GLint destLevel,
+                                                     GLint xoffset,
+                                                     GLint yoffset,
+                                                     GLint x,
+                                                     GLint y,
+                                                     GLint width,
+                                                     GLint height,
+                                                     GLboolean unpackFlipY,
+                                                     GLboolean unpackPremultiplyAlpha,
+                                                     GLboolean unpackUnmultiplyAlpha);
+
+// GL_CHROMIUM_framebuffer_mixed_samples
+ANGLE_EXPORT void GL_APIENTRY CoverageModulationCHROMIUM(GLenum components);
+ANGLE_EXPORT void GL_APIENTRY MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *matrix);
+ANGLE_EXPORT void GL_APIENTRY MatrixLoadIdentityCHROMIUM(GLenum matrixMode);
+
+// GL_CHROMIUM_path_rendering
+ANGLE_EXPORT GLuint GL_APIENTRY GenPathsCHROMIUM(GLsizei range);
+ANGLE_EXPORT void GL_APIENTRY DeletePathsCHROMIUM(GLuint first, GLsizei range);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsPathCHROMIUM(GLuint path);
+ANGLE_EXPORT void GL_APIENTRY PathCommandsCHROMIUM(GLuint path,
+                                                   GLsizei numCommands,
+                                                   const GLubyte *commands,
+                                                   GLsizei numCoords,
+                                                   GLenum coordType,
+                                                   const void *coords);
+ANGLE_EXPORT void GL_APIENTRY PathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value);
+ANGLE_EXPORT void GL_APIENTRY PathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value);
+ANGLE_EXPORT void GL_APIENTRY GetPathParameterfvCHROMIUM(GLuint path, GLenum pname, GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY GetPathParameterivCHROMIUM(GLuint path, GLenum pname, GLint *value);
+ANGLE_EXPORT void GL_APIENTRY PathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY StencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY StencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY CoverFillPathCHROMIUM(GLuint path, GLenum coverMode);
+ANGLE_EXPORT void GL_APIENTRY CoverStrokePathCHROMIUM(GLuint path, GLenum coverMode);
+ANGLE_EXPORT void GL_APIENTRY StencilThenCoverFillPathCHROMIUM(GLuint path,
+                                                               GLenum fillMode,
+                                                               GLuint mask,
+                                                               GLenum coverMode);
+ANGLE_EXPORT void GL_APIENTRY StencilThenCoverStrokePathCHROMIUM(GLuint path,
+                                                                 GLint reference,
+                                                                 GLuint mask,
+                                                                 GLenum coverMode);
+ANGLE_EXPORT void GL_APIENTRY CoverFillPathInstancedCHROMIUM(GLsizei numPath,
+                                                             GLenum pathNameType,
+                                                             const void *paths,
+                                                             GLuint pathBase,
+                                                             GLenum coverMode,
+                                                             GLenum transformType,
+                                                             const GLfloat *transformValues);
+ANGLE_EXPORT void GL_APIENTRY CoverStrokePathInstancedCHROMIUM(GLsizei numPath,
+                                                               GLenum pathNameType,
+                                                               const void *paths,
+                                                               GLuint pathBase,
+                                                               GLenum coverMode,
+                                                               GLenum transformType,
+                                                               const GLfloat *transformValues);
+ANGLE_EXPORT void GL_APIENTRY StencilStrokePathInstancedCHROMIUM(GLsizei numPath,
+                                                                 GLenum pathNameType,
+                                                                 const void *paths,
+                                                                 GLuint pathBase,
+                                                                 GLint reference,
+                                                                 GLuint mask,
+                                                                 GLenum transformType,
+                                                                 const GLfloat *transformValues);
+ANGLE_EXPORT void GL_APIENTRY StencilFillPathInstancedCHROMIUM(GLsizei numPaths,
+                                                               GLenum pathNameType,
+                                                               const void *paths,
+                                                               GLuint pathBase,
+                                                               GLenum fillMode,
+                                                               GLuint mask,
+                                                               GLenum transformType,
+                                                               const GLfloat *transformValues);
+ANGLE_EXPORT void GL_APIENTRY
+StencilThenCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
+                                          GLenum pathNameType,
+                                          const void *paths,
+                                          GLuint pathBase,
+                                          GLenum fillMode,
+                                          GLuint mask,
+                                          GLenum coverMode,
+                                          GLenum transformType,
+                                          const GLfloat *transformValues);
+ANGLE_EXPORT void GL_APIENTRY
+StencilThenCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
+                                            GLenum pathNameType,
+                                            const void *paths,
+                                            GLuint pathBase,
+                                            GLint reference,
+                                            GLuint mask,
+                                            GLenum coverMode,
+                                            GLenum transformType,
+                                            const GLfloat *transformValues);
+ANGLE_EXPORT void GL_APIENTRY BindFragmentInputLocationCHROMIUM(GLuint programs,
+                                                                GLint location,
+                                                                const GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY ProgramPathFragmentInputGenCHROMIUM(GLuint program,
+                                                                  GLint location,
+                                                                  GLenum genMode,
+                                                                  GLint components,
+                                                                  const GLfloat *coeffs);
+
 // GL_EXT_debug_marker
 ANGLE_EXPORT void GL_APIENTRY InsertEventMarkerEXT(GLsizei length, const GLchar *marker);
 ANGLE_EXPORT void GL_APIENTRY PopGroupMarkerEXT();
diff --git a/src/libGLESv2/gen_proc_table.py b/src/libGLESv2/gen_proc_table.py
index 40d93d8..cd2a3ab 100644
--- a/src/libGLESv2/gen_proc_table.py
+++ b/src/libGLESv2/gen_proc_table.py
@@ -31,7 +31,6 @@
 #include "libGLESv2/entry_points_egl_ext.h"
 #include "libGLESv2/entry_points_gles_1_0_autogen.h"
 #include "libGLESv2/entry_points_gles_2_0_autogen.h"
-#include "libGLESv2/entry_points_gles_2_0_ext.h"
 #include "libGLESv2/entry_points_gles_3_0_autogen.h"
 #include "libGLESv2/entry_points_gles_3_1_autogen.h"
 #include "libGLESv2/entry_points_gles_ext_autogen.h"
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index 9dce1ea..bfeeff8 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -10,7 +10,6 @@
 
 #include "libGLESv2/entry_points_gles_1_0_autogen.h"
 #include "libGLESv2/entry_points_gles_2_0_autogen.h"
-#include "libGLESv2/entry_points_gles_2_0_ext.h"
 #include "libGLESv2/entry_points_gles_3_0_autogen.h"
 #include "libGLESv2/entry_points_gles_3_1_autogen.h"
 #include "libGLESv2/entry_points_gles_ext_autogen.h"
diff --git a/src/libGLESv2/proc_table_autogen.cpp b/src/libGLESv2/proc_table_autogen.cpp
index fb1967e..6ec6001 100644
--- a/src/libGLESv2/proc_table_autogen.cpp
+++ b/src/libGLESv2/proc_table_autogen.cpp
@@ -15,7 +15,6 @@
 #include "libGLESv2/entry_points_egl_ext.h"
 #include "libGLESv2/entry_points_gles_1_0_autogen.h"
 #include "libGLESv2/entry_points_gles_2_0_autogen.h"
-#include "libGLESv2/entry_points_gles_2_0_ext.h"
 #include "libGLESv2/entry_points_gles_3_0_autogen.h"
 #include "libGLESv2/entry_points_gles_3_1_autogen.h"
 #include "libGLESv2/entry_points_gles_ext_autogen.h"
diff --git a/src/tests/BUILD.gn b/src/tests/BUILD.gn
index b575198..fc18151 100644
--- a/src/tests/BUILD.gn
+++ b/src/tests/BUILD.gn
@@ -577,6 +577,13 @@
       "//build/config/compiler:no_chromium_code",
       angle_root + ":internal_config",
     ]
+    if (is_clang) {
+      cflags_cc = [
+        # Supresses self assign warnings in SharedPtr_selfTest
+        # Can be removed if dEQP or clang are fixed
+        "-Wno-self-assign",
+      ]
+    }
 
     sources = rebase_path(deqp_gypi.deqp_libtester_decpp_sources, ".", "../..")
   }
@@ -589,6 +596,10 @@
       cflags_cc = [
         "-Wno-delete-non-virtual-dtor",
         "-Wno-deprecated",
+
+        # Supresses self assign warning in setLumSat
+        # Can be removed if dEQP or clang are fixed
+        "-Wno-self-assign",
       ]
     }
   }
diff --git a/src/tests/angle_end2end_tests.gypi b/src/tests/angle_end2end_tests.gypi
index c52a3bc..9e4e696 100644
--- a/src/tests/angle_end2end_tests.gypi
+++ b/src/tests/angle_end2end_tests.gypi
@@ -49,13 +49,16 @@
             '<(angle_path)/src/tests/gl_tests/GeometryShaderTest.cpp',
             '<(angle_path)/src/tests/gl_tests/gles1/AlphaFuncTest.cpp',
             '<(angle_path)/src/tests/gl_tests/gles1/ClientActiveTextureTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/gles1/ClientStateEnable.cpp',
             '<(angle_path)/src/tests/gl_tests/gles1/CurrentColorTest.cpp',
             '<(angle_path)/src/tests/gl_tests/gles1/CurrentNormalTest.cpp',
             '<(angle_path)/src/tests/gl_tests/gles1/CurrentTextureCoordsTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/gles1/MatrixBuiltinsTest.cpp',
             '<(angle_path)/src/tests/gl_tests/gles1/MatrixLoadTest.cpp',
             '<(angle_path)/src/tests/gl_tests/gles1/MatrixModeTest.cpp',
             '<(angle_path)/src/tests/gl_tests/gles1/MatrixMultTest.cpp',
             '<(angle_path)/src/tests/gl_tests/gles1/MatrixStackTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/gles1/VertexPointerTest.cpp',
             '<(angle_path)/src/tests/gl_tests/GLSLTest.cpp',
             '<(angle_path)/src/tests/gl_tests/ImageTest.cpp',
             '<(angle_path)/src/tests/gl_tests/IncompleteTextureTest.cpp',
diff --git a/src/tests/deqp.gypi b/src/tests/deqp.gypi
index a96a9a4..1c5dcc2 100644
--- a/src/tests/deqp.gypi
+++ b/src/tests/deqp.gypi
@@ -135,7 +135,10 @@
             '<(deqp_path)/modules/gles2/functional/es2fBufferWriteTests.hpp',
             '<(deqp_path)/modules/gles2/functional/es2fClippingTests.cpp',
             '<(deqp_path)/modules/gles2/functional/es2fClippingTests.hpp',
-            '<(deqp_path)/modules/gles2/functional/es2fColorClearTest.cpp',
+            # Work around a bug in this test by using a local override.
+            # TODO(jmadill): Restore after rolling dEQP.
+            #'<(deqp_path)/modules/gles2/functional/es2fColorClearTest.cpp',
+            '<(angle_path)/src/tests/deqp_support/es2fColorClearTest.cpp',
             '<(deqp_path)/modules/gles2/functional/es2fColorClearTest.hpp',
             '<(deqp_path)/modules/gles2/functional/es2fDebugMarkerTests.cpp',
             '<(deqp_path)/modules/gles2/functional/es2fDebugMarkerTests.hpp',
@@ -1114,8 +1117,7 @@
             '<(deqp_path)/framework/qphelper/qpCrashHandler.c',
             '<(deqp_path)/framework/qphelper/qpDebugOut.c',
             '<(deqp_path)/framework/qphelper/qpInfo.c',
-            # TODO(jmadill): Restore this when we upstream the change.
-            #'<(deqp_path)/framework/qphelper/qpTestLog.c',
+            '<(deqp_path)/framework/qphelper/qpTestLog.c',
             '<(deqp_path)/framework/qphelper/qpWatchDog.c',
             '<(deqp_path)/framework/qphelper/qpXmlWriter.c',
             '<(deqp_path)/framework/randomshaders/rsgBinaryOps.cpp',
@@ -1184,8 +1186,6 @@
             '<(deqp_path)/modules/glshared/glsTextureTestUtil.cpp',
             '<(deqp_path)/modules/glshared/glsUniformBlockCase.cpp',
             '<(deqp_path)/modules/glshared/glsVertexArrayTests.cpp',
-            # TODO(jmadill): Remove this when we upstream the change.
-            '<(angle_path)/src/tests/deqp_support/qpTestLog.c',
             '<(angle_path)/src/tests/deqp_support/tcuANGLENativeDisplayFactory.cpp',
             '<(angle_path)/src/tests/deqp_support/tcuANGLENativeDisplayFactory.h',
             # TODO(jmadill): integrate with dEQP
diff --git a/src/tests/deqp_support/deqp_gles2_test_expectations.txt b/src/tests/deqp_support/deqp_gles2_test_expectations.txt
index 9470de6..2d9cf9c 100644
--- a/src/tests/deqp_support/deqp_gles2_test_expectations.txt
+++ b/src/tests/deqp_support/deqp_gles2_test_expectations.txt
@@ -188,41 +188,51 @@
 1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.srgb8 = FAIL
 
 // Vulkan failures
-2455 VULKAN : dEQP-GLES2.functional.color_clear.masked_scissor* = SKIP
-2161 VULKAN : dEQP-GLES2.functional.color_clear.complex_* = SKIP
-2161 VULKAN : dEQP-GLES2.functional.color_clear.long_masked_* = SKIP
+2455 VULKAN : dEQP-GLES2.functional.color_clear.masked_rg* = FAIL
+2455 VULKAN : dEQP-GLES2.functional.color_clear.masked_scissor* = FAIL
+2455 VULKAN : dEQP-GLES2.functional.color_clear.complex_* = FAIL
+2455 VULKAN : dEQP-GLES2.functional.color_clear.long_masked_* = FAIL
 2161 VULKAN : dEQP-GLES2.functional.prerequisite.* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.implementation_limits.* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.buffer.* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.light_amount.* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.shaders.* = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.format.a8_cube_pot = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.format.l8_cube_pot = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.format.la88_cube_pot = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.format.rgb565_cube_pot = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.format.rgb888_cube_pot = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.format.rgba4444_cube_pot = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.format.rgba5551_cube_pot = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.format.rgba8888_cube_pot = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.64x64_l8_mipmap = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.64x64_rgba4444_mipmap = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.64x64_rgb888_mipmap = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.64x64_rgba8888_mipmap = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.512x512_l8_mipmap = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.512x512_rgba4444_mipmap = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.512x512_rgb888_mipmap = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.512x512_rgba8888_mipmap = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.1024x1024_l8_mipmap = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.1024x1024_rgba4444_mipmap = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.1024x1024_rgb888_mipmap = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.1024x1024_rgba8888_mipmap = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.2048x2048_l8_mipmap = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.2048x2048_rgba4444_mipmap = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.2048x2048_rgb888_mipmap = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.2048x2048_rgba8888_mipmap = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.size.cube.* = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.wrap.* = SKIP
-2161 VULKAN : dEQP-GLES2.functional.texture.filtering.* = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.64x64_l8_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.64x64_rgba4444_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.64x64_rgb888_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.64x64_rgba8888_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.512x512_l8_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.512x512_rgba4444_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.512x512_rgb888_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.512x512_rgba8888_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.1024x1024_l8_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.1024x1024_rgba4444_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.1024x1024_rgb888_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.1024x1024_rgba8888_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.2048x2048_l8_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.2048x2048_rgba4444_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.2048x2048_rgb888_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.2048x2048_rgba8888_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.16x16_rgba4444_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.16x16_rgb888_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.16x16_rgba8888_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.64x64_l8_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.64x64_rgba4444_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.64x64_rgb888_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.64x64_rgba8888_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.128x128_l8_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.128x128_rgba4444_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.128x128_rgb888_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.128x128_rgba8888_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.256x256_l8_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.256x256_rgb888_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.256x256_rgba8888_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.512x512_l8_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.512x512_rgb888_mipmap = SKIP
+2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.512x512_rgba8888_mipmap = SKIP
+2161 VULKAN : dEQP-GLES2.functional.texture.filtering.cube.* = SKIP
+2161 VULKAN : dEQP-GLES2.functional.texture.filtering.nearest_mipmap_* = SKIP
+2161 VULKAN : dEQP-GLES2.functional.texture.filtering.linear_mipmap_* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.texture.mipmap.* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.texture.specification.* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.texture.completeness.* = SKIP
@@ -312,7 +322,6 @@
 2161 VULKAN : dEQP-GLES2.functional.uniform_api.value.assigned.unused_uniforms.* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.uniform_api.random.* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.read_pixels.* = SKIP
-2161 VULKAN : dEQP-GLES2.functional.depth_range.* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.dither.* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.state_query.* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.clipping.* = SKIP
@@ -336,4 +345,4 @@
 2161 VULKAN : dEQP-GLES2.functional.draw.random.* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.default_vertex_attrib.* = SKIP
 2161 VULKAN : dEQP-GLES2.functional.lifetime.* = SKIP
-2161 VULKAN : dEQP-GLES2.functional.debug_marker.* = SKIP
\ No newline at end of file
+2161 VULKAN : dEQP-GLES2.functional.debug_marker.* = SKIP
diff --git a/src/tests/deqp_support/deqp_gles3_test_expectations.txt b/src/tests/deqp_support/deqp_gles3_test_expectations.txt
index f667685..6150f60 100644
--- a/src/tests/deqp_support/deqp_gles3_test_expectations.txt
+++ b/src/tests/deqp_support/deqp_gles3_test_expectations.txt
@@ -28,6 +28,10 @@
 998 DEBUG RELEASE : dEQP-GLES3.stress.* = SKIP
 1101 DEBUG RELEASE : dEQP-GLES3.functional.flush_finish.* = SKIP
 
+// Figure out why this caused this regression in Chrome:
+// https://bugs.chromium.org/p/chromium/issues/detail?id=833809#
+2321 DEBUG RELEASE : dEQP-GLES3.functional.state_query.fbo.framebuffer_unspecified_attachment_x_size_rbo = FAIL
+
 // TODO(jmadill): Figure out why these fail on the bots, but not locally.
 1108 WIN : dEQP-GLES3.functional.shaders.struct.local.dynamic_loop_struct_array_fragment = FAIL
 1094 WIN : dEQP-GLES3.functional.shaders.invariance.highp.loop_2 = FAIL
diff --git a/src/tests/deqp_support/es2fColorClearTest.cpp b/src/tests/deqp_support/es2fColorClearTest.cpp
new file mode 100644
index 0000000..bbc16da
--- /dev/null
+++ b/src/tests/deqp_support/es2fColorClearTest.cpp
@@ -0,0 +1,331 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 2.0 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Screen clearing test.
+ *//*--------------------------------------------------------------------*/
+
+#include "es2fColorClearTest.hpp"
+#include "tcuRGBA.hpp"
+#include "tcuSurface.hpp"
+#include "tcuTestLog.hpp"
+#include "gluRenderContext.hpp"
+#include "gluPixelTransfer.hpp"
+#include "tcuVector.hpp"
+#include "tcuRenderTarget.hpp"
+#include "deRandom.hpp"
+#include "deInt32.h"
+
+#include "glwFunctions.hpp"
+#include "glwEnums.hpp"
+
+#include <vector>
+
+using tcu::RGBA;
+using tcu::Surface;
+using tcu::TestLog;
+
+using namespace std;
+
+namespace deqp
+{
+namespace gles2
+{
+namespace Functional
+{
+
+class ColorClearCase : public TestCase
+{
+public:
+	ColorClearCase(Context& context, const char* name, int numIters, int numClearsMin, int numClearsMax, bool testAlpha, bool testScissoring, bool testColorMasks, bool firstClearFull)
+		: TestCase			(context, name, name)
+		, m_numIters		(numIters)
+		, m_numClearsMin	(numClearsMin)
+		, m_numClearsMax	(numClearsMax)
+		, m_testAlpha		(testAlpha)
+		, m_testScissoring	(testScissoring)
+		, m_testColorMasks	(testColorMasks)
+		, m_firstClearFull	(firstClearFull)
+	{
+		m_curIter = 0;
+	}
+
+	virtual ~ColorClearCase (void)
+	{
+	}
+
+	virtual IterateResult iterate (void);
+
+private:
+	const int		m_numIters;
+	const int		m_numClearsMin;
+	const int		m_numClearsMax;
+	const bool		m_testAlpha;
+	const bool		m_testScissoring;
+	const bool		m_testColorMasks;
+	const bool		m_firstClearFull;
+
+	int				m_curIter;
+};
+
+class ClearInfo
+{
+public:
+	ClearInfo (const tcu::IVec4& rect, deUint8 colorMask, tcu::RGBA color)
+		: m_rect(rect), m_colorMask(colorMask), m_color(color)
+	{
+	}
+
+	tcu::IVec4		m_rect;
+	deUint8			m_colorMask;
+	tcu::RGBA		m_color;
+};
+
+TestCase::IterateResult ColorClearCase::iterate (void)
+{
+	TestLog&					log						= m_testCtx.getLog();
+	const glw::Functions&		gl						= m_context.getRenderContext().getFunctions();
+	const tcu::RenderTarget&	renderTarget			= m_context.getRenderTarget();
+	const tcu::PixelFormat&		pixelFormat				= renderTarget.getPixelFormat();
+	const int					targetWidth				= renderTarget.getWidth();
+	const int					targetHeight			= renderTarget.getHeight();
+	const int					numPixels				= targetWidth * targetHeight;
+
+	de::Random					rnd						(deInt32Hash(m_curIter));
+	vector<deUint8>				pixelKnownChannelMask	(numPixels, 0);
+	Surface						refImage				(targetWidth, targetHeight);
+	Surface						resImage				(targetWidth, targetHeight);
+	Surface						diffImage				(targetWidth, targetHeight);
+	int							numClears				= rnd.getUint32() % (m_numClearsMax + 1 - m_numClearsMin) + m_numClearsMin;
+	std::vector<ClearInfo>		clearOps;
+
+	if (m_testScissoring)
+		gl.enable(GL_SCISSOR_TEST);
+
+	for (int clearNdx = 0; clearNdx < numClears; clearNdx++)
+	{
+		// Rectangle.
+		int clearX;
+		int clearY;
+		int clearWidth;
+		int clearHeight;
+		if (!m_testScissoring || (clearNdx == 0 && m_firstClearFull))
+		{
+			clearX		= 0;
+			clearY		= 0;
+			clearWidth	= targetWidth;
+			clearHeight	= targetHeight;
+		}
+		else
+		{
+			clearX		= (rnd.getUint32() % (2*targetWidth)) - targetWidth;
+			clearY		= (rnd.getUint32() % (2*targetHeight)) - targetHeight;
+			clearWidth	= (rnd.getUint32() % targetWidth);
+			clearHeight	= (rnd.getUint32() % targetHeight);
+		}
+		gl.scissor(clearX, clearY, clearWidth, clearHeight);
+
+		// Color.
+		int		r = (int)(rnd.getUint32() & 0xFF);
+		int		g = (int)(rnd.getUint32() & 0xFF);
+		int		b = (int)(rnd.getUint32() & 0xFF);
+		int		a = m_testAlpha ? (int)(rnd.getUint32() & 0xFF) : 0xFF;
+		RGBA	clearCol(r, g, b, a);
+		gl.clearColor(float(r)/255.0f, float(g)/255.0f, float(b)/255.0f, float(a)/255.0f);
+
+		// Mask.
+		deUint8	clearMask;
+		if (!m_testColorMasks || (clearNdx == 0 && m_firstClearFull))
+			clearMask = 0xF;
+		else
+			clearMask = (rnd.getUint32() & 0xF);
+		gl.colorMask((clearMask&0x1) != 0, (clearMask&0x2) != 0, (clearMask&0x4) != 0, (clearMask&0x8) != 0);
+
+		// Clear & store op.
+		gl.clear(GL_COLOR_BUFFER_BIT);
+		clearOps.push_back(ClearInfo(tcu::IVec4(clearX, clearY, clearWidth, clearHeight), clearMask, clearCol));
+
+		// Let watchdog know we're alive.
+		m_testCtx.touchWatchdog();
+	}
+
+	// Compute reference image.
+	{
+		for (int y = 0; y < targetHeight; y++)
+		{
+			std::vector<ClearInfo>	scanlineClearOps;
+
+			// Find all rectangles affecting this scanline.
+			for (int opNdx = 0; opNdx < (int)clearOps.size(); opNdx++)
+			{
+				ClearInfo& op = clearOps[opNdx];
+				if (de::inBounds(y, op.m_rect.y(), op.m_rect.y()+op.m_rect.w()))
+					scanlineClearOps.push_back(op);
+			}
+
+			// Compute reference for scanline.
+			int x = 0;
+			while (x < targetWidth)
+			{
+				tcu::RGBA	spanColor;
+				deUint8		spanKnownMask	= 0;
+				int			spanLength		= (targetWidth - x);
+
+				for (int opNdx = (int)scanlineClearOps.size() - 1; opNdx >= 0; opNdx--)
+				{
+					const ClearInfo& op = scanlineClearOps[opNdx];
+
+					if (de::inBounds(x, op.m_rect.x(), op.m_rect.x()+op.m_rect.z()) &&
+						de::inBounds(y, op.m_rect.y(), op.m_rect.y()+op.m_rect.w()))
+					{
+						// Compute span length until end of given rectangle.
+						spanLength = deMin32(spanLength, op.m_rect.x() + op.m_rect.z() - x);
+
+						tcu::RGBA	clearCol	= op.m_color;
+						deUint8		clearMask	= op.m_colorMask;
+						if ((clearMask & 0x1) && !(spanKnownMask & 0x1)) spanColor.setRed(clearCol.getRed());
+						if ((clearMask & 0x2) && !(spanKnownMask & 0x2)) spanColor.setGreen(clearCol.getGreen());
+						if ((clearMask & 0x4) && !(spanKnownMask & 0x4)) spanColor.setBlue(clearCol.getBlue());
+						if ((clearMask & 0x8) && !(spanKnownMask & 0x8)) spanColor.setAlpha(clearCol.getAlpha());
+						spanKnownMask |= clearMask;
+
+						// Break if have all colors.
+						if (spanKnownMask == 0xF)
+							break;
+					}
+					else if (op.m_rect.x() > x)
+						spanLength = deMin32(spanLength, op.m_rect.x() - x);
+				}
+
+				// Set reference alpha channel to 0xFF, if no alpha in target.
+				if (pixelFormat.alphaBits == 0)
+					spanColor.setAlpha(0xFF);
+
+				// Fill the span.
+				for (int ndx = 0; ndx < spanLength; ndx++)
+				{
+					refImage.setPixel(x + ndx, y, spanColor);
+					pixelKnownChannelMask[y*targetWidth + x + ndx] |= spanKnownMask;
+				}
+
+				x += spanLength;
+			}
+		}
+	}
+
+	glu::readPixels(m_context.getRenderContext(), 0, 0, resImage.getAccess());
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
+
+	// Compute difference image.
+	RGBA colorThreshold = pixelFormat.getColorThreshold();
+	RGBA matchColor(0, 255, 0, 255);
+	RGBA diffColor(255, 0, 0, 255);
+	RGBA maxDiff(0, 0, 0, 0);
+	bool isImageOk = true;
+
+	if (gl.isEnabled(GL_DITHER))
+	{
+		colorThreshold.setRed(colorThreshold.getRed() + 1);
+		colorThreshold.setGreen(colorThreshold.getGreen() + 1);
+		colorThreshold.setBlue(colorThreshold.getBlue() + 1);
+		colorThreshold.setAlpha(colorThreshold.getAlpha() + 1);
+	}
+
+	for (int y = 0; y < targetHeight; y++)
+	for (int x = 0; x < targetWidth; x++)
+	{
+		int			offset		= (y*targetWidth + x);
+		RGBA		refRGBA		= refImage.getPixel(x, y);
+		RGBA		resRGBA		= resImage.getPixel(x, y);
+		deUint8		colMask		= pixelKnownChannelMask[offset];
+		RGBA		diff		= computeAbsDiffMasked(refRGBA, resRGBA, colMask);
+		bool		isPixelOk	= diff.isBelowThreshold(colorThreshold);
+
+		diffImage.setPixel(x, y, isPixelOk ? matchColor : diffColor);
+
+		isImageOk	= isImageOk && isPixelOk;
+		maxDiff		= max(maxDiff, diff);
+	}
+
+	if (isImageOk)
+	{
+		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+	}
+	else
+	{
+		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+
+		m_testCtx.getLog() << tcu::TestLog::Message << "Image comparison failed, max diff = " << maxDiff << ", threshold = " << colorThreshold << tcu::TestLog::EndMessage;
+
+		log << TestLog::ImageSet("Result", "Resulting framebuffer")
+			<< TestLog::Image("Result",		"Resulting framebuffer",	resImage)
+			<< TestLog::Image("Reference",	"Reference image",			refImage)
+			<< TestLog::Image("DiffMask",	"Failing pixels",			diffImage)
+			<< TestLog::EndImageSet;
+		return TestCase::STOP;
+	}
+
+	bool isFinal = (++m_curIter == m_numIters);
+
+	// On final frame, dump images.
+	if (isFinal)
+	{
+		log << TestLog::ImageSet("Result", "Resulting framebuffer")
+			<< TestLog::Image("Result",		"Resulting framebuffer",	resImage)
+			<< TestLog::EndImageSet;
+	}
+
+	return isFinal ? TestCase::STOP : TestCase::CONTINUE;
+}
+
+ColorClearTest::ColorClearTest (Context& context) : TestCaseGroup(context, "color_clear", "Color Clear Tests")
+{
+}
+
+ColorClearTest::~ColorClearTest (void)
+{
+}
+
+void ColorClearTest::init (void)
+{
+	//										name					iters,	#..#,		alpha?,	scissor,masks,	1stfull?
+	addChild(new ColorClearCase(m_context, "single_rgb",			30,		1,3,		false,	false,	false,	true	));
+	addChild(new ColorClearCase(m_context, "single_rgba",			30,		1,3,		true,	false,	false,	true	));
+	addChild(new ColorClearCase(m_context, "multiple_rgb",			15,		4,20,		false,	false,	false,	true	));
+	addChild(new ColorClearCase(m_context, "multiple_rgba",			15,		4,20,		true,	false,	false,	true	));
+	addChild(new ColorClearCase(m_context, "long_rgb",				2,		100,500,	false,	false,	false,	true	));
+	addChild(new ColorClearCase(m_context, "long_rgba",				2,		100,500,	true,	false,	false,	true	));
+	addChild(new ColorClearCase(m_context, "subclears_rgb",			15,		4,30,		false,	false,	false,	false	));
+	addChild(new ColorClearCase(m_context, "subclears_rgba",		15,		4,30,		true,	false,	false,	false	));
+	addChild(new ColorClearCase(m_context, "short_scissored_rgb",	30,		2,4,		false,	true,	false,	true	));
+	addChild(new ColorClearCase(m_context, "scissored_rgb",			15,		4,30,		false,	true,	false,	true	));
+	addChild(new ColorClearCase(m_context, "scissored_rgba",		15,		4,30,		true,	true,	false,	true	));
+	addChild(new ColorClearCase(m_context, "masked_rgb",			15,		4,30,		false,	false,	true,	true	));
+	addChild(new ColorClearCase(m_context, "masked_rgba",			15,		4,30,		true,	false,	true,	true	));
+	addChild(new ColorClearCase(m_context, "masked_scissored_rgb",	15,		4,30,		false,	true,	true,	true	));
+	addChild(new ColorClearCase(m_context, "masked_scissored_rgba",	15,		4,30,		true,	true,	true,	true	));
+	addChild(new ColorClearCase(m_context, "complex_rgb",			15,		5,50,		false,	true,	true,	false	));
+	addChild(new ColorClearCase(m_context, "complex_rgba",			15,		5,50,		true,	true,	true,	false	));
+	addChild(new ColorClearCase(m_context, "long_masked_rgb",		2,		100,500,	false,	true,	true,	true	));
+	addChild(new ColorClearCase(m_context, "long_masked_rgba",		2,		100,500,	true,	true,	true,	true	));
+}
+
+} // Functional
+} // gles2
+} // deqp
diff --git a/src/tests/deqp_support/qpTestLog.c b/src/tests/deqp_support/qpTestLog.c
deleted file mode 100644
index 7252ae0..0000000
--- a/src/tests/deqp_support/qpTestLog.c
+++ /dev/null
@@ -1,1481 +0,0 @@
-/*-------------------------------------------------------------------------
- * drawElements TestLog Library
- * ----------------------------
- *
- * Copyright 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *//*!
- * \file
- * \brief Test case result logging
- *//*--------------------------------------------------------------------*/
-
-#include "qpTestLog.h"
-#include "qpXmlWriter.h"
-#include "qpInfo.h"
-#include "qpDebugOut.h"
-
-#include "deMemory.h"
-#include "deInt32.h"
-#include "deString.h"
-
-#include "deMutex.h"
-
-#if defined(QP_SUPPORT_PNG)
-#	include <png.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-#if (DE_OS == DE_OS_WIN32)
-#	include <windows.h>
-#	include <io.h>
-#endif
-
-#if defined(DE_DEBUG)
-
-/* Utils for verifying container (Section, ImageSet, EglConfigSet) usage in debug builds. */
-
-typedef enum ContainerType_e
-{
-	CONTAINERTYPE_SECTION = 0,
-	CONTAINERTYPE_IMAGESET,
-	CONTAINERTYPE_EGLCONFIGSET,
-	CONTAINERTYPE_SHADERPROGRAM,
-	CONTAINERTYPE_SAMPLELIST,
-	CONTAINERTYPE_SAMPLEINFO,
-	CONTAINERTYPE_SAMPLE,
-
-	CONTAINERTYPE_LAST
-} ContainerType;
-
-DE_INLINE deBool childContainersOk (ContainerType type)
-{
-	return type == CONTAINERTYPE_SECTION || type == CONTAINERTYPE_SAMPLELIST;
-}
-
-enum
-{
-	MAX_CONTAINER_STACK_DEPTH		= 32
-};
-
-typedef struct ContainerStack_s
-{
-	int				numElements;
-	ContainerType	elements[MAX_CONTAINER_STACK_DEPTH];
-} ContainerStack;
-
-DE_INLINE void ContainerStack_reset (ContainerStack* stack)
-{
-	deMemset(stack, 0, sizeof(ContainerStack));
-}
-
-DE_INLINE deBool ContainerStack_isEmpty (const ContainerStack* stack)
-{
-	return stack->numElements == 0;
-}
-
-DE_INLINE deBool ContainerStack_push (ContainerStack* stack, ContainerType type)
-{
-	if (stack->numElements == MAX_CONTAINER_STACK_DEPTH)
-		return DE_FALSE;
-
-	if (stack->numElements > 0 && !childContainersOk(stack->elements[stack->numElements-1]))
-		return DE_FALSE;
-
-	stack->elements[stack->numElements]  = type;
-	stack->numElements					+= 1;
-
-	return DE_TRUE;
-}
-
-DE_INLINE ContainerType ContainerStack_pop (ContainerStack* stack)
-{
-	DE_ASSERT(stack->numElements > 0);
-	stack->numElements -= 1;
-	return stack->elements[stack->numElements];
-}
-
-DE_INLINE ContainerType ContainerStack_getTop (const ContainerStack* stack)
-{
-	if (stack->numElements > 0)
-		return stack->elements[stack->numElements-1];
-	else
-		return CONTAINERTYPE_LAST;
-}
-
-#endif
-
-/* qpTestLog instance */
-struct qpTestLog_s
-{
-	deUint32				flags;				/*!< Logging flags.						*/
-
-	deMutex					lock;				/*!< Lock for mutable state below.		*/
-
-	/* State protected by lock. */
-	FILE*					outputFile;
-	qpXmlWriter*			writer;
-	deBool					isSessionOpen;
-	deBool					isCaseOpen;
-
-#if defined(DE_DEBUG)
-	ContainerStack			containerStack;		/*!< For container usage verification.	*/
-#endif
-};
-
-/* Maps integer to string. */
-typedef struct qpKeyStringMap_s
-{
-	int		key;
-	char*	string;
-} qpKeyStringMap;
-
-static const char* LOG_FORMAT_VERSION = "0.3.4";
-
-/* Mapping enum to above strings... */
-static const qpKeyStringMap s_qpTestTypeMap[] =
-{
-	{ QP_TEST_CASE_TYPE_SELF_VALIDATE,		"SelfValidate"	},
-	{ QP_TEST_CASE_TYPE_PERFORMANCE,		"Performance"	},
-	{ QP_TEST_CASE_TYPE_CAPABILITY,			"Capability"	},
-	{ QP_TEST_CASE_TYPE_ACCURACY,			"Accuracy"		},
-
-	{ QP_TEST_CASE_TYPE_LAST,				DE_NULL			}
-};
-
-DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpTestTypeMap) == QP_TEST_CASE_TYPE_LAST + 1);
-
-static const qpKeyStringMap s_qpTestResultMap[] =
-{
-	{ QP_TEST_RESULT_PASS,						"Pass"					},
-	{ QP_TEST_RESULT_FAIL,						"Fail"					},
-	{ QP_TEST_RESULT_QUALITY_WARNING,			"QualityWarning"		},
-	{ QP_TEST_RESULT_COMPATIBILITY_WARNING,		"CompatibilityWarning"	},
-	{ QP_TEST_RESULT_PENDING,					"Pending"				},	/* should not be needed here */
-	{ QP_TEST_RESULT_NOT_SUPPORTED,				"NotSupported"			},
-	{ QP_TEST_RESULT_RESOURCE_ERROR,			"ResourceError"			},
-	{ QP_TEST_RESULT_INTERNAL_ERROR,			"InternalError"			},
-	{ QP_TEST_RESULT_CRASH,						"Crash"					},
-	{ QP_TEST_RESULT_TIMEOUT,					"Timeout"				},
-
-	/* Add new values here if needed, remember to update qpTestResult enumeration. */
-
-	{ QP_TEST_RESULT_LAST,						DE_NULL					}
-};
-
-DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpTestResultMap) == QP_TEST_RESULT_LAST + 1);
-
-/* Key tag to string mapping. */
-
-static const qpKeyStringMap s_qpTagMap[] =
-{
-	{ QP_KEY_TAG_NONE,			DE_NULL			},
-	{ QP_KEY_TAG_PERFORMANCE,	"Performance"	},
-	{ QP_KEY_TAG_QUALITY,		"Quality"		},
-	{ QP_KEY_TAG_PRECISION,		"Precision"		},
-	{ QP_KEY_TAG_TIME,			"Time"			},
-
-	{ QP_KEY_TAG_LAST,			DE_NULL			}
-};
-
-DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpTagMap) == QP_KEY_TAG_LAST + 1);
-
-/* Sample value tag to string mapping. */
-
-static const qpKeyStringMap s_qpSampleValueTagMap[] =
-{
-	{ QP_SAMPLE_VALUE_TAG_PREDICTOR,	"Predictor"	},
-	{ QP_SAMPLE_VALUE_TAG_RESPONSE,		"Response"	},
-
-	{ QP_SAMPLE_VALUE_TAG_LAST,			DE_NULL		}
-};
-
-DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpSampleValueTagMap) == QP_SAMPLE_VALUE_TAG_LAST + 1);
-
-/* Image compression mode to string mapping. */
-
-static const qpKeyStringMap s_qpImageCompressionModeMap[] =
-{
-	{ QP_IMAGE_COMPRESSION_MODE_NONE,	"None"	},
-	{ QP_IMAGE_COMPRESSION_MODE_PNG,	"PNG"	},
-
-	{ QP_IMAGE_COMPRESSION_MODE_BEST,	DE_NULL	},	/* not allowed to be written! */
-
-	{ QP_IMAGE_COMPRESSION_MODE_LAST,	DE_NULL	}
-};
-
-DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpImageCompressionModeMap) == QP_IMAGE_COMPRESSION_MODE_LAST + 1);
-
-/* Image format to string mapping. */
-
-static const qpKeyStringMap s_qpImageFormatMap[] =
-{
-	{ QP_IMAGE_FORMAT_RGB888,	"RGB888"	},
-	{ QP_IMAGE_FORMAT_RGBA8888,	"RGBA8888"	},
-
-	{ QP_IMAGE_FORMAT_LAST,		DE_NULL		}
-};
-
-DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpImageFormatMap) == QP_IMAGE_FORMAT_LAST + 1);
-
-/* Shader type to string mapping. */
-
-static const qpKeyStringMap s_qpShaderTypeMap[] =
-{
-	{ QP_SHADER_TYPE_VERTEX,			"VertexShader"			},
-	{ QP_SHADER_TYPE_FRAGMENT,			"FragmentShader"		},
-	{ QP_SHADER_TYPE_GEOMETRY,			"GeometryShader"		},
-	{ QP_SHADER_TYPE_TESS_CONTROL,		"TessControlShader"		},
-	{ QP_SHADER_TYPE_TESS_EVALUATION,	"TessEvaluationShader"	},
-	{ QP_SHADER_TYPE_COMPUTE,			"ComputeShader"			},
-
-	{ QP_SHADER_TYPE_LAST,				DE_NULL					}
-};
-
-DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qpShaderTypeMap) == QP_SHADER_TYPE_LAST + 1);
-
-static void qpTestLog_flushFile (qpTestLog* log)
-{
-	DE_ASSERT(log && log->outputFile);
-	fflush(log->outputFile);
-#if (DE_OS == DE_OS_WIN32) && (DE_COMPILER == DE_COMPILER_MSC)
-	/* \todo [petri] Is this really necessary? */
-	FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(log->outputFile)));
-#endif
-}
-
-#define QP_LOOKUP_STRING(KEYMAP, KEY)	qpLookupString(KEYMAP, DE_LENGTH_OF_ARRAY(KEYMAP), (int)(KEY))
-
-static const char* qpLookupString (const qpKeyStringMap* keyMap, int keyMapSize, int key)
-{
-	DE_ASSERT(keyMap);
-	DE_ASSERT(deInBounds32(key, 0, keyMapSize));
-	DE_ASSERT(keyMap[key].key == key);
-	DE_UNREF(keyMapSize); /* for asserting only */
-	return keyMap[key].string;
-}
-
-DE_INLINE void int32ToString (int val, char buf[32])
-{
-	deSprintf(&buf[0], 32, "%d", val);
-}
-
-DE_INLINE void int64ToString (deInt64 val, char buf[32])
-{
-	deSprintf(&buf[0], 32, "%lld", (long long int)val);
-}
-
-DE_INLINE void floatToString (float value, char* buf, size_t bufSize)
-{
-	deSprintf(buf, bufSize, "%f", value);
-}
-
-DE_INLINE void doubleToString (double value, char* buf, size_t bufSize)
-{
-	deSprintf(buf, bufSize, "%f", value);
-}
-
-static deBool beginSession (qpTestLog* log)
-{
-	DE_ASSERT(log && !log->isSessionOpen);
-
-	/* Write session info. */
-	fprintf(log->outputFile, "#sessionInfo releaseName %s\n", qpGetReleaseName());
-	fprintf(log->outputFile, "#sessionInfo releaseId 0x%08x\n", qpGetReleaseId());
-	fprintf(log->outputFile, "#sessionInfo targetName \"%s\"\n", qpGetTargetName());
-
-    /* Write out #beginSession. */
-	fprintf(log->outputFile, "#beginSession\n");
-	qpTestLog_flushFile(log);
-
-	log->isSessionOpen = DE_TRUE;
-
-	return DE_TRUE;
-}
-
-static deBool endSession (qpTestLog* log)
-{
-	DE_ASSERT(log && log->isSessionOpen);
-
-    /* Make sure xml is flushed. */
-    qpXmlWriter_flush(log->writer);
-
-    /* Write out #endSession. */
-	fprintf(log->outputFile, "\n#endSession\n");
-	qpTestLog_flushFile(log);
-
-	log->isSessionOpen = DE_FALSE;
-
-	return DE_TRUE;
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief Create a file based logger instance
- * \param fileName Name of the file where to put logs
- * \return qpTestLog instance, or DE_NULL if cannot create file
- *//*--------------------------------------------------------------------*/
-qpTestLog* qpTestLog_createFileLog (const char* fileName, deUint32 flags)
-{
-	qpTestLog* log = (qpTestLog*)deCalloc(sizeof(qpTestLog));
-	if (!log)
-		return DE_NULL;
-
-	DE_ASSERT(fileName && fileName[0]); /* must have filename. */
-
-#if defined(DE_DEBUG)
-	ContainerStack_reset(&log->containerStack);
-#endif
-
-	qpPrintf("Writing test log into %s\n", fileName);
-
-	/* Create output file. */
-	log->outputFile = fopen(fileName, "wb");
-	if (!log->outputFile)
-	{
-		qpPrintf("ERROR: Unable to open test log output file '%s'.\n", fileName);
-		qpTestLog_destroy(log);
-		return DE_NULL;
-	}
-
-	log->flags			= flags;
-	log->writer			= qpXmlWriter_createFileWriter(log->outputFile, 0, !(flags & QP_TEST_LOG_NO_FLUSH));
-	log->lock			= deMutex_create(DE_NULL);
-	log->isSessionOpen	= DE_FALSE;
-	log->isCaseOpen		= DE_FALSE;
-
-	if (!log->writer)
-	{
-		qpPrintf("ERROR: Unable to create output XML writer to file '%s'.\n", fileName);
-		qpTestLog_destroy(log);
-		return DE_NULL;
-	}
-
-	if (!log->lock)
-	{
-		qpPrintf("ERROR: Unable to create mutex.\n");
-		qpTestLog_destroy(log);
-		return DE_NULL;
-	}
-
-	beginSession(log);
-
-	return log;
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief Destroy a logger instance
- * \param a	qpTestLog instance
- *//*--------------------------------------------------------------------*/
-void qpTestLog_destroy (qpTestLog* log)
-{
-	DE_ASSERT(log);
-
-	if (log->isSessionOpen)
-		endSession(log);
-
-	if (log->writer)
-		qpXmlWriter_destroy(log->writer);
-
-	if (log->outputFile)
-		fclose(log->outputFile);
-
-	if (log->lock)
-		deMutex_destroy(log->lock);
-
-	deFree(log);
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief Log start of test case
- * \param log qpTestLog instance
- * \param testCasePath	Full test case path (as seen in Candy).
- * \param testCaseType	Test case type
- * \return true if ok, false otherwise
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_startCase (qpTestLog* log, const char* testCasePath, qpTestCaseType testCaseType)
-{
-	const char*		typeStr				= QP_LOOKUP_STRING(s_qpTestTypeMap, testCaseType);
-	int				numResultAttribs	= 0;
-	qpXmlAttribute	resultAttribs[8];
-
-	DE_ASSERT(log && testCasePath && (testCasePath[0] != 0));
-	deMutex_lock(log->lock);
-
-	DE_ASSERT(!log->isCaseOpen);
-	DE_ASSERT(ContainerStack_isEmpty(&log->containerStack));
-
-	/* Flush XML and write out #beginTestCaseResult. */
-	qpXmlWriter_flush(log->writer);
-	fprintf(log->outputFile, "\n#beginTestCaseResult %s\n", testCasePath);
-	if (!(log->flags & QP_TEST_LOG_NO_FLUSH))
-		qpTestLog_flushFile(log);
-
-	log->isCaseOpen = DE_TRUE;
-
-	/* Fill in attributes. */
-	resultAttribs[numResultAttribs++] = qpSetStringAttrib("Version", LOG_FORMAT_VERSION);
-	resultAttribs[numResultAttribs++] = qpSetStringAttrib("CasePath", testCasePath);
-	resultAttribs[numResultAttribs++] = qpSetStringAttrib("CaseType", typeStr);
-
-	if (!qpXmlWriter_startDocument(log->writer) ||
-		!qpXmlWriter_startElement(log->writer, "TestCaseResult", numResultAttribs, resultAttribs))
-	{
-		qpPrintf("qpTestLog_startCase(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief Log end of test case
- * \param log qpTestLog instance
- * \param result Test result
- * \param description Description of a problem in case of error
- * \return true if ok, false otherwise
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_endCase (qpTestLog* log, qpTestResult result, const char* resultDetails)
-{
-	const char*		statusStr		= QP_LOOKUP_STRING(s_qpTestResultMap, result);
-	qpXmlAttribute	statusAttrib	= qpSetStringAttrib("StatusCode", statusStr);
-
-	deMutex_lock(log->lock);
-
-	DE_ASSERT(log->isCaseOpen);
-	DE_ASSERT(ContainerStack_isEmpty(&log->containerStack));
-
-	/* <Result StatusCode="Pass">Result details</Result>
-	 * </TestCaseResult>
-	 */
-	if (!qpXmlWriter_startElement(log->writer, "Result", 1, &statusAttrib) ||
-		(resultDetails && !qpXmlWriter_writeString(log->writer, resultDetails)) ||
-		!qpXmlWriter_endElement(log->writer, "Result") ||
-		!qpXmlWriter_endElement(log->writer, "TestCaseResult") ||
-		!qpXmlWriter_endDocument(log->writer))		/* Close any XML elements still open */
-	{
-		qpPrintf("qpTestLog_endCase(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	/* Flush XML and write #endTestCaseResult. */
-	qpXmlWriter_flush(log->writer);
-	fprintf(log->outputFile, "\n#endTestCaseResult\n");
-	if (!(log->flags & QP_TEST_LOG_NO_FLUSH))
-		qpTestLog_flushFile(log);
-
-	log->isCaseOpen = DE_FALSE;
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief Abrupt termination of logging.
- * \param log		qpTestLog instance
- * \param result	Result code, only Crash and Timeout are allowed.
- * \return true if ok, false otherwise
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_terminateCase (qpTestLog* log, qpTestResult result)
-{
-	const char* resultStr = QP_LOOKUP_STRING(s_qpTestResultMap, result);
-
-	DE_ASSERT(log);
-	DE_ASSERT(result == QP_TEST_RESULT_CRASH || result == QP_TEST_RESULT_TIMEOUT);
-
-	deMutex_lock(log->lock);
-
-	if (!log->isCaseOpen)
-	{
-		deMutex_unlock(log->lock);
-		return DE_FALSE; /* Soft error. This is called from error handler. */
-	}
-
-	/* Flush XML and write #terminateTestCaseResult. */
-	qpXmlWriter_flush(log->writer);
-	fprintf(log->outputFile, "\n#terminateTestCaseResult %s\n", resultStr);
-	qpTestLog_flushFile(log);
-
-	log->isCaseOpen = DE_FALSE;
-
-#if defined(DE_DEBUG)
-	ContainerStack_reset(&log->containerStack);
-#endif
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-static deBool qpTestLog_writeKeyValuePair (qpTestLog* log, const char* elementName, const char* name, const char* description, const char* unit, qpKeyValueTag tag, const char* text)
-{
-	const char*		tagString = QP_LOOKUP_STRING(s_qpTagMap, tag);
-	qpXmlAttribute	attribs[8];
-	int				numAttribs = 0;
-
-	DE_ASSERT(log && elementName && text);
-	deMutex_lock(log->lock);
-
-	/* Fill in attributes. */
-	if (name)			attribs[numAttribs++] = qpSetStringAttrib("Name", name);
-	if (description)	attribs[numAttribs++] = qpSetStringAttrib("Description", description);
-	if (tagString)		attribs[numAttribs++] = qpSetStringAttrib("Tag", tagString);
-	if (unit)			attribs[numAttribs++] = qpSetStringAttrib("Unit", unit);
-
-	if (!qpXmlWriter_startElement(log->writer, elementName, numAttribs, attribs) ||
-		!qpXmlWriter_writeString(log->writer, text) ||
-		!qpXmlWriter_endElement(log->writer, elementName))
-	{
-		qpPrintf("qpTestLog_writeKeyValuePair(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief Write a message to output log
- * \param log		qpTestLog instance
- * \param format	Format string of message
- * \param ...		Parameters for message
- * \return true if ok, false otherwise
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_writeMessage (qpTestLog* log, const char* format, ...)
-{
-	char	buffer[1024];
-	va_list	args;
-
-	/* \todo [petri] Handle buffer overflows! */
-
-	va_start(args, format);
-	buffer[DE_LENGTH_OF_ARRAY(buffer) - 1] = 0;
-	vsnprintf(buffer, sizeof(buffer), format, args);
-	va_end(args);
-
-	/* <Text>text</Text> */
-	return qpTestLog_writeKeyValuePair(log, "Text", DE_NULL, DE_NULL, DE_NULL, QP_KEY_TAG_LAST, buffer);
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief Write key-value-pair into log
- * \param log			qpTestLog instance
- * \param name			Unique identifier for entry
- * \param description	Human readable description
- * \param tag			Optional tag
- * \param value			Value of the key-value-pair
- * \return true if ok, false otherwise
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_writeText (qpTestLog* log, const char* name, const char* description, qpKeyValueTag tag, const char* text)
-{
-	/* <Text Name="name" Description="description" Tag="tag">text</Text> */
-	return qpTestLog_writeKeyValuePair(log, "Text", name, description, DE_NULL, tag, text);
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief Write key-value-pair into log
- * \param log			qpTestLog instance
- * \param name			Unique identifier for entry
- * \param description	Human readable description
- * \param tag			Optional tag
- * \param value			Value of the key-value-pair
- * \return true if ok, false otherwise
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_writeInteger (qpTestLog* log, const char* name, const char* description, const char* unit, qpKeyValueTag tag, deInt64 value)
-{
-	char tmpString[64];
-	int64ToString(value, tmpString);
-
-	/* <Number Name="name" Description="description" Tag="Performance">15</Number> */
-	return qpTestLog_writeKeyValuePair(log, "Number", name, description, unit, tag, tmpString);
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief Write key-value-pair into log
- * \param log			qpTestLog instance
- * \param name			Unique identifier for entry
- * \param description	Human readable description
- * \param tag			Optional tag
- * \param value			Value of the key-value-pair
- * \return true if ok, false otherwise
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_writeFloat (qpTestLog* log, const char* name, const char* description, const char* unit, qpKeyValueTag tag, float value)
-{
-	char tmpString[64];
-	floatToString(value, tmpString, sizeof(tmpString));
-
-	/* <Number Name="name" Description="description" Tag="Performance">15</Number> */
-	return qpTestLog_writeKeyValuePair(log, "Number", name, description, unit, tag, tmpString);
-}
-
-typedef struct Buffer_s
-{
-	size_t		capacity;
-	size_t		size;
-	deUint8*	data;
-} Buffer;
-
-void Buffer_init (Buffer* buffer)
-{
-	buffer->capacity	= 0;
-	buffer->size		= 0;
-	buffer->data		= DE_NULL;
-}
-
-void Buffer_deinit (Buffer* buffer)
-{
-	deFree(buffer->data);
-	Buffer_init(buffer);
-}
-
-deBool Buffer_resize (Buffer* buffer, size_t newSize)
-{
-	/* Grow buffer if necessary. */
-	if (newSize > buffer->capacity)
-	{
-		size_t		newCapacity	= (size_t)deAlign32(deMax32(2*(int)buffer->capacity, (int)newSize), 512);
-		deUint8*	newData		= (deUint8*)deMalloc(newCapacity);
-		if (!newData)
-			return DE_FALSE;
-
-		memcpy(newData, buffer->data, buffer->size);
-		deFree(buffer->data);
-		buffer->data		= newData;
-		buffer->capacity	= newCapacity;
-	}
-
-	buffer->size = newSize;
-	return DE_TRUE;
-}
-
-deBool Buffer_append (Buffer* buffer, const deUint8* data, size_t numBytes)
-{
-	size_t offset = buffer->size;
-
-	if (!Buffer_resize(buffer, buffer->size + numBytes))
-		return DE_FALSE;
-
-	/* Append bytes. */
-	memcpy(&buffer->data[offset], data, numBytes);
-	return DE_TRUE;
-}
-
-#if defined(QP_SUPPORT_PNG)
-void pngWriteData (png_structp png, png_bytep dataPtr, png_size_t numBytes)
-{
-	Buffer* buffer = (Buffer*)png_get_io_ptr(png);
-	if (!Buffer_append(buffer, (const deUint8*)dataPtr, numBytes))
-		png_error(png, "unable to resize PNG write buffer!");
-}
-
-void pngFlushData (png_structp png)
-{
-	DE_UNREF(png);
-	/* nada */
-}
-
-static deBool writeCompressedPNG (png_structp png, png_infop info, png_byte** rowPointers, int width, int height, int colorFormat)
-{
-	if (setjmp(png_jmpbuf(png)) == 0)
-	{
-		/* Write data. */
-		png_set_IHDR(png, info, (png_uint_32)width, (png_uint_32)height,
-			8,
-			colorFormat,
-			PNG_INTERLACE_NONE,
-			PNG_COMPRESSION_TYPE_BASE,
-			PNG_FILTER_TYPE_BASE);
-		png_write_info(png, info);
-		png_write_image(png, rowPointers);
-		png_write_end(png, NULL);
-
-		return DE_TRUE;
-	}
-	else
-		return DE_FALSE;
-}
-
-static deBool compressImagePNG (Buffer* buffer, qpImageFormat imageFormat, int width, int height, int rowStride, const void* data)
-{
-	deBool			compressOk		= DE_FALSE;
-	png_structp		png				= DE_NULL;
-	png_infop		info			= DE_NULL;
-	png_byte**		rowPointers		= DE_NULL;
-	deBool			hasAlpha		= imageFormat == QP_IMAGE_FORMAT_RGBA8888;
-	int				ndx;
-
-	/* Handle format. */
-	DE_ASSERT(imageFormat == QP_IMAGE_FORMAT_RGB888 || imageFormat == QP_IMAGE_FORMAT_RGBA8888);
-
-	/* Allocate & set row pointers. */
-	rowPointers = (png_byte**)deMalloc((size_t)height * sizeof(png_byte*));
-	if (!rowPointers)
-		return DE_FALSE;
-
-	for (ndx = 0; ndx < height; ndx++)
-		rowPointers[ndx] = (png_byte*)((const deUint8*)data + ndx*rowStride);
-
-	/* Initialize PNG compressor. */
-	png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
-	info = png ? png_create_info_struct(png) : DE_NULL;
-	if (png && info)
-	{
-		/* Set our own write function. */
-		png_set_write_fn(png, buffer, pngWriteData, pngFlushData);
-
-		compressOk = writeCompressedPNG(png, info, rowPointers, width, height,
-										hasAlpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB);
-	}
-
-	/* Cleanup & return. */
-	if (png && info)
-	{
-		png_destroy_info_struct(png, &info);
-		png_destroy_write_struct(&png, DE_NULL);
-	}
-	else if (png)
-		png_destroy_write_struct(&png, &info);
-
-	deFree(rowPointers);
-	return compressOk;
-}
-#endif /* QP_SUPPORT_PNG */
-
-/*--------------------------------------------------------------------*//*!
- * \brief Start image set
- * \param log			qpTestLog instance
- * \param name			Unique identifier for the set
- * \param description	Human readable description
- * \return true if ok, false otherwise
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_startImageSet (qpTestLog* log, const char* name, const char* description)
-{
-	qpXmlAttribute	attribs[4];
-	int				numAttribs = 0;
-
-	DE_ASSERT(log && name);
-	deMutex_lock(log->lock);
-
-	attribs[numAttribs++] = qpSetStringAttrib("Name", name);
-	if (description)
-		attribs[numAttribs++] = qpSetStringAttrib("Description", description);
-
-	/* <ImageSet Name="<name>"> */
-	if (!qpXmlWriter_startElement(log->writer, "ImageSet", numAttribs, attribs))
-	{
-		qpPrintf("qpTestLog_startImageSet(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_IMAGESET));
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief End image set
- * \param log			qpTestLog instance
- * \return true if ok, false otherwise
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_endImageSet (qpTestLog* log)
-{
-	DE_ASSERT(log);
-	deMutex_lock(log->lock);
-
-	/* <ImageSet Name="<name>"> */
-	if (!qpXmlWriter_endElement(log->writer, "ImageSet"))
-	{
-		qpPrintf("qpTestLog_endImageSet(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_IMAGESET);
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief Write base64 encoded raw image data into log
- * \param log				qpTestLog instance
- * \param name				Unique name (matching names can be compared across BatchResults).
- * \param description		Textual description (shown in Candy).
- * \param compressionMode	Compression mode
- * \param imageFormat		Color format
- * \param width				Width in pixels
- * \param height			Height in pixels
- * \param stride			Data stride (offset between rows)
- * \param data				Pointer to pixel data
- * \return 0 if OK, otherwise <0
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_writeImage	(
-	qpTestLog*				log,
-	const char*				name,
-	const char*				description,
-	qpImageCompressionMode	compressionMode,
-	qpImageFormat			imageFormat,
-	int						width,
-	int						height,
-	int						stride,
-	const void*				data)
-{
-	char			widthStr[32];
-	char			heightStr[32];
-	qpXmlAttribute	attribs[8];
-	int				numAttribs			= 0;
-	Buffer			compressedBuffer;
-	const void*		writeDataPtr		= DE_NULL;
-	size_t			writeDataBytes		= ~(size_t)0;
-
-	DE_ASSERT(log && name);
-	DE_ASSERT(deInRange32(width, 1, 16384));
-	DE_ASSERT(deInRange32(height, 1, 16384));
-	DE_ASSERT(data);
-
-	if (log->flags & QP_TEST_LOG_EXCLUDE_IMAGES)
-		return DE_TRUE; /* Image not logged. */
-
-	Buffer_init(&compressedBuffer);
-
-	/* BEST compression mode defaults to PNG. */
-	if (compressionMode == QP_IMAGE_COMPRESSION_MODE_BEST)
-	{
-#if defined(QP_SUPPORT_PNG)
-		compressionMode = QP_IMAGE_COMPRESSION_MODE_PNG;
-#else
-		compressionMode = QP_IMAGE_COMPRESSION_MODE_NONE;
-#endif
-	}
-
-#if defined(QP_SUPPORT_PNG)
-	/* Try storing with PNG compression. */
-	if (compressionMode == QP_IMAGE_COMPRESSION_MODE_PNG)
-	{
-		deBool compressOk = compressImagePNG(&compressedBuffer, imageFormat, width, height, stride, data);
-		if (compressOk)
-		{
-			writeDataPtr	= compressedBuffer.data;
-			writeDataBytes	= compressedBuffer.size;
-		}
-		else
-		{
-			/* Fall-back to default compression. */
-			qpPrintf("WARNING: PNG compression failed -- storing image uncompressed.\n");
-			compressionMode	= QP_IMAGE_COMPRESSION_MODE_NONE;
-		}
-	}
-#endif
-
-	/* Handle image compression. */
-	switch (compressionMode)
-	{
-		case QP_IMAGE_COMPRESSION_MODE_NONE:
-		{
-			int pixelSize		= imageFormat == QP_IMAGE_FORMAT_RGB888 ? 3 : 4;
-			int packedStride	= pixelSize*width;
-
-			if (packedStride == stride)
-				writeDataPtr = data;
-			else
-			{
-				/* Need to re-pack pixels. */
-				if (Buffer_resize(&compressedBuffer, (size_t)(packedStride*height)))
-				{
-					int row;
-					for (row = 0; row < height; row++)
-						memcpy(&compressedBuffer.data[packedStride*row], &((const deUint8*)data)[row*stride], (size_t)(pixelSize*width));
-				}
-				else
-				{
-					qpPrintf("ERROR: Failed to pack pixels for writing.\n");
-					Buffer_deinit(&compressedBuffer);
-					return DE_FALSE;
-				}
-			}
-
-			writeDataBytes = (size_t)(packedStride*height);
-			break;
-		}
-
-#if defined(QP_SUPPORT_PNG)
-		case QP_IMAGE_COMPRESSION_MODE_PNG:
-			DE_ASSERT(writeDataPtr); /* Already handled. */
-			break;
-#endif
-
-		default:
-			qpPrintf("qpTestLog_writeImage(): Unknown compression mode: %s\n", QP_LOOKUP_STRING(s_qpImageCompressionModeMap, compressionMode));
-			Buffer_deinit(&compressedBuffer);
-			return DE_FALSE;
-	}
-
-	/* Fill in attributes. */
-	int32ToString(width, widthStr);
-	int32ToString(height, heightStr);
-	attribs[numAttribs++] = qpSetStringAttrib("Name", name);
-	attribs[numAttribs++] = qpSetStringAttrib("Width", widthStr);
-	attribs[numAttribs++] = qpSetStringAttrib("Height", heightStr);
-	attribs[numAttribs++] = qpSetStringAttrib("Format", QP_LOOKUP_STRING(s_qpImageFormatMap, imageFormat));
-	attribs[numAttribs++] = qpSetStringAttrib("CompressionMode", QP_LOOKUP_STRING(s_qpImageCompressionModeMap, compressionMode));
-	if (description) attribs[numAttribs++] = qpSetStringAttrib("Description", description);
-
-	/* \note Log lock is acquired after compression! */
-	deMutex_lock(log->lock);
-
-	/* <Image ID="result" Name="Foobar" Width="640" Height="480" Format="RGB888" CompressionMode="None">base64 data</Image> */
-	if (!qpXmlWriter_startElement(log->writer, "Image", numAttribs, attribs) ||
-		!qpXmlWriter_writeBase64(log->writer, (const deUint8*)writeDataPtr, writeDataBytes) ||
-		!qpXmlWriter_endElement(log->writer, "Image"))
-	{
-		qpPrintf("qpTestLog_writeImage(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		Buffer_deinit(&compressedBuffer);
-		return DE_FALSE;
-	}
-
-	deMutex_unlock(log->lock);
-
-	/* Free compressed data if allocated. */
-	Buffer_deinit(&compressedBuffer);
-
-	return DE_TRUE;
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief Write a OpenGL ES shader program into the log.
- * \param linkOk			Shader program link result, false on failure
- * \param linkInfoLog		Implementation provided linkage log
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_startShaderProgram (qpTestLog* log, deBool linkOk, const char* linkInfoLog)
-{
-	qpXmlAttribute	programAttribs[4];
-	int				numProgramAttribs = 0;
-
-	DE_ASSERT(log);
-	deMutex_lock(log->lock);
-
-	programAttribs[numProgramAttribs++] = qpSetStringAttrib("LinkStatus", linkOk ? "OK" : "Fail");
-
-	if (!qpXmlWriter_startElement(log->writer, "ShaderProgram", numProgramAttribs, programAttribs) ||
-		!qpXmlWriter_writeStringElement(log->writer, "InfoLog", linkInfoLog))
-	{
-		qpPrintf("qpTestLog_startShaderProgram(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_SHADERPROGRAM));
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief End shader program
- * \param log			qpTestLog instance
- * \return true if ok, false otherwise
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_endShaderProgram (qpTestLog* log)
-{
-	DE_ASSERT(log);
-	deMutex_lock(log->lock);
-
-	/* </ShaderProgram> */
-	if (!qpXmlWriter_endElement(log->writer, "ShaderProgram"))
-	{
-		qpPrintf("qpTestLog_endShaderProgram(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_SHADERPROGRAM);
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief Write a OpenGL ES shader into the log.
- * \param type				Shader type
- * \param source			Shader source
- * \param compileOk			Shader compilation result, false on failure
- * \param infoLog			Implementation provided shader compilation log
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_writeShader (qpTestLog* log, qpShaderType type, const char* source, deBool compileOk, const char* infoLog)
-{
-	const char*		tagName				= QP_LOOKUP_STRING(s_qpShaderTypeMap, type);
-	const char*		sourceStr			= ((log->flags & QP_TEST_LOG_EXCLUDE_SHADER_SOURCES) == 0 || !compileOk) ? source : "";
-	int				numShaderAttribs	= 0;
-	qpXmlAttribute	shaderAttribs[4];
-
-	deMutex_lock(log->lock);
-
-	DE_ASSERT(source);
-	DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SHADERPROGRAM);
-
-	shaderAttribs[numShaderAttribs++]	= qpSetStringAttrib("CompileStatus", compileOk ? "OK" : "Fail");
-
-	if (!qpXmlWriter_startElement(log->writer, tagName, numShaderAttribs, shaderAttribs) ||
-		!qpXmlWriter_writeStringElement(log->writer, "ShaderSource", sourceStr) ||
-		!qpXmlWriter_writeStringElement(log->writer, "InfoLog", infoLog) ||
-		!qpXmlWriter_endElement(log->writer, tagName))
-	{
-		qpPrintf("qpTestLog_writeShader(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief Start writing a set of EGL configurations into the log.
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_startEglConfigSet (qpTestLog* log, const char* name, const char* description)
-{
-	qpXmlAttribute	attribs[4];
-	int				numAttribs = 0;
-
-	DE_ASSERT(log && name);
-	deMutex_lock(log->lock);
-
-	attribs[numAttribs++] = qpSetStringAttrib("Name", name);
-	if (description)
-		attribs[numAttribs++] = qpSetStringAttrib("Description", description);
-
-	/* <EglConfigSet Name="<name>"> */
-	if (!qpXmlWriter_startElement(log->writer, "EglConfigSet", numAttribs, attribs))
-	{
-		qpPrintf("qpTestLog_startEglImageSet(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_EGLCONFIGSET));
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief End an EGL config set
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_endEglConfigSet (qpTestLog* log)
-{
-	DE_ASSERT(log);
-	deMutex_lock(log->lock);
-
-	/* <EglConfigSet Name="<name>"> */
-	if (!qpXmlWriter_endElement(log->writer, "EglConfigSet"))
-	{
-		qpPrintf("qpTestLog_endEglImageSet(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_EGLCONFIGSET);
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief Write an EGL config inside an EGL config set
- * \see   qpElgConfigInfo for details
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_writeEglConfig (qpTestLog* log, const qpEglConfigInfo* config)
-{
-	qpXmlAttribute	attribs[64];
-	int				numAttribs = 0;
-
-	DE_ASSERT(log && config);
-	deMutex_lock(log->lock);
-
-	attribs[numAttribs++] = qpSetIntAttrib		("BufferSize", config->bufferSize);
-	attribs[numAttribs++] = qpSetIntAttrib		("RedSize", config->redSize);
-	attribs[numAttribs++] = qpSetIntAttrib		("GreenSize", config->greenSize);
-	attribs[numAttribs++] = qpSetIntAttrib		("BlueSize", config->blueSize);
-	attribs[numAttribs++] = qpSetIntAttrib		("LuminanceSize", config->luminanceSize);
-	attribs[numAttribs++] = qpSetIntAttrib		("AlphaSize", config->alphaSize);
-	attribs[numAttribs++] = qpSetIntAttrib		("AlphaMaskSize", config->alphaMaskSize);
-	attribs[numAttribs++] = qpSetBoolAttrib		("BindToTextureRGB", config->bindToTextureRGB);
-	attribs[numAttribs++] = qpSetBoolAttrib		("BindToTextureRGBA", config->bindToTextureRGBA);
-	attribs[numAttribs++] = qpSetStringAttrib	("ColorBufferType", config->colorBufferType);
-	attribs[numAttribs++] = qpSetStringAttrib	("ConfigCaveat", config->configCaveat);
-	attribs[numAttribs++] = qpSetIntAttrib		("ConfigID", config->configID);
-	attribs[numAttribs++] = qpSetStringAttrib	("Conformant", config->conformant);
-	attribs[numAttribs++] = qpSetIntAttrib		("DepthSize", config->depthSize);
-	attribs[numAttribs++] = qpSetIntAttrib		("Level", config->level);
-	attribs[numAttribs++] = qpSetIntAttrib		("MaxPBufferWidth", config->maxPBufferWidth);
-	attribs[numAttribs++] = qpSetIntAttrib		("MaxPBufferHeight", config->maxPBufferHeight);
-	attribs[numAttribs++] = qpSetIntAttrib		("MaxPBufferPixels", config->maxPBufferPixels);
-	attribs[numAttribs++] = qpSetIntAttrib		("MaxSwapInterval", config->maxSwapInterval);
-	attribs[numAttribs++] = qpSetIntAttrib		("MinSwapInterval", config->minSwapInterval);
-	attribs[numAttribs++] = qpSetBoolAttrib		("NativeRenderable", config->nativeRenderable);
-	attribs[numAttribs++] = qpSetStringAttrib	("RenderableType", config->renderableType);
-	attribs[numAttribs++] = qpSetIntAttrib		("SampleBuffers", config->sampleBuffers);
-	attribs[numAttribs++] = qpSetIntAttrib		("Samples", config->samples);
-	attribs[numAttribs++] = qpSetIntAttrib		("StencilSize", config->stencilSize);
-	attribs[numAttribs++] = qpSetStringAttrib	("SurfaceTypes", config->surfaceTypes);
-	attribs[numAttribs++] = qpSetStringAttrib	("TransparentType", config->transparentType);
-	attribs[numAttribs++] = qpSetIntAttrib		("TransparentRedValue", config->transparentRedValue);
-	attribs[numAttribs++] = qpSetIntAttrib		("TransparentGreenValue", config->transparentGreenValue);
-	attribs[numAttribs++] = qpSetIntAttrib		("TransparentBlueValue", config->transparentBlueValue);
-	DE_ASSERT(numAttribs <= DE_LENGTH_OF_ARRAY(attribs));
-
-	if (!qpXmlWriter_startElement(log->writer, "EglConfig", numAttribs, attribs) ||
-		!qpXmlWriter_endElement(log->writer, "EglConfig"))
-	{
-		qpPrintf("qpTestLog_writeEglConfig(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief Start section in log.
- * \param log			qpTestLog instance
- * \param name			Section name
- * \param description	Human readable description
- * \return true if ok, false otherwise
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_startSection (qpTestLog* log, const char* name, const char* description)
-{
-	qpXmlAttribute	attribs[2];
-	int				numAttribs = 0;
-
-	DE_ASSERT(log && name);
-	deMutex_lock(log->lock);
-
-	attribs[numAttribs++] = qpSetStringAttrib("Name", name);
-	if (description)
-		attribs[numAttribs++] = qpSetStringAttrib("Description", description);
-
-	/* <Section Name="<name>" Description="<description>"> */
-	if (!qpXmlWriter_startElement(log->writer, "Section", numAttribs, attribs))
-	{
-		qpPrintf("qpTestLog_startSection(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_SECTION));
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief End section in log.
- * \param log			qpTestLog instance
- * \return true if ok, false otherwise
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_endSection (qpTestLog* log)
-{
-	DE_ASSERT(log);
-	deMutex_lock(log->lock);
-
-	/* </Section> */
-	if (!qpXmlWriter_endElement(log->writer, "Section"))
-	{
-		qpPrintf("qpTestLog_endSection(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_SECTION);
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief Write OpenCL compute kernel source into the log.
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_writeKernelSource (qpTestLog* log, const char* source)
-{
-	const char*		sourceStr	= (log->flags & QP_TEST_LOG_EXCLUDE_SHADER_SOURCES) != 0 ? "" : source;
-
-	DE_ASSERT(log);
-	deMutex_lock(log->lock);
-
-	if (!qpXmlWriter_writeStringElement(log->writer, "KernelSource", sourceStr))
-	{
-		qpPrintf("qpTestLog_writeKernelSource(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief Write a SPIR-V module assembly source into the log.
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_writeSpirVAssemblySource (qpTestLog* log, const char* source)
-{
-	const char* const	sourceStr	= (log->flags & QP_TEST_LOG_EXCLUDE_SHADER_SOURCES) != 0 ? "" : source;
-
-	deMutex_lock(log->lock);
-
-	DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SHADERPROGRAM);
-
-	if (!qpXmlWriter_writeStringElement(log->writer, "SpirVAssemblySource", sourceStr))
-	{
-		qpPrintf("qpTestLog_writeSpirVAssemblySource(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-/*--------------------------------------------------------------------*//*!
- * \brief Write OpenCL kernel compilation results into the log
- *//*--------------------------------------------------------------------*/
-deBool qpTestLog_writeCompileInfo (qpTestLog* log, const char* name, const char* description, deBool compileOk, const char* infoLog)
-{
-	int				numAttribs = 0;
-	qpXmlAttribute	attribs[3];
-
-	DE_ASSERT(log && name && description && infoLog);
-	deMutex_lock(log->lock);
-
-	attribs[numAttribs++] = qpSetStringAttrib("Name", name);
-	attribs[numAttribs++] = qpSetStringAttrib("Description", description);
-	attribs[numAttribs++] = qpSetStringAttrib("CompileStatus", compileOk ? "OK" : "Fail");
-
-	if (!qpXmlWriter_startElement(log->writer, "CompileInfo", numAttribs, attribs) ||
-		!qpXmlWriter_writeStringElement(log->writer, "InfoLog", infoLog) ||
-		!qpXmlWriter_endElement(log->writer, "CompileInfo"))
-	{
-		qpPrintf("qpTestLog_writeCompileInfo(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-deBool qpTestLog_startSampleList (qpTestLog* log, const char* name, const char* description)
-{
-	int				numAttribs = 0;
-	qpXmlAttribute	attribs[2];
-
-	DE_ASSERT(log && name && description);
-	deMutex_lock(log->lock);
-
-	attribs[numAttribs++] = qpSetStringAttrib("Name", name);
-	attribs[numAttribs++] = qpSetStringAttrib("Description", description);
-
-	if (!qpXmlWriter_startElement(log->writer, "SampleList", numAttribs, attribs))
-	{
-		qpPrintf("qpTestLog_startSampleList(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_SAMPLELIST));
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-deBool qpTestLog_startSampleInfo (qpTestLog* log)
-{
-	DE_ASSERT(log);
-	deMutex_lock(log->lock);
-
-	if (!qpXmlWriter_startElement(log->writer, "SampleInfo", 0, DE_NULL))
-	{
-		qpPrintf("qpTestLog_startSampleInfo(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_SAMPLEINFO));
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-deBool qpTestLog_writeValueInfo (qpTestLog* log, const char* name, const char* description, const char* unit, qpSampleValueTag tag)
-{
-	const char*		tagName		= QP_LOOKUP_STRING(s_qpSampleValueTagMap, tag);
-	int				numAttribs	= 0;
-	qpXmlAttribute	attribs[4];
-
-	DE_ASSERT(log && name && description && tagName);
-	deMutex_lock(log->lock);
-
-	DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SAMPLEINFO);
-
-	attribs[numAttribs++] = qpSetStringAttrib("Name", name);
-	attribs[numAttribs++] = qpSetStringAttrib("Description", description);
-	attribs[numAttribs++] = qpSetStringAttrib("Tag", tagName);
-
-	if (unit)
-		attribs[numAttribs++] = qpSetStringAttrib("Unit", unit);
-
-	if (!qpXmlWriter_startElement(log->writer, "ValueInfo", numAttribs, attribs) ||
-		!qpXmlWriter_endElement(log->writer, "ValueInfo"))
-	{
-		qpPrintf("qpTestLog_writeValueInfo(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-deBool qpTestLog_endSampleInfo (qpTestLog* log)
-{
-	DE_ASSERT(log);
-	deMutex_lock(log->lock);
-
-	if (!qpXmlWriter_endElement(log->writer, "SampleInfo"))
-	{
-		qpPrintf("qpTestLog_endSampleInfo(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_SAMPLEINFO);
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-deBool qpTestLog_startSample (qpTestLog* log)
-{
-	DE_ASSERT(log);
-	deMutex_lock(log->lock);
-
-	DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SAMPLELIST);
-
-	if (!qpXmlWriter_startElement(log->writer, "Sample", 0, DE_NULL))
-	{
-		qpPrintf("qpTestLog_startSample(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_SAMPLE));
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-deBool qpTestLog_writeValueFloat (qpTestLog* log, double value)
-{
-	char tmpString[512];
-	doubleToString(value, tmpString, (int)sizeof(tmpString));
-
-	deMutex_lock(log->lock);
-
-	DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SAMPLE);
-
-	if (!qpXmlWriter_writeStringElement(log->writer, "Value", &tmpString[0]))
-	{
-		qpPrintf("qpTestLog_writeSampleValue(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-deBool qpTestLog_writeValueInteger (qpTestLog* log, deInt64 value)
-{
-	char tmpString[64];
-	int64ToString(value, tmpString);
-
-	deMutex_lock(log->lock);
-
-	DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SAMPLE);
-
-	if (!qpXmlWriter_writeStringElement(log->writer, "Value", &tmpString[0]))
-	{
-		qpPrintf("qpTestLog_writeSampleValue(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-deBool qpTestLog_endSample (qpTestLog* log)
-{
-	DE_ASSERT(log);
-	deMutex_lock(log->lock);
-
-	if (!qpXmlWriter_endElement(log->writer, "Sample"))
-	{
-		qpPrintf("qpTestLog_endSample(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_SAMPLE);
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-deBool qpTestLog_endSampleList (qpTestLog* log)
-{
-	DE_ASSERT(log);
-	deMutex_lock(log->lock);
-
-	if (!qpXmlWriter_endElement(log->writer, "SampleList"))
-	{
-		qpPrintf("qpTestLog_endSampleList(): Writing XML failed\n");
-		deMutex_unlock(log->lock);
-		return DE_FALSE;
-	}
-
-	DE_ASSERT(ContainerStack_pop(&log->containerStack) == CONTAINERTYPE_SAMPLELIST);
-
-	deMutex_unlock(log->lock);
-	return DE_TRUE;
-}
-
-deUint32 qpTestLog_getLogFlags (const qpTestLog* log)
-{
-	DE_ASSERT(log);
-	return log->flags;
-}
-
-const char* qpGetTestResultName (qpTestResult result)
-{
-	return QP_LOOKUP_STRING(s_qpTestResultMap, result);
-}
diff --git a/src/tests/egl_tests/EGLContextCompatibilityTest.cpp b/src/tests/egl_tests/EGLContextCompatibilityTest.cpp
index 0e90616..8240483 100644
--- a/src/tests/egl_tests/EGLContextCompatibilityTest.cpp
+++ b/src/tests/egl_tests/EGLContextCompatibilityTest.cpp
@@ -361,5 +361,9 @@
 // scales with the square of the number of configs exposed and can time out in some debug builds.
 // http://anglebug.com/2121
 #if defined(NDEBUG)
-ANGLE_INSTANTIATE_TEST(EGLContextCompatibilityTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL());
+ANGLE_INSTANTIATE_TEST(EGLContextCompatibilityTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES());
 #endif
diff --git a/src/tests/gl_tests/AtomicCounterBufferTest.cpp b/src/tests/gl_tests/AtomicCounterBufferTest.cpp
index e8c0194..650702c 100644
--- a/src/tests/gl_tests/AtomicCounterBufferTest.cpp
+++ b/src/tests/gl_tests/AtomicCounterBufferTest.cpp
@@ -116,15 +116,6 @@
 // Test atomic counter read.
 TEST_P(AtomicCounterBufferTest31, AtomicCounterRead)
 {
-    const std::string &vertShader =
-        "#version 310 es\n"
-        "precision highp float;\n"
-        "in highp vec4 a_position;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = a_position;\n"
-        "}\n";
-
     const std::string &fragShader =
         "#version 310 es\n"
         "precision highp float;\n"
@@ -137,7 +128,7 @@
         "    if (a1 == 3u) my_color = vec4(1.0);\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, vertShader, fragShader);
+    ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), fragShader);
 
     glUseProgram(program.get());
 
@@ -149,7 +140,7 @@
 
     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 2, atomicCounterBuffer);
 
-    drawQuad(program.get(), "a_position", 0.0f);
+    drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.0f);
     ASSERT_GL_NO_ERROR();
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
 }
diff --git a/src/tests/gl_tests/BindUniformLocationTest.cpp b/src/tests/gl_tests/BindUniformLocationTest.cpp
index bc42b2e..1b297c8 100644
--- a/src/tests/gl_tests/BindUniformLocationTest.cpp
+++ b/src/tests/gl_tests/BindUniformLocationTest.cpp
@@ -59,13 +59,6 @@
 
     ASSERT_NE(mBindUniformLocation, nullptr);
 
-    const std::string vsSource =
-        R"(attribute vec4 a_position;
-        void main()
-        {
-            gl_Position = a_position;
-        })";
-
     const std::string fsSource =
         R"(precision mediump float;
         uniform vec4 u_colorC;
@@ -80,7 +73,7 @@
     GLint colorBLocation = 10;
     GLint colorCLocation = 5;
 
-    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, essl1_shaders::vs::Simple());
     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
 
     mProgram = glCreateProgram();
@@ -112,7 +105,7 @@
     glUniform4fv(colorBLocation, 2, colorB);
     glUniform4f(colorCLocation, 0.0f, 0.0f, 0.0f, 1.0f);
 
-    drawQuad(mProgram, "a_position", 0.5f);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
 
     EXPECT_GL_NO_ERROR();
     EXPECT_PIXEL_NEAR(0, 0, 64, 128, 192, 255, 1.0);
@@ -125,13 +118,6 @@
 
     ASSERT_NE(nullptr, mBindUniformLocation);
 
-    const std::string vsSource =
-        R"(attribute vec4 a_position;
-        void main()
-        {
-            gl_Position = a_position;
-        })";
-
     const std::string fsSource =
         R"(precision mediump float;
         uniform vec4 u_colorA;
@@ -144,7 +130,7 @@
     GLint colorALocation = 3;
     GLint colorBLocation = 4;
 
-    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, essl1_shaders::vs::Simple());
     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
 
     mProgram = glCreateProgram();
@@ -281,13 +267,6 @@
 
     ASSERT_NE(nullptr, mBindUniformLocation);
 
-    const std::string vsSource =
-        R"(attribute vec4 a_position;
-        void main()
-        {
-            gl_Position = a_position;
-        })";
-
     const std::string fsSource =
         R"(precision mediump float;
         uniform vec4 u_colorA;
@@ -302,7 +281,7 @@
     const GLint nonexistingLocation = 5;
     const GLint unboundLocation     = 6;
 
-    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, essl1_shaders::vs::Simple());
     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
 
     mProgram = glCreateProgram();
@@ -381,12 +360,6 @@
 
     ASSERT_NE(nullptr, mBindUniformLocation);
 
-    const std::string vsSource =
-        R"(void main()
-        {
-            gl_Position = vec4(0);
-        })";
-
     const std::string fsSource =
         R"(uniform sampler2D tex;
         void main()
@@ -396,7 +369,7 @@
 
     const GLuint texLocation = 54;
 
-    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, essl1_shaders::vs::Simple());
     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
 
     mProgram = glCreateProgram();
@@ -425,12 +398,6 @@
 
     ASSERT_NE(nullptr, mBindUniformLocation);
 
-    const std::string vsSource =
-        R"(void main()
-        {
-            gl_Position = vec4(0);
-        })";
-
     const std::string fsSource =
         R"(precision mediump float;
         uniform vec4 a;
@@ -442,7 +409,7 @@
 
     const GLuint location = 54;
 
-    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, essl1_shaders::vs::Zero());
     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
 
     mProgram = glCreateProgram();
@@ -492,13 +459,6 @@
 {
     ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_CHROMIUM_bind_uniform_location"));
 
-    const std::string vsSource =
-        "#version 310 es\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = vec4(0);\n"
-        "}\n";
-
     const std::string fsSource =
         "#version 310 es\n"
         "uniform layout(location=2) highp sampler2D tex;\n"
@@ -510,7 +470,7 @@
 
     const GLuint texLocation = 2;
 
-    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, essl31_shaders::vs::Zero());
     EXPECT_NE(0u, vs);
     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
     EXPECT_NE(0u, fs);
@@ -533,13 +493,6 @@
 {
     ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_CHROMIUM_bind_uniform_location"));
 
-    const std::string vsSource =
-        "#version 310 es\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = vec4(0);\n"
-        "}\n";
-
     const std::string fsSource =
         "#version 310 es\n"
         "uniform layout(location=2) highp sampler2D tex;\n"
@@ -552,7 +505,7 @@
     const GLuint shaderTexLocation = 2;
     const GLuint texLocation       = 3;
 
-    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, essl31_shaders::vs::Zero());
     EXPECT_NE(0u, vs);
     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
     EXPECT_NE(0u, fs);
@@ -577,13 +530,6 @@
 {
     ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_CHROMIUM_bind_uniform_location"));
 
-    const std::string vsSource =
-        "#version 310 es\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = vec4(0);\n"
-        "}\n";
-
     const std::string fsSource =
         "#version 310 es\n"
         "uniform layout(location=2) highp sampler2D tex;\n"
@@ -596,7 +542,7 @@
 
     const GLuint tex2Location = 2;
 
-    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, essl31_shaders::vs::Zero());
     EXPECT_NE(0u, vs);
     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
     EXPECT_NE(0u, fs);
@@ -612,16 +558,6 @@
 {
     ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_CHROMIUM_bind_uniform_location"));
 
-    const std::string vsSource =
-        R"(#version 310 es
-
-        in vec4 a_position;
-
-        void main()
-        {
-            gl_Position = a_position;
-        })";
-
     const std::string fsSource =
         R"(#version 310 es
         precision highp float;
@@ -634,7 +570,7 @@
 
     const GLuint location = 8;
 
-    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+    GLuint vs = CompileShader(GL_VERTEX_SHADER, essl31_shaders::vs::Simple());
     EXPECT_NE(0u, vs);
     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
     EXPECT_NE(0u, fs);
@@ -647,7 +583,7 @@
     glUseProgram(mProgram);
     glUniform4f(location, 0.0f, 1.0f, 0.0f, 1.0f);
 
-    drawQuad(mProgram, "a_position", 0.5f);
+    drawQuad(mProgram, essl31_shaders::PositionAttrib(), 0.5f);
     EXPECT_GL_NO_ERROR();
 
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
diff --git a/src/tests/gl_tests/BlendMinMaxTest.cpp b/src/tests/gl_tests/BlendMinMaxTest.cpp
index b76c1bb..35f7a0e 100644
--- a/src/tests/gl_tests/BlendMinMaxTest.cpp
+++ b/src/tests/gl_tests/BlendMinMaxTest.cpp
@@ -72,7 +72,7 @@
             bool blendMin = (rand() % 2 == 0);
             glBlendEquation(blendMin ? GL_MIN : GL_MAX);
 
-            drawQuad(mProgram, "aPosition", 0.5f);
+            drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
 
             float pixel[4];
             if (type == GL_UNSIGNED_BYTE)
@@ -112,27 +112,13 @@
     {
         ANGLETest::SetUp();
 
-        const std::string testVertexShaderSource =
-            R"(attribute highp vec4 aPosition;
-            void main(void)
-            {
-                gl_Position = aPosition;
-            })";
-
-        const std::string testFragmentShaderSource =
-            R"(uniform highp vec4 color;
-            void main(void)
-            {
-                gl_FragColor = color;
-            })";
-
-        mProgram = CompileProgram(testVertexShaderSource, testFragmentShaderSource);
+        mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
         if (mProgram == 0)
         {
             FAIL() << "shader compilation failed.";
         }
 
-        mColorLocation = glGetUniformLocation(mProgram, "color");
+        mColorLocation = glGetUniformLocation(mProgram, essl1_shaders::ColorUniform());
 
         glUseProgram(mProgram);
 
diff --git a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
index 6e8de98..c698316 100644
--- a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
+++ b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
@@ -5,7 +5,6 @@
 //
 
 #include "test_utils/ANGLETest.h"
-
 #include "test_utils/gl_raii.h"
 
 using namespace angle;
@@ -65,44 +64,9 @@
     {
         ANGLETest::SetUp();
 
-        const std::string passthroughVS =
-            R"(precision highp float;
-            attribute vec4 position;
-            varying vec4 pos;
-
-            void main()
-            {
-                gl_Position = position;
-                pos = position;
-            })";
-
-        const std::string checkeredFS =
-            R"(precision highp float;
-            varying vec4 pos;
-
-            void main()
-            {
-                if (pos.x * pos.y > 0.0)
-                {
-                    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
-                }
-                else
-                {
-                    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
-                }
-            })";
-
-        const std::string blueFS =
-            R"(precision highp float;
-            varying vec4 pos;
-
-            void main()
-            {
-                gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
-            })";
-
-        mCheckerProgram = CompileProgram(passthroughVS, checkeredFS);
-        mBlueProgram = CompileProgram(passthroughVS, blueFS);
+        mCheckerProgram =
+            CompileProgram(essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Checkered());
+        mBlueProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
         if (mCheckerProgram == 0 || mBlueProgram == 0)
         {
             FAIL() << "shader compilation failed.";
@@ -415,7 +379,7 @@
 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
-    drawQuad(mCheckerProgram, "position", 0.8f);
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.8f);
 
     EXPECT_GL_NO_ERROR();
 
@@ -442,7 +406,7 @@
 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
-    drawQuad(mCheckerProgram, "position", 0.8f);
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.8f);
 
     EXPECT_GL_NO_ERROR();
 
@@ -469,7 +433,7 @@
 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
-    drawQuad(mCheckerProgram, "position", 0.8f);
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.8f);
 
     EXPECT_GL_NO_ERROR();
 
@@ -504,7 +468,7 @@
 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
-    drawQuad(mCheckerProgram, "position", 0.8f);
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.8f);
 
     EXPECT_GL_NO_ERROR();
 
@@ -539,7 +503,7 @@
 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
-    drawQuad(mCheckerProgram, "position", 0.8f);
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.8f);
 
     EXPECT_GL_NO_ERROR();
 
@@ -569,7 +533,7 @@
 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
-    drawQuad(mCheckerProgram, "position", 0.8f);
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.8f);
 
     EXPECT_GL_NO_ERROR();
 
@@ -601,7 +565,7 @@
 
     glEnable(GL_DEPTH_TEST);
 
-    drawQuad(mCheckerProgram, "position", 0.3f);
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.3f);
 
     EXPECT_GL_NO_ERROR();
 
@@ -618,7 +582,7 @@
     glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
 
     // if blit is happening correctly, this quad will not draw, because it is behind the blitted one
-    drawQuad(mBlueProgram, "position", 0.8f);
+    drawQuad(mBlueProgram, essl1_shaders::PositionAttrib(), 0.8f);
 
     glDisable(GL_DEPTH_TEST);
 
@@ -637,7 +601,7 @@
 
     glEnable(GL_DEPTH_TEST);
 
-    drawQuad(mCheckerProgram, "position", 0.3f);
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.3f);
 
     EXPECT_GL_NO_ERROR();
 
@@ -655,7 +619,7 @@
 
     // if blit is happening correctly, this quad will not draw, because it is behind the blitted one
 
-    drawQuad(mBlueProgram, "position", 0.8f);
+    drawQuad(mBlueProgram, essl1_shaders::PositionAttrib(), 0.8f);
 
     glDisable(GL_DEPTH_TEST);
 
@@ -672,7 +636,7 @@
 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
-    drawQuad(mCheckerProgram, "position", 0.3f);
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.3f);
 
     EXPECT_GL_NO_ERROR();
 
@@ -688,7 +652,7 @@
 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
-    drawQuad(mCheckerProgram, "position", 0.3f);
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.3f);
 
     EXPECT_GL_NO_ERROR();
 
@@ -703,7 +667,7 @@
 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
-    drawQuad(mCheckerProgram, "position", 0.5f);
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.5f);
 
     EXPECT_GL_NO_ERROR();
 
@@ -732,7 +696,7 @@
 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
-    drawQuad(mCheckerProgram, "position", 0.5f);
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.5f);
 
     EXPECT_GL_NO_ERROR();
 
@@ -759,7 +723,7 @@
     glBindFramebuffer(GL_FRAMEBUFFER, mColorOnlyFBO);
 
     glClear(GL_COLOR_BUFFER_BIT);
-    drawQuad(mCheckerProgram, "position", 0.3f);
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.3f);
 
     glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
     glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mColorOnlyFBO);
@@ -802,7 +766,7 @@
     glStencilFunc(GL_ALWAYS, 0x1, 0xFF);
     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
     glEnable(GL_STENCIL_TEST);
-    drawQuad(mCheckerProgram, "position", 0.3f);
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.3f);
 
     glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
     glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
@@ -825,7 +789,8 @@
     EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
 
     glStencilFunc(GL_EQUAL, 0x1, 0xFF); // only pass if stencil buffer at pixel reads 0x1
-    drawQuad(mBlueProgram, "position", 0.8f); // blue quad will draw if stencil buffer was copied
+    drawQuad(mBlueProgram, essl1_shaders::PositionAttrib(),
+             0.8f);  // blue quad will draw if stencil buffer was copied
     glDisable(GL_STENCIL_TEST);
 
     EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4,   0,   0, 255, 255);
@@ -841,7 +806,7 @@
 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
-    drawQuad(mCheckerProgram, "position", 0.5f);
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.5f);
 
     EXPECT_GL_NO_ERROR();
 
@@ -869,9 +834,9 @@
     glBindFramebuffer(GL_FRAMEBUFFER, mColorOnlyFBO);
 
     glClear(GL_COLOR_BUFFER_BIT);
-    
-    drawQuad(mCheckerProgram, "position", 0.8f);
-    
+
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.8f);
+
     EXPECT_GL_NO_ERROR();
 
     glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mColorOnlyFBO);
@@ -962,7 +927,7 @@
 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
-    drawQuad(mCheckerProgram, "position", 0.5f);
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.5f);
 
     EXPECT_GL_NO_ERROR();
 
@@ -981,7 +946,7 @@
 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
-    drawQuad(mCheckerProgram, "position", 0.5f);
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.5f);
 
     EXPECT_GL_NO_ERROR();
 
@@ -999,7 +964,7 @@
 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
-    drawQuad(mCheckerProgram, "position", 0.5f);
+    drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.5f);
 
     EXPECT_GL_NO_ERROR();
 
@@ -1047,12 +1012,6 @@
     glBindRenderbuffer(GL_RENDERBUFFER, renderbuf.get());
     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_DEPTH_COMPONENT24, 256, 256);
 
-    const std::string &vertex =
-        "#version 300 es\n"
-        "in vec2 position;\n"
-        "void main() {\n"
-        "  gl_Position = vec4(position, 0.0, 0.5);\n"
-        "}";
     const std::string &fragment =
         "#version 300 es\n"
         "out mediump vec4 red;\n"
@@ -1061,7 +1020,7 @@
         "   gl_FragDepth = 0.5;\n"
         "}";
 
-    ANGLE_GL_PROGRAM(drawRed, vertex, fragment);
+    ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), fragment);
 
     GLFramebuffer framebuffer;
     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
@@ -1102,7 +1061,7 @@
     // Draw with 0.5f test and the test should pass.
     glEnable(GL_DEPTH_TEST);
     glDepthFunc(GL_EQUAL);
-    drawQuad(drawRed.get(), "position", 0.5f);
+    drawQuad(drawRed.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
 
     ASSERT_GL_NO_ERROR();
@@ -1115,20 +1074,7 @@
     glBindRenderbuffer(GL_RENDERBUFFER, renderbuf.get());
     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_STENCIL_INDEX8, 256, 256);
 
-    const std::string &vertex =
-        "#version 300 es\n"
-        "in vec2 position;\n"
-        "void main() {\n"
-        "  gl_Position = vec4(position, 0.0, 1.0);\n"
-        "}";
-    const std::string &fragment =
-        "#version 300 es\n"
-        "out mediump vec4 red;\n"
-        "void main() {\n"
-        "   red = vec4(1.0, 0.0, 0.0, 1.0);\n"
-        "}";
-
-    ANGLE_GL_PROGRAM(drawRed, vertex, fragment);
+    ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
 
     GLFramebuffer framebuffer;
     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
@@ -1141,7 +1087,7 @@
     glStencilFunc(GL_ALWAYS, 0x1, 0xFF);
     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
     glEnable(GL_STENCIL_TEST);
-    drawQuad(drawRed.get(), "position", 0.5f);
+    drawQuad(drawRed.get(), essl3_shaders::PositionAttrib(), 0.5f);
 
     GLTexture destColorbuf;
     glBindTexture(GL_TEXTURE_2D, destColorbuf.get());
@@ -1172,7 +1118,7 @@
 
     // Draw red if the stencil is 0x1, which should be true after the blit/resolve.
     glStencilFunc(GL_EQUAL, 0x1, 0xFF);
-    drawQuad(drawRed.get(), "position", 0.5f);
+    drawQuad(drawRed.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
 
     ASSERT_GL_NO_ERROR();
diff --git a/src/tests/gl_tests/BuiltinVariableTest.cpp b/src/tests/gl_tests/BuiltinVariableTest.cpp
index 36cf0aa..9ef9219 100644
--- a/src/tests/gl_tests/BuiltinVariableTest.cpp
+++ b/src/tests/gl_tests/BuiltinVariableTest.cpp
@@ -214,13 +214,6 @@
     {
         ANGLETest::SetUp();
 
-        const std::string vs =
-            R"(#version 300 es
-            in vec4 a_position;
-            void main(){
-                gl_Position = a_position;
-            })";
-
         // Writes a fixed detph value and green.
         // Section 15.2.3 of the GL 4.5 specification says that conversion is not
         // done but clamping is so the output depth should be in [0.0, 1.0]
@@ -234,7 +227,7 @@
                 fragColor = vec4(0.0, 1.0, 0.0, 1.0);
             })";
 
-        mProgram = CompileProgram(vs, depthFs);
+        mProgram = CompileProgram(essl3_shaders::vs::Simple(), depthFs);
         ASSERT_NE(0u, mProgram);
 
         mDepthLocation = glGetUniformLocation(mProgram, "u_depth");
diff --git a/src/tests/gl_tests/ClearTest.cpp b/src/tests/gl_tests/ClearTest.cpp
index 486b6d5..aee323b 100644
--- a/src/tests/gl_tests/ClearTest.cpp
+++ b/src/tests/gl_tests/ClearTest.cpp
@@ -36,7 +36,7 @@
 class ClearTestBase : public ANGLETest
 {
   protected:
-    ClearTestBase() : mProgram(0)
+    ClearTestBase()
     {
         setWindowWidth(128);
         setWindowHeight(128);
@@ -59,8 +59,6 @@
 
     void TearDown() override
     {
-        glDeleteProgram(mProgram);
-
         if (!mFBOs.empty())
         {
             glDeleteFramebuffers(static_cast<GLsizei>(mFBOs.size()), mFBOs.data());
@@ -74,30 +72,6 @@
         ANGLETest::TearDown();
     }
 
-    void setupDefaultProgram()
-    {
-        const std::string vertexShaderSource =
-            R"(precision highp float;
-            attribute vec4 position;
-
-            void main()
-            {
-                gl_Position = position;
-            })";
-
-        const std::string fragmentShaderSource =
-            R"(precision highp float;
-
-            void main()
-            {
-                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
-            })";
-
-        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
-        ASSERT_NE(0u, mProgram);
-    }
-
-    GLuint mProgram;
     std::vector<GLuint> mFBOs;
     std::vector<GLuint> mTextures;
 };
@@ -133,10 +107,6 @@
 
 TEST_P(ClearTest, ClearIssue)
 {
-    // Skip this test because of an issue on older Windows AMD Vulkan drivers.
-    // TODO(jmadill): Re-enable this once Chromium bots are upgraded. http://crbug.com/821522
-    ANGLE_SKIP_TEST_IF(IsVulkan() && IsAMD() && IsWindows());
-
     glEnable(GL_DEPTH_TEST);
     glDepthFunc(GL_LEQUAL);
 
@@ -167,8 +137,8 @@
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
     glBindBuffer(GL_ARRAY_BUFFER, 0);
 
-    setupDefaultProgram();
-    drawQuad(mProgram, "position", 0.5f);
+    ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
+    drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
 
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
@@ -228,7 +198,7 @@
     glClearBufferfv(GL_COLOR, 0, clearValues1);
 
     ASSERT_GL_NO_ERROR();
-    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 
     // Next make a second framebuffer, and draw it to red
     // (Triggers bad applied render target serial)
@@ -242,15 +212,15 @@
 
     glDrawBuffers(1, drawBuffers);
 
-    setupDefaultProgram();
-    drawQuad(mProgram, "position", 0.5f);
+    ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
+    drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
 
     ASSERT_GL_NO_ERROR();
-    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
 
     // Check that the first framebuffer is still green.
     glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]);
-    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
 // Test that SRGB framebuffers clear to the linearized clear color
@@ -334,8 +304,7 @@
         "    color = texture(tex, v_coord);\n"
         "}\n";
 
-    mProgram = CompileProgram(vertexSource, fragmentSource);
-    ASSERT_NE(0u, mProgram);
+    ANGLE_GL_PROGRAM(program, vertexSource, fragmentSource);
 
     mTextures.resize(1, 0);
     glGenTextures(1, mTextures.data());
@@ -363,16 +332,16 @@
     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
 
     // larger fbo bound -- clear to transparent black
-    glUseProgram(mProgram);
-    GLint uniLoc = glGetUniformLocation(mProgram, "tex");
+    glUseProgram(program);
+    GLint uniLoc = glGetUniformLocation(program, "tex");
     ASSERT_NE(-1, uniLoc);
     glUniform1i(uniLoc, 0);
     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
 
-    GLint positionLocation = glGetAttribLocation(mProgram, "position");
+    GLint positionLocation = glGetAttribLocation(program, "position");
     ASSERT_NE(-1, positionLocation);
 
-    glUseProgram(mProgram);
+    glUseProgram(program);
 
     for (int cellY = 0; cellY < numRowsCols; cellY++)
     {
@@ -388,7 +357,7 @@
 
             // Method 1: Set viewport and draw full-viewport quad
             glViewport(cellX * cellSize, cellY * cellSize, cellSize, cellSize);
-            drawQuad(mProgram, "position", 0.5f);
+            drawQuad(program, "position", 0.5f);
 
             // Uncommenting the glFinish call seems to make the test pass.
             // glFinish();
diff --git a/src/tests/gl_tests/ClientArraysTest.cpp b/src/tests/gl_tests/ClientArraysTest.cpp
index 6b854ed..4a738fb 100644
--- a/src/tests/gl_tests/ClientArraysTest.cpp
+++ b/src/tests/gl_tests/ClientArraysTest.cpp
@@ -83,14 +83,7 @@
         "    gl_Position = vec4(a_pos, 1.0);\n"
         "}\n";
 
-    const std::string &frag =
-        "precision highp float;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_FragColor = vec4(1.0);\n"
-        "}\n";
-
-    ANGLE_GL_PROGRAM(program, vert, frag);
+    ANGLE_GL_PROGRAM(program, vert, essl1_shaders::fs::Red());
 
     GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
     ASSERT_NE(-1, posLocation);
diff --git a/src/tests/gl_tests/ColorMaskTest.cpp b/src/tests/gl_tests/ColorMaskTest.cpp
index d2ad638..be35c20 100644
--- a/src/tests/gl_tests/ColorMaskTest.cpp
+++ b/src/tests/gl_tests/ColorMaskTest.cpp
@@ -29,28 +29,10 @@
     {
         ANGLETest::SetUp();
 
-        const std::string vsSource =
-            "precision highp float;\n"
-            "attribute vec4 position;\n"
-            "\n"
-            "void main()\n"
-            "{\n"
-            "    gl_Position = position;\n"
-            "}\n";
-
-        const std::string fsSource =
-            "precision highp float;\n"
-            "uniform vec4 color;\n"
-            "\n"
-            "void main()\n"
-            "{\n"
-            "    gl_FragColor = color;\n"
-            "}\n";
-
-        mProgram = CompileProgram(vsSource, fsSource);
+        mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
         ASSERT_NE(0u, mProgram) << "shader compilation failed.";
 
-        mColorUniform = glGetUniformLocation(mProgram, "color");
+        mColorUniform = glGetUniformLocation(mProgram, essl1_shaders::ColorUniform());
     }
 
     void TearDown() override
@@ -82,7 +64,7 @@
     glUseProgram(mProgram);
     glUniform4f(mColorUniform, 1.0f, 0.0f, 0.0f, 0.0f);
     EXPECT_GL_NO_ERROR();
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_EQ(x, y, 0, 0, 255, 255);
 
     // Re-enable the color mask, should be red (with blend disabled, the red should overwrite
@@ -91,7 +73,7 @@
     glUseProgram(mProgram);
     glUniform4f(mColorUniform, 1.0f, 0.0f, 0.0f, 0.0f);
     EXPECT_GL_NO_ERROR();
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_EQ(x, y, 255, 0, 0, 0);
 }
 
diff --git a/src/tests/gl_tests/CopyTextureTest.cpp b/src/tests/gl_tests/CopyTextureTest.cpp
index 1a56c9b..d15d94a 100644
--- a/src/tests/gl_tests/CopyTextureTest.cpp
+++ b/src/tests/gl_tests/CopyTextureTest.cpp
@@ -1288,6 +1288,29 @@
         testOutput(destTexture, expectedColor);
     };
 
+    auto testSubCopyCombination = [this, testOutput](
+                                      GLenum sourceInternalFormat, GLenum sourceFormat,
+                                      GLenum sourceType, const GLColor &sourceColor,
+                                      GLenum destInternalFormat, GLenum destFormat, GLenum destType,
+                                      bool flipY, bool premultiplyAlpha, bool unmultiplyAlpha,
+                                      const GLColor &expectedColor) {
+
+        GLTexture sourceTexture;
+        glBindTexture(GL_TEXTURE_2D, sourceTexture);
+        glTexImage2D(GL_TEXTURE_2D, 0, sourceInternalFormat, 1, 1, 0, sourceFormat, sourceType,
+                     &sourceColor);
+
+        GLTexture destTexture;
+        glBindTexture(GL_TEXTURE_2D, destTexture);
+
+        glTexImage2D(GL_TEXTURE_2D, 0, destInternalFormat, 1, 1, 0, destFormat, destType, nullptr);
+        glCopySubTextureCHROMIUM(sourceTexture, 0, GL_TEXTURE_2D, destTexture, 0, 0, 0, 0, 0, 1, 1,
+                                 flipY, premultiplyAlpha, unmultiplyAlpha);
+        ASSERT_GL_NO_ERROR();
+
+        testOutput(destTexture, expectedColor);
+    };
+
     // New LUMA source formats
     testCopyCombination(GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, GLColor(128, 0, 0, 0), GL_RGB,
                         GL_UNSIGNED_BYTE, false, false, false, GLColor(128, 128, 128, 255));
@@ -1315,6 +1338,14 @@
     testCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128),
                         GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, false, false, false,
                         GLColor(55, 13, 4, 128));
+
+    testSubCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128), GL_SRGB,
+                           GL_SRGB, GL_UNSIGNED_BYTE, false, false, false, GLColor(55, 13, 4, 255));
+    testSubCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128), GL_SRGB,
+                           GL_SRGB, GL_UNSIGNED_BYTE, false, true, false, GLColor(13, 4, 1, 255));
+    testSubCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128),
+                           GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, false, false,
+                           false, GLColor(55, 13, 4, 128));
 }
 
 // Test the newly added ES3 float formats
diff --git a/src/tests/gl_tests/CubeMapTextureTest.cpp b/src/tests/gl_tests/CubeMapTextureTest.cpp
index f6ceae0..514fbc6 100644
--- a/src/tests/gl_tests/CubeMapTextureTest.cpp
+++ b/src/tests/gl_tests/CubeMapTextureTest.cpp
@@ -25,27 +25,13 @@
     {
         ANGLETest::SetUp();
 
-        const std::string vsSource =
-            R"(attribute highp vec4 position;
-            void main(void)
-            {
-                gl_Position = position;
-            })";
-
-        const std::string fsSource =
-            R"(uniform highp vec4 color;
-            void main(void)
-            {
-                gl_FragColor = color;
-            })";
-
-        mProgram = CompileProgram(vsSource, fsSource);
+        mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
         if (mProgram == 0)
         {
             FAIL() << "shader compilation failed.";
         }
 
-        mColorLocation = glGetUniformLocation(mProgram, "color");
+        mColorLocation = glGetUniformLocation(mProgram, essl1_shaders::ColorUniform());
 
         glUseProgram(mProgram);
 
@@ -108,7 +94,7 @@
         const GLfloat *faceColor = faceColors + (face * 4);
         glUniform4f(mColorLocation, faceColor[0], faceColor[1], faceColor[2], faceColor[3]);
 
-        drawQuad(mProgram, "position", 0.5f);
+        drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
         EXPECT_GL_NO_ERROR();
     }
 
diff --git a/src/tests/gl_tests/DepthStencilFormatsTest.cpp b/src/tests/gl_tests/DepthStencilFormatsTest.cpp
index c61c653..2180590 100644
--- a/src/tests/gl_tests/DepthStencilFormatsTest.cpp
+++ b/src/tests/gl_tests/DepthStencilFormatsTest.cpp
@@ -192,21 +192,7 @@
 {
     ANGLE_SKIP_TEST_IF(IsIntel() && (IsOSX() || IsWindows()));
 
-    constexpr char vertexShaderSource[] =
-        R"(attribute vec4 position;
-        void main()
-        {
-          gl_Position = position;
-        })";
-
-    constexpr char fragmentShaderSource[] =
-        R"(precision mediump float;
-        void main()
-        {
-          gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
-        })";
-
-    ANGLE_GL_PROGRAM(program, vertexShaderSource, fragmentShaderSource);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
 
     glEnable(GL_STENCIL_TEST);
     glDisable(GL_DEPTH_TEST);
@@ -245,7 +231,7 @@
         glViewport(0, 0, viewport[0], viewport[1]);
         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb);
 
-        drawQuad(program.get(), "position", 0.0f);
+        drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.0f);
         ASSERT_GL_NO_ERROR();
 
         glBindFramebuffer(GL_READ_FRAMEBUFFER, fb);
@@ -294,13 +280,7 @@
         "  gl_Position = vec4(vertex.x, vertex.y, vertex.z * 2.0 - 1.0, 1);\n"
         "}\n";
 
-    const std::string &drawFS =
-        "#version 100\n"
-        "void main () {\n"
-        "  gl_FragColor = vec4 (1.);\n"
-        "}\n";
-
-    ANGLE_GL_PROGRAM(drawProgram, drawVS, drawFS);
+    ANGLE_GL_PROGRAM(drawProgram, drawVS, essl1_shaders::fs::Red());
 
     const std::string &blitVS =
         "#version 100\n"
diff --git a/src/tests/gl_tests/DifferentStencilMasksTest.cpp b/src/tests/gl_tests/DifferentStencilMasksTest.cpp
index b3b2279..76110b6 100644
--- a/src/tests/gl_tests/DifferentStencilMasksTest.cpp
+++ b/src/tests/gl_tests/DifferentStencilMasksTest.cpp
@@ -32,24 +32,7 @@
     {
         ANGLETest::SetUp();
 
-        const std::string vertexShaderSource =
-            R"(precision highp float;
-            attribute vec4 position;
-
-            void main()
-            {
-                gl_Position = position;
-            })";
-
-        const std::string fragmentShaderSource =
-            R"(precision highp float;
-
-            void main()
-            {
-                gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
-            })";
-
-        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
         ASSERT_NE(0u, mProgram);
 
         glEnable(GL_STENCIL_TEST);
@@ -77,7 +60,7 @@
 
     glUseProgram(mProgram);
 
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
 
     EXPECT_GL_NO_ERROR();
 }
@@ -90,7 +73,7 @@
 
     glUseProgram(mProgram);
 
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
 
     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
 }
@@ -114,24 +97,7 @@
     {
         ANGLETest::SetUp();
 
-        const std::string vertexShaderSource =
-            R"(precision highp float;
-            attribute vec4 position;
-
-            void main()
-            {
-                gl_Position = position;
-            })";
-
-        const std::string fragmentShaderSource =
-            R"(precision highp float;
-
-            void main()
-            {
-                gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
-            })";
-
-        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
         ASSERT_NE(0u, mProgram);
 
         glEnable(GL_STENCIL_TEST);
@@ -158,7 +124,7 @@
 
     glUseProgram(mProgram);
 
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
 
     EXPECT_GL_NO_ERROR();
 }
diff --git a/src/tests/gl_tests/DrawBuffersTest.cpp b/src/tests/gl_tests/DrawBuffersTest.cpp
index 28b7624..f7a5cd9 100644
--- a/src/tests/gl_tests/DrawBuffersTest.cpp
+++ b/src/tests/gl_tests/DrawBuffersTest.cpp
@@ -82,13 +82,6 @@
 
     void setupMRTProgramESSL3(bool bufferEnabled[8], GLuint *programOut)
     {
-        const std::string vertexShaderSource =
-            "#version 300 es\n"
-            "in vec4 position;\n"
-            "void main() {\n"
-            "    gl_Position = position;\n"
-            "}\n";
-
         std::stringstream strstr;
 
         strstr << "#version 300 es\n"
@@ -122,7 +115,7 @@
 
         strstr << "}\n";
 
-        *programOut = CompileProgram(vertexShaderSource, strstr.str());
+        *programOut = CompileProgram(essl3_shaders::vs::Simple(), strstr.str());
         if (*programOut == 0)
         {
             FAIL() << "shader compilation failed.";
@@ -131,12 +124,6 @@
 
     void setupMRTProgramESSL1(bool bufferEnabled[8], GLuint *programOut)
     {
-        const std::string vertexShaderSource =
-            "attribute vec4 position;\n"
-            "void main() {\n"
-            "    gl_Position = position;\n"
-            "}\n";
-
         std::stringstream strstr;
 
         strstr << "#extension GL_EXT_draw_buffers : enable\n"
@@ -160,7 +147,7 @@
 
         strstr << "}\n";
 
-        *programOut = CompileProgram(vertexShaderSource, strstr.str());
+        *programOut = CompileProgram(essl1_shaders::vs::Simple(), strstr.str());
         if (*programOut == 0)
         {
             FAIL() << "shader compilation failed.";
@@ -180,6 +167,18 @@
         }
     }
 
+    const char *positionAttrib()
+    {
+        if (getClientMajorVersion() == 3)
+        {
+            return essl3_shaders::PositionAttrib();
+        }
+        else
+        {
+            return essl1_shaders::PositionAttrib();
+        }
+    }
+
     static GLColor getColorForIndex(unsigned int index)
     {
         GLubyte r = (((index + 1) & 1) > 0) ? 255 : 0;
@@ -257,7 +256,7 @@
         GL_COLOR_ATTACHMENT1
     };
     setDrawBuffers(2, bufs);
-    drawQuad(program, "position", 0.5);
+    drawQuad(program, positionAttrib(), 0.5);
 
     verifyAttachment2D(1, mTextures[0], GL_TEXTURE_2D, 0);
 
@@ -291,7 +290,7 @@
     };
 
     setDrawBuffers(4, bufs);
-    drawQuad(program, "position", 0.5);
+    drawQuad(program, positionAttrib(), 0.5);
 
     verifyAttachment2D(0, mTextures[0], GL_TEXTURE_2D, 0);
     verifyAttachment2D(3, mTextures[1], GL_TEXTURE_2D, 0);
@@ -325,7 +324,7 @@
     setupMRTProgram(flags, &program);
 
     setDrawBuffers(mMaxDrawBuffers, bufs);
-    drawQuad(program, "position", 0.5);
+    drawQuad(program, positionAttrib(), 0.5);
 
     for (GLuint texIndex = 0; texIndex < halfMaxDrawBuffers; texIndex++)
     {
@@ -364,7 +363,7 @@
     setDrawBuffers(4, bufs);
 
     // This call should not crash when we dynamically generate the HLSL code.
-    drawQuad(program, "position", 0.5);
+    drawQuad(program, positionAttrib(), 0.5);
 
     verifyAttachment2D(0, mTextures[0], GL_TEXTURE_2D, 0);
 
@@ -386,12 +385,6 @@
 
     const GLenum bufs[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
 
-    const std::string vertexShaderSource =
-        "attribute vec4 position;\n"
-        "void main() {\n"
-        "    gl_Position = position;\n"
-        "}\n";
-
     const std::string fragmentShaderSource =
         "#extension GL_EXT_draw_buffers : enable\n"
         "precision highp float;\n"
@@ -405,14 +398,14 @@
         "    }\n"
         "}\n";
 
-    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    GLuint program = CompileProgram(essl1_shaders::vs::Simple(), fragmentShaderSource);
     if (program == 0)
     {
         FAIL() << "shader compilation failed.";
     }
 
     setDrawBuffers(2, bufs);
-    drawQuad(program, "position", 0.5);
+    drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
 
     verifyAttachment2D(0, mTextures[0], GL_TEXTURE_2D, 0);
     verifyAttachment2D(0, mTextures[1], GL_TEXTURE_2D, 0);
@@ -449,7 +442,7 @@
     };
 
     glDrawBuffers(4, bufs);
-    drawQuad(program, "position", 0.5);
+    drawQuad(program, positionAttrib(), 0.5);
 
     verifyAttachmentLayer(0, texture.get(), 0, 0);
     verifyAttachmentLayer(1, texture.get(), 0, 1);
@@ -484,7 +477,7 @@
     };
 
     glDrawBuffers(4, bufs);
-    drawQuad(program, "position", 0.5);
+    drawQuad(program, positionAttrib(), 0.5);
 
     verifyAttachmentLayer(0, texture.get(), 0, 0);
     verifyAttachmentLayer(1, texture.get(), 0, 1);
diff --git a/src/tests/gl_tests/DrawElementsTest.cpp b/src/tests/gl_tests/DrawElementsTest.cpp
index a5b6c95..696d78b 100644
--- a/src/tests/gl_tests/DrawElementsTest.cpp
+++ b/src/tests/gl_tests/DrawElementsTest.cpp
@@ -74,14 +74,7 @@
         "    gl_Position = vec4(a_pos, 1.0);\n"
         "}\n";
 
-    const std::string &frag =
-        "precision highp float;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_FragColor = vec4(1.0);\n"
-        "}\n";
-
-    ANGLE_GL_PROGRAM(program, vert, frag);
+    ANGLE_GL_PROGRAM(program, vert, essl1_shaders::fs::Blue());
 
     GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
     ASSERT_NE(-1, posLocation);
@@ -276,14 +269,7 @@
         "    gl_Position = vec4(a_pos, 1.0);\n"
         "}\n";
 
-    const std::string &frag =
-        "precision highp float;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_FragColor = vec4(1.0);\n"
-        "}\n";
-
-    ANGLE_GL_PROGRAM(program, vert, frag);
+    ANGLE_GL_PROGRAM(program, vert, essl1_shaders::fs::Blue());
 
     GLint posLocation = glGetAttribLocation(program, "a_pos");
     ASSERT_NE(-1, posLocation);
diff --git a/src/tests/gl_tests/FloatingPointSurfaceTest.cpp b/src/tests/gl_tests/FloatingPointSurfaceTest.cpp
index 8d57984..05e8984 100644
--- a/src/tests/gl_tests/FloatingPointSurfaceTest.cpp
+++ b/src/tests/gl_tests/FloatingPointSurfaceTest.cpp
@@ -28,14 +28,6 @@
     {
         ANGLETest::SetUp();
 
-        const std::string vsSource =
-            "precision highp float;\n"
-            "attribute vec4 position;\n"
-            "void main()\n"
-            "{\n"
-            "   gl_Position = position;\n"
-            "}\n";
-
         const std::string fsSource =
             "precision highp float;\n"
             "void main()\n"
@@ -43,7 +35,7 @@
             "   gl_FragColor = vec4(1.0, 2.0, 3.0, 4.0);\n"
             "}\n";
 
-        mProgram = CompileProgram(vsSource, fsSource);
+        mProgram = CompileProgram(essl1_shaders::vs::Simple(), fsSource);
         ASSERT_NE(0u, mProgram) << "shader compilation failed.";
 
         ASSERT_GL_NO_ERROR();
@@ -74,7 +66,7 @@
 TEST_P(FloatingPointSurfaceTest, Drawing)
 {
     glUseProgram(mProgram);
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
 
     EXPECT_PIXEL_32F_EQ(0, 0, 1.0f, 2.0f, 3.0f, 4.0f);
 }
diff --git a/src/tests/gl_tests/FramebufferMixedSamplesTest.cpp b/src/tests/gl_tests/FramebufferMixedSamplesTest.cpp
index 9a16345..f102585 100644
--- a/src/tests/gl_tests/FramebufferMixedSamplesTest.cpp
+++ b/src/tests/gl_tests/FramebufferMixedSamplesTest.cpp
@@ -9,7 +9,6 @@
 //   sample counts for different render buffers (stencil, depth, color)
 
 #include "test_utils/ANGLETest.h"
-#include "shader_utils.h"
 
 using namespace angle;
 
@@ -38,24 +37,10 @@
     {
         ANGLETest::SetUp();
 
-        // clang-format off
-        static const char* kVertexShaderSource =
-            "attribute mediump vec4 position;\n"
-            "void main() {\n"
-            "  gl_Position = position;\n"
-            "}\n";
+        mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
 
-        static const char* kFragmentShaderSource =
-            "uniform mediump vec4 color;\n"
-            "void main() {\n"
-            "  gl_FragColor = color;\n"
-            "}\n";
-
-        // clang-format on
-        mProgram = CompileProgram(kVertexShaderSource, kFragmentShaderSource);
-
-        GLuint position_loc = glGetAttribLocation(mProgram, "position");
-        mColorLoc           = glGetUniformLocation(mProgram, "color");
+        GLuint position_loc = glGetAttribLocation(mProgram, essl1_shaders::PositionAttrib());
+        mColorLoc           = glGetUniformLocation(mProgram, essl1_shaders::ColorUniform());
 
         glGenBuffers(1, &mVBO);
         glBindBuffer(GL_ARRAY_BUFFER, mVBO);
diff --git a/src/tests/gl_tests/FramebufferRenderMipmapTest.cpp b/src/tests/gl_tests/FramebufferRenderMipmapTest.cpp
index edc6287..eefd86c 100644
--- a/src/tests/gl_tests/FramebufferRenderMipmapTest.cpp
+++ b/src/tests/gl_tests/FramebufferRenderMipmapTest.cpp
@@ -25,27 +25,13 @@
     {
         ANGLETest::SetUp();
 
-        const std::string vsSource =
-            R"(attribute highp vec4 position;
-            void main(void)
-            {
-                gl_Position = position;
-            })";
-
-        const std::string fsSource =
-            R"(uniform highp vec4 color;
-            void main(void)
-            {
-                gl_FragColor = color;
-            })";
-
-        mProgram = CompileProgram(vsSource, fsSource);
+        mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
         if (mProgram == 0)
         {
             FAIL() << "shader compilation failed.";
         }
 
-        mColorLocation = glGetUniformLocation(mProgram, "color");
+        mColorLocation = glGetUniformLocation(mProgram, essl1_shaders::ColorUniform());
 
         glUseProgram(mProgram);
 
@@ -158,7 +144,7 @@
         glUseProgram(mProgram);
         glUniform4fv(mColorLocation, 1, levelColors + (i * 4));
 
-        drawQuad(mProgram, "position", 0.5f);
+        drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
         EXPECT_GL_NO_ERROR();
     }
 
diff --git a/src/tests/gl_tests/FramebufferTest.cpp b/src/tests/gl_tests/FramebufferTest.cpp
index f932a34..fddd542 100644
--- a/src/tests/gl_tests/FramebufferTest.cpp
+++ b/src/tests/gl_tests/FramebufferTest.cpp
@@ -305,11 +305,9 @@
                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
 
     // Verify drawing with the incomplete framebuffer produces a GL error
-    const std::string &vs = "attribute vec4 position; void main() { gl_Position = position; }";
-    const std::string &ps = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
-    mProgram = CompileProgram(vs, ps);
+    mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
     ASSERT_NE(0u, mProgram);
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
     ASSERT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
 }
 
diff --git a/src/tests/gl_tests/GLSLTest.cpp b/src/tests/gl_tests/GLSLTest.cpp
index 0e81917..2b8a096 100644
--- a/src/tests/gl_tests/GLSLTest.cpp
+++ b/src/tests/gl_tests/GLSLTest.cpp
@@ -29,13 +29,6 @@
     virtual void SetUp()
     {
         ANGLETest::SetUp();
-
-        mSimpleVSSource =
-            R"(attribute vec4 inputAttribute;
-            void main()
-            {
-                gl_Position = inputAttribute;
-            })";
     }
 
     std::string GenerateVaryingType(GLint vectorSize)
@@ -475,8 +468,6 @@
         glDeleteProgram(program);
         ASSERT_GL_NO_ERROR();
     }
-
-    std::string mSimpleVSSource;
 };
 
 class GLSLTestNoValidation : public GLSLTest
@@ -490,14 +481,6 @@
     void SetUp() override
     {
         ANGLETest::SetUp();
-
-        mSimpleVSSource =
-            R"(#version 300 es
-            in vec4 inputAttribute;
-            void main()
-            {
-                gl_Position = inputAttribute;
-            })";
     }
 };
 
@@ -506,14 +489,6 @@
     void SetUp() override
     {
         ANGLETest::SetUp();
-
-        mSimpleVSSource =
-            R"(#version 310 es
-            in vec4 inputAttribute;
-            void main()
-            {
-                gl_Position = inputAttribute;
-            })";
     }
 };
 
@@ -532,7 +507,7 @@
             gl_FragColor.a += b.q;
         })";
 
-    GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
+    GLuint program = CompileProgram(essl1_shaders::vs::Simple(), fragmentShaderSource);
     EXPECT_NE(0u, program);
 }
 
@@ -544,6 +519,11 @@
     // (http://anglebug.com/1291)
     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL() && (IsOSX() || !IsNVIDIA()));
 
+    // TODO(lucferron): Support for inner scoped structs being redeclared in inner scopes
+    // This bug in glslang is preventing us from supporting this use case for now.
+    // https://github.com/KhronosGroup/glslang/issues/1358
+    ANGLE_SKIP_TEST_IF(IsVulkan());
+
     const std::string fragmentShaderSource =
         R"(precision mediump float;
 
@@ -568,7 +548,7 @@
             gl_FragColor.a += b.q;
         })";
 
-    GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
+    GLuint program = CompileProgram(essl1_shaders::vs::Simple(), fragmentShaderSource);
     EXPECT_NE(0u, program);
 }
 
@@ -598,7 +578,7 @@
             gl_FragColor.a += b.v.x;
         })";
 
-    GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
+    GLuint program = CompileProgram(essl1_shaders::vs::Simple(), fragmentShaderSource);
     EXPECT_NE(0u, program);
 }
 
@@ -738,13 +718,9 @@
 // Test that we can release the shader compiler and still compile things properly.
 TEST_P(GLSLTest, ReleaseCompilerThenCompile)
 {
-    const std::string &simpleVS =
-        "attribute vec4 position; void main() { gl_Position = position; }";
-    const std::string &simpleFS = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
-
     // Draw with the first program.
-    ANGLE_GL_PROGRAM(program1, simpleVS, simpleFS);
-    drawQuad(program1, "position", 0.5f);
+    ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
+    drawQuad(program1, essl1_shaders::PositionAttrib(), 0.5f);
     ASSERT_GL_NO_ERROR();
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
 
@@ -756,8 +732,8 @@
     ASSERT_GL_NO_ERROR();
 
     // Draw with a second program.
-    ANGLE_GL_PROGRAM(program2, simpleVS, simpleFS);
-    drawQuad(program2, "position", 0.5f);
+    ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
+    drawQuad(program2, essl1_shaders::PositionAttrib(), 0.5f);
     ASSERT_GL_NO_ERROR();
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
 }
@@ -765,33 +741,10 @@
 // Verify that linking shaders declaring different shading language versions fails.
 TEST_P(GLSLTest_ES3, VersionMismatch)
 {
-    const std::string fragmentShaderSource100 =
-        "precision mediump float;\n"
-        "varying float v_varying;\n"
-        "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
-
-    const std::string vertexShaderSource100 =
-        "attribute vec4 a_position;\n"
-        "varying float v_varying;\n"
-        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
-
-    const std::string fragmentShaderSource300 =
-        "#version 300 es\n"
-        "precision mediump float;\n"
-        "in float v_varying;\n"
-        "out vec4 my_FragColor;\n"
-        "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
-
-    const std::string vertexShaderSource300 =
-        "#version 300 es\n"
-        "in vec4 a_position;\n"
-        "out float v_varying;\n"
-        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
-
-    GLuint program = CompileProgram(vertexShaderSource300, fragmentShaderSource100);
+    GLuint program = CompileProgram(essl3_shaders::vs::Simple(), essl1_shaders::fs::Red());
     EXPECT_EQ(0u, program);
 
-    program = CompileProgram(vertexShaderSource100, fragmentShaderSource300);
+    program = CompileProgram(essl1_shaders::vs::Simple(), essl3_shaders::fs::Red());
     EXPECT_EQ(0u, program);
 }
 
@@ -981,11 +934,7 @@
         "float f() { if (v_varying > 0.0) return 1.0; }\n"
         "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
 
-    const std::string fragmentShaderSource =
-        "precision mediump float;\n"
-        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
-
-    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    GLuint program = CompileProgram(vertexShaderSource, essl1_shaders::fs::Red());
     EXPECT_NE(0u, program);
 }
 
@@ -997,11 +946,7 @@
         "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
 
-    const std::string fragmentShaderSource =
-        "precision mediump float;\n"
-        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
-
-    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    GLuint program = CompileProgram(vertexShaderSource, essl1_shaders::fs::Red());
     EXPECT_NE(0u, program);
 }
 
@@ -1013,11 +958,7 @@
         "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
 
-    const std::string fragmentShaderSource =
-        "precision mediump float;\n"
-        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
-
-    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    GLuint program = CompileProgram(vertexShaderSource, essl1_shaders::fs::Red());
     EXPECT_NE(0u, program);
 }
 
@@ -1029,11 +970,7 @@
         "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
 
-    const std::string fragmentShaderSource =
-        "precision mediump float;\n"
-        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
-
-    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    GLuint program = CompileProgram(vertexShaderSource, essl1_shaders::fs::Red());
     EXPECT_NE(0u, program);
 }
 
@@ -1045,11 +982,7 @@
         "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
 
-    const std::string fragmentShaderSource =
-        "precision mediump float;\n"
-        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
-
-    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    GLuint program = CompileProgram(vertexShaderSource, essl1_shaders::fs::Red());
     EXPECT_NE(0u, program);
 }
 
@@ -1061,11 +994,7 @@
         "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
         "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
 
-    const std::string fragmentShaderSource =
-        "precision mediump float;\n"
-        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
-
-    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    GLuint program = CompileProgram(vertexShaderSource, essl1_shaders::fs::Red());
     EXPECT_NE(0u, program);
 }
 
@@ -1078,11 +1007,7 @@
         "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
         "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
 
-    const std::string fragmentShaderSource =
-        "precision mediump float;\n"
-        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
-
-    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    GLuint program = CompileProgram(vertexShaderSource, essl1_shaders::fs::Red());
     EXPECT_NE(0u, program);
 }
 
@@ -1095,13 +1020,7 @@
         "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
         "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
 
-    const std::string fragmentShaderSource =
-        "#version 300 es\n"
-        "precision mediump float;\n"
-        "out vec4 my_FragColor;\n"
-        "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
-
-    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    GLuint program = CompileProgram(vertexShaderSource, essl3_shaders::fs::Red());
     EXPECT_NE(0u, program);
 }
 
@@ -1116,13 +1035,7 @@
         "vec2(1.0, 1.0))); } }\n"
         "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
 
-    const std::string fragmentShaderSource =
-        "#version 300 es\n"
-        "precision mediump float;\n"
-        "out vec4 my_FragColor;\n"
-        "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
-
-    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    GLuint program = CompileProgram(vertexShaderSource, essl3_shaders::fs::Red());
     EXPECT_NE(0u, program);
 }
 
@@ -1143,13 +1056,7 @@
         "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n"
         "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n";
 
-    const std::string fragmentShaderSource =
-        "#version 300 es\n"
-        "precision mediump float;\n"
-        "out vec4 my_FragColor;\n"
-        "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
-
-    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    GLuint program = CompileProgram(vertexShaderSource, essl3_shaders::fs::Red());
     EXPECT_NE(0u, program);
 }
 
@@ -1423,7 +1330,7 @@
 {
     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
 
-    const char *sourceArray[1] = { "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" };
+    const char *sourceArray[1] = {essl1_shaders::fs::Red()};
     GLint lengths[1] = { -10 };
     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
     glCompileShader(shader);
@@ -1565,7 +1472,7 @@
     const std::string fragmentShaderSource =
         R"(precision mediump float;
 
-        uniform struct S { float field;} s;
+        uniform struct S { float field; } s;
 
         void main()
         {
@@ -1573,10 +1480,84 @@
             gl_FragColor.a += s.field;
         })";
 
-    GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
+    GLuint program = CompileProgram(essl1_shaders::vs::Simple(), fragmentShaderSource);
     EXPECT_NE(0u, program);
 }
 
+// Test that structs declaration followed directly by an initialization is translated correctly.
+TEST_P(GLSLTest, StructWithInitializer)
+{
+    const std::string fragmentShaderSource =
+        R"(precision mediump float;
+
+        struct S { float a; } s = S(1.0);
+
+        void main()
+        {
+            gl_FragColor = vec4(0, 0, 0, 1);
+            gl_FragColor.r += s.a;
+        })";
+
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShaderSource);
+    glUseProgram(program);
+
+    // Test drawing, should be red.
+    drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that structs without initializer, followed by a uniform usage works as expected.
+TEST_P(GLSLTest, UniformStructWithoutInitializer)
+{
+    const std::string fragmentShaderSource =
+        R"(precision mediump float;
+
+        struct S { float a; };
+        uniform S u_s;
+
+        void main()
+        {
+            gl_FragColor = vec4(u_s.a);
+        })";
+
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShaderSource);
+    glUseProgram(program);
+
+    // Test drawing, should be red.
+    drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that structs declaration followed directly by an initialization in a uniform.
+TEST_P(GLSLTest, StructWithUniformInitializer)
+{
+    const std::string fragmentShaderSource =
+        R"(precision mediump float;
+
+        struct S { float a; } s = S(1.0);
+        uniform S us;
+
+        void main()
+        {
+            gl_FragColor = vec4(0, 0, 0, 1);
+            gl_FragColor.r += s.a;
+            gl_FragColor.g += us.a;
+        })";
+
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShaderSource);
+    glUseProgram(program);
+
+    // Test drawing, should be red.
+    drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+    EXPECT_GL_NO_ERROR();
+}
+
 // Test that gl_DepthRange is not stored as a uniform location. Since uniforms
 // beginning with "gl_" are filtered out by our validation logic, we must
 // bypass the validation to test the behaviour of the implementation.
@@ -1591,14 +1572,14 @@
             gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
         })";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShaderSource);
 
     // We need to bypass validation for this call.
     GLint nearIndex = glGetUniformLocation(program.get(), "gl_DepthRange.near");
     EXPECT_EQ(-1, nearIndex);
 
     // Test drawing does not throw an exception.
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
 
     EXPECT_GL_NO_ERROR();
 }
@@ -1661,9 +1642,9 @@
     {
         const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, testExponent);
 
-        ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
+        ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShaderSource);
 
-        drawQuad(program.get(), "inputAttribute", 0.5f);
+        drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
 
         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
         EXPECT_GL_NO_ERROR();
@@ -1849,15 +1830,6 @@
 // HLSL).
 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
 {
-    const std::string fragmentShaderSource =
-        "#version 300 es\n"
-        "precision highp float;\n"
-        "out vec4 my_FragColor;\n"
-        "void main()\n"
-        "{\n"
-        "    my_FragColor = vec4(0.0);\n"
-        "}";
-
     const std::string vertexShaderSource =
         "#version 300 es\n"
         "precision highp float;\n"
@@ -1868,7 +1840,7 @@
         "    gl_Position = vec4(a_vec) + vec4(a_mat);\n"
         "}";
 
-    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    GLuint program = CompileProgram(vertexShaderSource, essl3_shaders::fs::Red());
     EXPECT_NE(0u, program);
 }
 
@@ -1877,15 +1849,6 @@
 // the function signatures in this case.
 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
 {
-    const std::string fragmentShaderSource =
-        "#version 300 es\n"
-        "precision highp float;\n"
-        "out vec4 my_FragColor;\n"
-        "void main()\n"
-        "{\n"
-        "    my_FragColor = vec4(0.0);\n"
-        "}";
-
     const std::string vertexShaderSource =
         "#version 300 es\n"
         "precision highp float;\n"
@@ -1896,22 +1859,13 @@
         "    gl_Position = vec4(a_matA) + vec4(a_matB);\n"
         "}";
 
-    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    GLuint program = CompileProgram(vertexShaderSource, essl3_shaders::fs::Red());
     EXPECT_NE(0u, program);
 }
 
 // Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
 TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
 {
-    const std::string fragmentShaderSource =
-        "#version 300 es\n"
-        "precision highp float;\n"
-        "out vec4 my_FragColor;\n"
-        "void main()\n"
-        "{\n"
-        "    my_FragColor = vec4(0.0);\n"
-        "}";
-
     const std::string vertexShaderSource =
         "#version 300 es\n"
         "precision highp float;\n"
@@ -1930,7 +1884,7 @@
         "    gl_Position = foo(a_vec) + foo(a_mat);\n"
         "}";
 
-    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    GLuint program = CompileProgram(vertexShaderSource, essl3_shaders::fs::Red());
     EXPECT_NE(0u, program);
 }
 
@@ -1938,15 +1892,6 @@
 // the function name being too long.
 TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
 {
-    const std::string fragmentShaderSource =
-        "#version 300 es\n"
-        "precision highp float;\n"
-        "out vec4 my_FragColor;\n"
-        "void main()\n"
-        "{\n"
-        "    my_FragColor = vec4(0.0);\n"
-        "}";
-
     std::stringstream vertexShaderStream;
     const unsigned int paramCount = 1024u;
 
@@ -1977,7 +1922,7 @@
     vertexShaderStream << "a_vec);\n"
                           "}";
 
-    GLuint program = CompileProgram(vertexShaderStream.str(), fragmentShaderSource);
+    GLuint program = CompileProgram(vertexShaderStream.str(), essl3_shaders::fs::Red());
     EXPECT_NE(0u, program);
 }
 
@@ -1993,15 +1938,6 @@
     // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1428 is fixed
     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
 
-    const std::string vertexShaderSource =
-        "#version 300 es\n"
-        "precision highp float;\n"
-        "in vec4 a_vec;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = vec4(a_vec);\n"
-        "}";
-
     const std::string fragmentShaderSource =
         "#version 300 es\n"
         "precision highp float;\n"
@@ -2013,21 +1949,18 @@
         "    my_FragColor = vec4(h[1]);\n"
         "}";
 
-    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    GLuint program = CompileProgram(essl3_shaders::vs::Simple(), fragmentShaderSource);
     EXPECT_NE(0u, program);
 }
 
 // Test that index-constant sampler array indexing is supported.
 TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
 {
-    ANGLE_SKIP_TEST_IF(IsD3D11_FL93());
+    // TODO(lucferron): Samplers array support.
+    // http://anglebug.com/2462
+    ANGLE_SKIP_TEST_IF(IsVulkan());
 
-    const std::string vertexShaderSource =
-        "attribute vec4 vPosition;\n"
-        "void main()\n"
-        "{\n"
-        "      gl_Position = vPosition;\n"
-        "}";
+    ANGLE_SKIP_TEST_IF(IsD3D11_FL93());
 
     const std::string fragmentShaderSource =
         "precision mediump float;\n"
@@ -2054,7 +1987,7 @@
         "    gl_FragColor = c;\n"
         "}";
 
-    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    GLuint program = CompileProgram(essl1_shaders::vs::Simple(), fragmentShaderSource);
     EXPECT_NE(0u, program);
 }
 
@@ -2070,14 +2003,7 @@
         "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
         "}\n";
 
-    const std::string fragmentShaderSource =
-        "precision mediump float;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_FragColor = vec4(1.0);\n"
-        "}\n";
-
-    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    GLuint program = CompileProgram(vertexShaderSource, essl1_shaders::fs::Red());
     EXPECT_NE(0u, program);
 }
 
@@ -2103,10 +2029,10 @@
         "    my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
         "}\n";
 
-    GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
+    GLuint program = CompileProgram(essl3_shaders::vs::Simple(), fragmentShaderSource);
     ASSERT_NE(0u, program);
 
-    drawQuad(program, "inputAttribute", 0.5f);
+    drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
 
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
@@ -2126,10 +2052,10 @@
         "    my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
         "}\n";
 
-    GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
+    GLuint program = CompileProgram(essl3_shaders::vs::Simple(), fragmentShaderSource);
     ASSERT_NE(0u, program);
 
-    drawQuad(program, "inputAttribute", 0.5f);
+    drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
 
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
@@ -2155,10 +2081,10 @@
         "    my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
         "}\n";
 
-    GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
+    GLuint program = CompileProgram(essl3_shaders::vs::Simple(), fragmentShaderSource);
     ASSERT_NE(0u, program);
 
-    drawQuad(program, "inputAttribute", 0.5f);
+    drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
 
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
@@ -2190,12 +2116,6 @@
 // Convers a bug with the integer pow statement workaround.
 TEST_P(GLSLTest, NestedPowStatements)
 {
-    const std::string &vert =
-        "attribute vec2 position;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = vec4(position, 0, 1);\n"
-        "}";
     const std::string &frag =
         "precision mediump float;\n"
         "float func(float v)\n"
@@ -2209,20 +2129,14 @@
         "    gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
         "}";
 
-    ANGLE_GL_PROGRAM(prog, vert, frag);
-    drawQuad(prog.get(), "position", 0.5f);
+    ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), frag);
+    drawQuad(prog.get(), essl1_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
 // Test that -float calculation is correct.
 TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
 {
-    const std::string &vert =
-        "#version 300 es\n"
-        "in highp vec4 position;\n"
-        "void main() {\n"
-        "    gl_Position = position;\n"
-        "}\n";
     const std::string &frag =
         "#version 300 es\n"
         "out highp vec4 o_color;\n"
@@ -2233,20 +2147,14 @@
         "    o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(prog, vert, frag);
-    drawQuad(prog.get(), "position", 0.5f);
+    ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), frag);
+    drawQuad(prog.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
 // Test that atan(vec2, vec2) calculation is correct.
 TEST_P(GLSLTest_ES3, AtanVec2)
 {
-    const std::string &vert =
-        "#version 300 es\n"
-        "in highp vec4 position;\n"
-        "void main() {\n"
-        "    gl_Position = position;\n"
-        "}\n";
     const std::string &frag =
         "#version 300 es\n"
         "out highp vec4 o_color;\n"
@@ -2258,8 +2166,8 @@
         "vec4(1, 0, 0, 1);\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(prog, vert, frag);
-    drawQuad(prog.get(), "position", 0.5f);
+    ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), frag);
+    drawQuad(prog.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -2361,13 +2269,6 @@
 // intended to be such that it gets converted to an if statement on the HLSL backend.
 TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
 {
-    const std::string &vert =
-        "attribute vec2 position;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = vec4(position, 0, 1);\n"
-        "}";
-
     // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
     // its default value false.
     const std::string &frag =
@@ -2381,8 +2282,8 @@
         "    gl_FragColor = vec4(0, -flop, 0, 1);\n"
         "}";
 
-    ANGLE_GL_PROGRAM(prog, vert, frag);
-    drawQuad(prog.get(), "position", 0.5f);
+    ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), frag);
+    drawQuad(prog.get(), essl1_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -2403,7 +2304,7 @@
             gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);
         })";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShader);
 }
 
 // Test that literal infinity can be written out from the shader translator.
@@ -2422,8 +2323,8 @@
         "   out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -2443,8 +2344,8 @@
         "   out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -2475,7 +2376,7 @@
             color = vec4(b + c);
         })";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
 }
 
 // Test that passes splitting multiple declarations and comma operators and for loops are
@@ -2504,7 +2405,7 @@
             }
         })";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
 }
 
 // Test that splitting multiple declaration in for loops works with no loop condition
@@ -2524,7 +2425,7 @@
         " }\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
 }
 
 // Test that splitting multiple declaration in for loops works with no loop expression
@@ -2544,7 +2445,7 @@
         " }\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
 }
 
 // Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
@@ -2563,8 +2464,8 @@
         "    my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -2662,8 +2563,8 @@
         "    }\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -2689,8 +2590,8 @@
         "0, 0, 1);\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -2853,8 +2754,8 @@
         "    }\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -2890,8 +2791,8 @@
         "    }\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -2962,8 +2863,8 @@
         "    }\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -2987,8 +2888,8 @@
         "    }\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -3007,8 +2908,8 @@
         "    }\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -3037,8 +2938,8 @@
         "    my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0);\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -3060,8 +2961,8 @@
         "    gl_FragColor = foo + vec4(0, 1, 0, 1);\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -3084,8 +2985,8 @@
         "    gl_FragColor = vec4(0.0, get(s) + get(s2), 0.0, 1.0);\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -3189,12 +3090,9 @@
     // Shader failed to compile on Android. http://anglebug.com/2114
     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
 
-    const std::string &vertexShader =
-        "attribute vec2 position;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = vec4(position, 0, 1);\n"
-        "}\n";
+    // TODO(lucferron): Sampler arrays support
+    // http://anglebug.com/2462
+    ANGLE_SKIP_TEST_IF(IsVulkan());
 
     const std::string &fragmentShader =
         "precision mediump float;\n"
@@ -3214,7 +3112,7 @@
         "    gl_FragColor = foo(uStructs);\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShader);
 
     // Initialize the texture with green.
     GLTexture tex;
@@ -3235,7 +3133,7 @@
     ASSERT_NE(-1, texCoordLoc);
     glUniform2f(texCoordLoc, 0.5f, 0.5f);
 
-    drawQuad(program, "position", 0.5f);
+    drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
     ASSERT_GL_NO_ERROR();
 
     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
@@ -3247,12 +3145,9 @@
     // Shader failed to compile on Android. http://anglebug.com/2114
     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
 
-    const std::string &vertexShader =
-        "attribute vec2 position;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = vec4(position, 0, 1);\n"
-        "}\n";
+    // TODO(lucferron): Sampler arrays support
+    // http://anglebug.com/2462
+    ANGLE_SKIP_TEST_IF(IsVulkan());
 
     const std::string &fragmentShader =
         "precision mediump float;\n"
@@ -3272,7 +3167,7 @@
         "    gl_FragColor = foo(uStruct);\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShader);
 
     // Initialize the texture with green.
     GLTexture tex;
@@ -3293,7 +3188,7 @@
     ASSERT_NE(-1, texCoordLoc);
     glUniform2f(texCoordLoc, 0.5f, 0.5f);
 
-    drawQuad(program, "position", 0.5f);
+    drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
     ASSERT_GL_NO_ERROR();
 
     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
@@ -3322,8 +3217,8 @@
         "    return foo;\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -3358,8 +3253,8 @@
             }
         })";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -3393,8 +3288,8 @@
             }
         })";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -3427,8 +3322,8 @@
             }
         })";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -3451,7 +3346,7 @@
                     i.yx;
             }
         })";
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
 }
 
 // Test that switch fall-through works correctly.
@@ -3488,8 +3383,8 @@
             }
         })";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -3511,7 +3406,7 @@
                     {}
             }
         })";
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
 }
 
 // Test that a switch statement with an empty declaration inside as a final statement compiles.
@@ -3532,7 +3427,7 @@
                     float;
             }
         })";
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
 }
 
 // Test switch/case where break/return statements are within blocks.
@@ -3572,8 +3467,8 @@
             my_FragColor = test(u_zero + 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
         })";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -3602,8 +3497,8 @@
             }
         })";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -3641,8 +3536,8 @@
             }
         })";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -3665,8 +3560,8 @@
             my_FragColor = (i == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
         })";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -3702,8 +3597,8 @@
             }
         })";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -3775,8 +3670,8 @@
             }
         })";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -3805,8 +3700,8 @@
             }
         })";
 
-    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
-    drawQuad(program.get(), "inputAttribute", 0.5f);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShader);
+    drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -4095,7 +3990,7 @@
         })";
 
     validateComponentsInErrorMessage(vertexShader, fragmentShader, "Types",
-                                     "interface block 'S' member 'S.val2'");
+                                     "uniform block 'S' member 'S.val2'");
 }
 
 // Validate error messages  when the link mismatch occurs on the type of a member of a uniform block
@@ -4145,7 +4040,7 @@
         })";
 
     validateComponentsInErrorMessage(vertexShader, fragmentShader, "Types",
-                                     "interface block 'S' member 'S.val1.t2'");
+                                     "uniform block 'S' member 'S.val1.t2'");
 }
 
 // Test a vertex shader that doesn't declare any varyings with a fragment shader that statically
@@ -4210,13 +4105,12 @@
 
 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
 // tests should be run against.
-// TODO(lucferron): Enable tests for Vulkan and debug/open bugs for each failing ones.
-// http://anglebug.com/2460
 ANGLE_INSTANTIATE_TEST(GLSLTest,
                        ES2_D3D9(),
                        ES2_D3D11(),
                        ES2_D3D11_FL9_3(),
                        ES2_OPENGL(),
+                       ES2_VULKAN(),
                        ES3_OPENGL(),
                        ES2_OPENGLES(),
                        ES3_OPENGLES());
diff --git a/src/tests/gl_tests/GeometryShaderTest.cpp b/src/tests/gl_tests/GeometryShaderTest.cpp
index 8904f67..c4e0d35 100644
--- a/src/tests/gl_tests/GeometryShaderTest.cpp
+++ b/src/tests/gl_tests/GeometryShaderTest.cpp
@@ -45,22 +45,6 @@
                    "}";
         return ostream.str();
     }
-
-    const std::string kDefaultVertexShader =
-        R"(#version 310 es
-        void main()
-        {
-            gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
-        })";
-
-    const std::string kDefaultFragmentShader =
-        R"(#version 310 es
-        precision mediump float;
-        layout (location = 0) out vec4 frag_out;
-        void main()
-        {
-            frag_out = vec4(1.0, 0.0, 0.0, 1.0);
-        })";
 };
 
 class GeometryShaderTestES3 : public ANGLETest
@@ -174,12 +158,12 @@
 }
 
 // Verify that linking a program with an uncompiled geometry shader causes a link failure.
-TEST_P(GeometryShaderTest, LinkWithUncompiledGeoemtryShader)
+TEST_P(GeometryShaderTest, LinkWithUncompiledGeometryShader)
 {
     ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_geometry_shader"));
 
-    GLuint vertexShader   = CompileShader(GL_VERTEX_SHADER, kDefaultVertexShader);
-    GLuint fragmentShader = CompileShader(GL_FRAGMENT_SHADER, kDefaultFragmentShader);
+    GLuint vertexShader   = CompileShader(GL_VERTEX_SHADER, essl31_shaders::vs::Simple());
+    GLuint fragmentShader = CompileShader(GL_FRAGMENT_SHADER, essl31_shaders::fs::Red());
     ASSERT_NE(0u, vertexShader);
     ASSERT_NE(0u, fragmentShader);
 
@@ -209,26 +193,10 @@
 {
     ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_geometry_shader"));
 
-    const std::string &kDefaultVertexShaderVersion300 =
-        R"(#version 300 es
-        void main()
-        {
-            gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
-        })";
-
-    const std::string kDefaultFragmentShaderVersion300 =
-        R"(#version 300 es
-        precision mediump float;
-        layout (location = 0) out vec4 frag_out;
-        void main()
-        {
-            frag_out = vec4(1.0, 0.0, 0.0, 1.0);
-        })";
-
     const std::string &emptyGeometryShader = CreateEmptyGeometryShader("points", "points", 2, 1);
 
-    GLuint program = CompileProgramWithGS(kDefaultVertexShaderVersion300, emptyGeometryShader,
-                                          kDefaultFragmentShaderVersion300);
+    GLuint program = CompileProgramWithGS(essl3_shaders::vs::Simple(), emptyGeometryShader,
+                                          essl3_shaders::fs::Red());
     EXPECT_EQ(0u, program);
 }
 
@@ -245,24 +213,24 @@
 
     // Linking a program with a geometry shader that only lacks 'invocations' should not cause a
     // link failure.
-    GLuint program =
-        CompileProgramWithGS(kDefaultVertexShader, gsWithoutInvocations, kDefaultFragmentShader);
+    GLuint program = CompileProgramWithGS(essl31_shaders::vs::Simple(), gsWithoutInvocations,
+                                          essl31_shaders::fs::Red());
     EXPECT_NE(0u, program);
 
     glDeleteProgram(program);
 
     // Linking a program with a geometry shader that lacks input primitive, output primitive or
     // 'max_vertices' causes a link failure.
-    program =
-        CompileProgramWithGS(kDefaultVertexShader, gsWithoutInputPrimitive, kDefaultFragmentShader);
+    program = CompileProgramWithGS(essl31_shaders::vs::Simple(), gsWithoutInputPrimitive,
+                                   essl31_shaders::fs::Red());
     EXPECT_EQ(0u, program);
 
-    program = CompileProgramWithGS(kDefaultVertexShader, gsWithoutOutputPrimitive,
-                                   kDefaultFragmentShader);
+    program = CompileProgramWithGS(essl31_shaders::vs::Simple(), gsWithoutOutputPrimitive,
+                                   essl31_shaders::fs::Red());
     EXPECT_EQ(0u, program);
 
-    program =
-        CompileProgramWithGS(kDefaultVertexShader, gsWithoutMaxVertices, kDefaultFragmentShader);
+    program = CompileProgramWithGS(essl31_shaders::vs::Simple(), gsWithoutMaxVertices,
+                                   essl31_shaders::fs::Red());
     EXPECT_EQ(0u, program);
 
     ASSERT_GL_NO_ERROR();
@@ -398,7 +366,7 @@
               "}\n";
 
     GLuint program =
-        CompileProgramWithGS(kDefaultVertexShader, stream.str(), kDefaultFragmentShader);
+        CompileProgramWithGS(essl31_shaders::vs::Simple(), stream.str(), essl31_shaders::fs::Red());
     EXPECT_EQ(0u, program);
 
     EXPECT_GL_NO_ERROR();
@@ -437,7 +405,105 @@
               "}\n";
 
     GLuint program =
-        CompileProgramWithGS(kDefaultVertexShader, stream.str(), kDefaultFragmentShader);
+        CompileProgramWithGS(essl31_shaders::vs::Simple(), stream.str(), essl31_shaders::fs::Red());
+    EXPECT_EQ(0u, program);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Verify that an link error occurs when the definition of a unform block in the vertex shader is
+// different from that in a geometry shader.
+TEST_P(GeometryShaderTest, UniformBlockMismatchBetweenVertexAndGeometryShader)
+{
+    ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_geometry_shader"));
+
+    const std::string &vertexShader =
+        R"(#version 310 es
+        uniform ubo
+        {
+            vec4 uniform_value_vert;
+        } block0;
+        in vec4 vertex_in;
+        out vec4 vertex_out;
+        void main()
+        {
+            gl_Position = vertex_in;
+            vertex_out = block0.uniform_value_vert;
+        })";
+
+    const std::string &geometryShader =
+        R"(#version 310 es
+        #extension GL_EXT_geometry_shader : require
+        uniform ubo
+        {
+            vec4 uniform_value_geom;
+        } block0;
+        layout (triangles) in;
+        layout (points, max_vertices = 1) out;
+        in vec4 vertex_out[];
+        void main()
+        {
+            gl_Position = gl_in[0].gl_Position + vertex_out[0];
+            gl_Position += block0.uniform_value_geom;
+            EmitVertex();
+        })";
+
+    GLuint program = CompileProgramWithGS(vertexShader, geometryShader, essl31_shaders::fs::Red());
+    EXPECT_EQ(0u, program);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Verify that an link error occurs when the definition of a shader storage block in the geometry
+// shader is different from that in a fragment shader.
+TEST_P(GeometryShaderTest, ShaderStorageBlockMismatchBetweenGeometryAndFragmentShader)
+{
+    ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_geometry_shader"));
+
+    GLint maxGeometryShaderStorageBlocks = 0;
+    glGetIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT, &maxGeometryShaderStorageBlocks);
+
+    // The minimun value of MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT can be 0.
+    // [EXT_geometry_shader] Table 20.43gs
+    ANGLE_SKIP_TEST_IF(maxGeometryShaderStorageBlocks == 0);
+
+    GLint maxFragmentShaderStorageBlocks = 0;
+    glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
+
+    // The minimun value of MAX_FRAGMENT_SHADER_STORAGE_BLOCKS can be 0.
+    // [OpenGL ES 3.1] Table 20.44
+    ANGLE_SKIP_TEST_IF(maxFragmentShaderStorageBlocks == 0);
+
+    const std::string &geometryShader =
+        R"(#version 310 es
+        #extension GL_EXT_geometry_shader : require
+        buffer ssbo
+        {
+            vec4 ssbo_value;
+        } block0;
+        layout (triangles) in;
+        layout (points, max_vertices = 1) out;
+        void main()
+        {
+            gl_Position = gl_in[0].gl_Position + block0.ssbo_value;
+            EmitVertex();
+        })";
+
+    const std::string &fragmentShader =
+        R"(#version 310 es
+        precision highp float;
+        buffer ssbo
+        {
+            vec3 ssbo_value;
+        } block0;
+        layout (location = 0) out vec4 output_color;
+        void main()
+        {
+            output_color = vec4(block0.ssbo_value, 1);
+        })";
+
+    GLuint program =
+        CompileProgramWithGS(essl31_shaders::vs::Simple(), geometryShader, fragmentShader);
     EXPECT_EQ(0u, program);
 
     EXPECT_GL_NO_ERROR();
diff --git a/src/tests/gl_tests/ImageTest.cpp b/src/tests/gl_tests/ImageTest.cpp
index 66b2394..0f6e094 100644
--- a/src/tests/gl_tests/ImageTest.cpp
+++ b/src/tests/gl_tests/ImageTest.cpp
@@ -1638,19 +1638,7 @@
         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"));
 
-    // Simple shader
-    const std::string &vertexSource =
-        "attribute vec2 position;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = vec4(position, 0, 1);\n"
-        "}";
-    const std::string &fragmentSource =
-        "void main()\n"
-        "{\n"
-        "    gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
-        "}";
-    GLuint program = CompileProgram(vertexSource, fragmentSource);
+    GLuint program = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
     ASSERT_NE(0u, program);
 
     GLubyte originalData[4] = {255, 0, 255, 255};
@@ -1670,8 +1658,8 @@
     glGenFramebuffers(1, &fbo);
     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target, 0);
-    drawQuad(program, "position", 0.5f);
-    EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
+    drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
 
     // Respecify source with same parameters. This should not change the texture storage in D3D11.
     glBindTexture(GL_TEXTURE_2D, source);
@@ -1681,8 +1669,8 @@
     verifyResults2D(source, updateData);
 
     // Render to the target texture again and verify it gets the rendered pixels.
-    drawQuad(program, "position", 0.5f);
-    EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
+    drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
 
     // Clean up
     glDeleteTextures(1, &source);
diff --git a/src/tests/gl_tests/InstancingTest.cpp b/src/tests/gl_tests/InstancingTest.cpp
index 0532e73..8540c65 100644
--- a/src/tests/gl_tests/InstancingTest.cpp
+++ b/src/tests/gl_tests/InstancingTest.cpp
@@ -110,14 +110,7 @@
 
     void setupDrawArraysTest(const std::string &vs)
     {
-        const std::string fs =
-            "precision mediump float;\n"
-            "void main()\n"
-            "{\n"
-            "    gl_FragColor = vec4(1.0, 0, 0, 1.0);\n"
-            "}\n";
-
-        mProgram = CompileProgram(vs, fs);
+        mProgram = CompileProgram(vs, essl1_shaders::fs::Red());
         ASSERT_NE(0u, mProgram);
 
         // Set the viewport
@@ -148,16 +141,9 @@
             "    gl_Position  = vec4(a_instancePos.xyz, 1.0);\n"
             "    gl_PointSize = 6.0;\n"
             "}\n";
-
-        const std::string fs =
-            "precision mediump float;\n"
-            "void main()\n"
-            "{\n"
-            "    gl_FragColor = vec4(1.0, 0, 0, 1.0);\n"
-            "}\n";
         // clang-format on
 
-        mProgram = CompileProgram(vs, fs);
+        mProgram = CompileProgram(vs, essl1_shaders::fs::Red());
         ASSERT_NE(0u, mProgram);
 
         // Set the viewport
diff --git a/src/tests/gl_tests/LineLoopTest.cpp b/src/tests/gl_tests/LineLoopTest.cpp
index 4566a37..26cc40d 100644
--- a/src/tests/gl_tests/LineLoopTest.cpp
+++ b/src/tests/gl_tests/LineLoopTest.cpp
@@ -25,28 +25,14 @@
     {
         ANGLETest::SetUp();
 
-        const std::string vsSource =
-            R"(attribute highp vec4 position;
-            void main(void)
-            {
-                gl_Position = position;
-            })";
-
-        const std::string fsSource =
-            R"(uniform highp vec4 color;
-            void main(void)
-            {
-                gl_FragColor = color;
-            })";
-
-        mProgram = CompileProgram(vsSource, fsSource);
+        mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
         if (mProgram == 0)
         {
             FAIL() << "shader compilation failed.";
         }
 
-        mPositionLocation = glGetAttribLocation(mProgram, "position");
-        mColorLocation    = glGetUniformLocation(mProgram, "color");
+        mPositionLocation = glGetAttribLocation(mProgram, essl1_shaders::PositionAttrib());
+        mColorLocation    = glGetUniformLocation(mProgram, essl1_shaders::ColorUniform());
 
         glBlendFunc(GL_ONE, GL_ONE);
         glEnable(GL_BLEND);
@@ -112,6 +98,9 @@
 
 TEST_P(LineLoopTest, LineLoopUByteIndices)
 {
+    // TODO(fjhenigman): UByte not yet supported in VertexArrayVk
+    ANGLE_SKIP_TEST_IF(IsVulkan());
+
     // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
     // On Win7, the D3D SDK Layers emits a false warning for these tests.
     // This doesn't occur on Windows 10 (Version 1511) though.
@@ -146,6 +135,9 @@
 
 TEST_P(LineLoopTest, LineLoopUByteIndexBuffer)
 {
+    // TODO(fjhenigman): UByte not yet supported in VertexArrayVk
+    ANGLE_SKIP_TEST_IF(IsVulkan());
+
     // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
     ignoreD3D11SDKLayersWarnings();
 
@@ -202,4 +194,9 @@
 
 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
 // tests should be run against.
-ANGLE_INSTANTIATE_TEST(LineLoopTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
+ANGLE_INSTANTIATE_TEST(LineLoopTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES2_VULKAN());
diff --git a/src/tests/gl_tests/MultisampleCompatibilityTest.cpp b/src/tests/gl_tests/MultisampleCompatibilityTest.cpp
index daa6904..4c15361 100644
--- a/src/tests/gl_tests/MultisampleCompatibilityTest.cpp
+++ b/src/tests/gl_tests/MultisampleCompatibilityTest.cpp
@@ -9,7 +9,6 @@
 
 #include "test_utils/ANGLETest.h"
 #include "test_utils/gl_raii.h"
-#include "shader_utils.h"
 
 using namespace angle;
 
@@ -37,20 +36,10 @@
     {
         ANGLETest::SetUp();
 
-        static const char* v_shader_str =
-            "attribute vec4 a_Position;\n"
-            "void main()\n"
-            "{ gl_Position = a_Position; }";
+        mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
 
-        static const char* f_shader_str =
-            "precision mediump float;\n"
-            "uniform vec4 color;"
-            "void main() { gl_FragColor = color; }";
-
-        mProgram = CompileProgram(v_shader_str, f_shader_str);
-
-        GLuint position_loc = glGetAttribLocation(mProgram, "a_Position");
-        mColorLoc = glGetUniformLocation(mProgram, "color");
+        GLuint position_loc = glGetAttribLocation(mProgram, essl1_shaders::PositionAttrib());
+        mColorLoc           = glGetUniformLocation(mProgram, essl1_shaders::ColorUniform());
 
         glGenBuffers(1, &mVBO);
         glBindBuffer(GL_ARRAY_BUFFER, mVBO);
@@ -395,15 +384,7 @@
     // TODO: Figure out why this fails on Android.
     ANGLE_SKIP_TEST_IF(IsAndroid());
 
-    const std::string &vertex =
-        "attribute vec4 position;\n"
-        "void main()\n"
-        "{ gl_Position = position; }";
-    const std::string &fragment =
-        "void main()\n"
-        "{ gl_FragColor =  vec4(1.0, 0.0, 0.0, 1.0); }";
-
-    ANGLE_GL_PROGRAM(drawRed, vertex, fragment);
+    ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
 
     GLsizei maxSamples = 0;
     glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
@@ -413,7 +394,7 @@
         prepareForDraw(samples);
         glEnable(GL_SAMPLE_COVERAGE);
         glSampleCoverage(1.0, false);
-        drawQuad(drawRed.get(), "position", 0.5f);
+        drawQuad(drawRed.get(), essl1_shaders::PositionAttrib(), 0.5f);
 
         prepareForVerify();
         GLsizei pixelCount = kWidth * kHeight;
diff --git a/src/tests/gl_tests/OcclusionQueriesTest.cpp b/src/tests/gl_tests/OcclusionQueriesTest.cpp
index 6bfaab9..5f91772 100644
--- a/src/tests/gl_tests/OcclusionQueriesTest.cpp
+++ b/src/tests/gl_tests/OcclusionQueriesTest.cpp
@@ -4,9 +4,9 @@
 // found in the LICENSE file.
 //
 
+#include "random_utils.h"
 #include "system_utils.h"
 #include "test_utils/ANGLETest.h"
-#include "random_utils.h"
 
 using namespace angle;
 
@@ -28,21 +28,7 @@
     {
         ANGLETest::SetUp();
 
-        const std::string passthroughVS =
-            R"(attribute highp vec4 position;
-            void main(void)
-            {
-                gl_Position = position;
-            })";
-
-        const std::string passthroughPS =
-            R"(precision highp float;
-            void main(void)
-            {
-               gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
-            })";
-
-        mProgram = CompileProgram(passthroughVS, passthroughPS);
+        mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
         ASSERT_NE(0u, mProgram);
     }
 
@@ -68,7 +54,7 @@
     // draw a quad at depth 0.3
     glEnable(GL_DEPTH_TEST);
     glUseProgram(mProgram);
-    drawQuad(mProgram, "position", 0.3f);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.3f);
     glUseProgram(0);
 
     EXPECT_GL_NO_ERROR();
@@ -76,7 +62,8 @@
     GLuint query = 0;
     glGenQueriesEXT(1, &query);
     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
-    drawQuad(mProgram, "position", 0.8f); // this quad should be occluded by first quad
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(),
+             0.8f);  // this quad should be occluded by first quad
     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
 
     EXPECT_GL_NO_ERROR();
@@ -113,7 +100,7 @@
     GLuint query = 0;
     glGenQueriesEXT(1, &query);
     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
-    drawQuad(mProgram, "position", 0.8f); // this quad should not be occluded
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f);  // this quad should not be occluded
     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
 
     EXPECT_GL_NO_ERROR();
@@ -157,7 +144,7 @@
     EXPECT_GL_TRUE(glIsQueryEXT(query));
     EXPECT_GL_FALSE(glIsQueryEXT(query2));  // have not called begin
 
-    drawQuad(mProgram, "position", 0.8f); // this quad should not be occluded
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f);  // this quad should not be occluded
     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT); // no active query for this target
     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
@@ -172,7 +159,8 @@
     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, query2); // should be ok now
     EXPECT_GL_TRUE(glIsQueryEXT(query2));
 
-    drawQuad(mProgram, "position", 0.3f); // this should draw in front of other quad
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(),
+             0.3f);                 // this should draw in front of other quad
     glDeleteQueriesEXT(1, &query2); // should delete when query becomes inactive
     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT); // should not incur error; should delete query + 1 at end of execution.
     EXPECT_GL_NO_ERROR();
@@ -205,7 +193,7 @@
 
     // draw a quad at depth 0.5
     glEnable(GL_DEPTH_TEST);
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
 
     EGLWindow *window = getEGLWindow();
 
@@ -265,21 +253,7 @@
 
         eglMakeCurrent(display, surface, surface, context.context);
 
-        const std::string passthroughVS =
-            R"(attribute highp vec4 position;
-            void main(void)
-            {
-                gl_Position = position;
-            })";
-
-        const std::string passthroughPS =
-            R"(precision highp float;
-            void main(void)
-            {
-               gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
-            })";
-
-        context.program = CompileProgram(passthroughVS, passthroughPS);
+        context.program = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
         ASSERT_NE(context.program, 0u);
 
         glDepthMask(GL_FALSE);
@@ -299,7 +273,7 @@
 
             float depth = context.visiblePasses[pass] ? mRNG.randomFloatBetween(0.0f, 0.4f)
                                                       : mRNG.randomFloatBetween(0.6f, 1.0f);
-            drawQuad(context.program, "position", depth);
+            drawQuad(context.program, essl1_shaders::PositionAttrib(), depth);
 
             EXPECT_GL_NO_ERROR();
         }
diff --git a/src/tests/gl_tests/PackUnpackTest.cpp b/src/tests/gl_tests/PackUnpackTest.cpp
index 3263cf1..896de80 100644
--- a/src/tests/gl_tests/PackUnpackTest.cpp
+++ b/src/tests/gl_tests/PackUnpackTest.cpp
@@ -31,17 +31,6 @@
     {
         ANGLETest::SetUp();
 
-        // Vertex Shader source
-        const std::string vs =
-            R"(#version 300 es
-            precision mediump float;
-            in vec4 position;
-
-            void main()
-            {
-                gl_Position = position;
-            })";
-
         // Fragment Shader source
         const std::string sNormFS =
             R"(#version 300 es
@@ -84,9 +73,9 @@
                  fragColor = vec4(r, 0.0, 1.0);
              })";
 
-        mSNormProgram = CompileProgram(vs, sNormFS);
-        mUNormProgram = CompileProgram(vs, uNormFS);
-        mHalfProgram = CompileProgram(vs, halfFS);
+        mSNormProgram = CompileProgram(essl3_shaders::vs::Simple(), sNormFS);
+        mUNormProgram = CompileProgram(essl3_shaders::vs::Simple(), uNormFS);
+        mHalfProgram  = CompileProgram(essl3_shaders::vs::Simple(), halfFS);
         if (mSNormProgram == 0 || mUNormProgram == 0 || mHalfProgram == 0)
         {
             FAIL() << "shader compilation failed.";
@@ -129,7 +118,7 @@
         glUseProgram(program);
         glUniform2f(vec2Location, input1, input2);
 
-        drawQuad(program, "position", 0.5f);
+        drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
 
         ASSERT_GL_NO_ERROR();
 
diff --git a/src/tests/gl_tests/PointSpritesTest.cpp b/src/tests/gl_tests/PointSpritesTest.cpp
index 6e40e3f..cae6f07 100644
--- a/src/tests/gl_tests/PointSpritesTest.cpp
+++ b/src/tests/gl_tests/PointSpritesTest.cpp
@@ -147,13 +147,6 @@
     // http://anglebug.com/2447
     ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
 
-    const std::string fs =
-        R"(precision mediump float;
-        void main()
-        {
-            gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
-        })";
-
     const std::string vs =
         R"(void main()
         {
@@ -161,7 +154,7 @@
             gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
         })";
 
-    ANGLE_GL_PROGRAM(program, vs, fs);
+    ANGLE_GL_PROGRAM(program, vs, essl1_shaders::fs::Blue());
     ASSERT_GL_NO_ERROR();
 
     glUseProgram(program);
@@ -169,8 +162,8 @@
     glDrawArrays(GL_POINTS, 0, 1);
     ASSERT_GL_NO_ERROR();
 
-    // expect the center pixel to be green
-    EXPECT_PIXEL_EQ((windowWidth - 1) / 2, (windowHeight - 1) / 2, 0, 255, 0, 255);
+    // expect the center pixel to be blue
+    EXPECT_PIXEL_COLOR_EQ((windowWidth - 1) / 2, (windowHeight - 1) / 2, GLColor::blue);
 }
 
 // This is a regression test for a graphics driver bug affecting end caps on roads in MapsGL
@@ -392,13 +385,7 @@
             gl_Position  = position;
         })";
 
-    const std::string fs =
-        R"(void main(void)
-        {
-            gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
-        })";
-
-    ANGLE_GL_PROGRAM(program, vs, fs);
+    ANGLE_GL_PROGRAM(program, vs, essl1_shaders::fs::Red());
     ASSERT_GL_NO_ERROR();
 
     glUseProgram(program);
@@ -418,13 +405,6 @@
     // http://anglebug.com/2447
     ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
 
-    const std::string pointFS =
-        R"(precision mediump float;
-        void main()
-        {
-            gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
-        })";
-
     const std::string pointVS =
         R"(void main()
         {
@@ -432,24 +412,9 @@
             gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
         })";
 
-    const std::string quadFS =
-        R"(precision mediump float;
-        void main()
-        {
-            gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
-        })";
+    ANGLE_GL_PROGRAM(pointProgram, pointVS, essl1_shaders::fs::Blue());
 
-    const std::string quadVS =
-        R"(precision mediump float;
-        attribute vec4 pos;
-        void main()
-        {
-            gl_Position = pos;
-        })";
-
-    ANGLE_GL_PROGRAM(pointProgram, pointVS, pointFS);
-
-    ANGLE_GL_PROGRAM(quadProgram, quadVS, quadFS);
+    ANGLE_GL_PROGRAM(quadProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
     ASSERT_GL_NO_ERROR();
 
     glEnable(GL_CULL_FACE);
@@ -462,7 +427,7 @@
     };
 
     glUseProgram(quadProgram);
-    GLint positionLocation = glGetAttribLocation(quadProgram, "pos");
+    GLint positionLocation = glGetAttribLocation(quadProgram, essl1_shaders::PositionAttrib());
     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices);
     glEnableVertexAttribArray(positionLocation);
     glDrawArrays(GL_TRIANGLES, 0, 6);
@@ -471,8 +436,8 @@
     glDrawArrays(GL_POINTS, 0, 1);
     ASSERT_GL_NO_ERROR();
 
-    // expect the center pixel to be green
-    EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 255, 0, 255);
+    // expect the center pixel to be blue
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue);
 }
 
 // This checks for an NVIDIA driver bug where points larger than the maximum reported point size can
@@ -510,13 +475,7 @@
         "    gl_PointSize = uPointSize;\n"
         "    gl_Position  = vPosition;\n"
         "}\n";
-    const std::string &fs =
-        "precision mediump float;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_FragColor = vec4(1, 0, 0, 1);\n"
-        "}\n";
-    ANGLE_GL_PROGRAM(program, vs, fs);
+    ANGLE_GL_PROGRAM(program, vs, essl1_shaders::fs::Red());
     glUseProgram(program);
     ASSERT_GL_NO_ERROR();
 
diff --git a/src/tests/gl_tests/ProgramBinaryTest.cpp b/src/tests/gl_tests/ProgramBinaryTest.cpp
index b2925b5..95897c5 100644
--- a/src/tests/gl_tests/ProgramBinaryTest.cpp
+++ b/src/tests/gl_tests/ProgramBinaryTest.cpp
@@ -34,20 +34,7 @@
     {
         ANGLETest::SetUp();
 
-        const std::string vertexShaderSource =
-            R"(attribute vec4 inputAttribute;
-            void main()
-            {
-                gl_Position = inputAttribute;
-            })";
-
-        const std::string fragmentShaderSource =
-            R"(void main()
-            {
-                gl_FragColor = vec4(1,0,0,1);
-            })";
-
-        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
         if (mProgram == 0)
         {
             FAIL() << "shader compilation failed.";
@@ -140,7 +127,7 @@
     glUseProgram(mProgram);
     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
 
-    GLint attribLocation = glGetAttribLocation(mProgram, "inputAttribute");
+    GLint attribLocation = glGetAttribLocation(mProgram, essl1_shaders::PositionAttrib());
     ASSERT_NE(-1, attribLocation);
     glEnableVertexAttribArray(attribLocation);
 
@@ -244,7 +231,7 @@
     ANGLE_GL_BINARY_OES_PROGRAM(binaryProgram, binaryBlob, binaryFormat);
     ASSERT_GL_NO_ERROR();
 
-    drawQuad(binaryProgram, "inputAttribute", 0.5f);
+    drawQuad(binaryProgram, essl1_shaders::PositionAttrib(), 0.5f);
     ASSERT_GL_NO_ERROR();
 }
 
@@ -608,46 +595,12 @@
 
     GLuint createES2ProgramFromSource()
     {
-        const std::string testVertexShaderSource =
-            R"(attribute highp vec4 position;
-
-            void main(void)
-            {
-                gl_Position = position;
-            })";
-
-        const std::string testFragmentShaderSource =
-            R"(void main(void)
-            {
-                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
-            })";
-
-        return CompileProgram(testVertexShaderSource, testFragmentShaderSource);
+        return CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
     }
 
     GLuint createES3ProgramFromSource()
     {
-        const std::string testVertexShaderSource =
-            R"(#version 300 es
-            precision highp float;
-            in highp vec4 position;
-
-            void main(void)
-            {
-                gl_Position = position;
-            })";
-
-        const std::string testFragmentShaderSource =
-            R"(#version 300 es
-            precision highp float;
-            out vec4 out_FragColor;
-
-            void main(void)
-            {
-                out_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
-            })";
-
-        return CompileProgram(testVertexShaderSource, testFragmentShaderSource);
+        return CompileProgram(essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
     }
 
     void drawWithProgram(GLuint program)
@@ -655,7 +608,7 @@
         glClearColor(0, 0, 0, 1);
         glClear(GL_COLOR_BUFFER_BIT);
 
-        GLint positionLocation = glGetAttribLocation(program, "position");
+        GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
 
         glUseProgram(program);
 
diff --git a/src/tests/gl_tests/ProgramInterfaceTest.cpp b/src/tests/gl_tests/ProgramInterfaceTest.cpp
index 29165ff..1cd621f 100644
--- a/src/tests/gl_tests/ProgramInterfaceTest.cpp
+++ b/src/tests/gl_tests/ProgramInterfaceTest.cpp
@@ -6,6 +6,7 @@
 
 // ProgramInterfaceTest: Tests of program interfaces.
 
+#include "common/string_utils.h"
 #include "test_utils/ANGLETest.h"
 #include "test_utils/gl_raii.h"
 
@@ -31,15 +32,6 @@
 // Tests glGetProgramResourceIndex.
 TEST_P(ProgramInterfaceTestES31, GetResourceIndex)
 {
-    const std::string &vertexShaderSource =
-        "#version 310 es\n"
-        "precision highp float;\n"
-        "in highp vec4 position;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = position;\n"
-        "}";
-
     const std::string &fragmentShaderSource =
         "#version 310 es\n"
         "precision highp float;\n"
@@ -50,9 +42,10 @@
         "    oColor = color;\n"
         "}";
 
-    ANGLE_GL_PROGRAM(program, vertexShaderSource, fragmentShaderSource);
+    ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), fragmentShaderSource);
 
-    GLuint index = glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, "position");
+    GLuint index =
+        glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, essl31_shaders::PositionAttrib());
     EXPECT_GL_NO_ERROR();
     EXPECT_NE(GL_INVALID_INDEX, index);
 
@@ -75,15 +68,6 @@
 // Tests glGetProgramResourceName.
 TEST_P(ProgramInterfaceTestES31, GetResourceName)
 {
-    const std::string &vertexShaderSource =
-        "#version 310 es\n"
-        "precision highp float;\n"
-        "in highp vec4 position;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = position;\n"
-        "}";
-
     const std::string &fragmentShaderSource =
         "#version 310 es\n"
         "precision highp float;\n"
@@ -94,9 +78,10 @@
         "    oColor[0] = color;\n"
         "}";
 
-    ANGLE_GL_PROGRAM(program, vertexShaderSource, fragmentShaderSource);
+    ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), fragmentShaderSource);
 
-    GLuint index = glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, "position");
+    GLuint index =
+        glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, essl31_shaders::PositionAttrib());
     EXPECT_GL_NO_ERROR();
     EXPECT_NE(GL_INVALID_INDEX, index);
 
@@ -104,13 +89,13 @@
     GLsizei length;
     glGetProgramResourceName(program, GL_PROGRAM_INPUT, index, sizeof(name), &length, name);
     EXPECT_GL_NO_ERROR();
-    EXPECT_EQ(8, length);
-    EXPECT_EQ("position", std::string(name));
+    EXPECT_EQ(static_cast<int>(strlen(essl31_shaders::PositionAttrib())), length);
+    EXPECT_EQ(essl31_shaders::PositionAttrib(), std::string(name));
 
     glGetProgramResourceName(program, GL_PROGRAM_INPUT, index, 4, &length, name);
     EXPECT_GL_NO_ERROR();
     EXPECT_EQ(3, length);
-    EXPECT_EQ("pos", std::string(name));
+    EXPECT_TRUE(angle::BeginsWith(essl31_shaders::PositionAttrib(), name));
 
     glGetProgramResourceName(program, GL_PROGRAM_INPUT, index, -1, &length, name);
     EXPECT_GL_ERROR(GL_INVALID_VALUE);
@@ -268,15 +253,6 @@
 // Tests glGetProgramInterfaceiv.
 TEST_P(ProgramInterfaceTestES31, GetProgramInterface)
 {
-    const std::string &vertexShaderSource =
-        "#version 310 es\n"
-        "precision highp float;\n"
-        "in highp vec4 position;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = position;\n"
-        "}";
-
     const std::string &fragmentShaderSource =
         "#version 310 es\n"
         "precision highp float;\n"
@@ -299,7 +275,7 @@
         "    blockInstance2[0].target = vec3(1, 1, 1);\n"
         "}";
 
-    ANGLE_GL_PROGRAM(program, vertexShaderSource, fragmentShaderSource);
+    ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), fragmentShaderSource);
 
     GLint num;
     glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &num);
@@ -308,7 +284,7 @@
 
     glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, &num);
     EXPECT_GL_NO_ERROR();
-    EXPECT_EQ(9, num);
+    EXPECT_EQ(static_cast<GLint>(strlen(essl3_shaders::PositionAttrib())) + 1, num);
 
     glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NUM_ACTIVE_VARIABLES, &num);
     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
diff --git a/src/tests/gl_tests/RobustResourceInitTest.cpp b/src/tests/gl_tests/RobustResourceInitTest.cpp
index fca4285..20e932d 100644
--- a/src/tests/gl_tests/RobustResourceInitTest.cpp
+++ b/src/tests/gl_tests/RobustResourceInitTest.cpp
@@ -766,6 +766,62 @@
 }
 
 // Reading an uninitialized portion of a texture (copyTexImage2D with negative x and y) should
+// succeed with all bytes set to 0. Regression test for a bug where the zeroing out of the
+// texture was done via the same code path as glTexImage2D, causing the PIXEL_UNPACK_BUFFER
+// to be used.
+TEST_P(RobustResourceInitTestES3, ReadingOutOfboundsCopiedTextureWithUnpackBuffer)
+{
+    ANGLE_SKIP_TEST_IF(!hasGLExtension());
+    // TODO(geofflang@chromium.org): CopyTexImage from GL_RGBA4444 to GL_ALPHA fails when looking
+    // up which resulting format the texture should have.
+    ANGLE_SKIP_TEST_IF(IsOpenGL());
+
+    // GL_ALPHA texture can't be read with glReadPixels, for convenience this test uses
+    // glCopyTextureCHROMIUM to copy GL_ALPHA into GL_RGBA
+    ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_CHROMIUM_copy_texture"));
+    PFNGLCOPYTEXTURECHROMIUMPROC glCopyTextureCHROMIUM =
+        reinterpret_cast<PFNGLCOPYTEXTURECHROMIUMPROC>(eglGetProcAddress("glCopyTextureCHROMIUM"));
+
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    GLRenderbuffer rbo;
+    glBindRenderbuffer(GL_RENDERBUFFER, rbo);
+    constexpr int fboWidth  = 16;
+    constexpr int fboHeight = 16;
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, fboWidth, fboHeight);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+    glClearColor(1.0, 0.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_GL_NO_ERROR();
+    constexpr int x = -8;
+    constexpr int y = -8;
+
+    GLBuffer buffer;
+    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
+    std::vector<GLColor> bunchOfGreen(fboWidth * fboHeight, GLColor::green);
+    glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(bunchOfGreen), bunchOfGreen.data(), GL_STATIC_DRAW);
+    EXPECT_GL_NO_ERROR();
+
+    // Use GL_ALPHA to force a CPU readback in the D3D11 backend
+    GLTexture texAlpha;
+    glBindTexture(GL_TEXTURE_2D, texAlpha);
+    glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, x, y, kWidth, kHeight, 0);
+    EXPECT_GL_NO_ERROR();
+
+    // GL_ALPHA cannot be glReadPixels, so copy into a GL_RGBA texture
+    GLTexture texRGBA;
+    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+    setupTexture(&texRGBA);
+    glCopyTextureCHROMIUM(texAlpha, 0, GL_TEXTURE_2D, texRGBA, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                          GL_FALSE, GL_FALSE, GL_FALSE);
+    EXPECT_GL_NO_ERROR();
+
+    checkNonZeroPixels(&texRGBA, -x, -y, fboWidth, fboHeight, GLColor(0, 0, 0, 255));
+    EXPECT_GL_NO_ERROR();
+}
+
+// Reading an uninitialized portion of a texture (copyTexImage2D with negative x and y) should
 // succeed with all bytes set to 0.
 TEST_P(RobustResourceInitTest, ReadingOutOfboundsCopiedTexture)
 {
@@ -800,9 +856,7 @@
     // http://anglebug.com/2407
     ANGLE_SKIP_TEST_IF(IsAndroid());
 
-    const std::string vs = "attribute vec4 position; void main() { gl_Position = position; }";
-    const std::string fs = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
-    ANGLE_GL_PROGRAM(program, vs, fs);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
 
     // Make the destination non-multisampled depth FBO.
     GLTexture color;
@@ -845,7 +899,7 @@
     glDepthMask(GL_FALSE);
     glEnable(GL_DEPTH_TEST);
     glDepthFunc(GL_EQUAL);
-    drawQuad(program, "position", 1.0f);
+    drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f);
     ASSERT_GL_NO_ERROR();
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
 }
@@ -1168,16 +1222,13 @@
     glEnable(GL_DEPTH_TEST);
     glDepthFunc(GL_EQUAL);
 
-    const std::string vertexShader =
-        "attribute vec4 position; void main() { gl_Position = position; }";
-    const std::string fragmentShader = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
-    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
 
-    drawQuad(program, "position", 0.5f);
+    drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
     ASSERT_GL_NO_ERROR();
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black) << "depth should not be 0.5f";
 
-    drawQuad(program, "position", 1.0f);
+    drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "depth should be initialized to 1.0f";
 }
 
@@ -1249,12 +1300,9 @@
     glStencilFunc(GL_EQUAL, 0x00, 0xFF);
     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
 
-    const std::string vertexShader =
-        "attribute vec4 position; void main() { gl_Position = position; }";
-    const std::string fragmentShader = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
-    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
 
-    drawQuad(program, "position", 0.5f);
+    drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
     ASSERT_GL_NO_ERROR();
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "stencil should be equal to zero";
 }
diff --git a/src/tests/gl_tests/SRGBFramebufferTest.cpp b/src/tests/gl_tests/SRGBFramebufferTest.cpp
index 57169eb..a575732 100644
--- a/src/tests/gl_tests/SRGBFramebufferTest.cpp
+++ b/src/tests/gl_tests/SRGBFramebufferTest.cpp
@@ -29,26 +29,10 @@
     {
         ANGLETest::SetUp();
 
-        const std::string vs =
-            "precision highp float;\n"
-            "attribute vec4 position;\n"
-            "void main()\n"
-            "{\n"
-            "   gl_Position = vec4(position.xy, 0.0, 1.0);\n"
-            "}\n";
-
-        const std::string fs =
-            "precision highp float;\n"
-            "uniform vec4 color;\n"
-            "void main()\n"
-            "{\n"
-            "   gl_FragColor = color;\n"
-            "}\n";
-
-        mProgram = CompileProgram(vs, fs);
+        mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
         ASSERT_NE(0u, mProgram);
 
-        mColorLocation = glGetUniformLocation(mProgram, "color");
+        mColorLocation = glGetUniformLocation(mProgram, essl1_shaders::ColorUniform());
         ASSERT_NE(-1, mColorLocation);
     }
 
@@ -119,11 +103,11 @@
     glUniform4fv(mColorLocation, 1, srgbColor.toNormalizedVector().data());
 
     glEnable(GL_FRAMEBUFFER_SRGB_EXT);
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor, 1.0);
 
     glDisable(GL_FRAMEBUFFER_SRGB_EXT);
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_NEAR(0, 0, srgbColor, 1.0);
 }
 
diff --git a/src/tests/gl_tests/SRGBTextureTest.cpp b/src/tests/gl_tests/SRGBTextureTest.cpp
index 76e73b7..67af201 100644
--- a/src/tests/gl_tests/SRGBTextureTest.cpp
+++ b/src/tests/gl_tests/SRGBTextureTest.cpp
@@ -118,14 +118,7 @@
         EXPECT_GL_NO_ERROR();
 
         glGenerateMipmap(GL_TEXTURE_2D);
-        if (getClientMajorVersion() == 2)
-        {
-            EXPECT_GL_ERROR(GL_INVALID_OPERATION);
-        }
-        else
-        {
-            EXPECT_GL_NO_ERROR();
-        }
+        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
     }
     else
     {
@@ -135,6 +128,30 @@
     glDeleteTextures(1, &tex);
 }
 
+// Test that sized SRGBA formats allow generating mipmaps
+TEST_P(SRGBTextureTest, SRGBASizedValidation)
+{
+    // TODO(fjhenigman): Figure out why this fails on Ozone Intel.
+    ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel() && IsOpenGLES());
+
+    // ES3 required for sized SRGB textures
+    ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
+
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex);
+
+    GLubyte pixel[4] = {0};
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
+
+    EXPECT_GL_NO_ERROR();
+
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
+    EXPECT_GL_NO_ERROR();
+
+    glGenerateMipmap(GL_TEXTURE_2D);
+    EXPECT_GL_NO_ERROR();
+}
+
 TEST_P(SRGBTextureTest, SRGBARenderbuffer)
 {
     bool supported = extensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() == 3;
diff --git a/src/tests/gl_tests/SimpleOperationTest.cpp b/src/tests/gl_tests/SimpleOperationTest.cpp
index f51c439..6ea8e6d 100644
--- a/src/tests/gl_tests/SimpleOperationTest.cpp
+++ b/src/tests/gl_tests/SimpleOperationTest.cpp
@@ -30,6 +30,11 @@
     gl_FragColor = vec4(0, 1, 0, 1);
 })";
 
+constexpr std::array<GLenum, 6> kCubeFaces = {
+    {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+     GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
+     GL_TEXTURE_CUBE_MAP_NEGATIVE_Z}};
+
 class SimpleOperationTest : public ANGLETest
 {
   protected:
@@ -696,7 +701,7 @@
     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
 }
 
-// Creates a texture, no other operations.
+// Creates a 2D texture, no other operations.
 TEST_P(SimpleOperationTest, CreateTexture2DNoData)
 {
     GLTexture texture;
@@ -705,7 +710,7 @@
     ASSERT_GL_NO_ERROR();
 }
 
-// Creates a texture, no other operations.
+// Creates a 2D texture, no other operations.
 TEST_P(SimpleOperationTest, CreateTexture2DWithData)
 {
     std::vector<GLColor> colors(16 * 16, GLColor::red);
@@ -716,6 +721,32 @@
     ASSERT_GL_NO_ERROR();
 }
 
+// Creates a cube texture, no other operations.
+TEST_P(SimpleOperationTest, CreateTextureCubeNoData)
+{
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
+    for (GLenum cubeFace : kCubeFaces)
+    {
+        glTexImage2D(cubeFace, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    }
+    ASSERT_GL_NO_ERROR();
+}
+
+// Creates a cube texture, no other operations.
+TEST_P(SimpleOperationTest, CreateTextureCubeWithData)
+{
+    std::vector<GLColor> colors(16 * 16, GLColor::red);
+
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
+    for (GLenum cubeFace : kCubeFaces)
+    {
+        glTexImage2D(cubeFace, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
+    }
+    ASSERT_GL_NO_ERROR();
+}
+
 // Creates a program with a texture.
 TEST_P(SimpleOperationTest, LinkProgramWithTexture)
 {
@@ -723,8 +754,8 @@
     ASSERT_GL_NO_ERROR();
 }
 
-// Creates a program with a texture and renders with it.
-TEST_P(SimpleOperationTest, DrawWithTexture)
+// Creates a program with a 2D texture and renders with it.
+TEST_P(SimpleOperationTest, DrawWith2DTexture)
 {
     std::array<GLColor, 4> colors = {
         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
@@ -747,6 +778,184 @@
     EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
 }
 
+// Draw a line loop using a drawElement call and client side memory.
+TEST_P(SimpleOperationTest, DrawElementsLineLoopUsingClientSideMemory)
+{
+    ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
+    glUseProgram(program);
+
+    // We expect to draw a square with these 4 vertices with a drawArray call.
+    std::vector<Vector3> vertices;
+    CreatePixelCenterWindowCoords({{32, 96}, {32, 32}, {96, 32}, {96, 96}}, getWindowWidth(),
+                                  getWindowHeight(), &vertices);
+
+    // If we use these indices to draw however, we should be drawing an hourglass.
+    std::vector<GLushort> indices{3, 2, 1, 0};
+
+    GLint positionLocation = glGetAttribLocation(program, "position");
+    ASSERT_NE(-1, positionLocation);
+
+    GLBuffer vertexBuffer;
+    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
+                 GL_STATIC_DRAW);
+
+    glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
+    glEnableVertexAttribArray(positionLocation);
+    glClear(GL_COLOR_BUFFER_BIT);
+    glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, indices.data());
+    glDisableVertexAttribArray(positionLocation);
+
+    ASSERT_GL_NO_ERROR();
+
+    int quarterWidth  = getWindowWidth() / 4;
+    int quarterHeight = getWindowHeight() / 4;
+
+    // Bottom left
+    EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight, GLColor::green);
+
+    // Top left
+    EXPECT_PIXEL_COLOR_EQ(quarterWidth, (quarterHeight * 3), GLColor::green);
+
+    // Top right
+    EXPECT_PIXEL_COLOR_EQ((quarterWidth * 3), (quarterHeight * 3) - 1, GLColor::green);
+
+    // Verify line is closed between the 2 last vertices
+    EXPECT_PIXEL_COLOR_EQ((quarterWidth * 2), quarterHeight, GLColor::green);
+}
+
+// Creates a program with a cube texture and renders with it.
+TEST_P(SimpleOperationTest, DrawWithCubeTexture)
+{
+    std::array<Vector2, 6 * 4> positions = {{
+        {0, 1}, {1, 1}, {1, 2}, {0, 2} /* first face */,
+        {1, 0}, {2, 0}, {2, 1}, {1, 1} /* second face */,
+        {1, 1}, {2, 1}, {2, 2}, {1, 2} /* third face */,
+        {1, 2}, {2, 2}, {2, 3}, {1, 3} /* fourth face */,
+        {2, 1}, {3, 1}, {3, 2}, {2, 2} /* fifth face */,
+        {3, 1}, {4, 1}, {4, 2}, {3, 2} /* sixth face */,
+    }};
+
+    const float w4 = 1.0f / 4.0f;
+    const float h3 = 1.0f / 3.0f;
+
+    // This draws a "T" shape based on the four faces of the cube. The window is divided into four
+    // tiles horizontally and three tiles vertically (hence the w4 and h3 variable naming).
+    for (Vector2 &pos : positions)
+    {
+        pos.data()[0] = pos.data()[0] * w4 * 2.0f - 1.0f;
+        pos.data()[1] = pos.data()[1] * h3 * 2.0f - 1.0f;
+    }
+
+    const Vector3 posX(1, 0, 0);
+    const Vector3 negX(-1, 0, 0);
+    const Vector3 posY(0, 1, 0);
+    const Vector3 negY(0, -1, 0);
+    const Vector3 posZ(0, 0, 1);
+    const Vector3 negZ(0, 0, -1);
+
+    std::array<Vector3, 6 * 4> coords = {{
+        posX, posX, posX, posX /* first face */, negX, negX, negX, negX /* second face */,
+        posY, posY, posY, posY /* third face */, negY, negY, negY, negY /* fourth face */,
+        posZ, posZ, posZ, posZ /* fifth face */, negZ, negZ, negZ, negZ /* sixth face */,
+    }};
+
+    const std::array<std::array<GLColor, 4>, 6> colors = {{
+        {GLColor::red, GLColor::red, GLColor::red, GLColor::red},
+        {GLColor::green, GLColor::green, GLColor::green, GLColor::green},
+        {GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue},
+        {GLColor::yellow, GLColor::yellow, GLColor::yellow, GLColor::yellow},
+        {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan},
+        {GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta},
+    }};
+
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
+
+    for (size_t faceIndex = 0; faceIndex < kCubeFaces.size(); ++faceIndex)
+    {
+        glTexImage2D(kCubeFaces[faceIndex], 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                     colors[faceIndex].data());
+    }
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    constexpr char kVertexShader[] = R"(attribute vec2 pos;
+attribute vec3 coord;
+varying vec3 texCoord;
+void main()
+{
+    gl_Position = vec4(pos, 0, 1);
+    texCoord = coord;
+})";
+
+    constexpr char kFragmentShader[] = R"(precision mediump float;
+varying vec3 texCoord;
+uniform samplerCube tex;
+void main()
+{
+    gl_FragColor = textureCube(tex, texCoord);
+})";
+
+    ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
+    GLint samplerLoc = glGetUniformLocation(program, "tex");
+    ASSERT_EQ(samplerLoc, 0);
+
+    glUseProgram(program);
+
+    GLint posLoc = glGetAttribLocation(program, "pos");
+    ASSERT_NE(-1, posLoc);
+
+    GLint coordLoc = glGetAttribLocation(program, "coord");
+    ASSERT_NE(-1, coordLoc);
+
+    GLBuffer posBuffer;
+    glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
+    glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(Vector2), positions.data(),
+                 GL_STATIC_DRAW);
+    glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
+    glEnableVertexAttribArray(posLoc);
+
+    GLBuffer coordBuffer;
+    glBindBuffer(GL_ARRAY_BUFFER, coordBuffer);
+    glBufferData(GL_ARRAY_BUFFER, coords.size() * sizeof(Vector3), coords.data(), GL_STATIC_DRAW);
+    glVertexAttribPointer(coordLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
+    glEnableVertexAttribArray(coordLoc);
+
+    auto quadIndices = GetQuadIndices();
+    std::array<GLushort, 6 * 6> kElementsData;
+    for (GLushort quadIndex = 0; quadIndex < 6; ++quadIndex)
+    {
+        for (GLushort elementIndex = 0; elementIndex < 6; ++elementIndex)
+        {
+            kElementsData[quadIndex * 6 + elementIndex] = quadIndices[elementIndex] + 4 * quadIndex;
+        }
+    }
+
+    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    GLBuffer elementBuffer;
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, kElementsData.size() * sizeof(GLushort),
+                 kElementsData.data(), GL_STATIC_DRAW);
+    glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(kElementsData.size()), GL_UNSIGNED_SHORT,
+                   nullptr);
+    ASSERT_GL_NO_ERROR();
+
+    for (int faceIndex = 0; faceIndex < 6; ++faceIndex)
+    {
+        int index      = faceIndex * 4;
+        Vector2 center = (positions[index] + positions[index + 1] + positions[index + 2] +
+                          positions[index + 3]) /
+                         4.0f;
+        center *= 0.5f;
+        center += Vector2(0.5f);
+        center *= Vector2(getWindowWidth(), getWindowHeight());
+        EXPECT_PIXEL_COLOR_EQ(center.x(), center.y(), colors[faceIndex][0]);
+    }
+}
+
 // Tests rendering to a user framebuffer.
 TEST_P(SimpleOperationTest, RenderToTexture)
 {
diff --git a/src/tests/gl_tests/StateChangeTest.cpp b/src/tests/gl_tests/StateChangeTest.cpp
index a85ba46..c46e536 100644
--- a/src/tests/gl_tests/StateChangeTest.cpp
+++ b/src/tests/gl_tests/StateChangeTest.cpp
@@ -15,6 +15,18 @@
 
 namespace
 {
+constexpr char kBasicVertexShader[] =
+    R"(attribute vec3 position;
+void main()
+{
+    gl_Position = vec4(position, 1);
+})";
+
+constexpr char kGreenFragmentShader[] =
+    R"(void main()
+{
+    gl_FragColor = vec4(0, 1, 0, 1);
+})";
 
 class StateChangeTest : public ANGLETest
 {
@@ -946,6 +958,123 @@
     glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
 }
 
+// Simple state change tests for line loop drawing. There is some very specific handling of line
+// line loops in Vulkan and we need to test switching between drawElements and drawArrays calls to
+// validate every edge cases.
+class LineLoopStateChangeTest : public StateChangeTest
+{
+  protected:
+    LineLoopStateChangeTest()
+    {
+        setWindowWidth(32);
+        setWindowHeight(32);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void validateSquareAndHourglass()
+    {
+        ASSERT_GL_NO_ERROR();
+
+        int quarterWidth  = getWindowWidth() / 4;
+        int quarterHeight = getWindowHeight() / 4;
+
+        // Bottom left
+        EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight, GLColor::green);
+
+        // Top left
+        EXPECT_PIXEL_COLOR_EQ(quarterWidth, (quarterHeight * 3), GLColor::green);
+
+        // Top right
+        // The last pixel isn't filled on a line loop so we check the pixel right before.
+        EXPECT_PIXEL_COLOR_EQ((quarterWidth * 3), (quarterHeight * 3) - 1, GLColor::green);
+
+        // dead center to validate the hourglass.
+        EXPECT_PIXEL_COLOR_EQ((quarterWidth * 2), quarterHeight * 2, GLColor::green);
+
+        // Verify line is closed between the 2 last vertices
+        EXPECT_PIXEL_COLOR_EQ((quarterWidth * 2), quarterHeight, GLColor::green);
+    }
+
+    GLint mPositionLocation;
+};
+
+// Draw an hourglass with a drawElements call followed by a square with drawArrays.
+TEST_P(LineLoopStateChangeTest, DrawElementsThenDrawArrays)
+{
+    ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
+    glUseProgram(program);
+
+    // We expect to draw a square with these 4 vertices with a drawArray call.
+    std::vector<Vector3> vertices;
+    CreatePixelCenterWindowCoords({{8, 8}, {8, 24}, {24, 8}, {24, 24}}, getWindowWidth(),
+                                  getWindowHeight(), &vertices);
+
+    // If we use these indices to draw however, we should be drawing an hourglass.
+    auto indices = std::vector<GLushort>{0, 2, 1, 3};
+
+    mPositionLocation = glGetAttribLocation(program, "position");
+    ASSERT_NE(-1, mPositionLocation);
+
+    GLBuffer vertexBuffer;
+    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
+                 GL_STATIC_DRAW);
+
+    GLBuffer indexBuffer;
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
+                 GL_STATIC_DRAW);
+
+    glVertexAttribPointer(mPositionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
+    glEnableVertexAttribArray(mPositionLocation);
+    glClear(GL_COLOR_BUFFER_BIT);
+    glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, nullptr);  // hourglass
+    glDrawArrays(GL_LINE_LOOP, 0, 4);                             // square
+    glDisableVertexAttribArray(mPositionLocation);
+
+    validateSquareAndHourglass();
+}
+
+// Draw line loop using a drawArrays followed by an hourglass with drawElements.
+TEST_P(LineLoopStateChangeTest, DrawArraysThenDrawElements)
+{
+    ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
+    glUseProgram(program);
+
+    // We expect to draw a square with these 4 vertices with a drawArray call.
+    std::vector<Vector3> vertices;
+    CreatePixelCenterWindowCoords({{8, 8}, {8, 24}, {24, 8}, {24, 24}}, getWindowWidth(),
+                                  getWindowHeight(), &vertices);
+
+    // If we use these indices to draw however, we should be drawing an hourglass.
+    auto indices = std::vector<GLushort>{0, 2, 1, 3};
+
+    mPositionLocation = glGetAttribLocation(program, "position");
+    ASSERT_NE(-1, mPositionLocation);
+
+    GLBuffer vertexBuffer;
+    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
+                 GL_STATIC_DRAW);
+
+    GLBuffer indexBuffer;
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
+                 GL_STATIC_DRAW);
+
+    glVertexAttribPointer(mPositionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
+    glEnableVertexAttribArray(mPositionLocation);
+    glClear(GL_COLOR_BUFFER_BIT);
+    glDrawArrays(GL_LINE_LOOP, 0, 4);                             // square
+    glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, nullptr);  // hourglass
+    glDisableVertexAttribArray(mPositionLocation);
+
+    validateSquareAndHourglass();
+}
+
 // Simple state change tests, primarily focused on basic object lifetime and dependency management
 // with back-ends that don't support that automatically (i.e. Vulkan).
 class SimpleStateChangeTest : public ANGLETest
@@ -1008,6 +1137,61 @@
     simpleDrawWithBuffer(&colorBuffer);
 }
 
+// Test that we can do a drawElements call successfully after making a drawArrays call in the same
+// frame.
+TEST_P(SimpleStateChangeTest, DrawArraysThenDrawElements)
+{
+    ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
+    glUseProgram(program);
+
+    // We expect to draw a triangle with the first 3 points to the left, then another triangle with
+    // the last 3 vertices using a drawElements call.
+    auto vertices = std::vector<Vector3>{{-1.0f, -1.0f, 0.0f},
+                                         {-1.0f, 1.0f, 0.0f},
+                                         {0.0f, 0.0f, 0.0f},
+                                         {1.0f, 1.0f, 0.0f},
+                                         {1.0f, -1.0f, 0.0f}};
+
+    // If we use these indices to draw we'll be using the last 2 vertex only to draw.
+    auto indices = std::vector<GLushort>{2, 3, 4};
+
+    GLint positionLocation = glGetAttribLocation(program, "position");
+    ASSERT_NE(-1, positionLocation);
+
+    GLBuffer vertexBuffer;
+    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
+                 GL_STATIC_DRAW);
+
+    GLBuffer indexBuffer;
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
+                 GL_STATIC_DRAW);
+
+    glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
+    glEnableVertexAttribArray(positionLocation);
+
+    for (int i = 0; i < 10; i++)
+    {
+        glClear(GL_COLOR_BUFFER_BIT);
+        glDrawArrays(GL_TRIANGLES, 0, 3);                             // triangle to the left
+        glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, nullptr);  // triangle to the right
+        swapBuffers();
+    }
+    glDisableVertexAttribArray(positionLocation);
+
+    ASSERT_GL_NO_ERROR();
+
+    int quarterWidth = getWindowWidth() / 4;
+    int halfHeight   = getWindowHeight() / 2;
+
+    // Validate triangle to the left
+    EXPECT_PIXEL_COLOR_EQ(quarterWidth, halfHeight, GLColor::green);
+
+    // Validate triangle to the right
+    EXPECT_PIXEL_COLOR_EQ((quarterWidth * 3), halfHeight, GLColor::green);
+}
+
 // Handles deleting a Buffer when it's being used.
 TEST_P(SimpleStateChangeTest, DeleteBufferInUse)
 {
@@ -1101,6 +1285,46 @@
     EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
 }
 
+// Tests that modifying a texture parameter in-flight does not cause problems.
+TEST_P(SimpleStateChangeTest, ChangeTextureFilterModeBetweenTwoDraws)
+{
+    std::array<GLColor, 4> colors = {
+        {GLColor::black, GLColor::white, GLColor::black, GLColor::white}};
+
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
+
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    // Draw to the left side of the window only with NEAREST.
+    glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    draw2DTexturedQuad(0.5f, 1.0f, true);
+
+    // Draw to the right side of the window only with LINEAR.
+    glViewport(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    draw2DTexturedQuad(0.5f, 1.0f, true);
+    EXPECT_GL_NO_ERROR();
+
+    glViewport(0, 0, getWindowWidth(), getWindowHeight());
+
+    // The first half (left) should be only black followed by plain white.
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
+    EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::black);
+    EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 3, 0, GLColor::white);
+    EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 4, 0, GLColor::white);
+
+    // The second half (right) should be a gradient so we shouldn't find plain black/white in the
+    // middle.
+    EXPECT_NE(angle::ReadColor((getWindowWidth() / 4) * 3, 0), GLColor::black);
+    EXPECT_NE(angle::ReadColor((getWindowWidth() / 4) * 3, 0), GLColor::white);
+}
+
 // Tests that redefining an in-flight Texture does not affect the in-flight resource.
 TEST_P(SimpleStateChangeTest, RedefineTextureInUse)
 {
@@ -1490,9 +1714,97 @@
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
+// Validate that we can draw -> change frame buffer size -> draw and we'll be rendering
+// at the full size of the new framebuffer.
+TEST_P(SimpleStateChangeTest, ChangeFramebufferSizeBetweenTwoDraws)
+{
+    constexpr char vertexShader[] =
+        R"(attribute vec2 position;
+void main()
+{
+    gl_Position = vec4(position, 0, 1);
+})";
+
+    constexpr char fragShader[] = R"(precision mediump float;
+uniform vec4 color;
+void main() {
+    gl_FragColor = color;
+})";
+
+    constexpr size_t kSmallTextureSize = 2;
+    constexpr size_t kBigTextureSize   = 4;
+
+    // Create 2 textures, one of 2x2 and the other 4x4
+    GLTexture texture1;
+    glBindTexture(GL_TEXTURE_2D, texture1);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSmallTextureSize, kSmallTextureSize, 0, GL_RGBA,
+                 GL_UNSIGNED_BYTE, nullptr);
+    ASSERT_GL_NO_ERROR();
+
+    GLTexture texture2;
+    glBindTexture(GL_TEXTURE_2D, texture2);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kBigTextureSize, kBigTextureSize, 0, GL_RGBA,
+                 GL_UNSIGNED_BYTE, nullptr);
+    ASSERT_GL_NO_ERROR();
+
+    // A framebuffer for each texture to draw on.
+    GLFramebuffer framebuffer1;
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
+    ASSERT_GL_NO_ERROR();
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    GLFramebuffer framebuffer2;
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
+    ASSERT_GL_NO_ERROR();
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    ANGLE_GL_PROGRAM(program, vertexShader, fragShader);
+    glUseProgram(program);
+    GLint uniformLocation = glGetUniformLocation(program, "color");
+    ASSERT_NE(uniformLocation, -1);
+
+    // Bind to the first framebuffer for drawing.
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
+
+    // Set a scissor, that will trigger setting the internal scissor state in Vulkan to
+    // (0,0,framebuffer.width, framebuffer.height) size since the scissor isn't enabled.
+    glScissor(0, 0, 16, 16);
+    ASSERT_GL_NO_ERROR();
+
+    // Set color to red.
+    glUniform4f(uniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
+    glViewport(0, 0, kSmallTextureSize, kSmallTextureSize);
+
+    // Draw a full sized red quad
+    drawQuad(program, "position", 1.0f, 1.0f, true);
+    ASSERT_GL_NO_ERROR();
+
+    // Bind to the second (bigger) framebuffer
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
+    glViewport(0, 0, kBigTextureSize, kBigTextureSize);
+
+    ASSERT_GL_NO_ERROR();
+
+    // Set color to green.
+    glUniform4f(uniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
+
+    // Draw again and we should fill everything with green and expect everything to be green.
+    drawQuad(program, "position", 1.0f, 1.0f, true);
+    ASSERT_GL_NO_ERROR();
+
+    EXPECT_PIXEL_RECT_EQ(0, 0, kBigTextureSize, kBigTextureSize, GLColor::green);
+}
+
 }  // anonymous namespace
 
 ANGLE_INSTANTIATE_TEST(StateChangeTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL());
+ANGLE_INSTANTIATE_TEST(LineLoopStateChangeTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES2_OPENGL(),
+                       ES2_VULKAN());
 ANGLE_INSTANTIATE_TEST(StateChangeRenderTest,
                        ES2_D3D9(),
                        ES2_D3D11(),
diff --git a/src/tests/gl_tests/TextureRectangleTest.cpp b/src/tests/gl_tests/TextureRectangleTest.cpp
index 01c1be5..7412be5 100644
--- a/src/tests/gl_tests/TextureRectangleTest.cpp
+++ b/src/tests/gl_tests/TextureRectangleTest.cpp
@@ -291,13 +291,6 @@
     glTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                  &GLColor::green);
 
-    const std::string vs =
-        "attribute vec4 position;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
-        "}\n";
-
     const std::string fs =
         "#extension GL_ARB_texture_rectangle : require\n"
         "precision mediump float;\n"
@@ -307,7 +300,7 @@
         "    gl_FragColor = texture2DRect(tex, vec2(0, 0));\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, vs, fs);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fs);
     glUseProgram(program);
 
     GLint location = glGetUniformLocation(program, "tex");
@@ -316,7 +309,7 @@
 
     glClearColor(0.0, 0.0, 0.0, 0.0);
     glClear(GL_COLOR_BUFFER_BIT);
-    drawQuad(program, "position", 0.5f, 1.0f, false);
+    drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, false);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
     ASSERT_GL_NO_ERROR();
 }
@@ -331,14 +324,6 @@
     glTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                  &GLColor::green);
 
-    const std::string vs =
-        "#version 300 es\n"
-        "in vec4 position;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
-        "}\n";
-
     const std::string fs =
         "#version 300 es\n"
         "#extension GL_ARB_texture_rectangle : require\n"
@@ -350,7 +335,7 @@
         "    fragColor = texture(tex, vec2(0, 0));\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, vs, fs);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs);
     glUseProgram(program);
 
     GLint location = glGetUniformLocation(program, "tex");
@@ -359,7 +344,7 @@
 
     glClearColor(0.0, 0.0, 0.0, 0.0);
     glClear(GL_COLOR_BUFFER_BIT);
-    drawQuad(program, "position", 0.5f, 1.0f, false);
+    drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, false);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
     ASSERT_GL_NO_ERROR();
 }
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
index eecc591..08730db 100644
--- a/src/tests/gl_tests/TextureTest.cpp
+++ b/src/tests/gl_tests/TextureTest.cpp
@@ -755,13 +755,7 @@
 
     std::string getVertexShaderSource() override
     {
-        return std::string(
-            "#version 300 es\n"
-            "in vec4 position;\n"
-            "void main()\n"
-            "{\n"
-            "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
-            "}\n");
+        return std::string(essl3_shaders::vs::Simple());
     }
 
     std::string getFragmentShaderSource() override
@@ -2367,7 +2361,7 @@
     glUniform1i(mTexture0Location, 0);
     glUniform1i(mTexture1Location, 1);
 
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_GL_NO_ERROR();
     // Red channel: width of level 1 of texture A: 32.
     // Green channel: width of level 3 of texture B: 16.
diff --git a/src/tests/gl_tests/TimerQueriesTest.cpp b/src/tests/gl_tests/TimerQueriesTest.cpp
index 1e8d9d8..d15d91c 100644
--- a/src/tests/gl_tests/TimerQueriesTest.cpp
+++ b/src/tests/gl_tests/TimerQueriesTest.cpp
@@ -7,9 +7,9 @@
 //   Various tests for EXT_disjoint_timer_query functionality and validation
 //
 
+#include "random_utils.h"
 #include "system_utils.h"
 #include "test_utils/ANGLETest.h"
-#include "random_utils.h"
 
 using namespace angle;
 
@@ -31,18 +31,6 @@
     {
         ANGLETest::SetUp();
 
-        const std::string passthroughVS =
-            "attribute highp vec4 position; void main(void)\n"
-            "{\n"
-            "    gl_Position = position;\n"
-            "}\n";
-
-        const std::string passthroughPS =
-            "precision highp float; void main(void)\n"
-            "{\n"
-            "    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
-            "}\n";
-
         const std::string costlyVS =
             "attribute highp vec4 position; varying highp vec4 testPos; void main(void)\n"
             "{\n"
@@ -61,7 +49,7 @@
             "    gl_FragColor = test;\n"
             "}\n";
 
-        mProgram = CompileProgram(passthroughVS, passthroughPS);
+        mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
         ASSERT_NE(0u, mProgram) << "shader compilation failed.";
 
         mProgramCostly = CompileProgram(costlyVS, costlyPS);
@@ -121,7 +109,7 @@
 
     // Test time elapsed for a single quad
     glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query1);
-    drawQuad(mProgram, "position", 0.8f);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f);
     glEndQueryEXT(GL_TIME_ELAPSED_EXT);
     ASSERT_GL_NO_ERROR();
 
@@ -329,19 +317,6 @@
     };
     ContextInfo contexts[2];
 
-    // Shaders
-    const std::string cheapVS =
-        "attribute highp vec4 position; void main(void)\n"
-        "{\n"
-        "    gl_Position = position;\n"
-        "}\n";
-
-    const std::string cheapPS =
-        "precision highp float; void main(void)\n"
-        "{\n"
-        "    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
-        "}\n";
-
     const std::string costlyVS =
         "attribute highp vec4 position; varying highp vec4 testPos; void main(void)\n"
         "{\n"
@@ -365,7 +340,7 @@
     contexts[0].display = display;
     ASSERT_NE(contexts[0].context, EGL_NO_CONTEXT);
     eglMakeCurrent(display, surface, surface, contexts[0].context);
-    contexts[0].program = CompileProgram(cheapVS, cheapPS);
+    contexts[0].program = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
     glGenQueriesEXT(1, &contexts[0].query);
     ASSERT_GL_NO_ERROR();
 
@@ -381,7 +356,7 @@
     // Start the query and draw a quad on the first context without ending the query
     eglMakeCurrent(display, surface, surface, contexts[0].context);
     glBeginQueryEXT(GL_TIME_ELAPSED_EXT, contexts[0].query);
-    drawQuad(contexts[0].program, "position", 0.8f);
+    drawQuad(contexts[0].program, essl1_shaders::PositionAttrib(), 0.8f);
     ASSERT_GL_NO_ERROR();
 
     // Switch contexts, draw the expensive quad and end its query
@@ -443,7 +418,7 @@
     glGenQueriesEXT(1, &query1);
     glGenQueriesEXT(1, &query2);
     glQueryCounterEXT(query1, GL_TIMESTAMP_EXT);
-    drawQuad(mProgram, "position", 0.8f);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f);
     glQueryCounterEXT(query2, GL_TIMESTAMP_EXT);
 
     ASSERT_GL_NO_ERROR();
@@ -506,7 +481,7 @@
     GLint64 result1 = 0;
     GLint64 result2 = 0;
     glGetInteger64v(GL_TIMESTAMP_EXT, &result1);
-    drawQuad(mProgram, "position", 0.8f);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f);
     glGetInteger64v(GL_TIMESTAMP_EXT, &result2);
     ASSERT_GL_NO_ERROR();
     std::cout << "Timestamps (getInteger64v): " << result1 << " " << result2 << std::endl;
diff --git a/src/tests/gl_tests/TransformFeedbackTest.cpp b/src/tests/gl_tests/TransformFeedbackTest.cpp
index e0471be..158d016 100644
--- a/src/tests/gl_tests/TransformFeedbackTest.cpp
+++ b/src/tests/gl_tests/TransformFeedbackTest.cpp
@@ -77,25 +77,8 @@
     {
         ASSERT_EQ(0u, mProgram);
 
-        const std::string vertexShaderSource =
-            R"(precision highp float;
-            attribute vec4 position;
-
-            void main()
-            {
-                gl_Position = position;
-            })";
-
-        const std::string fragmentShaderSource =
-            R"(precision highp float;
-
-            void main()
-            {
-                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
-            })";
-
-        mProgram = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
-                                                       tfVaryings, bufferMode);
+        mProgram = CompileProgramWithTransformFeedback(
+            essl1_shaders::vs::Simple(), essl1_shaders::fs::Red(), tfVaryings, bufferMode);
         ASSERT_NE(0u, mProgram);
     }
 };
@@ -122,7 +105,7 @@
     // a quad
     glViewport(0, 0, 0, 0);
 
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
 
     // End the query and transform feedkback
     glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
@@ -175,7 +158,7 @@
         glBeginTransformFeedback(GL_TRIANGLES);
 
         float z = (loopIdx + 1 == loopCount) ? finalZ : rng.randomFloatBetween(0.1f, 0.5f);
-        drawQuad(mProgram, "position", z);
+        drawQuad(mProgram, essl1_shaders::PositionAttrib(), z);
 
         glEndTransformFeedback();
     }
@@ -228,7 +211,7 @@
 
     glUseProgram(mProgram);
 
-    GLint positionLocation = glGetAttribLocation(mProgram, "position");
+    GLint positionLocation = glGetAttribLocation(mProgram, essl1_shaders::PositionAttrib());
 
     // First pass: draw 6 points to the XFB buffer
     glEnable(GL_RASTERIZER_DISCARD);
@@ -299,7 +282,7 @@
     std::vector<std::string> tfVaryings;
     tfVaryings.push_back("gl_Position");
     compileDefaultProgram(tfVaryings, GL_INTERLEAVED_ATTRIBS);
-    GLint positionLocation = glGetAttribLocation(mProgram, "position");
+    GLint positionLocation = glGetAttribLocation(mProgram, essl1_shaders::PositionAttrib());
 
     glUseProgram(mProgram);
 
@@ -1026,7 +1009,7 @@
 
     glUseProgram(mProgram);
 
-    GLint positionLocation = glGetAttribLocation(mProgram, "position");
+    GLint positionLocation = glGetAttribLocation(mProgram, essl1_shaders::PositionAttrib());
 
     glEnable(GL_RASTERIZER_DISCARD);
 
@@ -1110,19 +1093,19 @@
     glUseProgram(mProgram);
 
     glBeginTransformFeedback(GL_TRIANGLES);
-    drawQuad(mProgram, "position", 0.5f, 1.0f, true);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
     glEndTransformFeedback();
 
     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
 
     // TODO(jmadill): Remove this when http://anglebug.com/1351 is fixed.
     glBindVertexArray(0);
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
     glBindVertexArray(1);
 
     // Next, draw vertices with mTransformFeedbackBuffer. This will link to mVertexArray.
     glBindBuffer(GL_ARRAY_BUFFER, mTransformFeedbackBuffer);
-    GLint loc = glGetAttribLocation(mProgram, "position");
+    GLint loc = glGetAttribLocation(mProgram, essl1_shaders::PositionAttrib());
     ASSERT_NE(-1, loc);
     glVertexAttribPointer(loc, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
     glEnableVertexAttribArray(loc);
@@ -1138,7 +1121,7 @@
     // Then draw again with transform feedback, dereferencing the stranded pointer.
     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedback);
     glBeginTransformFeedback(GL_TRIANGLES);
-    drawQuad(mProgram, "position", 0.5f, 1.0f, true);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
     glEndTransformFeedback();
     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
 
@@ -1426,28 +1409,11 @@
 // Test that nonexistent transform feedback varyings don't assert when linking.
 TEST_P(TransformFeedbackTest, NonExistentTransformFeedbackVarying)
 {
-    const std::string &vertexShaderSource =
-        "#version 300 es\n"
-        "in vec4 a_position;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = a_position;\n"
-        "}\n";
-
-    const std::string &fragmentShaderSource =
-        "#version 300 es\n"
-        "precision mediump float;\n"
-        "out vec4 fragColor;\n"
-        "void main()\n"
-        "{\n"
-        "    fragColor = vec4(0);\n"
-        "}\n";
-
     std::vector<std::string> tfVaryings;
     tfVaryings.push_back("bogus");
 
-    mProgram = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
-                                                   tfVaryings, GL_INTERLEAVED_ATTRIBS);
+    mProgram = CompileProgramWithTransformFeedback(
+        essl3_shaders::vs::Simple(), essl3_shaders::fs::Red(), tfVaryings, GL_INTERLEAVED_ATTRIBS);
     ASSERT_EQ(0u, mProgram);
 }
 
@@ -1455,28 +1421,11 @@
 // nonexistent varying is prefixed with "gl_".
 TEST_P(TransformFeedbackTest, NonExistentTransformFeedbackVaryingWithGLPrefix)
 {
-    const std::string &vertexShaderSource =
-        "#version 300 es\n"
-        "in vec4 a_position;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = a_position;\n"
-        "}\n";
-
-    const std::string &fragmentShaderSource =
-        "#version 300 es\n"
-        "precision mediump float;\n"
-        "out vec4 fragColor;\n"
-        "void main()\n"
-        "{\n"
-        "    fragColor = vec4(0);\n"
-        "}\n";
-
     std::vector<std::string> tfVaryings;
     tfVaryings.push_back("gl_Bogus");
 
-    mProgram = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
-                                                   tfVaryings, GL_INTERLEAVED_ATTRIBS);
+    mProgram = CompileProgramWithTransformFeedback(
+        essl3_shaders::vs::Simple(), essl3_shaders::fs::Red(), tfVaryings, GL_INTERLEAVED_ATTRIBS);
     ASSERT_EQ(0u, mProgram);
 }
 
@@ -1555,24 +1504,7 @@
 // generate an INVALID_OPERATION error.
 TEST_P(TransformFeedbackTest, NoTransformFeedbackVaryingsInUse)
 {
-    const std::string &vertexShaderSource =
-        "#version 300 es\n"
-        "in vec4 a_position;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = a_position;\n"
-        "}\n";
-
-    const std::string &fragmentShaderSource =
-        "#version 300 es\n"
-        "precision mediump float;\n"
-        "out vec4 fragColor;\n"
-        "void main()\n"
-        "{\n"
-        "    fragColor = vec4(0);\n"
-        "}\n";
-
-    ANGLE_GL_PROGRAM(program, vertexShaderSource, fragmentShaderSource);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
 
     glUseProgram(program);
     glBeginTransformFeedback(GL_TRIANGLES);
diff --git a/src/tests/gl_tests/UniformBufferTest.cpp b/src/tests/gl_tests/UniformBufferTest.cpp
index 5767799..8833c1d 100644
--- a/src/tests/gl_tests/UniformBufferTest.cpp
+++ b/src/tests/gl_tests/UniformBufferTest.cpp
@@ -29,14 +29,6 @@
     {
         ANGLETest::SetUp();
 
-        mVertexShaderSource =
-            R"(#version 300 es
-            in vec4 position;
-            void main()
-            {
-                gl_Position = position;
-            })";
-
         mFragmentShaderSource =
             R"(#version 300 es
             precision highp float;
@@ -47,7 +39,7 @@
                 fragColor = color;
             })";
 
-        mProgram = CompileProgram(mVertexShaderSource, mFragmentShaderSource);
+        mProgram = CompileProgram(essl3_shaders::vs::Simple(), mFragmentShaderSource);
         ASSERT_NE(mProgram, 0u);
 
         mUniformBufferIndex = glGetUniformBlockIndex(mProgram, "uni");
@@ -65,7 +57,6 @@
         ANGLETest::TearDown();
     }
 
-    std::string mVertexShaderSource;
     std::string mFragmentShaderSource;
     GLuint mProgram;
     GLint mUniformBufferIndex;
@@ -84,7 +75,7 @@
     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
 
     glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
 
     ASSERT_GL_NO_ERROR();
     EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
@@ -147,7 +138,7 @@
     // Use a size which is smaller than the alignment to check
     // to check that this case is handle correctly in the conversion to 11.1.
     glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, 0, vec4Size);
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_GL_NO_ERROR();
     EXPECT_PIXEL_EQ(px, py, 10, 20, 30, 40);
 
@@ -156,7 +147,7 @@
     // (256 bytes) hence it will try to map the range [stride, 2 * stride] which is out-of-bound of
     // the buffer bufferSize = stride + vec4Size < 2 * stride. Ensure that this behaviour works.
     glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, stride, vec4Size);
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_GL_NO_ERROR();
     EXPECT_PIXEL_EQ(px, py, 110, 120, 130, 140);
 }
@@ -187,7 +178,7 @@
     // Try to bind the buffer to binding point 2
     glUniformBlockBinding(mProgram, mUniformBufferIndex, 2);
     glBindBufferBase(GL_UNIFORM_BUFFER, 2, mUniformBuffer);
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_GL_NO_ERROR();
     EXPECT_PIXEL_EQ(px, py, 10, 20, 30, 40);
 
@@ -199,7 +190,7 @@
     // Try to bind the buffer to another binding point
     glUniformBlockBinding(mProgram, mUniformBufferIndex, 5);
     glBindBufferBase(GL_UNIFORM_BUFFER, 5, mUniformBuffer);
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_GL_NO_ERROR();
     EXPECT_PIXEL_EQ(px, py, 10, 20, 30, 40);
 }
@@ -213,7 +204,7 @@
     glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0);
     EXPECT_GL_NO_ERROR();
 
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
 }
 
@@ -248,7 +239,7 @@
 
         glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(data), data);
 
-        drawQuad(mProgram, "position", 0.5f);
+        drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
         EXPECT_GL_NO_ERROR();
         EXPECT_PIXEL_EQ(px, py, i + 10, i + 20, i + 30, i + 40);
     }
@@ -306,7 +297,7 @@
     for (size_t i = 0; i < 8; ++i)
     {
         glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, i * stride, stride);
-        drawQuad(mProgram, "position", 0.5f);
+        drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
         EXPECT_GL_NO_ERROR();
         EXPECT_PIXEL_EQ(px, py, 10 + i, 20 + i, 30 + i, 40 + i);
     }
@@ -315,7 +306,7 @@
     for (size_t i = 0; i < 7; ++i)
     {
         glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, i * stride, 2 * stride);
-        drawQuad(mProgram, "position", 0.5f);
+        drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
         EXPECT_GL_NO_ERROR();
         EXPECT_PIXEL_EQ(px, py, 10 + i, 20 + i, 30 + i, 40 + i);
     }
@@ -324,7 +315,7 @@
     for (size_t i = 0; i < 5; ++i)
     {
         glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, i * stride, 4 * stride);
-        drawQuad(mProgram, "position", 0.5f);
+        drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
         EXPECT_GL_NO_ERROR();
         EXPECT_PIXEL_EQ(px, py, 10 + i, 20 + i, 30 + i, 40 + i);
     }
@@ -579,7 +570,7 @@
     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
 
     glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
 
     ASSERT_GL_NO_ERROR();
     EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
@@ -612,7 +603,7 @@
     // Draw with the buffer.
     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
     glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
-    drawQuad(mProgram, "position", 0.5f);
+    drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
 
     ASSERT_GL_NO_ERROR();
     EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
@@ -732,13 +723,6 @@
 // Test uniform blocks used as instanced array take next binding point for each subsequent element.
 TEST_P(UniformBufferTest31, ConsecutiveBindingsForBlockArray)
 {
-    const std::string &vertexShaderSource =
-        "#version 310 es\n"
-        "in vec4 position;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = position;\n"
-        "}";
     const std::string &fragmentShaderSource =
         "#version 310 es\n"
         "precision highp float;\n"
@@ -751,7 +735,7 @@
         "    fragColor = blocks[0].color + blocks[1].color;\n"
         "}";
 
-    ANGLE_GL_PROGRAM(program, vertexShaderSource, fragmentShaderSource);
+    ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), fragmentShaderSource);
     std::array<GLBuffer, 2> uniformBuffers;
 
     int px = getWindowWidth() / 2;
@@ -779,7 +763,7 @@
     EXPECT_GL_NO_ERROR();
     glBindBufferBase(GL_UNIFORM_BUFFER, 3, uniformBuffers[1].get());
 
-    drawQuad(program, "position", 0.5f);
+    drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
     EXPECT_GL_NO_ERROR();
     EXPECT_PIXEL_EQ(px, py, 20, 40, 60, 80);
 }
@@ -840,7 +824,7 @@
         "    my_FragColor = lighting;\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mVertexShaderSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "lightData");
 
     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
@@ -858,7 +842,7 @@
 
     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
     glUniformBlockBinding(program, uniformBufferIndex, 0);
-    drawQuad(program.get(), "position", 0.5f);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -889,7 +873,7 @@
             my_FragColor = lighting;
         })";
 
-    ANGLE_GL_PROGRAM(program, mVertexShaderSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
     GLint uniformBufferIndex  = glGetUniformBlockIndex(program, "lightData[0]");
     GLint uniformBuffer2Index = glGetUniformBlockIndex(program, "lightData[1]");
 
@@ -918,7 +902,7 @@
     glBindBufferBase(GL_UNIFORM_BUFFER, 1, uniformBuffer2);
     glUniformBlockBinding(program, uniformBufferIndex, 0);
     glUniformBlockBinding(program, uniformBuffer2Index, 1);
-    drawQuad(program.get(), "position", 0.5f);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -947,7 +931,7 @@
             my_FragColor = lighting;
         })";
 
-    ANGLE_GL_PROGRAM(program, mVertexShaderSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "lightData");
 
     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
@@ -966,7 +950,7 @@
     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
     glUniformBlockBinding(program, uniformBufferIndex, 0);
-    drawQuad(program.get(), "position", 0.5f);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -999,7 +983,7 @@
         "    my_FragColor = lighting;\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mVertexShaderSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "lightData");
 
     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
@@ -1015,7 +999,7 @@
     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
     glUniformBlockBinding(program, uniformBufferIndex, 0);
-    drawQuad(program.get(), "position", 0.5f);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -1040,7 +1024,7 @@
         "    my_FragColor = color;\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mVertexShaderSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
 
     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
@@ -1056,7 +1040,7 @@
     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
     glUniformBlockBinding(program, uniformBufferIndex, 0);
-    drawQuad(program.get(), "position", 0.5f);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -1073,7 +1057,7 @@
         "    my_FragColor = buffer.color;\n"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, mVertexShaderSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "dmat2");
 
     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
@@ -1089,7 +1073,7 @@
     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
     glUniformBlockBinding(program, uniformBufferIndex, 0);
-    drawQuad(program.get(), "position", 0.5f);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -1130,7 +1114,7 @@
             accessStruct(buffer.s);
         })";
 
-    ANGLE_GL_PROGRAM(program, mVertexShaderSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "structBuffer");
 
     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
@@ -1148,7 +1132,7 @@
     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
     glUniformBlockBinding(program, uniformBufferIndex, 0);
-    drawQuad(program.get(), "position", 0.5f);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
@@ -1156,7 +1140,7 @@
 // This covers a bug in ANGLE's D3D back-end.
 TEST_P(UniformBufferTest, DetachShaders)
 {
-    GLuint vertexShader = CompileShader(GL_VERTEX_SHADER, mVertexShaderSource);
+    GLuint vertexShader = CompileShader(GL_VERTEX_SHADER, essl3_shaders::vs::Simple());
     ASSERT_NE(0u, vertexShader);
     GLuint fragmentShader = CompileShader(GL_FRAGMENT_SHADER, mFragmentShaderSource);
     ASSERT_NE(0u, fragmentShader);
@@ -1184,7 +1168,7 @@
     ASSERT_NE(uniformBufferIndex, -1);
 
     glUniformBlockBinding(program, uniformBufferIndex, 0);
-    drawQuad(program, "position", 0.5f);
+    drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
 
     ASSERT_GL_NO_ERROR();
     EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
@@ -1216,7 +1200,7 @@
             my_FragColor = vec4(buffer.m);
         })";
 
-    ANGLE_GL_PROGRAM(program, mVertexShaderSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "matrixBuffer");
 
     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
@@ -1234,7 +1218,7 @@
     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
     glUniformBlockBinding(program, uniformBufferIndex, 0);
-    drawQuad(program.get(), "position", 0.5f);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     ASSERT_GL_NO_ERROR();
     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 64, 128, 32), 5);
 }
@@ -1264,7 +1248,7 @@
             my_FragColor = vec4(buffer.m);
         })";
 
-    ANGLE_GL_PROGRAM(program, mVertexShaderSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "matrixBuffer");
 
     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
@@ -1282,7 +1266,7 @@
     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
     glUniformBlockBinding(program, uniformBufferIndex, 0);
-    drawQuad(program.get(), "position", 0.5f);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     ASSERT_GL_NO_ERROR();
     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 64, 128, 32), 5);
 }
@@ -1309,7 +1293,7 @@
             my_FragColor = vec4(buffer.m);
         })";
 
-    ANGLE_GL_PROGRAM(program, mVertexShaderSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "matrixBuffer");
 
     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
@@ -1329,7 +1313,7 @@
     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
     glUniformBlockBinding(program, uniformBufferIndex, 0);
-    drawQuad(program.get(), "position", 0.5f);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     ASSERT_GL_NO_ERROR();
     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 192, 128, 96), 5);
 }
@@ -1363,7 +1347,7 @@
             my_FragColor = vec4(buffer.s.m);
         })";
 
-    ANGLE_GL_PROGRAM(program, mVertexShaderSource, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader);
     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "matrixBuffer");
 
     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
@@ -1381,18 +1365,11 @@
     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
     glUniformBlockBinding(program, uniformBufferIndex, 0);
-    drawQuad(program.get(), "position", 0.5f);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
     ASSERT_GL_NO_ERROR();
     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 64, 128, 32), 5);
 }
 
-constexpr char kVertexShader[] = R"(#version 300 es
-in vec4 a_vertex;
-void main()
-{
-  gl_Position = a_vertex;
-})";
-
 constexpr char kFragmentShader[] = R"(#version 300 es
 precision mediump float;
 
@@ -1413,9 +1390,9 @@
     // http://anglebug.com/2287
     ANGLE_SKIP_TEST_IF(IsOSX() && IsNVIDIA() && IsDesktopOpenGL());
 
-    ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFragmentShader);
 
-    glBindAttribLocation(program, 0, "a_vertex");
+    glBindAttribLocation(program, 0, essl3_shaders::PositionAttrib());
     glUseProgram(program);
     GLint uboIndex = glGetUniformBlockIndex(program, "color_ubo");
 
@@ -1458,9 +1435,9 @@
 // Regression test for a dirty bit bug in ANGLE. Same as above but for the indexed bindings.
 TEST_P(UniformBufferTest, SimpleBufferChange)
 {
-    ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFragmentShader);
 
-    glBindAttribLocation(program, 0, "a_vertex");
+    glBindAttribLocation(program, 0, essl3_shaders::PositionAttrib());
     glUseProgram(program);
     GLint uboIndex = glGetUniformBlockIndex(program, "color_ubo");
 
@@ -1502,9 +1479,9 @@
 // update in the State Manager class.
 TEST_P(UniformBufferTest, DependentBufferChange)
 {
-    ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFragmentShader);
 
-    glBindAttribLocation(program, 0, "a_vertex");
+    glBindAttribLocation(program, 0, essl3_shaders::PositionAttrib());
     glUseProgram(program);
     GLint uboIndex = glGetUniformBlockIndex(program, "color_ubo");
 
diff --git a/src/tests/gl_tests/UniformTest.cpp b/src/tests/gl_tests/UniformTest.cpp
index df94a79..c8247aa 100644
--- a/src/tests/gl_tests/UniformTest.cpp
+++ b/src/tests/gl_tests/UniformTest.cpp
@@ -14,10 +14,6 @@
 
 namespace
 {
-constexpr char kBasicVertexShader[] = R"(void main()
-{
-    gl_Position = vec4(1);
-})";
 
 class SimpleUniformTest : public ANGLETest
 {
@@ -42,7 +38,7 @@
     gl_FragColor = vec4(uniF, 0.0, 0.0, 0.0);
 })";
 
-    ANGLE_GL_PROGRAM(program, kBasicVertexShader, kFragShader);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
     glUseProgram(program);
     GLint uniformLocation = glGetUniformLocation(program, "uniF");
     ASSERT_NE(uniformLocation, -1);
@@ -64,7 +60,7 @@
     gl_FragColor = vec4(uniI, 0.0, 0.0, 0.0);
 })";
 
-    ANGLE_GL_PROGRAM(program, kBasicVertexShader, kFragShader);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
     glUseProgram(program);
 
     GLint uniformLocation = glGetUniformLocation(program, "uniI");
@@ -88,7 +84,7 @@
     gl_FragColor = vec4(uniVec2, 0.0, 0.0);
 })";
 
-    ANGLE_GL_PROGRAM(program, kBasicVertexShader, kFragShader);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
     glUseProgram(program);
 
     GLint uniformLocation = glGetUniformLocation(program, "uniVec2");
@@ -112,7 +108,7 @@
     gl_FragColor = vec4(uniVec3, 0.0);
 })";
 
-    ANGLE_GL_PROGRAM(program, kBasicVertexShader, kFragShader);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
     glUseProgram(program);
 
     GLint uniformLocation = glGetUniformLocation(program, "uniVec3");
@@ -136,7 +132,7 @@
     gl_FragColor = uniVec4;
 })";
 
-    ANGLE_GL_PROGRAM(program, kBasicVertexShader, kFragShader);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
     glUseProgram(program);
 
     GLint uniformLocation = glGetUniformLocation(program, "uniVec4");
@@ -160,7 +156,7 @@
     gl_FragColor = vec4(umat2);
 })";
 
-    ANGLE_GL_PROGRAM(program, kBasicVertexShader, kFragShader);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
     glUseProgram(program);
 
     GLint uniformLocation = glGetUniformLocation(program, "umat2");
@@ -184,7 +180,7 @@
     gl_FragColor = vec4(umat3);
 })";
 
-    ANGLE_GL_PROGRAM(program, kBasicVertexShader, kFragShader);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
     glUseProgram(program);
 
     GLint uniformLocation = glGetUniformLocation(program, "umat3");
@@ -208,7 +204,7 @@
     gl_FragColor = umat4 * vec4(1.0, 1.0, 1.0, 1.0);
 })";
 
-    ANGLE_GL_PROGRAM(program, kBasicVertexShader, kFragShader);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
     glUseProgram(program);
 
     GLint uniformLocation = glGetUniformLocation(program, "umat4");
@@ -234,7 +230,7 @@
     gl_FragColor = vec4(ufloats[0], ufloats[1], ufloats[2], ufloats[3]);
 })";
 
-    ANGLE_GL_PROGRAM(program, kBasicVertexShader, kFragShader);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
     glUseProgram(program);
     std::vector<GLfloat> expected = {{0.1f, 0.2f, 0.3f, 0.4f}};
 
@@ -263,7 +259,7 @@
     gl_FragColor = vec4(uints[0], uints[1], uints[2], uints[3]);
 })";
 
-    ANGLE_GL_PROGRAM(program, kBasicVertexShader, kFragShader);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
     glUseProgram(program);
     std::vector<GLint> expected = {{1, 2, 3, 4}};
 
@@ -674,9 +670,6 @@
 // Test queries for transposed arrays of non-square matrix uniforms.
 TEST_P(UniformTestES3, TransposedMatrixArrayUniformStateQuery)
 {
-    const std::string &vertexShader =
-        "#version 300 es\n"
-        "void main() { gl_Position = vec4(1); }";
     const std::string &fragShader =
         "#version 300 es\n"
         "precision mediump float;\n"
@@ -690,7 +683,7 @@
         "  color += vec4(uniMat3x2[4][0][0]);\n"
         "}";
 
-    mProgram = CompileProgram(vertexShader, fragShader);
+    mProgram = CompileProgram(essl3_shaders::vs::Zero(), fragShader);
     ASSERT_NE(mProgram, 0u);
 
     glUseProgram(mProgram);
@@ -736,9 +729,6 @@
 // Check that trying setting too many elements of an array doesn't overflow
 TEST_P(UniformTestES3, OverflowArray)
 {
-    const std::string &vertexShader =
-        "#version 300 es\n"
-        "void main() { gl_Position = vec4(1); }";
     const std::string &fragShader =
         "#version 300 es\n"
         "precision mediump float;\n"
@@ -753,7 +743,7 @@
         "  color = vec4(uniMat3x2[4][0][0] + uniF[4]);\n"
         "}";
 
-    mProgram = CompileProgram(vertexShader, fragShader);
+    mProgram = CompileProgram(essl3_shaders::vs::Zero(), fragShader);
     ASSERT_NE(mProgram, 0u);
 
     glUseProgram(mProgram);
@@ -1049,13 +1039,6 @@
 // ESSL 3.10.4 section 4.4.3.
 TEST_P(UniformTestES31, StructLocationLayoutQualifier)
 {
-    const std::string &vertShader =
-        "#version 310 es\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = vec4(0);\n"
-        "}";
-
     const std::string &fragShader =
         "#version 310 es\n"
         "out highp vec4 my_FragColor;\n"
@@ -1070,7 +1053,7 @@
         "    my_FragColor = vec4(uS.f, uS.f2, 0, 1);\n"
         "}";
 
-    ANGLE_GL_PROGRAM(program, vertShader, fragShader);
+    ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Zero(), fragShader);
 
     EXPECT_EQ(12, glGetUniformLocation(program.get(), "uS.f"));
     EXPECT_EQ(13, glGetUniformLocation(program.get(), "uS.f2"));
@@ -1160,15 +1143,6 @@
 // Minimal test case for a bug revealed by dEQP tests.
 TEST_P(UniformTestES3, StructWithNonSquareMatrixAndBool)
 {
-    const std::string &vertShader =
-        "#version 300 es\n"
-        "precision highp float;\n"
-        "in highp vec4 a_position;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = a_position;\n"
-        "}\n";
-
     const std::string &fragShader =
         "#version 300 es\n"
         "precision highp float;\n"
@@ -1185,7 +1159,7 @@
         "    if (!uni.b) { my_color.g = 0.0; }"
         "}\n";
 
-    ANGLE_GL_PROGRAM(program, vertShader, fragShader);
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragShader);
 
     glUseProgram(program.get());
 
@@ -1193,7 +1167,7 @@
     ASSERT_NE(-1, location);
     glUniform1i(location, 1);
 
-    drawQuad(program.get(), "a_position", 0.0f);
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.0f);
 
     ASSERT_GL_NO_ERROR();
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
@@ -1202,12 +1176,6 @@
 // Test that uniforms with reserved OpenGL names that aren't reserved in GL ES 2 work correctly.
 TEST_P(UniformTest, UniformWithReservedOpenGLName)
 {
-    const char *vertexShader =
-        "attribute highp vec4 a_position;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = a_position;\n"
-        "}\n";
     const char *fragShader =
         "precision mediump float;\n"
         "uniform float buffer;"
@@ -1215,7 +1183,7 @@
         "    gl_FragColor = vec4(buffer);\n"
         "}";
 
-    mProgram = CompileProgram(vertexShader, fragShader);
+    mProgram = CompileProgram(essl1_shaders::vs::Simple(), fragShader);
     ASSERT_NE(mProgram, 0u);
 
     GLint location = glGetUniformLocation(mProgram, "buffer");
@@ -1224,7 +1192,7 @@
     glUseProgram(mProgram);
     glUniform1f(location, 1.0f);
 
-    drawQuad(mProgram, "a_position", 0.0f);
+    drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.0f);
 
     ASSERT_GL_NO_ERROR();
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
diff --git a/src/tests/gl_tests/UnpackAlignmentTest.cpp b/src/tests/gl_tests/UnpackAlignmentTest.cpp
index 056bfa1..91c2961 100644
--- a/src/tests/gl_tests/UnpackAlignmentTest.cpp
+++ b/src/tests/gl_tests/UnpackAlignmentTest.cpp
@@ -31,15 +31,6 @@
     {
         ANGLETest::SetUp();
 
-        const std::string vertexShaderSource =
-            R"(precision highp float;
-            attribute vec4 position;
-
-            void main()
-            {
-                gl_Position = position;
-            })";
-
         const std::string fragmentShaderSource =
             R"(uniform sampler2D tex;
 
@@ -48,7 +39,7 @@
                 gl_FragColor = texture2D(tex, vec2(0.0, 1.0));
             })";
 
-        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        mProgram = CompileProgram(essl1_shaders::vs::Simple(), fragmentShaderSource);
         if (mProgram == 0)
         {
             FAIL() << "shader compilation failed.";
@@ -127,7 +118,7 @@
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
-        drawQuad(mProgram, "position", 0.5f);
+        drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
 
         GLubyte expectedRGB = formatHasRGB(format) ? 255 : 0;
         EXPECT_PIXEL_EQ(0, 0, expectedRGB, expectedRGB, expectedRGB, 255);
diff --git a/src/tests/gl_tests/UnpackRowLength.cpp b/src/tests/gl_tests/UnpackRowLength.cpp
index bacd70f..7ae81cc 100644
--- a/src/tests/gl_tests/UnpackRowLength.cpp
+++ b/src/tests/gl_tests/UnpackRowLength.cpp
@@ -31,15 +31,6 @@
     {
         ANGLETest::SetUp();
 
-        const std::string vertexShaderSource =
-            R"(precision highp float;
-            attribute vec4 position;
-
-            void main()
-            {
-                gl_Position = position;
-            })";
-
         const std::string fragmentShaderSource =
             R"(uniform sampler2D tex;
 
@@ -48,7 +39,7 @@
                 gl_FragColor = texture2D(tex, vec2(0.0, 1.0));
             })";
 
-        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
+        mProgram = CompileProgram(essl1_shaders::vs::Simple(), fragmentShaderSource);
         if (mProgram == 0)
         {
             FAIL() << "shader compilation failed.";
@@ -87,7 +78,7 @@
             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
-            drawQuad(mProgram, "position", 0.5f);
+            drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
 
             EXPECT_PIXEL_EQ(0, 0, 255, 255, 255, 255);
             EXPECT_PIXEL_EQ(1, 0, 255, 255, 255, 255);
diff --git a/src/tests/gl_tests/ViewportTest.cpp b/src/tests/gl_tests/ViewportTest.cpp
index 7e8da21..ce19d57 100644
--- a/src/tests/gl_tests/ViewportTest.cpp
+++ b/src/tests/gl_tests/ViewportTest.cpp
@@ -59,7 +59,7 @@
         glClear(GL_COLOR_BUFFER_BIT);
 
         // Draw a red quad centered in the middle of the viewport, with dimensions 25% of the size of the viewport.
-        drawQuad(mProgram, "position", 0.5f, 0.25f);
+        drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f, 0.25f);
 
         GLint centerViewportX = viewportSize[0] + (viewportSize[2] / 2);
         GLint centerViewportY = viewportSize[1] + (viewportSize[3] / 2);
@@ -122,21 +122,7 @@
     {
         ANGLETest::SetUp();
 
-        const std::string testVertexShaderSource =
-            R"(attribute highp vec4 position;
-
-            void main(void)
-            {
-                gl_Position = position;
-            })";
-
-        const std::string testFragmentShaderSource =
-            R"(void main(void)
-            {
-                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
-            })";
-
-        mProgram = CompileProgram(testVertexShaderSource, testFragmentShaderSource);
+        mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
         if (mProgram == 0)
         {
             FAIL() << "shader compilation failed.";
diff --git a/src/tests/gl_tests/VulkanUniformUpdatesTest.cpp b/src/tests/gl_tests/VulkanUniformUpdatesTest.cpp
index 854ac37..a4e0003 100644
--- a/src/tests/gl_tests/VulkanUniformUpdatesTest.cpp
+++ b/src/tests/gl_tests/VulkanUniformUpdatesTest.cpp
@@ -28,39 +28,39 @@
 
 class VulkanUniformUpdatesTest : public ANGLETest
 {
+  protected:
+    rx::ContextVk *hackANGLE()
+    {
+        // Hack the angle!
+        const gl::Context *context = reinterpret_cast<gl::Context *>(getEGLWindow()->getContext());
+        return rx::GetImplAs<rx::ContextVk>(context);
+    }
 };
 
 // This test updates a uniform until a new buffer is allocated and then make sure the uniform
 // updates still work.
-TEST_P(VulkanUniformUpdatesTest, UpdateUniformUntilNewBufferIsAllocated)
+TEST_P(VulkanUniformUpdatesTest, UpdateUntilNewBufferIsAllocated)
 {
     ASSERT_TRUE(IsVulkan());
 
-    constexpr char kPositionUniformVertexShader[] = R"(
-precision mediump float;
-attribute vec2 position;
+    constexpr char kPositionUniformVertexShader[] = R"(attribute vec2 position;
 uniform vec2 uniPosModifier;
 void main()
 {
     gl_Position = vec4(position + uniPosModifier, 0, 1);
 })";
 
-    constexpr char kColorUniformFragmentShader[] = R"(
-precision mediump float;
+    constexpr char kColorUniformFragmentShader[] = R"(precision mediump float;
 uniform vec4 uniColor;
 void main()
 {
     gl_FragColor = uniColor;
 })";
 
-    // Hack the angle!
-    const gl::Context *context = reinterpret_cast<gl::Context *>(getEGLWindow()->getContext());
-    auto *contextVk            = rx::GetImplAs<rx::ContextVk>(context);
-
     ANGLE_GL_PROGRAM(program, kPositionUniformVertexShader, kColorUniformFragmentShader);
     glUseProgram(program);
 
-    const gl::State &state   = contextVk->getGLState();
+    const gl::State &state   = hackANGLE()->getGLState();
     rx::ProgramVk *programVk = rx::vk::GetImpl(state.getProgram());
 
     // Set a really small min size so that uniform updates often allocates a new buffer.
@@ -83,6 +83,43 @@
     }
 }
 
+// Force uniform updates until the dynamic descriptor pool wraps into a new pool allocation.
+TEST_P(VulkanUniformUpdatesTest, DescriptorPoolUpdates)
+{
+    ASSERT_TRUE(IsVulkan());
+
+    // Force a small limit on the max sets per pool to more easily trigger a new allocation.
+    constexpr uint32_t kMaxSetsForTesting                = 32;
+    rx::vk::DynamicDescriptorPool *dynamicDescriptorPool = hackANGLE()->getDynamicDescriptorPool();
+    dynamicDescriptorPool->setMaxSetsPerPoolForTesting(kMaxSetsForTesting);
+
+    // Initialize texture program.
+    GLuint program = get2DTexturedQuadProgram();
+    ASSERT_NE(0u, program);
+    glUseProgram(program);
+
+    GLint texLoc = glGetUniformLocation(program, "tex");
+    ASSERT_NE(-1, texLoc);
+
+    // Initialize basic red texture.
+    const std::vector<GLColor> redColors(4, GLColor::red);
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redColors.data());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    ASSERT_GL_NO_ERROR();
+
+    // Draw multiple times, each iteration will create a new descriptor set.
+    for (uint32_t iteration = 0; iteration < kMaxSetsForTesting * 8; ++iteration)
+    {
+        glUniform1i(texLoc, 0);
+        drawQuad(program, "position", 0.5f, 1.0f, true);
+        swapBuffers();
+        ASSERT_GL_NO_ERROR();
+    }
+}
+
 ANGLE_INSTANTIATE_TEST(VulkanUniformUpdatesTest, ES2_VULKAN());
 
 }  // anonymous namespace
diff --git a/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
index 7d5e374..3249c4b 100644
--- a/src/tests/gl_tests/WebGLCompatibilityTest.cpp
+++ b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
@@ -200,27 +200,14 @@
 
         ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
 
-        const std::string renderingVs =
-            "attribute vec4 position;\n"
-            "void main()\n"
-            "{\n"
-            "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
-            "}\n";
-
-        const std::string renderingFs =
-            "precision mediump float;\n"
-            "uniform vec4 writeValue;\n"
-            "void main()\n"
-            "{\n"
-            "   gl_FragColor = writeValue;\n"
-            "}\n";
-
-        ANGLE_GL_PROGRAM(renderingProgram, renderingVs, renderingFs);
+        ANGLE_GL_PROGRAM(renderingProgram, essl1_shaders::vs::Simple(),
+                         essl1_shaders::fs::UniformColor());
         glUseProgram(renderingProgram.get());
 
-        glUniform4fv(glGetUniformLocation(renderingProgram.get(), "writeValue"), 1, floatData);
+        glUniform4fv(glGetUniformLocation(renderingProgram.get(), essl1_shaders::ColorUniform()), 1,
+                     floatData);
 
-        drawQuad(renderingProgram.get(), "position", 0.5f, 1.0f, true);
+        drawQuad(renderingProgram.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
 
         EXPECT_PIXEL_COLOR32F_NEAR(
             0, 0, GLColor32F(floatData[0], floatData[1], floatData[2], floatData[3]), 1.0f);
@@ -440,6 +427,74 @@
     }
 }
 
+// Test enabling the EGL image extensions
+TEST_P(WebGLCompatibilityTest, EnableExtensionEGLImage)
+{
+    EXPECT_FALSE(extensionEnabled("GL_OES_EGL_image"));
+    EXPECT_FALSE(extensionEnabled("GL_OES_EGL_image_external"));
+    EXPECT_FALSE(extensionEnabled("GL_OES_EGL_image_external_essl3"));
+    EXPECT_FALSE(extensionEnabled("NV_EGL_stream_consumer_external"));
+
+    const std::string &fragES2 =
+        "#extension GL_OES_EGL_image_external : require\n"
+        "precision highp float;\n"
+        "uniform samplerExternalOES sampler;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = texture2D(sampler, vec2(0, 0));\n"
+        "}";
+    EXPECT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, fragES2));
+
+    const std::string &fragES3 =
+        "#version 300 es\n"
+        "#extension GL_OES_EGL_image_external : require\n"
+        "precision highp float;\n"
+        "uniform samplerExternalOES sampler;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = texture(sampler, vec2(0, 0));\n"
+        "}";
+    if (getClientMajorVersion() > 3)
+    {
+        EXPECT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, fragES3));
+    }
+
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    GLint result;
+    glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &result);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    if (extensionRequestable("GL_OES_EGL_image_external"))
+    {
+        glRequestExtensionANGLE("GL_OES_EGL_image_external");
+        EXPECT_GL_NO_ERROR();
+        EXPECT_TRUE(extensionEnabled("GL_OES_EGL_image_external"));
+
+        EXPECT_NE(0u, CompileShader(GL_FRAGMENT_SHADER, fragES2));
+
+        glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
+        EXPECT_GL_NO_ERROR();
+
+        glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &result);
+        EXPECT_GL_NO_ERROR();
+
+        if (getClientMajorVersion() > 3 && extensionRequestable("GL_OES_EGL_image_external_essl3"))
+        {
+            glRequestExtensionANGLE("GL_OES_EGL_image_external_essl3");
+            EXPECT_GL_NO_ERROR();
+            EXPECT_TRUE(extensionEnabled("GL_OES_EGL_image_external_essl3"));
+
+            EXPECT_NE(0u, CompileShader(GL_FRAGMENT_SHADER, fragES3));
+        }
+        else
+        {
+            EXPECT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, fragES3));
+        }
+    }
+}
+
 // Verify that shaders are of a compatible spec when the extension is enabled.
 TEST_P(WebGLCompatibilityTest, ExtensionCompilerSpec)
 {
@@ -495,6 +550,47 @@
     }
 }
 
+// Test enabling the GL_EXT_texture_storage extension
+TEST_P(WebGLCompatibilityTest, EnableTextureStorage)
+{
+    EXPECT_FALSE(extensionEnabled("GL_EXT_texture_storage"));
+
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_2D, texture);
+
+    GLint result;
+    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_IMMUTABLE_FORMAT, &result);
+    if (getClientMajorVersion() >= 3)
+    {
+        EXPECT_GL_NO_ERROR();
+    }
+    else
+    {
+        EXPECT_GL_ERROR(GL_INVALID_ENUM);
+    }
+
+    if (extensionRequestable("GL_EXT_texture_storage"))
+    {
+        glRequestExtensionANGLE("GL_EXT_texture_storage");
+        EXPECT_GL_NO_ERROR();
+        EXPECT_TRUE(extensionEnabled("GL_EXT_texture_storage"));
+
+        glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_IMMUTABLE_FORMAT, &result);
+        EXPECT_GL_NO_ERROR();
+
+        const GLenum alwaysAcceptableFormats[] = {
+            GL_ALPHA8_EXT, GL_LUMINANCE8_EXT, GL_LUMINANCE8_ALPHA8_EXT,
+        };
+        for (const auto &acceptableFormat : alwaysAcceptableFormats)
+        {
+            GLTexture localTexture;
+            glBindTexture(GL_TEXTURE_2D, localTexture);
+            glTexStorage2DEXT(GL_TEXTURE_2D, 1, acceptableFormat, 1, 1);
+            EXPECT_GL_NO_ERROR();
+        }
+    }
+}
+
 // Test enabling the GL_OES_mapbuffer and GL_EXT_map_buffer_range extensions
 TEST_P(WebGLCompatibilityTest, EnableMapBufferExtensions)
 {
@@ -989,6 +1085,41 @@
     }
 }
 
+// Test enabling the GL_OES_vertex_array_object extension
+TEST_P(WebGLCompatibilityTest, EnableVertexArrayExtension)
+{
+    EXPECT_FALSE(extensionEnabled("GL_OES_vertex_array_object"));
+
+    // This extensions become core in in ES3/WebGL2.
+    ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
+
+    GLint result = 0;
+    glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &result);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+    // Expect that GL_OES_vertex_array_object is always available.  It is implemented in the GL
+    // frontend.
+    EXPECT_TRUE(extensionRequestable("GL_OES_vertex_array_object"));
+
+    glRequestExtensionANGLE("GL_OES_vertex_array_object");
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_TRUE(extensionEnabled("GL_OES_vertex_array_object"));
+
+    glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &result);
+    EXPECT_GL_NO_ERROR();
+
+    GLuint vao = 0;
+    glGenVertexArraysOES(0, &vao);
+    EXPECT_GL_NO_ERROR();
+
+    glBindVertexArrayOES(vao);
+    EXPECT_GL_NO_ERROR();
+
+    glDeleteVertexArraysOES(1, &vao);
+    EXPECT_GL_NO_ERROR();
+}
+
 // Verify that the context generates the correct error when the framebuffer attachments are
 // different sizes
 TEST_P(WebGLCompatibilityTest, FramebufferAttachmentSizeMismatch)
@@ -1294,14 +1425,7 @@
         "    gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
         "}\n";
 
-    const std::string &frag =
-        "precision highp float;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_FragColor = vec4(1.0);\n"
-        "}\n";
-
-    ANGLE_GL_PROGRAM(program, vert, frag);
+    ANGLE_GL_PROGRAM(program, vert, essl1_shaders::fs::Red());
     GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
     ASSERT_NE(-1, posLocation);
     glUseProgram(program.get());
@@ -1357,14 +1481,7 @@
         "    gl_Position = vec4(a_pos, a_pos, a_pos, a_w);\n"
         "}\n";
 
-    const std::string &frag =
-        "precision highp float;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_FragColor = vec4(1.0);\n"
-        "}\n";
-
-    ANGLE_GL_PROGRAM(program, vert, frag);
+    ANGLE_GL_PROGRAM(program, vert, essl1_shaders::fs::Red());
     GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
     GLint wLocation = glGetAttribLocation(program.get(), "a_w");
     ASSERT_NE(-1, posLocation);
@@ -1430,14 +1547,7 @@
         "    gl_Position = vec4(a_pos, a_pos, a_pos, a_w);\n"
         "}\n";
 
-    const std::string &frag =
-        "precision highp float;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_FragColor = vec4(1.0);\n"
-        "}\n";
-
-    ANGLE_GL_PROGRAM(program, vert, frag);
+    ANGLE_GL_PROGRAM(program, vert, essl1_shaders::fs::Red());
     GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
     GLint wLocation = glGetAttribLocation(program.get(), "a_w");
     ASSERT_NE(-1, posLocation);
@@ -1498,14 +1608,7 @@
         "    gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
         "}\n";
 
-    const std::string &frag =
-        "precision highp float;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_FragColor = vec4(1.0);\n"
-        "}\n";
-
-    ANGLE_GL_PROGRAM(program, vert, frag);
+    ANGLE_GL_PROGRAM(program, vert, essl1_shaders::fs::Red());
     GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
     ASSERT_NE(-1, posLocation);
     glUseProgram(program.get());
@@ -1558,14 +1661,7 @@
         "    gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
         "}\n";
 
-    const std::string &frag =
-        "precision highp float;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_FragColor = vec4(1.0);\n"
-        "}\n";
-
-    ANGLE_GL_PROGRAM(program, vert, frag);
+    ANGLE_GL_PROGRAM(program, vert, essl1_shaders::fs::Red());
     GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
     ASSERT_NE(-1, posLocation);
     glUseProgram(program.get());
@@ -1829,14 +1925,7 @@
         "    gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
         "}\n";
 
-    const std::string &frag =
-        "precision highp float;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_FragColor = vec4(1.0);\n"
-        "}\n";
-
-    ANGLE_GL_PROGRAM(program, vert, frag);
+    ANGLE_GL_PROGRAM(program, vert, essl1_shaders::fs::Red());
 
     GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
     ASSERT_NE(-1, posLocation);
@@ -2056,14 +2145,7 @@
         "    gl_Position = vec4(a_pos, 1.0);\n"
         "}\n";
 
-    const std::string &frag =
-        "precision highp float;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_FragColor = vec4(1.0);\n"
-        "}\n";
-
-    ANGLE_GL_PROGRAM(program, vert, frag);
+    ANGLE_GL_PROGRAM(program, vert, essl1_shaders::fs::Red());
 
     GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
     ASSERT_NE(-1, posLocation);
@@ -3640,20 +3722,6 @@
 
     ASSERT_GL_NO_ERROR();
 
-    const char *vertESSL1 =
-        "attribute vec4 a_pos;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = a_pos;\n"
-        "}\n";
-    const char *vertESSL3 =
-        "#version 300 es\n"
-        "in vec4 a_pos;\n"
-        "void main()\n"
-        "{\n"
-        "    gl_Position = a_pos;\n"
-        "}\n";
-
     GLenum allDrawBuffers[] = {
         GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3,
     };
@@ -3669,14 +3737,14 @@
         "{\n"
         "    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
         "}\n";
-    ANGLE_GL_PROGRAM(programESSL1, vertESSL1, fragESSL1);
+    ANGLE_GL_PROGRAM(programESSL1, essl1_shaders::vs::Simple(), fragESSL1);
 
     {
         ClearEverythingToRed(renderbuffers);
 
         glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
         DrawBuffers(useEXT, 4, allDrawBuffers);
-        drawQuad(programESSL1, "a_pos", 0.5, 1.0, true);
+        drawQuad(programESSL1, essl1_shaders::PositionAttrib(), 0.5, 1.0, true);
         ASSERT_GL_NO_ERROR();
 
         CheckColors(renderbuffers, 0b0001, GLColor::green);
@@ -3690,7 +3758,7 @@
 
         glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
         DrawBuffers(useEXT, 4, halfDrawBuffers);
-        drawQuad(programESSL1, "a_pos", 0.5, 1.0, true);
+        drawQuad(programESSL1, essl1_shaders::PositionAttrib(), 0.5, 1.0, true);
         ASSERT_GL_NO_ERROR();
 
         CheckColors(renderbuffers, 0b1111, GLColor::red);
@@ -3701,6 +3769,7 @@
     // array of size MAX_DRAW_BUFFERS, so the WebGL spec stipulates that elements not written to
     // should default to 0. On the contrary, in ES3 outputs are specified one by one, so
     // attachments not declared in the shader should not be written to.
+    const char *positionAttrib;
     const char *writeOddOutputsVert;
     const char *writeOddOutputsFrag;
     GLColor unwrittenColor;
@@ -3708,7 +3777,8 @@
     {
         // In the extension, when an attachment isn't written to, it should get 0's
         unwrittenColor      = GLColor(0, 0, 0, 0);
-        writeOddOutputsVert = vertESSL1;
+        positionAttrib      = essl1_shaders::PositionAttrib();
+        writeOddOutputsVert = essl1_shaders::vs::Simple();
         writeOddOutputsFrag =
             "#extension GL_EXT_draw_buffers : require\n"
             "precision highp float;\n"
@@ -3723,7 +3793,8 @@
         // In ES3 if an attachment isn't declared, it shouldn't get written and should be red
         // because of the preceding clears.
         unwrittenColor      = GLColor::red;
-        writeOddOutputsVert = vertESSL3;
+        positionAttrib      = essl3_shaders::PositionAttrib();
+        writeOddOutputsVert = essl3_shaders::vs::Simple();
         writeOddOutputsFrag =
             "#version 300 es\n"
             "precision highp float;\n"
@@ -3743,7 +3814,7 @@
 
         glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
         DrawBuffers(useEXT, 4, allDrawBuffers);
-        drawQuad(writeOddOutputsProgram, "a_pos", 0.5, 1.0, true);
+        drawQuad(writeOddOutputsProgram, positionAttrib, 0.5, 1.0, true);
         ASSERT_GL_NO_ERROR();
 
         CheckColors(renderbuffers, 0b1010, GLColor::green);
@@ -3757,7 +3828,7 @@
 
         glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
         DrawBuffers(useEXT, 4, halfDrawBuffers);
-        drawQuad(writeOddOutputsProgram, "a_pos", 0.5, 1.0, true);
+        drawQuad(writeOddOutputsProgram, positionAttrib, 0.5, 1.0, true);
         ASSERT_GL_NO_ERROR();
 
         CheckColors(renderbuffers, 0b1000, GLColor::green);
@@ -4044,21 +4115,13 @@
         "    ivec2 xy = ivec2(gl_VertexID % 2, (gl_VertexID / 2 + gl_VertexID / 3) % 2);\n"
         "    gl_Position = vec4(vec2(xy) * 2. - 1., 0, 1);\n"
         "}";
-    const std::string fragmentShader =
-        "#version 300 es\n"
-        "precision mediump float;\n"
-        "out vec4 result;\n"
-        "void main()\n"
-        "{\n"
-        "    result = vec4(0, 1, 0, 1);\n"
-        "}";
 
-    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+    ANGLE_GL_PROGRAM(program, vertexShader, essl3_shaders::fs::Red());
     glUseProgram(program);
 
     glDrawArrays(GL_TRIANGLES, 0, 6);
     ASSERT_GL_NO_ERROR();
-    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
 }
 
 // Tests bindAttribLocations for length limit
@@ -4072,6 +4135,23 @@
     EXPECT_GL_ERROR(GL_INVALID_VALUE);
 }
 
+// Covers a bug in transform feedback loop detection.
+TEST_P(WebGL2CompatibilityTest, TransformFeedbackCheckNullDeref)
+{
+    constexpr char kVS[] = R"(attribute vec4 color; void main() { color.r; })";
+    constexpr char kFS[] = R"(void main(){})";
+    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    glUseProgram(program);
+
+    GLBuffer buffer;
+    glBindBuffer(GL_ARRAY_BUFFER, buffer);
+    glEnableVertexAttribArray(0);
+    glDrawArrays(GL_POINTS, 0, 1);
+
+    // This should fail because it is trying to pull one vertex from an empty buffer.
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
 // tests should be run against.
 ANGLE_INSTANTIATE_TEST(WebGLCompatibilityTest,
diff --git a/src/tests/gl_tests/WebGLFramebufferTest.cpp b/src/tests/gl_tests/WebGLFramebufferTest.cpp
index 4a3bce7..657a5a5 100644
--- a/src/tests/gl_tests/WebGLFramebufferTest.cpp
+++ b/src/tests/gl_tests/WebGLFramebufferTest.cpp
@@ -224,30 +224,18 @@
     Vector4 vecColor = color.toNormalizedVector();
     glUseProgram(program);
     glUniform4fv(uniformLoc, 1, vecColor.data());
-    drawQuad(program, "position", 0.5f, 1.0f, true);
+    drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
 }
 
 void WebGLFramebufferTest::testDepthStencilDepthStencil(GLint width, GLint height)
 {
-    const std::string &vertexShader =
-        "attribute vec4 position;\n"
-        "void main() {\n"
-        "    gl_Position = position;\n"
-        "}";
-    const std::string &fragmentShader =
-        "precision mediump float;\n"
-        "uniform vec4 color;\n"
-        "void main() {\n"
-        "    gl_FragColor = color;\n"
-        "}";
-
     if (width == 0 || height == 0)
     {
         return;
     }
 
-    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
-    GLint uniformLoc = glGetUniformLocation(program.get(), "color");
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
+    GLint uniformLoc = glGetUniformLocation(program.get(), essl1_shaders::ColorUniform());
     ASSERT_NE(-1, uniformLoc);
 
     struct TestInfo
@@ -551,7 +539,7 @@
     EXPECT_GL_NO_ERROR();
 
     // drawArrays with incomplete framebuffer
-    drawQuad(program, "position", 0.5f, 1.0f, true);
+    drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
     EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
 
     // readPixels from incomplete framebuffer
@@ -583,11 +571,7 @@
                                                           GLenum depthAttachment)
 {
     // Simple draw program.
-    const std::string &vertexShader =
-        "attribute vec4 position; void main() { gl_Position = position; }";
-    const std::string &fragmentShader = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
-
-    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
 
     GLFramebuffer fbo;
     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
@@ -793,19 +777,17 @@
 void WebGLFramebufferTest::testDrawingMissingAttachment()
 {
     // Simple draw program.
-    const std::string &vertexShader   = "attribute vec4 pos; void main() { gl_Position = pos; }";
-    const std::string &fragmentShader = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
-    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
 
     glClear(GL_COLOR_BUFFER_BIT);
     EXPECT_GL_NO_ERROR();
 
     // try glDrawArrays
-    drawQuad(program, "pos", 0.5f, 1.0f, true);
+    drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
     EXPECT_GL_NO_ERROR();
 
     // try glDrawElements
-    drawIndexedQuad(program, "pos", 0.5f, 1.0f, true);
+    drawIndexedQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
     EXPECT_GL_NO_ERROR();
 }
 
diff --git a/src/tests/gl_tests/gles1/ClientStateEnable.cpp b/src/tests/gl_tests/gles1/ClientStateEnable.cpp
new file mode 100644
index 0000000..6ef1203
--- /dev/null
+++ b/src/tests/gl_tests/gles1/ClientStateEnable.cpp
@@ -0,0 +1,92 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ClientStateEnable.cpp: Tests basic usage of gl(Enable|Disable)ClientState.
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+#include <vector>
+
+using namespace angle;
+
+class ClientStateEnable : public ANGLETest
+{
+  protected:
+    ClientStateEnable()
+    {
+        setWindowWidth(32);
+        setWindowHeight(32);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+    }
+
+    std::vector<GLenum> mClientStates = {
+        GL_VERTEX_ARRAY,         GL_NORMAL_ARRAY,        GL_COLOR_ARRAY,
+        GL_POINT_SIZE_ARRAY_OES, GL_TEXTURE_COORD_ARRAY,
+    };
+};
+
+// Checks that all client vertex array states are disabled to start with.
+TEST_P(ClientStateEnable, InitialState)
+{
+    for (auto clientState : mClientStates)
+    {
+        EXPECT_GL_FALSE(glIsEnabled(clientState));
+        EXPECT_GL_NO_ERROR();
+    }
+}
+
+// Checks that glEnableClientState sets the state to be enabled,
+// and glDisableClientState sets the state to be disabled.
+TEST_P(ClientStateEnable, EnableState)
+{
+    for (auto clientState : mClientStates)
+    {
+        EXPECT_GL_FALSE(glIsEnabled(clientState));
+        glEnableClientState(clientState);
+        EXPECT_GL_NO_ERROR();
+        EXPECT_GL_TRUE(glIsEnabled(clientState));
+        glDisableClientState(clientState);
+        EXPECT_GL_NO_ERROR();
+        EXPECT_GL_FALSE(glIsEnabled(clientState));
+    }
+}
+
+// Negative test: Checks that invalid enums for client state generate the proper GL error.
+TEST_P(ClientStateEnable, Negative)
+{
+    glEnableClientState(0);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+}
+
+// Checks that enable/disable states are different if we are in different client texture unit
+// states.
+TEST_P(ClientStateEnable, TextureUnit)
+{
+    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+    // Spec minimum lets us assume 2 multitexturing units.
+    glClientActiveTexture(GL_TEXTURE1);
+    EXPECT_GL_FALSE(glIsEnabled(GL_TEXTURE_COORD_ARRAY));
+
+    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+    EXPECT_GL_TRUE(glIsEnabled(GL_TEXTURE_COORD_ARRAY));
+
+    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+    EXPECT_GL_FALSE(glIsEnabled(GL_TEXTURE_COORD_ARRAY));
+
+    glClientActiveTexture(GL_TEXTURE0);
+    EXPECT_GL_TRUE(glIsEnabled(GL_TEXTURE_COORD_ARRAY));
+
+    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+    EXPECT_GL_FALSE(glIsEnabled(GL_TEXTURE_COORD_ARRAY));
+}
+
+ANGLE_INSTANTIATE_TEST(ClientStateEnable, ES1_D3D11(), ES1_OPENGL(), ES1_OPENGLES());
diff --git a/src/tests/gl_tests/gles1/MatrixBuiltinsTest.cpp b/src/tests/gl_tests/gles1/MatrixBuiltinsTest.cpp
new file mode 100644
index 0000000..8798431
--- /dev/null
+++ b/src/tests/gl_tests/gles1/MatrixBuiltinsTest.cpp
@@ -0,0 +1,176 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// MatrixBuiltinsTest.cpp: Tests basic usage of builtin matrix operations.
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+#include "common/matrix_utils.h"
+#include "random_utils.h"
+
+#include <stdint.h>
+
+using namespace angle;
+
+class MatrixBuiltinsTest : public ANGLETest
+{
+  protected:
+    MatrixBuiltinsTest()
+    {
+        setWindowWidth(32);
+        setWindowHeight(32);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+    }
+};
+
+// Test rotation and check the matrix for closeness to a rotation matrix.
+TEST_P(MatrixBuiltinsTest, Rotate)
+{
+    constexpr float angle = 90.0f;
+    constexpr float x     = 1.0f;
+    constexpr float y     = 1.0f;
+    constexpr float z     = 1.0f;
+
+    angle::Mat4 testMatrix = angle::Mat4::Rotate(angle, angle::Vector3(x, y, z));
+
+    glRotatef(angle, x, y, z);
+    EXPECT_GL_NO_ERROR();
+
+    angle::Mat4 outputMatrix;
+    glGetFloatv(GL_MODELVIEW_MATRIX, outputMatrix.data());
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_TRUE(testMatrix.nearlyEqual(0.00001f, outputMatrix));
+}
+
+// Test translation and check the matrix for closeness to a translation matrix.
+TEST_P(MatrixBuiltinsTest, Translate)
+{
+    constexpr float x = 1.0f;
+    constexpr float y = 1.0f;
+    constexpr float z = 1.0f;
+
+    angle::Mat4 testMatrix = angle::Mat4::Translate(angle::Vector3(x, y, z));
+
+    glTranslatef(1.0f, 0.0f, 0.0f);
+    glTranslatef(0.0f, 1.0f, 0.0f);
+    glTranslatef(0.0f, 0.0f, 1.0f);
+    EXPECT_GL_NO_ERROR();
+
+    angle::Mat4 outputMatrix;
+    glGetFloatv(GL_MODELVIEW_MATRIX, outputMatrix.data());
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_TRUE(testMatrix.nearlyEqual(0.00001f, outputMatrix));
+}
+
+// Test scale and check the matrix for closeness to a scale matrix.
+TEST_P(MatrixBuiltinsTest, Scale)
+{
+    constexpr float x = 3.0f;
+    constexpr float y = 9.0f;
+    constexpr float z = 27.0f;
+
+    angle::Mat4 testMatrix = angle::Mat4::Scale(angle::Vector3(x, y, z));
+
+    glScalef(3.0f, 3.0f, 3.0f);
+    glScalef(1.0f, 3.0f, 3.0f);
+    glScalef(1.0f, 1.0f, 3.0f);
+    EXPECT_GL_NO_ERROR();
+
+    angle::Mat4 outputMatrix;
+    glGetFloatv(GL_MODELVIEW_MATRIX, outputMatrix.data());
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_TRUE(testMatrix.nearlyEqual(0.00001f, outputMatrix));
+}
+
+// Test frustum projection and check the matrix values.
+TEST_P(MatrixBuiltinsTest, Frustum)
+{
+
+    constexpr float l = -1.0f;
+    constexpr float r = 1.0f;
+    constexpr float b = -1.0f;
+    constexpr float t = 1.0f;
+    constexpr float n = 0.1f;
+    constexpr float f = 1.0f;
+
+    angle::Mat4 testMatrix = angle::Mat4::Frustum(l, r, b, t, n, f);
+
+    glFrustumf(l, r, b, t, n, f);
+    EXPECT_GL_NO_ERROR();
+
+    angle::Mat4 outputMatrix;
+    glGetFloatv(GL_MODELVIEW_MATRIX, outputMatrix.data());
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_TRUE(testMatrix.nearlyEqual(0.00001f, outputMatrix));
+}
+
+// Test orthographic projection and check the matrix values.
+TEST_P(MatrixBuiltinsTest, Ortho)
+{
+    constexpr float l = -1.0f;
+    constexpr float r = 1.0f;
+    constexpr float b = -1.0f;
+    constexpr float t = 1.0f;
+    constexpr float n = 0.1f;
+    constexpr float f = 1.0f;
+
+    angle::Mat4 testMatrix = angle::Mat4::Ortho(l, r, b, t, n, f);
+
+    glOrthof(l, r, b, t, n, f);
+    EXPECT_GL_NO_ERROR();
+
+    angle::Mat4 outputMatrix;
+    glGetFloatv(GL_MODELVIEW_MATRIX, outputMatrix.data());
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_TRUE(testMatrix.nearlyEqual(0.00001f, outputMatrix));
+}
+
+// Test that GL_INVALID_VALUE is issued if potential divide by zero situations happen for
+// glFrustumf.
+TEST_P(MatrixBuiltinsTest, FrustumNegative)
+{
+    glFrustumf(1.0f, 1.0f, 0.0f, 1.0f, 0.1f, 1.0f);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    glFrustumf(0.0f, 1.0f, 1.0f, 1.0f, 0.1f, 1.0f);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    glFrustumf(0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    glFrustumf(0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    glFrustumf(0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    glFrustumf(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+}
+
+// Test that GL_INVALID_VALUE is issued if potential divide by zero situations happen for glOrthof.
+TEST_P(MatrixBuiltinsTest, OrthoNegative)
+{
+    glOrthof(1.0f, 1.0f, 0.0f, 1.0f, 0.1f, 1.0f);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    glOrthof(0.0f, 1.0f, 1.0f, 1.0f, 0.1f, 1.0f);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    glOrthof(0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    glOrthof(0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    glOrthof(0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+    glOrthof(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
+    EXPECT_GL_ERROR(GL_INVALID_VALUE);
+}
+
+ANGLE_INSTANTIATE_TEST(MatrixBuiltinsTest, ES1_D3D11(), ES1_OPENGL(), ES1_OPENGLES());
diff --git a/src/tests/gl_tests/gles1/VertexPointerTest.cpp b/src/tests/gl_tests/gles1/VertexPointerTest.cpp
new file mode 100644
index 0000000..24ad641
--- /dev/null
+++ b/src/tests/gl_tests/gles1/VertexPointerTest.cpp
@@ -0,0 +1,67 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexPointerTest.cpp: Tests basic usage of built-in vertex attributes of GLES1.
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+class VertexPointerTest : public ANGLETest
+{
+  protected:
+    VertexPointerTest()
+    {
+        setWindowWidth(32);
+        setWindowHeight(32);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+    }
+};
+
+// Checks that we can assign to client side vertex arrays
+TEST_P(VertexPointerTest, AssignRetrieve)
+{
+    std::vector<float> testVertexAttribute = {
+        1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
+        1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
+    };
+
+    glVertexPointer(4, GL_FLOAT, 0, testVertexAttribute.data());
+    EXPECT_GL_NO_ERROR();
+
+    void *ptr = nullptr;
+    glGetPointerv(GL_VERTEX_ARRAY_POINTER, &ptr);
+    EXPECT_EQ(testVertexAttribute.data(), ptr);
+
+    glColorPointer(4, GL_FLOAT, 0, testVertexAttribute.data() + 4);
+    glGetPointerv(GL_COLOR_ARRAY_POINTER, &ptr);
+    EXPECT_EQ(testVertexAttribute.data() + 4, ptr);
+
+    glNormalPointer(GL_FLOAT, 0, testVertexAttribute.data() + 8);
+    glGetPointerv(GL_NORMAL_ARRAY_POINTER, &ptr);
+    EXPECT_EQ(testVertexAttribute.data() + 8, ptr);
+
+    glPointSizePointerOES(GL_FLOAT, 0, testVertexAttribute.data() + 8);
+    glGetPointerv(GL_POINT_SIZE_ARRAY_POINTER_OES, &ptr);
+    EXPECT_EQ(testVertexAttribute.data() + 8, ptr);
+
+    GLint maxTextureUnits;
+    glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
+    for (int i = 0; i < maxTextureUnits; i++)
+    {
+        glClientActiveTexture(GL_TEXTURE0 + i);
+        glTexCoordPointer(4, GL_FLOAT, 0, testVertexAttribute.data() + i * 4);
+        glGetPointerv(GL_TEXTURE_COORD_ARRAY_POINTER, &ptr);
+        EXPECT_EQ(testVertexAttribute.data() + i * 4, ptr);
+    }
+}
+
+ANGLE_INSTANTIATE_TEST(VertexPointerTest, ES1_D3D11(), ES1_OPENGL(), ES1_OPENGLES());
diff --git a/src/tests/test_utils/ANGLETest.cpp b/src/tests/test_utils/ANGLETest.cpp
index 3e87c4b..e82fb5f 100644
--- a/src/tests/test_utils/ANGLETest.cpp
+++ b/src/tests/test_utils/ANGLETest.cpp
@@ -139,6 +139,19 @@
     return result;
 }
 
+void CreatePixelCenterWindowCoords(const std::vector<Vector2> &pixelPoints,
+                                   int windowWidth,
+                                   int windowHeight,
+                                   std::vector<Vector3> *outVertices)
+{
+    for (Vector2 pixelPoint : pixelPoints)
+    {
+        outVertices->emplace_back(Vector3((pixelPoint[0] + 0.5f) * 2.0f / windowWidth - 1.0f,
+                                          (pixelPoint[1] + 0.5f) * 2.0f / windowHeight - 1.0f,
+                                          0.0f));
+    }
+}
+
 angle::Vector4 GLColor::toNormalizedVector() const
 {
     return angle::Vector4(ColorNorm(R), ColorNorm(G), ColorNorm(B), ColorNorm(A));
diff --git a/src/tests/test_utils/ANGLETest.h b/src/tests/test_utils/ANGLETest.h
index 82b85fc..7b15dab 100644
--- a/src/tests/test_utils/ANGLETest.h
+++ b/src/tests/test_utils/ANGLETest.h
@@ -111,6 +111,14 @@
 
 struct WorkaroundsD3D;
 
+// The input here for pixelPoints are the expected integer window coordinates, we add .5 to every
+// one of them and re-scale the numbers to be between [-1,1]. Using this technique, we can make
+// sure the rasterization stage will end up drawing pixels at the expected locations.
+void CreatePixelCenterWindowCoords(const std::vector<Vector2> &pixelPoints,
+                                   int windowWidth,
+                                   int windowHeight,
+                                   std::vector<Vector3> *outVertices);
+
 // Useful to cast any type to GLubyte.
 template <typename TR, typename TG, typename TB, typename TA>
 GLColor MakeGLColor(TR r, TG g, TB b, TA a)
diff --git a/third_party/glslang/BUILD.gn b/third_party/glslang/BUILD.gn
index d890af8..1281e35 100644
--- a/third_party/glslang/BUILD.gn
+++ b/third_party/glslang/BUILD.gn
@@ -132,3 +132,18 @@
     sources += [ "src/glslang/OSDependent/Unix/ossource.cpp" ]
   }
 }
+
+executable("glslang_validator") {
+  sources = [
+    "src/StandAlone/DirStackFileIncluder.h",
+    "src/StandAlone/StandAlone.cpp",
+  ]
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [ "//build/config/compiler:no_chromium_code" ]
+  deps = [
+    "//build/config:exe_and_shlib_deps",
+  ]
+  public_deps = [
+    ":glslang",
+  ]
+}
diff --git a/third_party/vulkan-validation-layers/BUILD.gn b/third_party/vulkan-validation-layers/BUILD.gn
index 5a52d6e..b291557 100644
--- a/third_party/vulkan-validation-layers/BUILD.gn
+++ b/third_party/vulkan-validation-layers/BUILD.gn
@@ -67,16 +67,6 @@
     "helper_file_generator.py",
   ],
   [
-    "vulkan_gen_struct_size_helper_c",
-    "vk_struct_size_helper.c",
-    "helper_file_generator.py",
-  ],
-  [
-    "vulkan_gen_struct_size_helper_h",
-    "vk_struct_size_helper.h",
-    "helper_file_generator.py",
-  ],
-  [
     "vulkan_gen_thread_check_helper",
     "thread_check.h",
     "threading_generator.py",
@@ -121,8 +111,12 @@
     script = "src/scripts/lvl_genvk.py"
     inputs = [
       "src/scripts/$dep",
+      "src/scripts/cgenerator.py",
+      "src/scripts/common_codegen.py",
       "src/scripts/generator.py",
       "src/scripts/reg.py",
+      "src/scripts/vuid_mapping.py",
+      "src/layers/vk_validation_error_messages.h",
       "src/scripts/vk.xml",
     ]
     outputs = [
@@ -284,8 +278,8 @@
     sources = [
       "src/loader/cJSON.c",
       "src/loader/cJSON.h",
-      "src/loader/debug_report.c",
-      "src/loader/debug_report.h",
+      "src/loader/debug_utils.c",
+      "src/loader/debug_utils.h",
       "src/loader/dev_ext_trampoline.c",
       "src/loader/extension_manual.c",
       "src/loader/extension_manual.h",
@@ -502,10 +496,15 @@
       "//build/config:exe_and_shlib_deps",
     ]
     deps += [ ":vulkan_generate_mock_icd_files" ]
+    data_deps = [
+      ":vulkan_gen_icd_json_file",
+    ]
     sources = mock_icd_sources
     if (is_win) {
       sources += [ "src/icd/VkICD_mock_icd.def" ]
     }
+    configs -= [ "//build/config/compiler:chromium_code" ]
+    configs += [ "//build/config/compiler:no_chromium_code" ]
   }
 
   action("vulkan_gen_icd_json_file") {
diff --git a/third_party/vulkan-validation-layers/reg.py b/third_party/vulkan-validation-layers/reg.py
new file mode 100644
index 0000000..07a7e90
--- /dev/null
+++ b/third_party/vulkan-validation-layers/reg.py
@@ -0,0 +1,1060 @@
+#!/usr/bin/python3 -i
+#
+# Copyright (c) 2013-2018 The Khronos Group Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import io,os,pdb,re,string,sys,copy
+import xml.etree.ElementTree as etree
+from collections import defaultdict
+
+# matchAPIProfile - returns whether an API and profile
+#   being generated matches an element's profile
+# api - string naming the API to match
+# profile - string naming the profile to match
+# elem - Element which (may) have 'api' and 'profile'
+#   attributes to match to.
+# If a tag is not present in the Element, the corresponding API
+#   or profile always matches.
+# Otherwise, the tag must exactly match the API or profile.
+# Thus, if 'profile' = core:
+#   <remove> with no attribute will match
+#   <remove profile='core'> will match
+#   <remove profile='compatibility'> will not match
+# Possible match conditions:
+#   Requested   Element
+#   Profile     Profile
+#   ---------   --------
+#   None        None        Always matches
+#   'string'    None        Always matches
+#   None        'string'    Does not match. Can't generate multiple APIs
+#                           or profiles, so if an API/profile constraint
+#                           is present, it must be asked for explicitly.
+#   'string'    'string'    Strings must match
+#
+#   ** In the future, we will allow regexes for the attributes,
+#   not just strings, so that api="^(gl|gles2)" will match. Even
+#   this isn't really quite enough, we might prefer something
+#   like "gl(core)|gles1(common-lite)".
+def matchAPIProfile(api, profile, elem):
+    """Match a requested API & profile name to a api & profile attributes of an Element"""
+    match = True
+    # Match 'api', if present
+    if ('api' in elem.attrib):
+        if (api == None):
+            raise UserWarning("No API requested, but 'api' attribute is present with value '" +
+                              elem.get('api') + "'")
+        elif (api != elem.get('api')):
+            # Requested API doesn't match attribute
+            return False
+    if ('profile' in elem.attrib):
+        if (profile == None):
+            raise UserWarning("No profile requested, but 'profile' attribute is present with value '" +
+                elem.get('profile') + "'")
+        elif (profile != elem.get('profile')):
+            # Requested profile doesn't match attribute
+            return False
+    return True
+
+# BaseInfo - base class for information about a registry feature
+# (type/group/enum/command/API/extension).
+#   required - should this feature be defined during header generation
+#     (has it been removed by a profile or version)?
+#   declared - has this feature been defined already?
+#   elem - etree Element for this feature
+#   resetState() - reset required/declared to initial values. Used
+#     prior to generating a new API interface.
+#   compareElem(info) - return True if self.elem and info.elem have the
+#     same definition.
+class BaseInfo:
+    """Represents the state of a registry feature, used during API generation"""
+    def __init__(self, elem):
+        self.required = False
+        self.declared = False
+        self.elem = elem
+    def resetState(self):
+        self.required = False
+        self.declared = False
+    def compareElem(self, info):
+        # Just compares the tag and attributes.
+        # @@ This should be virtualized. In particular, comparing <enum>
+        # tags requires special-casing on the attributes, as 'extnumber' is
+        # only relevant when 'offset' is present.
+        selfKeys = sorted(self.elem.keys())
+        infoKeys = sorted(info.elem.keys())
+
+        if selfKeys != infoKeys:
+            return False
+
+        # Ignore value of 'extname', as this will inherently be different
+        # when redefining the same interface in different feature and/or
+        # extension blocks.
+        for key in selfKeys:
+            if (key != 'extname' and key != 'extnumber' and
+                (self.elem.get(key) != info.elem.get(key))):
+
+                return False
+
+        return True
+
+# TypeInfo - registry information about a type. No additional state
+#   beyond BaseInfo is required.
+class TypeInfo(BaseInfo):
+    """Represents the state of a registry type"""
+    def __init__(self, elem):
+        BaseInfo.__init__(self, elem)
+        self.additionalValidity = []
+        self.removedValidity = []
+    def resetState(self):
+        BaseInfo.resetState(self)
+        self.additionalValidity = []
+        self.removedValidity = []
+
+# GroupInfo - registry information about a group of related enums
+# in an <enums> block, generally corresponding to a C "enum" type.
+class GroupInfo(BaseInfo):
+    """Represents the state of a registry <enums> group"""
+    def __init__(self, elem):
+        BaseInfo.__init__(self, elem)
+
+# EnumInfo - registry information about an enum
+#   type - numeric type of the value of the <enum> tag
+#     ( '' for GLint, 'u' for GLuint, 'ull' for GLuint64 )
+class EnumInfo(BaseInfo):
+    """Represents the state of a registry enum"""
+    def __init__(self, elem):
+        BaseInfo.__init__(self, elem)
+        self.type = elem.get('type')
+        if (self.type == None):
+            self.type = ''
+
+# CmdInfo - registry information about a command
+class CmdInfo(BaseInfo):
+    """Represents the state of a registry command"""
+    def __init__(self, elem):
+        BaseInfo.__init__(self, elem)
+        self.additionalValidity = []
+        self.removedValidity = []
+    def resetState(self):
+        BaseInfo.resetState(self)
+        self.additionalValidity = []
+        self.removedValidity = []
+
+# FeatureInfo - registry information about an API <feature>
+# or <extension>
+#   name - feature name string (e.g. 'VK_KHR_surface')
+#   version - feature version number (e.g. 1.2). <extension>
+#     features are unversioned and assigned version number 0.
+#     ** This is confusingly taken from the 'number' attribute of <feature>.
+#        Needs fixing.
+#   number - extension number, used for ordering and for
+#     assigning enumerant offsets. <feature> features do
+#     not have extension numbers and are assigned number 0.
+#   category - category, e.g. VERSION or khr/vendor tag
+#   emit - has this feature been defined already?
+class FeatureInfo(BaseInfo):
+    """Represents the state of an API feature (version/extension)"""
+    def __init__(self, elem):
+        BaseInfo.__init__(self, elem)
+        self.name = elem.get('name')
+        # Determine element category (vendor). Only works
+        # for <extension> elements.
+        if (elem.tag == 'feature'):
+            self.category = 'VERSION'
+            self.version = elem.get('name')
+            self.versionNumber = elem.get('number')
+            self.number = "0"
+            self.supported = None
+        else:
+            self.category = self.name.split('_', 2)[1]
+            self.version = "0"
+            self.versionNumber = "0"
+            self.number = elem.get('number')
+            self.supported = elem.get('supported')
+        self.emit = False
+
+from generator import write, GeneratorOptions, OutputGenerator
+
+# Registry - object representing an API registry, loaded from an XML file
+# Members
+#   tree - ElementTree containing the root <registry>
+#   typedict - dictionary of TypeInfo objects keyed by type name
+#   groupdict - dictionary of GroupInfo objects keyed by group name
+#   enumdict - dictionary of EnumInfo objects keyed by enum name
+#   cmddict - dictionary of CmdInfo objects keyed by command name
+#   apidict - dictionary of <api> Elements keyed by API name
+#   extensions - list of <extension> Elements
+#   extdict - dictionary of <extension> Elements keyed by extension name
+#   gen - OutputGenerator object used to write headers / messages
+#   genOpts - GeneratorOptions object used to control which
+#     fetures to write and how to format them
+#   emitFeatures - True to actually emit features for a version / extension,
+#     or False to just treat them as emitted
+#   breakPat - regexp pattern to break on when generatng names
+# Public methods
+#   loadElementTree(etree) - load registry from specified ElementTree
+#   loadFile(filename) - load registry from XML file
+#   setGenerator(gen) - OutputGenerator to use
+#   breakOnName() - specify a feature name regexp to break on when
+#     generating features.
+#   parseTree() - parse the registry once loaded & create dictionaries
+#   dumpReg(maxlen, filehandle) - diagnostic to dump the dictionaries
+#     to specified file handle (default stdout). Truncates type /
+#     enum / command elements to maxlen characters (default 80)
+#   generator(g) - specify the output generator object
+#   apiGen(apiname, genOpts) - generate API headers for the API type
+#     and profile specified in genOpts, but only for the versions and
+#     extensions specified there.
+#   apiReset() - call between calls to apiGen() to reset internal state
+# Private methods
+#   addElementInfo(elem,info,infoName,dictionary) - add feature info to dict
+#   lookupElementInfo(fname,dictionary) - lookup feature info in dict
+class Registry:
+    """Represents an API registry loaded from XML"""
+    def __init__(self):
+        self.tree         = None
+        self.typedict     = {}
+        self.groupdict    = {}
+        self.enumdict     = {}
+        self.cmddict      = {}
+        self.apidict      = {}
+        self.extensions   = []
+        self.requiredextensions = [] # Hack - can remove it after validity generator goes away
+        self.validextensionstructs = defaultdict(list)
+        self.extdict      = {}
+        # A default output generator, so commands prior to apiGen can report
+        # errors via the generator object.
+        self.gen          = OutputGenerator()
+        self.genOpts      = None
+        self.emitFeatures = False
+        self.breakPat     = None
+        # self.breakPat     = re.compile('VkFenceImportFlagBits.*')
+    def loadElementTree(self, tree):
+        """Load ElementTree into a Registry object and parse it"""
+        self.tree = tree
+        self.parseTree()
+    def loadFile(self, file):
+        """Load an API registry XML file into a Registry object and parse it"""
+        self.tree = etree.parse(file)
+        self.parseTree()
+    def setGenerator(self, gen):
+        """Specify output generator object. None restores the default generator"""
+        self.gen = gen
+        self.gen.setRegistry(self)
+
+    # addElementInfo - add information about an element to the
+    # corresponding dictionary
+    #   elem - <type>/<enums>/<enum>/<command>/<feature>/<extension> Element
+    #   info - corresponding {Type|Group|Enum|Cmd|Feature}Info object
+    #   infoName - 'type' / 'group' / 'enum' / 'command' / 'feature' / 'extension'
+    #   dictionary - self.{type|group|enum|cmd|api|ext}dict
+    # If the Element has an 'api' attribute, the dictionary key is the
+    # tuple (name,api). If not, the key is the name. 'name' is an
+    # attribute of the Element
+    def addElementInfo(self, elem, info, infoName, dictionary):
+        # self.gen.logMsg('diag', 'Adding ElementInfo.required =',
+        #     info.required, 'name =', elem.get('name'))
+
+        if ('api' in elem.attrib):
+            key = (elem.get('name'),elem.get('api'))
+        else:
+            key = elem.get('name')
+        if key in dictionary:
+            if not dictionary[key].compareElem(info):
+                self.gen.logMsg('warn', 'Attempt to redefine', key,
+                                'with different value (this may be benign)')
+            #else:
+            #    self.gen.logMsg('warn', 'Benign redefinition of', key,
+            #                    'with identical value')
+        else:
+            dictionary[key] = info
+    #
+    # lookupElementInfo - find a {Type|Enum|Cmd}Info object by name.
+    # If an object qualified by API name exists, use that.
+    #   fname - name of type / enum / command
+    #   dictionary - self.{type|enum|cmd}dict
+    def lookupElementInfo(self, fname, dictionary):
+        key = (fname, self.genOpts.apiname)
+        if (key in dictionary):
+            # self.gen.logMsg('diag', 'Found API-specific element for feature', fname)
+            return dictionary[key]
+        elif (fname in dictionary):
+            # self.gen.logMsg('diag', 'Found generic element for feature', fname)
+            return dictionary[fname]
+        else:
+            return None
+    def breakOnName(self, regexp):
+        self.breakPat = re.compile(regexp)
+    def parseTree(self):
+        """Parse the registry Element, once created"""
+        # This must be the Element for the root <registry>
+        self.reg = self.tree.getroot()
+        #
+        # Create dictionary of registry types from toplevel <types> tags
+        # and add 'name' attribute to each <type> tag (where missing)
+        # based on its <name> element.
+        #
+        # There's usually one <types> block; more are OK
+        # Required <type> attributes: 'name' or nested <name> tag contents
+        self.typedict = {}
+        for type in self.reg.findall('types/type'):
+            # If the <type> doesn't already have a 'name' attribute, set
+            # it from contents of its <name> tag.
+            if (type.get('name') == None):
+                type.attrib['name'] = type.find('name').text
+            self.addElementInfo(type, TypeInfo(type), 'type', self.typedict)
+        #
+        # Create dictionary of registry enum groups from <enums> tags.
+        #
+        # Required <enums> attributes: 'name'. If no name is given, one is
+        # generated, but that group can't be identified and turned into an
+        # enum type definition - it's just a container for <enum> tags.
+        self.groupdict = {}
+        for group in self.reg.findall('enums'):
+            self.addElementInfo(group, GroupInfo(group), 'group', self.groupdict)
+        #
+        # Create dictionary of registry enums from <enum> tags
+        #
+        # <enums> tags usually define different namespaces for the values
+        #   defined in those tags, but the actual names all share the
+        #   same dictionary.
+        # Required <enum> attributes: 'name', 'value'
+        # For containing <enums> which have type="enum" or type="bitmask",
+        # tag all contained <enum>s are required. This is a stopgap until
+        # a better scheme for tagging core and extension enums is created.
+        self.enumdict = {}
+        for enums in self.reg.findall('enums'):
+            required = (enums.get('type') != None)
+            for enum in enums.findall('enum'):
+                enumInfo = EnumInfo(enum)
+                enumInfo.required = required
+                self.addElementInfo(enum, enumInfo, 'enum', self.enumdict)
+                # self.gen.logMsg('diag', 'parseTree: marked req =',
+                #                 required, 'for', enum.get('name'))
+        #
+        # Create dictionary of registry commands from <command> tags
+        # and add 'name' attribute to each <command> tag (where missing)
+        # based on its <proto><name> element.
+        #
+        # There's usually only one <commands> block; more are OK.
+        # Required <command> attributes: 'name' or <proto><name> tag contents
+        self.cmddict = {}
+        # List of commands which alias others. Contains
+        #   [ aliasName, element ]
+        # for each alias
+        cmdAlias = []
+        for cmd in self.reg.findall('commands/command'):
+            # If the <command> doesn't already have a 'name' attribute, set
+            # it from contents of its <proto><name> tag.
+            name = cmd.get('name')
+            if name == None:
+                name = cmd.attrib['name'] = cmd.find('proto/name').text
+            ci = CmdInfo(cmd)
+            self.addElementInfo(cmd, ci, 'command', self.cmddict)
+            alias = cmd.get('alias')
+            if alias:
+                cmdAlias.append([name, alias, cmd])
+        # Now loop over aliases, injecting a copy of the aliased command's
+        # Element with the aliased prototype name replaced with the command
+        # name - if it exists.
+        for (name, alias, cmd) in cmdAlias:
+            if alias in self.cmddict:
+                #@ pdb.set_trace()
+                aliasInfo = self.cmddict[alias]
+                cmdElem = copy.deepcopy(aliasInfo.elem)
+                cmdElem.find('proto/name').text = name
+                cmdElem.attrib['name'] = name
+                cmdElem.attrib['alias'] = alias
+                ci = CmdInfo(cmdElem)
+                # Replace the dictionary entry for the CmdInfo element
+                self.cmddict[name] = ci
+
+                #@  newString = etree.tostring(base, encoding="unicode").replace(aliasValue, aliasName)
+                #@elem.append(etree.fromstring(replacement))
+            else:
+                self.gen.logMsg('warn', 'No matching <command> found for command',
+                    cmd.get('name'), 'alias', alias)
+
+        #
+        # Create dictionaries of API and extension interfaces
+        #   from toplevel <api> and <extension> tags.
+        #
+        self.apidict = {}
+        for feature in self.reg.findall('feature'):
+            featureInfo = FeatureInfo(feature)
+            self.addElementInfo(feature, featureInfo, 'feature', self.apidict)
+
+            # Add additional enums defined only in <feature> tags
+            # to the corresponding core type.
+            # When seen here, the <enum> element, processed to contain the
+            # numeric enum value, is added to the corresponding <enums>
+            # element, as well as adding to the enum dictionary. It is
+            # *removed* from the <require> element it is introduced in.
+            # Not doing this will cause spurious genEnum()
+            # calls to be made in output generation, and it's easier
+            # to handle here than in genEnum().
+            #
+            # In lxml.etree, an Element can have only one parent, so the
+            # append() operation also removes the element. But in Python's
+            # ElementTree package, an Element can have multiple parents. So
+            # it must be explicitly removed from the <require> tag, leading
+            # to the nested loop traversal of <require>/<enum> elements
+            # below.
+            #
+            # This code also adds a 'version' attribute containing the
+            # api version.
+            #
+            # For <enum> tags which are actually just constants, if there's
+            # no 'extends' tag but there is a 'value' or 'bitpos' tag, just
+            # add an EnumInfo record to the dictionary. That works because
+            # output generation of constants is purely dependency-based, and
+            # doesn't need to iterate through the XML tags.
+            #
+            for elem in feature.findall('require'):
+              for enum in elem.findall('enum'):
+                addEnumInfo = False
+                groupName = enum.get('extends')
+                if (groupName != None):
+                    # self.gen.logMsg('diag', 'Found extension enum',
+                    #     enum.get('name'))
+                    # Add version number attribute to the <enum> element
+                    enum.attrib['version'] = featureInfo.version
+                    # Look up the GroupInfo with matching groupName
+                    if (groupName in self.groupdict.keys()):
+                        # self.gen.logMsg('diag', 'Matching group',
+                        #     groupName, 'found, adding element...')
+                        gi = self.groupdict[groupName]
+                        gi.elem.append(enum)
+                        # Remove element from parent <require> tag
+                        # This should be a no-op in lxml.etree
+                        elem.remove(enum)
+                    else:
+                        self.gen.logMsg('warn', 'NO matching group',
+                            groupName, 'for enum', enum.get('name'), 'found.')
+                    addEnumInfo = True
+                elif (enum.get('value') or enum.get('bitpos') or enum.get('alias')):
+                    # self.gen.logMsg('diag', 'Adding extension constant "enum"',
+                    #     enum.get('name'))
+                    addEnumInfo = True
+                if (addEnumInfo):
+                    enumInfo = EnumInfo(enum)
+                    self.addElementInfo(enum, enumInfo, 'enum', self.enumdict)
+
+        self.extensions = self.reg.findall('extensions/extension')
+        self.extdict = {}
+        for feature in self.extensions:
+            featureInfo = FeatureInfo(feature)
+            self.addElementInfo(feature, featureInfo, 'extension', self.extdict)
+
+            # Add additional enums defined only in <extension> tags
+            # to the corresponding core type.
+            # Algorithm matches that of enums in a "feature" tag as above.
+            #
+            # This code also adds a 'extnumber' attribute containing the
+            # extension number, used for enumerant value calculation.
+            #
+            for elem in feature.findall('require'):
+              for enum in elem.findall('enum'):
+                addEnumInfo = False
+                groupName = enum.get('extends')
+                if (groupName != None):
+                    # self.gen.logMsg('diag', 'Found extension enum',
+                    #     enum.get('name'))
+
+                    # Add <extension> block's extension number attribute to
+                    # the <enum> element unless specified explicitly, such
+                    # as when redefining an enum in another extension.
+                    extnumber = enum.get('extnumber')
+                    if not extnumber:
+                        enum.attrib['extnumber'] = featureInfo.number
+
+                    enum.attrib['extname'] = featureInfo.name
+                    enum.attrib['supported'] = featureInfo.supported
+                    # Look up the GroupInfo with matching groupName
+                    if (groupName in self.groupdict.keys()):
+                        # self.gen.logMsg('diag', 'Matching group',
+                        #     groupName, 'found, adding element...')
+                        gi = self.groupdict[groupName]
+                        gi.elem.append(enum)
+                        # Remove element from parent <require> tag
+                        # This should be a no-op in lxml.etree
+                        elem.remove(enum)
+                    else:
+                        self.gen.logMsg('warn', 'NO matching group',
+                            groupName, 'for enum', enum.get('name'), 'found.')
+                    addEnumInfo = True
+                elif (enum.get('value') or enum.get('bitpos') or enum.get('alias')):
+                    # self.gen.logMsg('diag', 'Adding extension constant "enum"',
+                    #     enum.get('name'))
+                    addEnumInfo = True
+                if (addEnumInfo):
+                    enumInfo = EnumInfo(enum)
+                    self.addElementInfo(enum, enumInfo, 'enum', self.enumdict)
+
+        # Construct a "validextensionstructs" list for parent structures
+        # based on "structextends" tags in child structures
+        for type in self.reg.findall('types/type'):
+            parentStructs = type.get('structextends')
+            if (parentStructs != None):
+                for parent in parentStructs.split(','):
+                    # self.gen.logMsg('diag', type.get('name'), 'extends', parent)
+                    self.validextensionstructs[parent].append(type.get('name'))
+        # Sort the lists so they don't depend on the XML order
+        for parent in self.validextensionstructs:
+            self.validextensionstructs[parent].sort()
+
+    def dumpReg(self, maxlen = 120, filehandle = sys.stdout):
+        """Dump all the dictionaries constructed from the Registry object"""
+        write('***************************************', file=filehandle)
+        write('    ** Dumping Registry contents **',     file=filehandle)
+        write('***************************************', file=filehandle)
+        write('// Types', file=filehandle)
+        for name in self.typedict:
+            tobj = self.typedict[name]
+            write('    Type', name, '->', etree.tostring(tobj.elem)[0:maxlen], file=filehandle)
+        write('// Groups', file=filehandle)
+        for name in self.groupdict:
+            gobj = self.groupdict[name]
+            write('    Group', name, '->', etree.tostring(gobj.elem)[0:maxlen], file=filehandle)
+        write('// Enums', file=filehandle)
+        for name in self.enumdict:
+            eobj = self.enumdict[name]
+            write('    Enum', name, '->', etree.tostring(eobj.elem)[0:maxlen], file=filehandle)
+        write('// Commands', file=filehandle)
+        for name in self.cmddict:
+            cobj = self.cmddict[name]
+            write('    Command', name, '->', etree.tostring(cobj.elem)[0:maxlen], file=filehandle)
+        write('// APIs', file=filehandle)
+        for key in self.apidict:
+            write('    API Version ', key, '->',
+                etree.tostring(self.apidict[key].elem)[0:maxlen], file=filehandle)
+        write('// Extensions', file=filehandle)
+        for key in self.extdict:
+            write('    Extension', key, '->',
+                etree.tostring(self.extdict[key].elem)[0:maxlen], file=filehandle)
+        # write('***************************************', file=filehandle)
+        # write('    ** Dumping XML ElementTree **', file=filehandle)
+        # write('***************************************', file=filehandle)
+        # write(etree.tostring(self.tree.getroot(),pretty_print=True), file=filehandle)
+    #
+    # typename - name of type
+    # required - boolean (to tag features as required or not)
+    def markTypeRequired(self, typename, required):
+        """Require (along with its dependencies) or remove (but not its dependencies) a type"""
+        self.gen.logMsg('diag', 'tagging type:', typename, '-> required =', required)
+        # Get TypeInfo object for <type> tag corresponding to typename
+        type = self.lookupElementInfo(typename, self.typedict)
+        if (type != None):
+            if (required):
+                # Tag type dependencies in 'alias' and 'required' attributes as
+                # required. This DOES NOT un-tag dependencies in a <remove>
+                # tag. See comments in markRequired() below for the reason.
+                for attrib in [ 'requires', 'alias' ]:
+                    depname = type.elem.get(attrib)
+                    if depname:
+                        self.gen.logMsg('diag', 'Generating dependent type',
+                            depname, 'for', attrib, 'type', typename)
+                        self.markTypeRequired(depname, required)
+                # Tag types used in defining this type (e.g. in nested
+                # <type> tags)
+                # Look for <type> in entire <command> tree,
+                # not just immediate children
+                for subtype in type.elem.findall('.//type'):
+                    self.gen.logMsg('diag', 'markRequired: type requires dependent <type>', subtype.text)
+                    self.markTypeRequired(subtype.text, required)
+                # Tag enums used in defining this type, for example in
+                #   <member><name>member</name>[<enum>MEMBER_SIZE</enum>]</member>
+                for subenum in type.elem.findall('.//enum'):
+                    self.gen.logMsg('diag', 'markRequired: type requires dependent <enum>', subenum.text)
+                    self.markEnumRequired(subenum.text, required)
+            type.required = required
+        else:
+            self.gen.logMsg('warn', 'type:', typename , 'IS NOT DEFINED')
+    #
+    # enumname - name of enum
+    # required - boolean (to tag features as required or not)
+    def markEnumRequired(self, enumname, required):
+        self.gen.logMsg('diag', 'tagging enum:', enumname, '-> required =', required)
+        enum = self.lookupElementInfo(enumname, self.enumdict)
+        if (enum != None):
+            enum.required = required
+            # Tag enum dependencies in 'alias' attribute as required
+            depname = enum.elem.get('alias')
+            if depname:
+                self.gen.logMsg('diag', 'Generating dependent enum',
+                    depname, 'for alias', enumname, 'required =', enum.required)
+                self.markEnumRequired(depname, required)
+        else:
+            self.gen.logMsg('warn', 'enum:', enumname , 'IS NOT DEFINED')
+    #
+    # cmdname - name of command
+    # required - boolean (to tag features as required or not)
+    def markCmdRequired(self, cmdname, required):
+        self.gen.logMsg('diag', 'tagging command:', cmdname, '-> required =', required)
+        cmd = self.lookupElementInfo(cmdname, self.cmddict)
+        if (cmd != None):
+            cmd.required = required
+            # Tag command dependencies in 'alias' attribute as required
+            depname = cmd.elem.get('alias')
+            if depname:
+                self.gen.logMsg('diag', 'Generating dependent command',
+                    depname, 'for alias', cmdname)
+                self.markCmdRequired(depname, required)
+            # Tag all parameter types of this command as required.
+            # This DOES NOT remove types of commands in a <remove>
+            # tag, because many other commands may use the same type.
+            # We could be more clever and reference count types,
+            # instead of using a boolean.
+            if (required):
+                # Look for <type> in entire <command> tree,
+                # not just immediate children
+                for type in cmd.elem.findall('.//type'):
+                    self.gen.logMsg('diag', 'markRequired: command implicitly requires dependent type', type.text)
+                    self.markTypeRequired(type.text, required)
+        else:
+            self.gen.logMsg('warn', 'command:', name, 'IS NOT DEFINED')
+    #
+    # features - Element for <require> or <remove> tag
+    # required - boolean (to tag features as required or not)
+    def markRequired(self, features, required):
+        """Require or remove features specified in the Element"""
+        self.gen.logMsg('diag', 'markRequired (features = <too long to print>, required =', required, ')')
+        # Loop over types, enums, and commands in the tag
+        # @@ It would be possible to respect 'api' and 'profile' attributes
+        #  in individual features, but that's not done yet.
+        for typeElem in features.findall('type'):
+            self.markTypeRequired(typeElem.get('name'), required)
+        for enumElem in features.findall('enum'):
+            self.markEnumRequired(enumElem.get('name'), required)
+        for cmdElem in features.findall('command'):
+            self.markCmdRequired(cmdElem.get('name'), required)
+    #
+    # interface - Element for <version> or <extension>, containing
+    #   <require> and <remove> tags
+    # api - string specifying API name being generated
+    # profile - string specifying API profile being generated
+    def requireAndRemoveFeatures(self, interface, api, profile):
+        """Process <recquire> and <remove> tags for a <version> or <extension>"""
+        # <require> marks things that are required by this version/profile
+        for feature in interface.findall('require'):
+            if (matchAPIProfile(api, profile, feature)):
+                self.markRequired(feature,True)
+        # <remove> marks things that are removed by this version/profile
+        for feature in interface.findall('remove'):
+            if (matchAPIProfile(api, profile, feature)):
+                self.markRequired(feature,False)
+
+    def assignAdditionalValidity(self, interface, api, profile):
+        #
+        # Loop over all usage inside all <require> tags.
+        for feature in interface.findall('require'):
+            if (matchAPIProfile(api, profile, feature)):
+                for v in feature.findall('usage'):
+                    if v.get('command'):
+                        self.cmddict[v.get('command')].additionalValidity.append(copy.deepcopy(v))
+                    if v.get('struct'):
+                        self.typedict[v.get('struct')].additionalValidity.append(copy.deepcopy(v))
+
+        #
+        # Loop over all usage inside all <remove> tags.
+        for feature in interface.findall('remove'):
+            if (matchAPIProfile(api, profile, feature)):
+                for v in feature.findall('usage'):
+                    if v.get('command'):
+                        self.cmddict[v.get('command')].removedValidity.append(copy.deepcopy(v))
+                    if v.get('struct'):
+                        self.typedict[v.get('struct')].removedValidity.append(copy.deepcopy(v))
+
+    #
+    # generateFeature - generate a single type / enum group / enum / command,
+    # and all its dependencies as needed.
+    #   fname - name of feature (<type>/<enum>/<command>)
+    #   ftype - type of feature, 'type' | 'enum' | 'command'
+    #   dictionary - of *Info objects - self.{type|enum|cmd}dict
+    def generateFeature(self, fname, ftype, dictionary):
+        #@ # Break to debugger on matching name pattern
+        #@ if self.breakPat and re.match(self.breakPat, fname):
+        #@    pdb.set_trace()
+
+        self.gen.logMsg('diag', 'generateFeature: generating', ftype, fname)
+        f = self.lookupElementInfo(fname, dictionary)
+        if (f == None):
+            # No such feature. This is an error, but reported earlier
+            self.gen.logMsg('diag', 'No entry found for feature', fname,
+                            'returning!')
+            return
+        #
+        # If feature isn't required, or has already been declared, return
+        if (not f.required):
+            self.gen.logMsg('diag', 'Skipping', ftype, fname, '(not required)')
+            return
+        if (f.declared):
+            self.gen.logMsg('diag', 'Skipping', ftype, fname, '(already declared)')
+            return
+        # Always mark feature declared, as though actually emitted
+        f.declared = True
+
+        # Determine if this is an alias, and of what, if so
+        alias = f.elem.get('alias')
+        if alias:
+            self.gen.logMsg('diag', fname, 'is an alias of', alias)
+
+        #
+        # Pull in dependent declaration(s) of the feature.
+        # For types, there may be one type in the 'required' attribute of
+        #   the element, one in the 'alias' attribute, and many in
+        #   imbedded <type> and <enum> tags within the element.
+        # For commands, there may be many in <type> tags within the element.
+        # For enums, no dependencies are allowed (though perhaps if you
+        #   have a uint64 enum, it should require that type).
+        genProc = None
+        if (ftype == 'type'):
+            genProc = self.gen.genType
+
+            # Generate type dependencies in 'alias' and 'required' attributes
+            if alias:
+                self.generateFeature(alias, 'type', self.typedict)
+            requires = f.elem.get('requires')
+            if requires:
+                self.generateFeature(requires, 'type', self.typedict)
+
+            # Generate types used in defining this type (e.g. in nested
+            # <type> tags)
+            # Look for <type> in entire <command> tree,
+            # not just immediate children
+            for subtype in f.elem.findall('.//type'):
+                self.gen.logMsg('diag', 'Generating required dependent <type>',
+                    subtype.text)
+                self.generateFeature(subtype.text, 'type', self.typedict)
+
+            # Generate enums used in defining this type, for example in
+            #   <member><name>member</name>[<enum>MEMBER_SIZE</enum>]</member>
+            for subtype in f.elem.findall('.//enum'):
+                self.gen.logMsg('diag', 'Generating required dependent <enum>',
+                    subtype.text)
+                self.generateFeature(subtype.text, 'enum', self.enumdict)
+
+            # If the type is an enum group, look up the corresponding
+            # group in the group dictionary and generate that instead.
+            if (f.elem.get('category') == 'enum'):
+                self.gen.logMsg('diag', 'Type', fname, 'is an enum group, so generate that instead')
+                group = self.lookupElementInfo(fname, self.groupdict)
+                if alias != None:
+                    # An alias of another group name.
+                    # Pass to genGroup with 'alias' parameter = aliased name
+                    self.gen.logMsg('diag', 'Generating alias', fname,
+                                    'for enumerated type', alias)
+                    # Now, pass the *aliased* GroupInfo to the genGroup, but
+                    # with an additional parameter which is the alias name.
+                    genProc = self.gen.genGroup
+                    f = self.lookupElementInfo(alias, self.groupdict)
+                elif group == None:
+                    self.gen.logMsg('warn', 'Skipping enum type', fname,
+                        ': No matching enumerant group')
+                    return
+                else:
+                    genProc = self.gen.genGroup
+                    f = group
+
+                    #@ The enum group is not ready for generation. At this
+                    #@   point, it contains all <enum> tags injected by
+                    #@   <extension> tags without any verification of whether
+                    #@   they're required or not. It may also contain
+                    #@   duplicates injected by multiple consistent
+                    #@   definitions of an <enum>.
+
+                    #@ Pass over each enum, marking its enumdict[] entry as
+                    #@ required or not. Mark aliases of enums as required,
+                    #@ too.
+
+                    enums = group.elem.findall('enum')
+
+                    self.gen.logMsg('diag', 'generateFeature: checking enums for group', fname)
+
+                    # Check for required enums, including aliases
+                    # LATER - Check for, report, and remove duplicates?
+                    enumAliases = []
+                    for elem in enums:
+                        name = elem.get('name')
+
+                        required = False
+
+                        extname = elem.get('extname')
+                        version = elem.get('version')
+                        if extname is not None:
+                            # 'supported' attribute was injected when the <enum> element was
+                            # moved into the <enums> group in Registry.parseTree()
+                            if self.genOpts.defaultExtensions == elem.get('supported'):
+                                required = True
+                            elif re.match(self.genOpts.addExtensions, extname) is not None:
+                                required = True
+                        elif version is not None:
+                            required = re.match(self.genOpts.emitversions, version) is not None
+                        else:
+                            required = True
+
+                        self.gen.logMsg('diag', '* required =', required, 'for', name)
+                        if required:
+                            # Mark this element as required (in the element, not the EnumInfo)
+                            elem.attrib['required'] = 'true'
+                            # If it's an alias, track that for later use
+                            enumAlias = elem.get('alias')
+                            if enumAlias:
+                                enumAliases.append(enumAlias)
+                    for elem in enums:
+                        name = elem.get('name')
+                        if name in enumAliases:
+                            elem.attrib['required'] = 'true'
+                            self.gen.logMsg('diag', '* also need to require alias', name)
+        elif (ftype == 'command'):
+            # Generate command dependencies in 'alias' attribute
+            if alias:
+                self.generateFeature(alias, 'command', self.cmddict)
+
+            genProc = self.gen.genCmd
+            for type in f.elem.findall('.//type'):
+                depname = type.text
+                self.gen.logMsg('diag', 'Generating required parameter type',
+                                depname)
+                self.generateFeature(depname, 'type', self.typedict)
+        elif (ftype == 'enum'):
+            # Generate enum dependencies in 'alias' attribute
+            if alias:
+                self.generateFeature(alias, 'enum', self.enumdict)
+            genProc = self.gen.genEnum
+
+        # Actually generate the type only if emitting declarations
+        if self.emitFeatures:
+            self.gen.logMsg('diag', 'Emitting', ftype, fname, 'declaration')
+            genProc(f, fname, alias)
+        else:
+            self.gen.logMsg('diag', 'Skipping', ftype, fname,
+                            '(should not be emitted)')
+    #
+    # generateRequiredInterface - generate all interfaces required
+    # by an API version or extension
+    #   interface - Element for <version> or <extension>
+    def generateRequiredInterface(self, interface):
+        """Generate required C interface for specified API version/extension"""
+
+        #
+        # Loop over all features inside all <require> tags.
+        for features in interface.findall('require'):
+            for t in features.findall('type'):
+                self.generateFeature(t.get('name'), 'type', self.typedict)
+            for e in features.findall('enum'):
+                self.generateFeature(e.get('name'), 'enum', self.enumdict)
+            for c in features.findall('command'):
+                self.generateFeature(c.get('name'), 'command', self.cmddict)
+
+    #
+    # apiGen(genOpts) - generate interface for specified versions
+    #   genOpts - GeneratorOptions object with parameters used
+    #   by the Generator object.
+    def apiGen(self, genOpts):
+        """Generate interfaces for the specified API type and range of versions"""
+        #
+        self.gen.logMsg('diag', '*******************************************')
+        self.gen.logMsg('diag', '  Registry.apiGen file:', genOpts.filename,
+                        'api:', genOpts.apiname,
+                        'profile:', genOpts.profile)
+        self.gen.logMsg('diag', '*******************************************')
+        #
+        self.genOpts = genOpts
+        # Reset required/declared flags for all features
+        self.apiReset()
+        #
+        # Compile regexps used to select versions & extensions
+        regVersions = re.compile(self.genOpts.versions)
+        regEmitVersions = re.compile(self.genOpts.emitversions)
+        regAddExtensions = re.compile(self.genOpts.addExtensions)
+        regRemoveExtensions = re.compile(self.genOpts.removeExtensions)
+        regEmitExtensions = re.compile(self.genOpts.emitExtensions)
+        #
+        # Get all matching API feature names & add to list of FeatureInfo
+        # Note we used to select on feature version attributes, not names.
+        features = []
+        apiMatch = False
+        for key in self.apidict:
+            fi = self.apidict[key]
+            api = fi.elem.get('api')
+            if (api == self.genOpts.apiname):
+                apiMatch = True
+                if (regVersions.match(fi.name)):
+                    # Matches API & version #s being generated. Mark for
+                    # emission and add to the features[] list .
+                    # @@ Could use 'declared' instead of 'emit'?
+                    fi.emit = (regEmitVersions.match(fi.name) != None)
+                    features.append(fi)
+                    if (not fi.emit):
+                        self.gen.logMsg('diag', 'NOT tagging feature api =', api,
+                            'name =', fi.name, 'version =', fi.version,
+                            'for emission (does not match emitversions pattern)')
+                    else:
+                        self.gen.logMsg('diag', 'Including feature api =', api,
+                            'name =', fi.name, 'version =', fi.version,
+                            'for emission (matches emitversions pattern)')
+                else:
+                    self.gen.logMsg('diag', 'NOT including feature api =', api,
+                        'name =', fi.name, 'version =', fi.version,
+                        '(does not match requested versions)')
+            else:
+                self.gen.logMsg('diag', 'NOT including feature api =', api,
+                    'name =', fi.name,
+                    '(does not match requested API)')
+        if (not apiMatch):
+            self.gen.logMsg('warn', 'No matching API versions found!')
+        #
+        # Get all matching extensions, in order by their extension number,
+        # and add to the list of features.
+        # Start with extensions tagged with 'api' pattern matching the API
+        # being generated. Add extensions matching the pattern specified in
+        # regExtensions, then remove extensions matching the pattern
+        # specified in regRemoveExtensions
+        for (extName,ei) in sorted(self.extdict.items(),key = lambda x : x[1].number):
+            extName = ei.name
+            include = False
+            #
+            # Include extension if defaultExtensions is not None and if the
+            # 'supported' attribute matches defaultExtensions. The regexp in
+            # 'supported' must exactly match defaultExtensions, so bracket
+            # it with ^(pat)$.
+            pat = '^(' + ei.elem.get('supported') + ')$'
+            if (self.genOpts.defaultExtensions and
+                     re.match(pat, self.genOpts.defaultExtensions)):
+                self.gen.logMsg('diag', 'Including extension',
+                    extName, "(defaultExtensions matches the 'supported' attribute)")
+                include = True
+            #
+            # Include additional extensions if the extension name matches
+            # the regexp specified in the generator options. This allows
+            # forcing extensions into an interface even if they're not
+            # tagged appropriately in the registry.
+            if (regAddExtensions.match(extName) != None):
+                self.gen.logMsg('diag', 'Including extension',
+                    extName, '(matches explicitly requested extensions to add)')
+                include = True
+            # Remove extensions if the name matches the regexp specified
+            # in generator options. This allows forcing removal of
+            # extensions from an interface even if they're tagged that
+            # way in the registry.
+            if (regRemoveExtensions.match(extName) != None):
+                self.gen.logMsg('diag', 'Removing extension',
+                    extName, '(matches explicitly requested extensions to remove)')
+                include = False
+            #
+            # If the extension is to be included, add it to the
+            # extension features list.
+            if (include):
+                ei.emit = (regEmitExtensions.match(extName) != None)
+                features.append(ei)
+                if (not ei.emit):
+                    self.gen.logMsg('diag', 'NOT tagging extension',
+                        extName,
+                        'for emission (does not match emitextensions pattern)')
+                # Hack - can be removed when validity generator goes away
+                # (Jon) I'm not sure what this does, or if it should respect
+                # the ei.emit flag above.
+                self.requiredextensions.append(extName)
+            else:
+                self.gen.logMsg('diag', 'NOT including extension',
+                    extName, '(does not match api attribute or explicitly requested extensions)')
+        #
+        # Sort the extension features list, if a sort procedure is defined
+        if (self.genOpts.sortProcedure):
+            self.genOpts.sortProcedure(features)
+        #
+        # Pass 1: loop over requested API versions and extensions tagging
+        #   types/commands/features as required (in an <require> block) or no
+        #   longer required (in an <remove> block). It is possible to remove
+        #   a feature in one version and restore it later by requiring it in
+        #   a later version.
+        # If a profile other than 'None' is being generated, it must
+        #   match the profile attribute (if any) of the <require> and
+        #   <remove> tags.
+        self.gen.logMsg('diag', '*******PASS 1: TAG FEATURES **********')
+        for f in features:
+            self.gen.logMsg('diag', 'PASS 1: Tagging required and removed features for',
+                f.name)
+            self.requireAndRemoveFeatures(f.elem, self.genOpts.apiname, self.genOpts.profile)
+            self.assignAdditionalValidity(f.elem, self.genOpts.apiname, self.genOpts.profile)
+        #
+        # Pass 2: loop over specified API versions and extensions printing
+        #   declarations for required things which haven't already been
+        #   generated.
+        self.gen.logMsg('diag', '*******PASS 2: GENERATE INTERFACES FOR FEATURES **********')
+        self.gen.beginFile(self.genOpts)
+        for f in features:
+            self.gen.logMsg('diag', 'PASS 2: Generating interface for',
+                f.name)
+            emit = self.emitFeatures = f.emit
+            if (not emit):
+                self.gen.logMsg('diag', 'PASS 2: NOT declaring feature',
+                    f.elem.get('name'), 'because it is not tagged for emission')
+            # Generate the interface (or just tag its elements as having been
+            # emitted, if they haven't been).
+            self.gen.beginFeature(f.elem, emit)
+            self.generateRequiredInterface(f.elem)
+            self.gen.endFeature()
+        self.gen.endFile()
+    #
+    # apiReset - use between apiGen() calls to reset internal state
+    #
+    def apiReset(self):
+        """Reset type/enum/command dictionaries before generating another API"""
+        for type in self.typedict:
+            self.typedict[type].resetState()
+        for enum in self.enumdict:
+            self.enumdict[enum].resetState()
+        for cmd in self.cmddict:
+            self.cmddict[cmd].resetState()
+        for cmd in self.apidict:
+            self.apidict[cmd].resetState()
+    #
+    # validateGroups - check that group= attributes match actual groups
+    #
+    def validateGroups(self):
+        """Validate group= attributes on <param> and <proto> tags"""
+        # Keep track of group names not in <group> tags
+        badGroup = {}
+        self.gen.logMsg('diag', 'VALIDATING GROUP ATTRIBUTES ***')
+        for cmd in self.reg.findall('commands/command'):
+            proto = cmd.find('proto')
+            funcname = cmd.find('proto/name').text
+            if ('group' in proto.attrib.keys()):
+                group = proto.get('group')
+                # self.gen.logMsg('diag', 'Command ', funcname, ' has return group ', group)
+                if (group not in self.groupdict.keys()):
+                    # self.gen.logMsg('diag', 'Command ', funcname, ' has UNKNOWN return group ', group)
+                    if (group not in badGroup.keys()):
+                        badGroup[group] = 1
+                    else:
+                        badGroup[group] = badGroup[group] +  1
+            for param in cmd.findall('param'):
+                pname = param.find('name')
+                if (pname != None):
+                    pname = pname.text
+                else:
+                    pname = type.get('name')
+                if ('group' in param.attrib.keys()):
+                    group = param.get('group')
+                    if (group not in self.groupdict.keys()):
+                        # self.gen.logMsg('diag', 'Command ', funcname, ' param ', pname, ' has UNKNOWN group ', group)
+                        if (group not in badGroup.keys()):
+                            badGroup[group] = 1
+                        else:
+                            badGroup[group] = badGroup[group] +  1
+        if (len(badGroup.keys()) > 0):
+            self.gen.logMsg('diag', 'SUMMARY OF UNRECOGNIZED GROUPS ***')
+            for key in sorted(badGroup.keys()):
+                self.gen.logMsg('diag', '    ', key, ' occurred ', badGroup[key], ' times')
diff --git a/util/shader_utils.cpp b/util/shader_utils.cpp
index a9962dd..d425077 100644
--- a/util/shader_utils.cpp
+++ b/util/shader_utils.cpp
@@ -248,3 +248,222 @@
     glLinkProgram(program);
     return (CheckLinkStatusAndReturnProgram(program, true) != 0);
 }
+
+namespace angle
+{
+
+namespace essl1_shaders
+{
+
+const char *PositionAttrib()
+{
+    return "a_position";
+}
+const char *ColorUniform()
+{
+    return "u_color";
+}
+
+namespace vs
+{
+
+// A shader that sets gl_Position to zero.
+const char *Zero()
+{
+    return R"(void main()
+{
+    gl_Position = vec4(0);
+})";
+}
+
+// A shader that sets gl_Position to attribute a_position.
+const char *Simple()
+{
+    return R"(precision highp float;
+attribute vec4 a_position;
+
+void main()
+{
+    gl_Position = a_position;
+})";
+}
+
+// A shader that simply passes through attribute a_position, setting it to gl_Position and varying
+// pos.
+const char *Passthrough()
+{
+    return R"(precision highp float;
+attribute vec4 a_position;
+varying vec4 v_position;
+
+void main()
+{
+    gl_Position = a_position;
+    v_position = a_position;
+})";
+}
+
+}  // namespace vs
+
+namespace fs
+{
+
+// A shader that renders a simple checker pattern of red and green. X axis and y axis separate the
+// different colors. Needs varying v_position.
+const char *Checkered()
+{
+    return R"(precision highp float;
+varying vec4 v_position;
+
+void main()
+{
+    if (v_position.x * v_position.y > 0.0)
+    {
+        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+    }
+    else
+    {
+        gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+    }
+})";
+}
+
+// A shader that fills with color taken from uniform named "color".
+const char *UniformColor()
+{
+    return R"(uniform mediump vec4 u_color;
+void main(void)
+{
+    gl_FragColor = u_color;
+})";
+}
+
+// A shader that fills with 100% opaque red.
+const char *Red()
+{
+    return R"(precision mediump float;
+
+void main()
+{
+    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+})";
+}
+
+// A shader that fills with 100% opaque blue.
+const char *Blue()
+{
+    return R"(precision mediump float;
+
+void main()
+{
+    gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
+})";
+}
+
+}  // namespace fs
+}  // namespace essl1_shaders
+
+namespace essl3_shaders
+{
+
+const char *PositionAttrib()
+{
+    return "a_position";
+}
+
+namespace vs
+{
+
+// A shader that sets gl_Position to zero.
+const char *Zero()
+{
+    return R"(#version 300 es
+void main()
+{
+    gl_Position = vec4(0);
+})";
+}
+
+// A shader that sets gl_Position to attribute a_position.
+const char *Simple()
+{
+    return R"(#version 300 es
+in vec4 a_position;
+void main()
+{
+    gl_Position = a_position;
+})";
+}
+
+}  // namespace vs
+
+namespace fs
+{
+
+// A shader that fills with 100% opaque red.
+const char *Red()
+{
+    return R"(#version 300 es
+precision highp float;
+out vec4 my_FragColor;
+void main()
+{
+    my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+})";
+}
+
+}  // namespace fs
+}  // namespace essl3_shaders
+
+namespace essl31_shaders
+{
+
+const char *PositionAttrib()
+{
+    return "a_position";
+}
+
+namespace vs
+{
+
+// A shader that sets gl_Position to zero.
+const char *Zero()
+{
+    return R"(#version 310 es
+void main()
+{
+    gl_Position = vec4(0);
+})";
+}
+
+// A shader that sets gl_Position to attribute a_position.
+const char *Simple()
+{
+    return R"(#version 310 es
+in vec4 a_position;
+void main()
+{
+    gl_Position = a_position;
+})";
+}
+
+}  // namespace vs
+
+namespace fs
+{
+
+// A shader that fills with 100% opaque red.
+const char *Red()
+{
+    return R"(#version 310 es
+precision highp float;
+out vec4 my_FragColor;
+void main()
+{
+    my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+})";
+}
+
+}  // namespace fs
+}  // namespace essl31_shaders
+}  // namespace angle
diff --git a/util/shader_utils.h b/util/shader_utils.h
index 6e94e34..fca921b 100644
--- a/util/shader_utils.h
+++ b/util/shader_utils.h
@@ -44,4 +44,98 @@
 ANGLE_EXPORT GLuint LoadBinaryProgramOES(const std::vector<uint8_t> &binary, GLenum binaryFormat);
 ANGLE_EXPORT GLuint LoadBinaryProgramES3(const std::vector<uint8_t> &binary, GLenum binaryFormat);
 
+namespace angle
+{
+
+namespace essl1_shaders
+{
+
+ANGLE_EXPORT const char *PositionAttrib();
+ANGLE_EXPORT const char *ColorUniform();
+
+namespace vs
+{
+
+// A shader that sets gl_Position to zero.
+ANGLE_EXPORT const char *Zero();
+
+// A shader that sets gl_Position to attribute a_position.
+ANGLE_EXPORT const char *Simple();
+
+// A shader that passes through attribute a_position, setting it to gl_Position and varying
+// v_position.
+ANGLE_EXPORT const char *Passthrough();
+
+}  // namespace vs
+
+namespace fs
+{
+
+// A shader that renders a simple checker pattern of red and green. X axis and y axis separate the
+// different colors. Needs varying v_position.
+ANGLE_EXPORT const char *Checkered();
+
+// A shader that fills with color taken from uniform named "color".
+ANGLE_EXPORT const char *UniformColor();
+
+// A shader that fills with 100% opaque red.
+ANGLE_EXPORT const char *Red();
+
+// A shader that fills with 100% opaque blue.
+ANGLE_EXPORT const char *Blue();
+
+}  // namespace fs
+}  // namespace essl1_shaders
+
+namespace essl3_shaders
+{
+
+ANGLE_EXPORT const char *PositionAttrib();
+
+namespace vs
+{
+
+// A shader that sets gl_Position to zero.
+ANGLE_EXPORT const char *Zero();
+
+// A shader that sets gl_Position to attribute a_position.
+ANGLE_EXPORT const char *Simple();
+
+}  // namespace vs
+
+namespace fs
+{
+
+// A shader that fills with 100% opaque red.
+ANGLE_EXPORT const char *Red();
+
+}  // namespace fs
+}  // namespace essl3_shaders
+
+namespace essl31_shaders
+{
+
+ANGLE_EXPORT const char *PositionAttrib();
+
+namespace vs
+{
+
+// A shader that sets gl_Position to zero.
+ANGLE_EXPORT const char *Zero();
+
+// A shader that sets gl_Position to attribute a_position.
+ANGLE_EXPORT const char *Simple();
+
+}  // namespace vs
+
+namespace fs
+{
+
+// A shader that fills with 100% opaque red.
+ANGLE_EXPORT const char *Red();
+
+}  // namespace fs
+}  // namespace essl31_shaders
+}  // namespace angle
+
 #endif // SAMPLE_UTIL_SHADER_UTILS_H