Bug 1214917. Update ANGLE to 2535
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Thu, 15 Oct 2015 00:07:30 -0400
changeset 267946 e261ab579dfb744fa1a9cd72eb36054d364907c4
parent 267945 e940ae9e0f7121e4b5dbba6f30db812d2e97b4ee
child 267947 03f521f50792b4b4fd453d30f584001cf52dffe0
push id15718
push usercbook@mozilla.com
push dateFri, 16 Oct 2015 13:01:35 +0000
treeherderfx-team@3da0fdd88673 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1214917
milestone44.0a1
Bug 1214917. Update ANGLE to 2535
gfx/angle/DEPS
gfx/angle/include/GLSLANG/ShaderLang.h
gfx/angle/moz.build
gfx/angle/src/commit.h
gfx/angle/src/common/Float16ToFloat32.cpp
gfx/angle/src/common/Float16ToFloat32.py
gfx/angle/src/common/mathutil.cpp
gfx/angle/src/common/mathutil.h
gfx/angle/src/common/utilities.cpp
gfx/angle/src/common/utilities.h
gfx/angle/src/compiler.gypi
gfx/angle/src/compiler/preprocessor/DiagnosticsBase.cpp
gfx/angle/src/compiler/preprocessor/DiagnosticsBase.h
gfx/angle/src/compiler/preprocessor/DirectiveParser.cpp
gfx/angle/src/compiler/preprocessor/ExpressionParser.cpp
gfx/angle/src/compiler/preprocessor/ExpressionParser.h
gfx/angle/src/compiler/preprocessor/ExpressionParser.y
gfx/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
gfx/angle/src/compiler/translator/BaseTypes.h
gfx/angle/src/compiler/translator/Compiler.cpp
gfx/angle/src/compiler/translator/Compiler.h
gfx/angle/src/compiler/translator/Initialize.cpp
gfx/angle/src/compiler/translator/IntermNode.h
gfx/angle/src/compiler/translator/IntermTraverse.cpp
gfx/angle/src/compiler/translator/OutputGLSL.cpp
gfx/angle/src/compiler/translator/OutputGLSLBase.cpp
gfx/angle/src/compiler/translator/OutputHLSL.cpp
gfx/angle/src/compiler/translator/ParseContext.cpp
gfx/angle/src/compiler/translator/RewriteDoWhile.cpp
gfx/angle/src/compiler/translator/RewriteDoWhile.h
gfx/angle/src/compiler/translator/RewriteElseBlocks.cpp
gfx/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
gfx/angle/src/compiler/translator/TranslatorESSL.cpp
gfx/angle/src/compiler/translator/TranslatorGLSL.cpp
gfx/angle/src/compiler/translator/TranslatorHLSL.cpp
gfx/angle/src/compiler/translator/Types.cpp
gfx/angle/src/compiler/translator/Types.h
gfx/angle/src/compiler/translator/VariableInfo.cpp
gfx/angle/src/compiler/translator/VariableInfo.h
gfx/angle/src/compiler/translator/blocklayout.h
gfx/angle/src/compiler/translator/depgraph/DependencyGraph.cpp
gfx/angle/src/compiler/translator/depgraph/DependencyGraph.h
gfx/angle/src/compiler/translator/intermOut.cpp
gfx/angle/src/compiler/translator/util.h
gfx/angle/src/libANGLE/AttributeMap.h
gfx/angle/src/libANGLE/BinaryStream.h
gfx/angle/src/libANGLE/Context.cpp
gfx/angle/src/libANGLE/Data.cpp
gfx/angle/src/libANGLE/Data.h
gfx/angle/src/libANGLE/Display.cpp
gfx/angle/src/libANGLE/Framebuffer.cpp
gfx/angle/src/libANGLE/Framebuffer.h
gfx/angle/src/libANGLE/FramebufferAttachment.h
gfx/angle/src/libANGLE/Program.cpp
gfx/angle/src/libANGLE/Program.h
gfx/angle/src/libANGLE/Query.cpp
gfx/angle/src/libANGLE/Query.h
gfx/angle/src/libANGLE/ResourceManager.cpp
gfx/angle/src/libANGLE/Sampler.cpp
gfx/angle/src/libANGLE/Sampler.h
gfx/angle/src/libANGLE/State.cpp
gfx/angle/src/libANGLE/State.h
gfx/angle/src/libANGLE/Uniform.cpp
gfx/angle/src/libANGLE/Uniform.h
gfx/angle/src/libANGLE/angletypes.h
gfx/angle/src/libANGLE/formatutils.cpp
gfx/angle/src/libANGLE/formatutils.h
gfx/angle/src/libANGLE/moz.build
gfx/angle/src/libANGLE/renderer/ImplFactory.h
gfx/angle/src/libANGLE/renderer/ProgramImpl.h
gfx/angle/src/libANGLE/renderer/SamplerImpl.h
gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h
gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.h
gfx/angle/src/libANGLE/renderer/d3d/SamplerD3D.h
gfx/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp
gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h
gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h
gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h
gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.h
gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
gfx/angle/src/libANGLE/renderer/gl/CompilerGL.h
gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.h
gfx/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp
gfx/angle/src/libANGLE/renderer/gl/ProgramGL.cpp
gfx/angle/src/libANGLE/renderer/gl/ProgramGL.h
gfx/angle/src/libANGLE/renderer/gl/QueryGL.cpp
gfx/angle/src/libANGLE/renderer/gl/QueryGL.h
gfx/angle/src/libANGLE/renderer/gl/RendererGL.cpp
gfx/angle/src/libANGLE/renderer/gl/RendererGL.h
gfx/angle/src/libANGLE/renderer/gl/SamplerGL.cpp
gfx/angle/src/libANGLE/renderer/gl/SamplerGL.h
gfx/angle/src/libANGLE/renderer/gl/ShaderGL.cpp
gfx/angle/src/libANGLE/renderer/gl/ShaderGL.h
gfx/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp
gfx/angle/src/libANGLE/renderer/gl/StateManagerGL.h
gfx/angle/src/libANGLE/renderer/gl/SurfaceGL.cpp
gfx/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h
gfx/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h
gfx/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm
gfx/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h
gfx/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm
gfx/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp
gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp
gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h
gfx/angle/src/libANGLE/validationES.cpp
gfx/angle/src/libANGLE/validationES.h
gfx/angle/src/libANGLE/validationES2.cpp
gfx/angle/src/libANGLE/validationES3.cpp
gfx/angle/src/libGLESv2.gypi
gfx/angle/src/libGLESv2/entry_points_gles_2_0.cpp
gfx/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp
gfx/angle/src/libGLESv2/entry_points_gles_3_0.cpp
gfx/angle/src/tests/BUILD.gn
gfx/angle/src/tests/angle_perftests.gypi
gfx/angle/src/tests/angle_unittests.gypi
gfx/angle/src/tests/angle_unittests_utils.h
gfx/angle/src/tests/compiler_tests/CollectVariables_test.cpp
gfx/angle/src/tests/compiler_tests/FragDepth_test.cpp
gfx/angle/src/tests/compiler_tests/MalformedShader_test.cpp
gfx/angle/src/tests/deqp.gypi
gfx/angle/src/tests/deqp_support/angle_deqp_gtest.cpp
gfx/angle/src/tests/deqp_support/angle_deqp_libtester_main.cpp
gfx/angle/src/tests/deqp_support/deqp_gles2_test_expectations.txt
gfx/angle/src/tests/deqp_support/deqp_gles3_test_expectations.txt
gfx/angle/src/tests/deqp_support/tcuANGLENativeDisplayFactory.cpp
gfx/angle/src/tests/egl_tests/EGLSurfaceTest.cpp
gfx/angle/src/tests/gl_tests/BlendMinMaxTest.cpp
gfx/angle/src/tests/gl_tests/ClearTest.cpp
gfx/angle/src/tests/gl_tests/D3D11FormatTablesTest.cpp
gfx/angle/src/tests/gl_tests/OcclusionQueriesTest.cpp
gfx/angle/src/tests/gl_tests/PackUnpackTest.cpp
gfx/angle/src/tests/gl_tests/PointSpritesTest.cpp
gfx/angle/src/tests/gl_tests/ProgramBinaryTest.cpp
gfx/angle/src/tests/gl_tests/SwizzleTest.cpp
gfx/angle/src/tests/gl_tests/TextureTest.cpp
gfx/angle/src/tests/gl_tests/TransformFeedbackTest.cpp
gfx/angle/src/tests/gl_tests/UniformBufferTest.cpp
gfx/angle/src/tests/gl_tests/UniformTest.cpp
gfx/angle/src/tests/gl_tests/VertexAttributeTest.cpp
gfx/angle/src/tests/preprocessor_tests/define_test.cpp
gfx/angle/src/tests/preprocessor_tests/location_test.cpp
--- a/gfx/angle/DEPS
+++ b/gfx/angle/DEPS
@@ -9,16 +9,20 @@ deps = {
   # TODO(kbr): figure out how to better stay in sync with Chromium's
   # versions of googletest and googlemock.
   "src/tests/third_party/googletest":
       Var('chromium_git') + "/external/googletest.git@9855a87157778d39b95eccfb201a9dc90f6d61c6",
 
   "src/tests/third_party/googlemock":
       Var('chromium_git') + "/external/googlemock.git@b2cb211e49d872101d991201362d7b97d7d69910",
 
+  # Cherry is a dEQP management GUI written in Go. We use it for viewing test results.
+  "third_party/cherry":
+      "https://android.googlesource.com/platform/external/cherry@af6c09fe05115f0cca61ae23ee871bda27cf1ff5",
+
   "third_party/deqp/src":
       "https://android.googlesource.com/platform/external/deqp@92f7752da82925ca5e7288c5b4814efa7a381d89",
 
   "third_party/libpng":
       "https://android.googlesource.com/platform/external/libpng@094e181e79a3d6c23fd005679025058b7df1ad6c",
 
   "third_party/zlib":
       Var('chromium_git') + "/chromium/src/third_party/zlib@afd8c4593c010c045902f6c0501718f1823064a3",
--- a/gfx/angle/include/GLSLANG/ShaderLang.h
+++ b/gfx/angle/include/GLSLANG/ShaderLang.h
@@ -194,16 +194,20 @@ typedef enum {
   // This flag makes the compiler not prune unused function early in the
   // compilation process. Pruning coupled with SH_LIMIT_CALL_STACK_DEPTH
   // helps avoid bad shaders causing stack overflows.
   SH_DONT_PRUNE_UNUSED_FUNCTIONS = 0x100000,
 
   // This flag works around a bug in NVIDIA 331 series drivers related
   // to pow(x, y) where y is a constant vector.
   SH_REMOVE_POW_WITH_CONSTANT_EXPONENT = 0x200000,
+
+  // This flag works around bugs in Mac drivers related to do-while by
+  // transforming them into an other construct.
+  SH_REWRITE_DO_WHILE_LOOPS = 0x400000,
 } ShCompileOptions;
 
 // Defines alternate strategies for implementing array index clamping.
 typedef enum {
   // Use the clamp intrinsic for array index clamping.
   SH_CLAMP_WITH_CLAMP_INTRINSIC = 1,
 
   // Use a user-defined function for array index clamping.
--- a/gfx/angle/moz.build
+++ b/gfx/angle/moz.build
@@ -67,16 +67,17 @@ UNIFIED_SOURCES += [
     'src/compiler/translator/ParseContext.cpp',
     'src/compiler/translator/PoolAlloc.cpp',
     'src/compiler/translator/PruneEmptyDeclarations.cpp',
     'src/compiler/translator/RecordConstantPrecision.cpp',
     'src/compiler/translator/RegenerateStructNames.cpp',
     'src/compiler/translator/RemoveDynamicIndexing.cpp',
     'src/compiler/translator/RemovePow.cpp',
     'src/compiler/translator/RemoveSwitchFallThrough.cpp',
+    'src/compiler/translator/RewriteDoWhile.cpp',
     'src/compiler/translator/RewriteElseBlocks.cpp',
     'src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp',
     'src/compiler/translator/SearchSymbol.cpp',
     'src/compiler/translator/SeparateArrayInitialization.cpp',
     'src/compiler/translator/SeparateDeclarations.cpp',
     'src/compiler/translator/SeparateExpressionsReturningArrays.cpp',
     'src/compiler/translator/ShaderLang.cpp',
     'src/compiler/translator/ShaderVars.cpp',
--- a/gfx/angle/src/commit.h
+++ b/gfx/angle/src/commit.h
@@ -1,3 +1,3 @@
-#define ANGLE_COMMIT_HASH "4a2a4c31a988"
+#define ANGLE_COMMIT_HASH "ffabe8783f4a"
 #define ANGLE_COMMIT_HASH_SIZE 12
-#define ANGLE_COMMIT_DATE "2015-09-29 14:41:08 -0400"
+#define ANGLE_COMMIT_DATE "2015-10-14 14:24:04 -0400"
--- a/gfx/angle/src/common/Float16ToFloat32.cpp
+++ b/gfx/angle/src/common/Float16ToFloat32.cpp
@@ -1,16 +1,18 @@
 //
 // Copyright (c) 2012 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 file is automatically generated.
 
+#include "common/mathutil.h"
+
 namespace gl
 {
 
 const static unsigned g_mantissa[2048] = {
     0x00000000,
     0x33800000,
     0x34000000,
     0x34400000,
@@ -2192,12 +2194,12 @@ const static unsigned g_offset[64] = {
     0x00000400,
     0x00000400,
     0x00000400,
 };
 
 float float16ToFloat32(unsigned short h)
 {
     unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10];
-    return *(float*) &i32;
+    return bitCast<float>(i32);
 }
 }
 
--- a/gfx/angle/src/common/Float16ToFloat32.py
+++ b/gfx/angle/src/common/Float16ToFloat32.py
@@ -2,16 +2,18 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 #
 
 # This script generates a function that converts 16-bit precision floating
 # point numbers to 32-bit.
 # It is based on ftp://ftp.fox-toolkit.org/pub/fasthalffloatconversion.pdf.
 
+#include "common/mathutil.h"
+
 def convertMantissa(i):
     if i == 0:
         return 0
     elif i < 1024:
         m = i << 13
         e = 0
         while not (m & 0x00800000):
             e -= 0x00800000
@@ -67,12 +69,12 @@ print "};\n"
 print "const static unsigned g_offset[64] = {"
 for i in range(0, 64):
     print "    %#010x," % convertOffset(i)
 print "};\n"
 
 print """float float16ToFloat32(unsigned short h)
 {
     unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10];
-    return *(float*) &i32;
+    return bitCast<float>(i32);
 }
 }
 """
--- a/gfx/angle/src/common/mathutil.cpp
+++ b/gfx/angle/src/common/mathutil.cpp
@@ -47,17 +47,17 @@ unsigned int convertRGBFloatsTo999E5(flo
     const int exp_s = static_cast<int>((max_s < pow(2.0f, g_sharedexp_mantissabits)) ? exp_p : exp_p + 1);
 
     RGB9E5Data output;
     output.R = static_cast<unsigned int>(floor((red_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
     output.G = static_cast<unsigned int>(floor((green_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
     output.B = static_cast<unsigned int>(floor((blue_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
     output.E = exp_s;
 
-    return *reinterpret_cast<unsigned int*>(&output);
+    return bitCast<unsigned int>(output);
 }
 
 void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float *blue)
 {
     const RGB9E5Data *inputData = reinterpret_cast<const RGB9E5Data*>(&input);
 
     *red = inputData->R * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits);
     *green = inputData->G * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits);
--- a/gfx/angle/src/common/mathutil.h
+++ b/gfx/angle/src/common/mathutil.h
@@ -64,24 +64,39 @@ inline unsigned int ceilPow2(unsigned in
 inline int clampToInt(unsigned int x)
 {
     return static_cast<int>(std::min(x, static_cast<unsigned int>(std::numeric_limits<int>::max())));
 }
 
 template <typename DestT, typename SrcT>
 inline DestT clampCast(SrcT value)
 {
-    SrcT lo = static_cast<SrcT>(std::numeric_limits<DestT>::min());
-    SrcT hi = static_cast<SrcT>(std::numeric_limits<DestT>::max());
+    static const DestT destLo = std::numeric_limits<DestT>::min();
+    static const DestT destHi = std::numeric_limits<DestT>::max();
+    static const SrcT srcLo = static_cast<SrcT>(destLo);
+    static const SrcT srcHi = static_cast<SrcT>(destHi);
 
-    // This assumes SrcT can properly represent DestT::min/max. Checking this is a bit tricky,
-    // especially given floating point representations.
-    ASSERT(lo < hi);
-
-    return static_cast<DestT>(value > lo ? (value > hi ? hi : value) : lo);
+    // When value is outside of or equal to the limits for DestT we use the DestT limit directly.
+    // This avoids undefined behaviors due to loss of precision when converting from floats to
+    // integers:
+    //    destHi for ints is 2147483647 but the closest float number is around 2147483648, so when
+    //  doing a conversion from float to int we run into an UB because the float is outside of the
+    //  range representable by the int.
+    if (value <= srcLo)
+    {
+        return destLo;
+    }
+    else if (value >= srcHi)
+    {
+        return destHi;
+    }
+    else
+    {
+        return static_cast<DestT>(value);
+    }
 }
 
 template<typename T, typename MIN, typename MAX>
 inline T clamp(T x, MIN min, MAX max)
 {
     // Since NaNs fail all comparison tests, a NaN value will default to min
     return x > min ? (x > max ? max : x) : min;
 }
@@ -146,17 +161,17 @@ destType bitCast(const sourceType &sourc
     size_t copySize = std::min(sizeof(destType), sizeof(sourceType));
     destType output;
     memcpy(&output, &source, copySize);
     return output;
 }
 
 inline unsigned short float32ToFloat16(float fp32)
 {
-    unsigned int fp32i = (unsigned int&)fp32;
+    unsigned int fp32i = bitCast<unsigned int>(fp32);
     unsigned int sign = (fp32i & 0x80000000) >> 16;
     unsigned int abs = fp32i & 0x7FFFFFFF;
 
     if(abs > 0x47FFEFFF)   // Infinity
     {
         return static_cast<unsigned short>(sign | 0x7FFF);
     }
     else if(abs < 0x38800000)   // Denormal
--- a/gfx/angle/src/common/utilities.cpp
+++ b/gfx/angle/src/common/utilities.cpp
@@ -634,18 +634,34 @@ std::string ParseUniformName(const std::
         {
             *outSubscript = GL_INVALID_INDEX;
         }
     }
 
     return name.substr(0, open);
 }
 
+unsigned int ParseAndStripArrayIndex(std::string *name)
+{
+    unsigned int subscript = GL_INVALID_INDEX;
+
+    // Strip any trailing array operator and retrieve the subscript
+    size_t open  = name->find_last_of('[');
+    size_t close = name->find_last_of(']');
+    if (open != std::string::npos && close == name->length() - 1)
+    {
+        subscript = atoi(name->c_str() + open + 1);
+        name->erase(open);
+    }
+
+    return subscript;
 }
 
+}  // namespace gl
+
 namespace egl
 {
 static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 1,
               "Unexpected EGL cube map enum value.");
 static_assert(EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 2,
               "Unexpected EGL cube map enum value.");
 static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 3,
               "Unexpected EGL cube map enum value.");
--- a/gfx/angle/src/common/utilities.h
+++ b/gfx/angle/src/common/utilities.h
@@ -63,17 +63,19 @@ GLuint GetPrimitiveRestartIndex(GLenum i
 bool IsTriangleMode(GLenum drawMode);
 
 // [OpenGL ES 3.0.2] Section 2.3.1 page 14
 // Data Conversion For State-Setting Commands
 // Floating-point values are rounded to the nearest integer, instead of truncated, as done by static_cast.
 template <typename outT> outT iround(GLfloat value) { return static_cast<outT>(value > 0.0f ? floor(value + 0.5f) : ceil(value - 0.5f)); }
 template <typename outT> outT uiround(GLfloat value) { return static_cast<outT>(value + 0.5f); }
 
-}
+unsigned int ParseAndStripArrayIndex(std::string *name);
+
+}  // namespace gl
 
 namespace egl
 {
 static const EGLenum FirstCubeMapTextureTarget = EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
 static const EGLenum LastCubeMapTextureTarget = EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR;
 bool IsCubeMapTextureTarget(EGLenum target);
 size_t CubeMapTextureTargetToLayerIndex(EGLenum target);
 EGLenum LayerIndexToCubeMapTextureTarget(size_t index);
--- a/gfx/angle/src/compiler.gypi
+++ b/gfx/angle/src/compiler.gypi
@@ -84,16 +84,18 @@
             'compiler/translator/PruneEmptyDeclarations.cpp',
             'compiler/translator/PruneEmptyDeclarations.h',
             'compiler/translator/RecordConstantPrecision.cpp',
             'compiler/translator/RecordConstantPrecision.h',
             'compiler/translator/RegenerateStructNames.cpp',
             'compiler/translator/RegenerateStructNames.h',
             'compiler/translator/RemovePow.cpp',
             'compiler/translator/RemovePow.h',
+            'compiler/translator/RewriteDoWhile.cpp',
+            'compiler/translator/RewriteDoWhile.h',
             'compiler/translator/RenameFunction.h',
             'compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp',
             'compiler/translator/ScalarizeVecAndMatConstructorArgs.h',
             'compiler/translator/SearchSymbol.cpp',
             'compiler/translator/SearchSymbol.h',
             'compiler/translator/SymbolTable.cpp',
             'compiler/translator/SymbolTable.h',
             'compiler/translator/TranslatorESSL.cpp',
--- a/gfx/angle/src/compiler/preprocessor/DiagnosticsBase.cpp
+++ b/gfx/angle/src/compiler/preprocessor/DiagnosticsBase.cpp
@@ -120,16 +120,18 @@ std::string Diagnostics::message(ID id)
       case PP_EOF_IN_DIRECTIVE:
         return "unexpected end of file found in directive";
       case PP_CONDITIONAL_UNEXPECTED_TOKEN:
         return "unexpected token after conditional expression";
       case PP_UNRECOGNIZED_PRAGMA:
         return "unrecognized pragma";
       case PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL1:
         return "extension directive should occur before any non-preprocessor tokens";
+      case PP_WARNING_MACRO_NAME_RESERVED:
+        return "macro name with a double underscore is reserved - unintented behavior is possible";
       // Warnings end.
       default:
         assert(false);
         return "";
     }
 }
 
 }  // namespace pp
--- a/gfx/angle/src/compiler/preprocessor/DiagnosticsBase.h
+++ b/gfx/angle/src/compiler/preprocessor/DiagnosticsBase.h
@@ -66,16 +66,17 @@ class Diagnostics
         PP_INVALID_LINE_DIRECTIVE,
         PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3,
         PP_ERROR_END,
 
         PP_WARNING_BEGIN,
         PP_EOF_IN_DIRECTIVE,
         PP_UNRECOGNIZED_PRAGMA,
         PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL1,
+        PP_WARNING_MACRO_NAME_RESERVED,
         PP_WARNING_END
     };
 
     virtual ~Diagnostics();
 
     void report(ID id, const SourceLocation &loc, const std::string &text);
 
   protected:
--- a/gfx/angle/src/compiler/preprocessor/DirectiveParser.cpp
+++ b/gfx/angle/src/compiler/preprocessor/DirectiveParser.cpp
@@ -114,24 +114,22 @@ void skipUntilEOD(pp::Lexer *lexer, pp::
     {
         lexer->lex(token);
     }
 }
 
 bool isMacroNameReserved(const std::string &name)
 {
     // Names prefixed with "GL_" are reserved.
-    if (name.substr(0, 3) == "GL_")
-        return true;
+    return (name.substr(0, 3) == "GL_");
+}
 
-    // Names containing two consecutive underscores are reserved.
-    if (name.find("__") != std::string::npos)
-        return true;
-
-    return false;
+bool hasDoubleUnderscores(const std::string &name)
+{
+    return (name.find("__") != std::string::npos);
 }
 
 bool isMacroPredefined(const std::string &name,
                        const pp::MacroSet &macroSet)
 {
     pp::MacroSet::const_iterator iter = macroSet.find(name);
     return iter != macroSet.end() ? iter->second.predefined : false;
 }
@@ -286,16 +284,26 @@ void DirectiveParser::parseDefine(Token 
         return;
     }
     if (isMacroNameReserved(token->text))
     {
         mDiagnostics->report(Diagnostics::PP_MACRO_NAME_RESERVED,
                              token->location, token->text);
         return;
     }
+    // Using double underscores is allowed, but may result in unintended
+    // behavior, so a warning is issued. At the time of writing this was
+    // specified in ESSL 3.10, but the intent judging from Khronos
+    // discussions and dEQP tests was that double underscores should be
+    // allowed in earlier ESSL versions too.
+    if (hasDoubleUnderscores(token->text))
+    {
+        mDiagnostics->report(Diagnostics::PP_WARNING_MACRO_NAME_RESERVED, token->location,
+                             token->text);
+    }
 
     Macro macro;
     macro.type = Macro::kTypeObj;
     macro.name = token->text;
 
     mTokenizer->lex(token);
     if (token->type == '(' && !token->hasLeadingSpace())
     {
@@ -759,82 +767,70 @@ void DirectiveParser::parseVersion(Token
         PredefineMacro(mMacroSet, "__VERSION__", version);
     }
 }
 
 void DirectiveParser::parseLine(Token *token)
 {
     assert(getDirective(token) == DIRECTIVE_LINE);
 
-    enum State
-    {
-        LINE_NUMBER,
-        FILE_NUMBER
-    };
-
     bool valid = true;
+    bool parsedFileNumber = false;
     int line = 0, file = 0;
-    int state = LINE_NUMBER;
 
     MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, false);
+
+    // Lex the first token after "#line" so we can check it for EOD.
     macroExpander.lex(token);
-    while ((token->type != '\n') && (token->type != Token::LAST))
+
+    if (isEOD(token))
+    {
+        mDiagnostics->report(Diagnostics::PP_INVALID_LINE_DIRECTIVE, token->location, token->text);
+        valid = false;
+    }
+    else
     {
-        switch (state++)
+        ExpressionParser expressionParser(&macroExpander, mDiagnostics);
+        ExpressionParser::ErrorSettings errorSettings;
+
+        // See GLES3 section 12.42
+        errorSettings.integerLiteralsMustFit32BitSignedRange = true;
+
+        errorSettings.unexpectedIdentifier = Diagnostics::PP_INVALID_LINE_NUMBER;
+        // The first token was lexed earlier to check if it was EOD. Include
+        // the token in parsing for a second time by setting the
+        // parsePresetToken flag to true.
+        expressionParser.parse(token, &line, true, errorSettings, &valid);
+        if (!isEOD(token) && valid)
         {
-          case LINE_NUMBER:
-            if (valid && (token->type != Token::CONST_INT))
-            {
-                mDiagnostics->report(Diagnostics::PP_INVALID_LINE_NUMBER,
-                                     token->location, token->text);
-                valid = false;
-            }
-            if (valid && !token->iValue(&line))
-            {
-                mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW,
-                                     token->location, token->text);
-                valid = false;
-            }
-            break;
-          case FILE_NUMBER:
-            if (valid && (token->type != Token::CONST_INT))
-            {
-                mDiagnostics->report(Diagnostics::PP_INVALID_FILE_NUMBER,
-                                     token->location, token->text);
-                valid = false;
-            }
-            if (valid && !token->iValue(&file))
-            {
-                mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW,
-                                     token->location, token->text);
-                valid = false;
-            }
-            break;
-          default:
+            errorSettings.unexpectedIdentifier = Diagnostics::PP_INVALID_FILE_NUMBER;
+            // After parsing the line expression expressionParser has also
+            // advanced to the first token of the file expression - this is the
+            // token that makes the parser reduce the "input" rule for the line
+            // expression and stop. So we're using parsePresetToken = true here
+            // as well.
+            expressionParser.parse(token, &file, true, errorSettings, &valid);
+            parsedFileNumber = true;
+        }
+        if (!isEOD(token))
+        {
             if (valid)
             {
                 mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
                                      token->location, token->text);
                 valid = false;
             }
-            break;
+            skipUntilEOD(mTokenizer, token);
         }
-        macroExpander.lex(token);
     }
 
-    if (valid && (state != FILE_NUMBER) && (state != FILE_NUMBER + 1))
-    {
-        mDiagnostics->report(Diagnostics::PP_INVALID_LINE_DIRECTIVE,
-                             token->location, token->text);
-        valid = false;
-    }
     if (valid)
     {
         mTokenizer->setLineNumber(line);
-        if (state == FILE_NUMBER + 1)
+        if (parsedFileNumber)
             mTokenizer->setFileNumber(file);
     }
 }
 
 bool DirectiveParser::skipping() const
 {
     if (mConditionalStack.empty())
         return false;
@@ -888,17 +884,22 @@ int DirectiveParser::parseExpressionIf(T
 {
     assert((getDirective(token) == DIRECTIVE_IF) ||
            (getDirective(token) == DIRECTIVE_ELIF));
 
     MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, true);
     ExpressionParser expressionParser(&macroExpander, mDiagnostics);
 
     int expression = 0;
-    expressionParser.parse(token, &expression);
+    ExpressionParser::ErrorSettings errorSettings;
+    errorSettings.integerLiteralsMustFit32BitSignedRange = false;
+    errorSettings.unexpectedIdentifier                   = Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN;
+
+    bool valid = true;
+    expressionParser.parse(token, &expression, false, errorSettings, &valid);
 
     // Check if there are tokens after #if expression.
     if (!isEOD(token))
     {
         mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
                              token->location, token->text);
         skipUntilEOD(mTokenizer, token);
     }
--- a/gfx/angle/src/compiler/preprocessor/ExpressionParser.cpp
+++ b/gfx/angle/src/compiler/preprocessor/ExpressionParser.cpp
@@ -118,16 +118,20 @@ typedef intmax_t YYSTYPE;
 
 namespace {
 struct Context
 {
     pp::Diagnostics* diagnostics;
     pp::Lexer* lexer;
     pp::Token* token;
     int* result;
+    bool parsePresetToken;
+
+    pp::ExpressionParser::ErrorSettings errorSettings;
+    bool *valid;
 
     void startIgnoreErrors() { ++ignoreErrors; }
     void endIgnoreErrors() { --ignoreErrors; }
 
     bool isIgnoringErrors() { return ignoreErrors > 0; }
 
     int ignoreErrors;
 };
@@ -491,19 +495,19 @@ static const yytype_uint8 yytranslate[] 
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        5,     6,    10,    11,    14,    15,    16,    17,    23
 };
 
 #if YYDEBUG
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   106,   106,   113,   114,   124,   124,   145,   145,   166,
-     169,   172,   175,   178,   181,   184,   187,   190,   193,   196,
-     199,   202,   205,   224,   243,   246,   249,   252,   255,   258
+       0,   110,   110,   117,   118,   129,   129,   150,   150,   171,
+     174,   177,   180,   183,   186,   189,   192,   195,   198,   201,
+     204,   207,   210,   230,   250,   253,   256,   259,   262,   265
 };
 #endif
 
 #if YYDEBUG || YYERROR_VERBOSE || 0
 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
 {
@@ -1338,18 +1342,19 @@ yyreduce:
 
   case 4:
 
     {
         if (!context->isIgnoringErrors())
         {
             // This rule should be applied right after the token is lexed, so we can
             // refer to context->token in the error message.
-            context->diagnostics->report(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
+            context->diagnostics->report(context->errorSettings.unexpectedIdentifier,
                                          context->token->location, context->token->text);
+            *(context->valid) = false;
         }
         (yyval) = (yyvsp[0]);
     }
 
     break;
 
   case 5:
 
@@ -1527,16 +1532,17 @@ yyreduce:
             if (!context->isIgnoringErrors())
             {
                 std::ostringstream stream;
                 stream << (yyvsp[-2]) << " % " << (yyvsp[0]);
                 std::string text = stream.str();
                 context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
                                              context->token->location,
                                              text.c_str());
+                *(context->valid) = false;
             }
             (yyval) = static_cast<YYSTYPE>(0);
         }
         else
         {
             (yyval) = (yyvsp[-2]) % (yyvsp[0]);
         }
     }
@@ -1551,16 +1557,17 @@ yyreduce:
             if (!context->isIgnoringErrors())
             {
                 std::ostringstream stream;
                 stream << (yyvsp[-2]) << " / " << (yyvsp[0]);
                 std::string text = stream.str();
                 context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
                                             context->token->location,
                                             text.c_str());
+                *(context->valid) = false;
             }
             (yyval) = static_cast<YYSTYPE>(0);
         }
         else
         {
             (yyval) = (yyvsp[-2]) / (yyvsp[0]);
         }
     }
@@ -1845,28 +1852,35 @@ yyreturn:
   return yyresult;
 }
 
 
 
 int yylex(YYSTYPE *lvalp, Context *context)
 {
     pp::Token *token = context->token;
-    context->lexer->lex(token);
+    if (!context->parsePresetToken)
+    {
+        context->lexer->lex(token);
+    }
+    context->parsePresetToken = false;
 
     int type = 0;
 
     switch (token->type)
     {
       case pp::Token::CONST_INT: {
         unsigned int val = 0;
-        if (!token->uValue(&val))
+        int testVal = 0;
+        if (!token->uValue(&val) || (!token->iValue(&testVal) &&
+                                     context->errorSettings.integerLiteralsMustFit32BitSignedRange))
         {
             context->diagnostics->report(pp::Diagnostics::PP_INTEGER_OVERFLOW,
                                          token->location, token->text);
+            *(context->valid) = false;
         }
         *lvalp = static_cast<YYSTYPE>(val);
         type = TOK_CONST_INT;
         break;
       }
       case pp::Token::IDENTIFIER:
         *lvalp = static_cast<YYSTYPE>(-1);
         type = TOK_IDENTIFIER;
@@ -1929,24 +1943,31 @@ void yyerror(Context *context, const cha
 namespace pp {
 
 ExpressionParser::ExpressionParser(Lexer *lexer, Diagnostics *diagnostics)
     : mLexer(lexer),
       mDiagnostics(diagnostics)
 {
 }
 
-bool ExpressionParser::parse(Token *token, int *result)
+bool ExpressionParser::parse(Token *token,
+                             int *result,
+                             bool parsePresetToken,
+                             const ErrorSettings &errorSettings,
+                             bool *valid)
 {
     Context context;
     context.diagnostics = mDiagnostics;
     context.lexer = mLexer;
     context.token = token;
     context.result = result;
     context.ignoreErrors = 0;
+    context.parsePresetToken = parsePresetToken;
+    context.errorSettings    = errorSettings;
+    context.valid            = valid;
     int ret = yyparse(&context);
     switch (ret)
     {
       case 0:
       case 1:
         break;
 
       case 2:
--- a/gfx/angle/src/compiler/preprocessor/ExpressionParser.h
+++ b/gfx/angle/src/compiler/preprocessor/ExpressionParser.h
@@ -2,31 +2,41 @@
 // Copyright (c) 2012 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.
 //
 
 #ifndef COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
 #define COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
 
+#include "DiagnosticsBase.h"
 #include "pp_utils.h"
 
 namespace pp
 {
 
-class Diagnostics;
 class Lexer;
 struct Token;
 
 class ExpressionParser
 {
   public:
+    struct ErrorSettings
+    {
+        Diagnostics::ID unexpectedIdentifier;
+        bool integerLiteralsMustFit32BitSignedRange;
+    };
+
     ExpressionParser(Lexer *lexer, Diagnostics *diagnostics);
 
-    bool parse(Token *token, int *result);
+    bool parse(Token *token,
+               int *result,
+               bool parsePresetToken,
+               const ErrorSettings &errorSettings,
+               bool *valid);
 
   private:
     PP_DISALLOW_COPY_AND_ASSIGN(ExpressionParser);
 
     Lexer *mLexer;
     Diagnostics *mDiagnostics;
 };
 
--- a/gfx/angle/src/compiler/preprocessor/ExpressionParser.y
+++ b/gfx/angle/src/compiler/preprocessor/ExpressionParser.y
@@ -60,16 +60,20 @@ typedef intmax_t YYSTYPE;
 
 namespace {
 struct Context
 {
     pp::Diagnostics* diagnostics;
     pp::Lexer* lexer;
     pp::Token* token;
     int* result;
+    bool parsePresetToken;
+
+    pp::ExpressionParser::ErrorSettings errorSettings;
+    bool *valid;
 
     void startIgnoreErrors() { ++ignoreErrors; }
     void endIgnoreErrors() { --ignoreErrors; }
 
     bool isIgnoringErrors() { return ignoreErrors > 0; }
 
     int ignoreErrors;
 };
@@ -111,18 +115,19 @@ input
 
 expression
     : TOK_CONST_INT
     | TOK_IDENTIFIER {
         if (!context->isIgnoringErrors())
         {
             // This rule should be applied right after the token is lexed, so we can
             // refer to context->token in the error message.
-            context->diagnostics->report(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
+            context->diagnostics->report(context->errorSettings.unexpectedIdentifier,
                                          context->token->location, context->token->text);
+            *(context->valid) = false;
         }
         $$ = $1;
     }
     | expression TOK_OP_OR {
         if ($1 != 0)
         {
             // Ignore errors in the short-circuited part of the expression.
             // ESSL3.00 section 3.4:
@@ -208,16 +213,17 @@ expression
             if (!context->isIgnoringErrors())
             {
                 std::ostringstream stream;
                 stream << $1 << " % " << $3;
                 std::string text = stream.str();
                 context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
                                              context->token->location,
                                              text.c_str());
+                *(context->valid) = false;
             }
             $$ = static_cast<YYSTYPE>(0);
         }
         else
         {
             $$ = $1 % $3;
         }
     }
@@ -227,16 +233,17 @@ expression
             if (!context->isIgnoringErrors())
             {
                 std::ostringstream stream;
                 stream << $1 << " / " << $3;
                 std::string text = stream.str();
                 context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
                                             context->token->location,
                                             text.c_str());
+                *(context->valid) = false;
             }
             $$ = static_cast<YYSTYPE>(0);
         }
         else
         {
             $$ = $1 / $3;
         }
     }
@@ -260,28 +267,35 @@ expression
     }
 ;
 
 %%
 
 int yylex(YYSTYPE *lvalp, Context *context)
 {
     pp::Token *token = context->token;
-    context->lexer->lex(token);
+    if (!context->parsePresetToken)
+    {
+        context->lexer->lex(token);
+    }
+    context->parsePresetToken = false;
 
     int type = 0;
 
     switch (token->type)
     {
       case pp::Token::CONST_INT: {
         unsigned int val = 0;
-        if (!token->uValue(&val))
+        int testVal = 0;
+        if (!token->uValue(&val) || (!token->iValue(&testVal) &&
+                                     context->errorSettings.integerLiteralsMustFit32BitSignedRange))
         {
             context->diagnostics->report(pp::Diagnostics::PP_INTEGER_OVERFLOW,
                                          token->location, token->text);
+            *(context->valid) = false;
         }
         *lvalp = static_cast<YYSTYPE>(val);
         type = TOK_CONST_INT;
         break;
       }
       case pp::Token::IDENTIFIER:
         *lvalp = static_cast<YYSTYPE>(-1);
         type = TOK_IDENTIFIER;
@@ -344,24 +358,31 @@ void yyerror(Context *context, const cha
 namespace pp {
 
 ExpressionParser::ExpressionParser(Lexer *lexer, Diagnostics *diagnostics)
     : mLexer(lexer),
       mDiagnostics(diagnostics)
 {
 }
 
-bool ExpressionParser::parse(Token *token, int *result)
+bool ExpressionParser::parse(Token *token,
+                             int *result,
+                             bool parsePresetToken,
+                             const ErrorSettings &errorSettings,
+                             bool *valid)
 {
     Context context;
     context.diagnostics = mDiagnostics;
     context.lexer = mLexer;
     context.token = token;
     context.result = result;
     context.ignoreErrors = 0;
+    context.parsePresetToken = parsePresetToken;
+    context.errorSettings    = errorSettings;
+    context.valid            = valid;
     int ret = yyparse(&context);
     switch (ret)
     {
       case 0:
       case 1:
         break;
 
       case 2:
--- a/gfx/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
+++ b/gfx/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
@@ -36,17 +36,17 @@ TIntermSymbol *CreateReturnValueOutSymbo
     return CreateReturnValueSymbol(outType);
 }
 
 TIntermAggregate *CreateReplacementCall(TIntermAggregate *originalCall, TIntermTyped *returnValueTarget)
 {
     TIntermAggregate *replacementCall = new TIntermAggregate(EOpFunctionCall);
     replacementCall->setType(TType(EbtVoid));
     replacementCall->setUserDefined();
-    replacementCall->setName(originalCall->getName());
+    replacementCall->setNameObj(originalCall->getNameObj());
     replacementCall->setFunctionId(originalCall->getFunctionId());
     replacementCall->setLine(originalCall->getLine());
     TIntermSequence *replacementParameters = replacementCall->getSequence();
     TIntermSequence *originalParameters = originalCall->getSequence();
     for (auto &param : *originalParameters)
     {
         replacementParameters->push_back(param);
     }
@@ -112,17 +112,17 @@ bool ArrayReturnValueToOutParameterTrave
             else if (node->getOp() == EOpPrototype)
             {
                 // Replace the whole prototype node with another node that has the out parameter added.
                 TIntermAggregate *replacement = new TIntermAggregate;
                 replacement->setOp(EOpPrototype);
                 CopyAggregateChildren(node, replacement);
                 replacement->getSequence()->push_back(CreateReturnValueOutSymbol(node->getType()));
                 replacement->setUserDefined();
-                replacement->setName(node->getName());
+                replacement->setNameObj(node->getNameObj());
                 replacement->setFunctionId(node->getFunctionId());
                 replacement->setLine(node->getLine());
                 replacement->setType(TType(EbtVoid));
 
                 mReplacements.push_back(NodeUpdateEntry(getParentNode(), node, replacement, false));
             }
             else if (node->getOp() == EOpFunctionCall)
             {
--- a/gfx/angle/src/compiler/translator/BaseTypes.h
+++ b/gfx/angle/src/compiler/translator/BaseTypes.h
@@ -319,17 +319,20 @@ enum TQualifier
     // built-ins read by fragment shader
     EvqFragCoord,
     EvqFrontFacing,
     EvqPointCoord,
 
     // built-ins written by fragment shader
     EvqFragColor,
     EvqFragData,
-    EvqFragDepth,
+
+    EvqFragDepth,     // gl_FragDepth for ESSL300.
+    EvqFragDepthEXT,  // gl_FragDepthEXT for ESSL100, EXT_frag_depth.
+
     EvqSecondaryFragColorEXT,  // EXT_blend_func_extended
     EvqSecondaryFragDataEXT,   // EXT_blend_func_extended
 
     // built-ins written by the shader_framebuffer_fetch extension(s)
     EvqLastFragColor,
     EvqLastFragData,
 
     // GLSL ES 3.0 vertex output and fragment input
@@ -384,58 +387,57 @@ struct TLayoutQualifier
     }
 };
 
 //
 // This is just for debug print out, carried along with the definitions above.
 //
 inline const char* getQualifierString(TQualifier q)
 {
+    // clang-format off
     switch(q)
     {
-    case EvqTemporary:      return "Temporary";      break;
-    case EvqGlobal:         return "Global";         break;
-    case EvqConst:          return "const";          break;
-    case EvqAttribute:      return "attribute";      break;
-    case EvqVaryingIn:      return "varying";        break;
-    case EvqVaryingOut:     return "varying";        break;
-    case EvqUniform:        return "uniform";        break;
-    case EvqVertexIn:       return "in";             break;
-    case EvqFragmentOut:    return "out";            break;
-    case EvqVertexOut:      return "out";            break;
-    case EvqFragmentIn:     return "in";             break;
-    case EvqIn:             return "in";             break;
-    case EvqOut:            return "out";            break;
-    case EvqInOut:          return "inout";          break;
-    case EvqConstReadOnly:  return "const";          break;
-    case EvqInstanceID:     return "InstanceID";     break;
-    case EvqPosition:       return "Position";       break;
-    case EvqPointSize:      return "PointSize";      break;
-    case EvqFragCoord:      return "FragCoord";      break;
-    case EvqFrontFacing:    return "FrontFacing";    break;
-    case EvqPointCoord:     return "PointCoord";     break;
-    case EvqFragColor:      return "FragColor";      break;
-    case EvqFragData:       return "FragData";       break;
-    case EvqFragDepth:      return "FragDepth";      break;
-    case EvqSecondaryFragColorEXT:
-        return "SecondaryFragColorEXT";
-        break;
-    case EvqSecondaryFragDataEXT:
-        return "SecondaryFragDataEXT";
-        break;
-    case EvqLastFragColor:  return "LastFragColor";  break;
-    case EvqLastFragData:   return "LastFragData";   break;
-    case EvqSmoothOut:      return "smooth out";     break;
-    case EvqCentroidOut:    return "centroid out";   break;
-    case EvqFlatOut:        return "flat out";       break;
-    case EvqSmoothIn:       return "smooth in";      break;
-    case EvqFlatIn:         return "flat in";        break;
-    case EvqCentroidIn:     return "centroid in";    break;
-    default: UNREACHABLE(); return "unknown qualifier";
+    case EvqTemporary:              return "Temporary";
+    case EvqGlobal:                 return "Global";
+    case EvqConst:                  return "const";
+    case EvqAttribute:              return "attribute";
+    case EvqVaryingIn:              return "varying";
+    case EvqVaryingOut:             return "varying";
+    case EvqUniform:                return "uniform";
+    case EvqVertexIn:               return "in";
+    case EvqFragmentOut:            return "out";
+    case EvqVertexOut:              return "out";
+    case EvqFragmentIn:             return "in";
+    case EvqIn:                     return "in";
+    case EvqOut:                    return "out";
+    case EvqInOut:                  return "inout";
+    case EvqConstReadOnly:          return "const";
+    case EvqInstanceID:             return "InstanceID";
+    case EvqPosition:               return "Position";
+    case EvqPointSize:              return "PointSize";
+    case EvqFragCoord:              return "FragCoord";
+    case EvqFrontFacing:            return "FrontFacing";
+    case EvqPointCoord:             return "PointCoord";
+    case EvqFragColor:              return "FragColor";
+    case EvqFragData:               return "FragData";
+    case EvqFragDepthEXT:           return "FragDepth";
+    case EvqFragDepth:              return "FragDepth";
+    case EvqSecondaryFragColorEXT:  return "SecondaryFragColorEXT";
+    case EvqSecondaryFragDataEXT:   return "SecondaryFragDataEXT";
+    case EvqLastFragColor:          return "LastFragColor";
+    case EvqLastFragData:           return "LastFragData";
+    case EvqSmoothOut:              return "smooth out";
+    case EvqCentroidOut:            return "centroid out";
+    case EvqFlatOut:                return "flat out";
+    case EvqSmoothIn:               return "smooth in";
+    case EvqFlatIn:                 return "flat in";
+    case EvqCentroidIn:             return "centroid in";
+    default: UNREACHABLE();         return "unknown qualifier";
     }
+    // clang-format on
 }
 
 inline const char* getMatrixPackingString(TLayoutMatrixPacking mpq)
 {
     switch (mpq)
     {
     case EmpUnspecified:    return "mp_unspecified";
     case EmpRowMajor:       return "row_major";
--- a/gfx/angle/src/compiler/translator/Compiler.cpp
+++ b/gfx/angle/src/compiler/translator/Compiler.cpp
@@ -11,16 +11,17 @@
 #include "compiler/translator/Initialize.h"
 #include "compiler/translator/InitializeParseContext.h"
 #include "compiler/translator/InitializeVariables.h"
 #include "compiler/translator/ParseContext.h"
 #include "compiler/translator/PruneEmptyDeclarations.h"
 #include "compiler/translator/RegenerateStructNames.h"
 #include "compiler/translator/RemovePow.h"
 #include "compiler/translator/RenameFunction.h"
+#include "compiler/translator/RewriteDoWhile.h"
 #include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
 #include "compiler/translator/UnfoldShortCircuitAST.h"
 #include "compiler/translator/ValidateLimitations.h"
 #include "compiler/translator/ValidateOutputs.h"
 #include "compiler/translator/VariablePacker.h"
 #include "compiler/translator/depgraph/DependencyGraph.h"
 #include "compiler/translator/depgraph/DependencyGraphOutput.h"
 #include "compiler/translator/timing/RestrictFragmentShaderTiming.h"
@@ -138,17 +139,18 @@ TCompiler::TCompiler(sh::GLenum type, Sh
       shaderSpec(spec),
       outputType(output),
       maxUniformVectors(0),
       maxExpressionComplexity(0),
       maxCallStackDepth(0),
       fragmentPrecisionHigh(false),
       clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
       builtInFunctionEmulator(),
-      mSourcePath(NULL)
+      mSourcePath(NULL),
+      mTemporaryIndex(0)
 {
 }
 
 TCompiler::~TCompiler()
 {
 }
 
 bool TCompiler::shouldRunLoopAndIndexingValidation(int compileOptions) const
@@ -315,16 +317,20 @@ TIntermNode *TCompiler::compileTreeImpl(
 
         // Clamping uniform array bounds needs to happen after validateLimitations pass.
         if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
             arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
 
         if (success && shaderType == GL_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION))
             initializeGLPosition(root);
 
+        // This pass might emit short circuits so keep it before the short circuit unfolding
+        if (success && (compileOptions & SH_REWRITE_DO_WHILE_LOOPS))
+            RewriteDoWhile(root, getTemporaryIndex());
+
         if (success && (compileOptions & SH_UNFOLD_SHORT_CIRCUIT))
         {
             UnfoldShortCircuitAST unfoldShortCircuit;
             root->traverse(&unfoldShortCircuit);
             unfoldShortCircuit.updateTree();
         }
 
         if (success && (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT))
@@ -498,16 +504,17 @@ void TCompiler::clearResults()
     varyings.clear();
     interfaceBlocks.clear();
 
     builtInFunctionEmulator.Cleanup();
 
     nameMap.clear();
 
     mSourcePath = NULL;
+    mTemporaryIndex = 0;
 }
 
 bool TCompiler::initCallDag(TIntermNode *root)
 {
     mCallDag.clear();
 
     switch (mCallDag.init(root, &infoSink.info))
     {
--- a/gfx/angle/src/compiler/translator/Compiler.h
+++ b/gfx/angle/src/compiler/translator/Compiler.h
@@ -149,16 +149,17 @@ class TCompiler : public TShHandleBase
     bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph);
     // Return true if the maximum expression complexity is below the limit.
     bool limitExpressionComplexity(TIntermNode* root);
     // Get built-in extensions with default behavior.
     const TExtensionBehavior& getExtensionBehavior() const;
     const char *getSourcePath() const;
     const TPragma& getPragma() const { return mPragma; }
     void writePragma();
+    unsigned int *getTemporaryIndex() { return &mTemporaryIndex; }
 
     const ArrayBoundsClamper& getArrayBoundsClamper() const;
     ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const;
     const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
 
     std::vector<sh::Attribute> attributes;
     std::vector<sh::OutputVariable> outputVariables;
     std::vector<sh::Uniform> uniforms;
@@ -225,16 +226,18 @@ class TCompiler : public TShHandleBase
     TInfoSink infoSink;  // Output sink.
     const char *mSourcePath; // Path of source file or NULL
 
     // name hashing.
     ShHashFunction64 hashFunction;
     NameMap nameMap;
 
     TPragma mPragma;
+
+    unsigned int mTemporaryIndex;
 };
 
 //
 // This is the interface between the machine independent code
 // and the machine dependent code.
 //
 // The machine dependent code should derive from the classes
 // above. Then Construct*() and Delete*() will create and
--- a/gfx/angle/src/compiler/translator/Initialize.cpp
+++ b/gfx/angle/src/compiler/translator/Initialize.cpp
@@ -518,20 +518,28 @@ void IdentifyBuiltIns(sh::GLenum type, S
                 secondaryFragData.setArraySize(resources.MaxDualSourceDrawBuffers);
                 symbolTable.insert(
                     ESSL1_BUILTINS, "GL_EXT_blend_func_extended",
                     new TVariable(NewPoolTString("gl_SecondaryFragDataEXT"), secondaryFragData));
             }
 
             if (resources.EXT_frag_depth)
             {
-                symbolTable.insert(ESSL1_BUILTINS, "GL_EXT_frag_depth", new TVariable(NewPoolTString("gl_FragDepthEXT"),
-                    TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1)));
+                symbolTable.insert(
+                    ESSL1_BUILTINS, "GL_EXT_frag_depth",
+                    new TVariable(
+                        NewPoolTString("gl_FragDepthEXT"),
+                        TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium,
+                              EvqFragDepthEXT, 1)));
             }
 
+            symbolTable.insert(ESSL3_BUILTINS,
+                               new TVariable(NewPoolTString("gl_FragDepth"),
+                                             TType(EbtFloat, EbpHigh, EvqFragDepth, 1)));
+
             if (resources.EXT_shader_framebuffer_fetch || resources.NV_shader_framebuffer_fetch)
             {
                 TType lastFragData(EbtFloat, EbpMedium, EvqLastFragData, 4, 1, true);
                 lastFragData.setArraySize(resources.MaxDrawBuffers);
 
                 if (resources.EXT_shader_framebuffer_fetch)
                 {
                     symbolTable.insert(ESSL1_BUILTINS, "GL_EXT_shader_framebuffer_fetch",
--- a/gfx/angle/src/compiler/translator/IntermNode.h
+++ b/gfx/angle/src/compiler/translator/IntermNode.h
@@ -889,35 +889,42 @@ class TLValueTrackingTraverser : public 
     // Use isLValueRequiredHere to check all conditions which require an l-value.
     void setOperatorRequiresLValue(bool lValueRequired)
     {
         mOperatorRequiresLValue = lValueRequired;
     }
     bool operatorRequiresLValue() const { return mOperatorRequiresLValue; }
 
     // Add a function encountered during traversal to the function map.
-    void addToFunctionMap(const TString &name, TIntermSequence *paramSequence);
+    void addToFunctionMap(const TName &name, TIntermSequence *paramSequence);
 
     // Return the parameters sequence from the function definition or prototype.
     TIntermSequence *getFunctionParameters(const TIntermAggregate *callNode);
 
     // Track whether an l-value is required inside a function call.
     void setInFunctionCallOutParameter(bool inOutParameter);
     bool isInFunctionCallOutParameter() const;
 
     bool mOperatorRequiresLValue;
     bool mInFunctionCallOutParameter;
 
-    struct TStringComparator
+    struct TNameComparator
     {
-        bool operator()(const TString &a, const TString &b) const { return a.compare(b) < 0; }
+        bool operator()(const TName &a, const TName &b) const
+        {
+            int compareResult = a.getString().compare(b.getString());
+            if (compareResult != 0)
+                return compareResult < 0;
+            // Internal functions may have same names as non-internal functions.
+            return !a.isInternal() && b.isInternal();
+        }
     };
 
     // Map from mangled function names to their parameter sequences
-    TMap<TString, TIntermSequence *, TStringComparator> mFunctionMap;
+    TMap<TName, TIntermSequence *, TNameComparator> mFunctionMap;
 
     const TSymbolTable &mSymbolTable;
     const int mShaderVersion;
 };
 
 //
 // For traversing the tree, and computing max depth.
 // Takes a maximum depth limit to prevent stack overflow.
--- a/gfx/angle/src/compiler/translator/IntermTraverse.cpp
+++ b/gfx/angle/src/compiler/translator/IntermTraverse.cpp
@@ -155,31 +155,31 @@ void TIntermTraverser::useTemporaryIndex
 }
 
 void TIntermTraverser::nextTemporaryIndex()
 {
     ASSERT(mTemporaryIndex != nullptr);
     ++(*mTemporaryIndex);
 }
 
-void TLValueTrackingTraverser::addToFunctionMap(const TString &name, TIntermSequence *paramSequence)
+void TLValueTrackingTraverser::addToFunctionMap(const TName &name, TIntermSequence *paramSequence)
 {
     mFunctionMap[name] = paramSequence;
 }
 
 bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
 {
     ASSERT(callNode->getOp() == EOpFunctionCall);
-    return (mFunctionMap.find(callNode->getName()) != mFunctionMap.end());
+    return (mFunctionMap.find(callNode->getNameObj()) != mFunctionMap.end());
 }
 
 TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
 {
     ASSERT(isInFunctionMap(callNode));
-    return mFunctionMap[callNode->getName()];
+    return mFunctionMap[callNode->getNameObj()];
 }
 
 void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
 {
     mInFunctionCallOutParameter = inOutParameter;
 }
 
 bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const
@@ -421,21 +421,21 @@ void TLValueTrackingTraverser::traverseA
     TIntermSequence *sequence = node->getSequence();
     switch (node->getOp())
     {
         case EOpFunction:
         {
             TIntermAggregate *params = sequence->front()->getAsAggregate();
             ASSERT(params != nullptr);
             ASSERT(params->getOp() == EOpParameters);
-            addToFunctionMap(node->getName(), params->getSequence());
+            addToFunctionMap(node->getNameObj(), params->getSequence());
             break;
         }
         case EOpPrototype:
-            addToFunctionMap(node->getName(), sequence);
+            addToFunctionMap(node->getNameObj(), sequence);
             break;
         default:
             break;
     }
 
     if (preVisit)
         visit = visitAggregate(PreVisit, node);
 
--- a/gfx/angle/src/compiler/translator/OutputGLSL.cpp
+++ b/gfx/angle/src/compiler/translator/OutputGLSL.cpp
@@ -70,16 +70,17 @@ TString TOutputGLSL::translateTextureFun
         "textureCubeGradEXT", "textureCubeGradARB",
         NULL, NULL
     };
     static const char *legacyToCoreRename[] = {
         "texture2D", "texture",
         "texture2DProj", "textureProj",
         "texture2DLod", "textureLod",
         "texture2DProjLod", "textureProjLod",
+        "texture2DRect", "texture",
         "textureCube", "texture",
         "textureCubeLod", "textureLod",
         // Extensions
         "texture2DLodEXT", "textureLod",
         "texture2DProjLodEXT", "textureProjLod",
         "textureCubeLodEXT", "textureLod",
         "texture2DGradEXT", "textureGrad",
         "texture2DProjGradEXT", "textureProjGrad",
--- a/gfx/angle/src/compiler/translator/OutputGLSLBase.cpp
+++ b/gfx/angle/src/compiler/translator/OutputGLSLBase.cpp
@@ -1070,87 +1070,86 @@ bool TOutputGLSLBase::visitAggregate(Vis
     return visitChildren;
 }
 
 bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node)
 {
     TInfoSinkBase &out = objSink();
 
     incrementDepth(node);
-    // Loop header.
+
     TLoopType loopType = node->getType();
+
+    // Only for loops can be unrolled
+    ASSERT(!node->getUnrollFlag() || loopType == ELoopFor);
+
     if (loopType == ELoopFor)  // for loop
     {
         if (!node->getUnrollFlag())
         {
             out << "for (";
             if (node->getInit())
                 node->getInit()->traverse(this);
             out << "; ";
 
             if (node->getCondition())
                 node->getCondition()->traverse(this);
             out << "; ";
 
             if (node->getExpression())
                 node->getExpression()->traverse(this);
             out << ")\n";
+
+            visitCodeBlock(node->getBody());
         }
         else
         {
             // Need to put a one-iteration loop here to handle break.
             TIntermSequence *declSeq =
                 node->getInit()->getAsAggregate()->getSequence();
             TIntermSymbol *indexSymbol =
                 (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode();
             TString name = hashVariableName(indexSymbol->getSymbol());
             out << "for (int " << name << " = 0; "
                 << name << " < 1; "
                 << "++" << name << ")\n";
+
+            out << "{\n";
+            mLoopUnrollStack.push(node);
+            while (mLoopUnrollStack.satisfiesLoopCondition())
+            {
+                visitCodeBlock(node->getBody());
+                mLoopUnrollStack.step();
+            }
+            mLoopUnrollStack.pop();
+            out << "}\n";
         }
     }
     else if (loopType == ELoopWhile)  // while loop
     {
         out << "while (";
         ASSERT(node->getCondition() != NULL);
         node->getCondition()->traverse(this);
         out << ")\n";
+
+        visitCodeBlock(node->getBody());
     }
     else  // do-while loop
     {
         ASSERT(loopType == ELoopDoWhile);
         out << "do\n";
-    }
 
-    // Loop body.
-    if (node->getUnrollFlag())
-    {
-        out << "{\n";
-        mLoopUnrollStack.push(node);
-        while (mLoopUnrollStack.satisfiesLoopCondition())
-        {
-            visitCodeBlock(node->getBody());
-            mLoopUnrollStack.step();
-        }
-        mLoopUnrollStack.pop();
-        out << "}\n";
-    }
-    else
-    {
         visitCodeBlock(node->getBody());
-    }
 
-    // Loop footer.
-    if (loopType == ELoopDoWhile)  // do-while loop
-    {
         out << "while (";
         ASSERT(node->getCondition() != NULL);
         node->getCondition()->traverse(this);
         out << ");\n";
     }
+
     decrementDepth();
 
     // No need to visit children. They have been already processed in
     // this function.
     return false;
 }
 
 bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch *node)
--- a/gfx/angle/src/compiler/translator/OutputHLSL.cpp
+++ b/gfx/angle/src/compiler/translator/OutputHLSL.cpp
@@ -1381,17 +1381,17 @@ void OutputHLSL::visitSymbol(TIntermSymb
             mUsesPointSize = true;
             out << name;
         }
         else if (qualifier == EvqInstanceID)
         {
             mUsesInstanceID = true;
             out << name;
         }
-        else if (name == "gl_FragDepthEXT")
+        else if (name == "gl_FragDepthEXT" || name == "gl_FragDepth")
         {
             mUsesFragDepth = true;
             out << "gl_Depth";
         }
         else
         {
             out << DecorateIfNeeded(node->getName());
         }
--- a/gfx/angle/src/compiler/translator/ParseContext.cpp
+++ b/gfx/angle/src/compiler/translator/ParseContext.cpp
@@ -2867,61 +2867,46 @@ TIntermTyped *TParseContext::addIndexExp
     {
         TConstantUnion *unionArray = new TConstantUnion[1];
         unionArray->setFConst(0.0f);
         indexedExpression =
             intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
     }
     else if (baseExpression->isArray())
     {
-        const TType &baseType = baseExpression->getType();
-        if (baseType.getStruct())
-        {
-            TType copyOfType(baseType.getStruct());
-            indexedExpression->setType(copyOfType);
-        }
-        else if (baseType.isInterfaceBlock())
-        {
-            TType copyOfType(baseType.getInterfaceBlock(), baseType.getQualifier(),
-                             baseType.getLayoutQualifier(), 0);
-            indexedExpression->setType(copyOfType);
-        }
-        else
-        {
-            indexedExpression->setType(
-                TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary,
-                      static_cast<unsigned char>(baseExpression->getNominalSize()),
-                      static_cast<unsigned char>(baseExpression->getSecondarySize())));
-        }
-
-        if (baseExpression->getType().getQualifier() == EvqConst)
-        {
-            indexedExpression->getTypePointer()->setQualifier(EvqConst);
-        }
+        TType indexedType = baseExpression->getType();
+        indexedType.clearArrayness();
+        indexedExpression->setType(indexedType);
     }
     else if (baseExpression->isMatrix())
     {
-        TQualifier qualifier =
-            baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
         indexedExpression->setType(TType(baseExpression->getBasicType(),
-                                         baseExpression->getPrecision(), qualifier,
+                                         baseExpression->getPrecision(), EvqTemporary,
                                          static_cast<unsigned char>(baseExpression->getRows())));
     }
     else if (baseExpression->isVector())
     {
-        TQualifier qualifier =
-            baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
         indexedExpression->setType(
-            TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier));
+            TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary));
     }
     else
     {
         indexedExpression->setType(baseExpression->getType());
     }
 
+    if (baseExpression->getType().getQualifier() == EvqConst &&
+        indexExpression->getType().getQualifier() == EvqConst)
+    {
+        indexedExpression->getTypePointer()->setQualifier(EvqConst);
+    }
+    else
+    {
+        indexedExpression->getTypePointer()->setQualifier(EvqTemporary);
+    }
+
     return indexedExpression;
 }
 
 TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
                                                          const TSourceLoc &dotLocation,
                                                          const TString &fieldString,
                                                          const TSourceLoc &fieldLocation)
 {
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/compiler/translator/RewriteDoWhile.cpp
@@ -0,0 +1,163 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RewriteDoWhile.cpp: rewrites do-while loops using another equivalent
+// construct.
+
+#include "compiler/translator/RewriteDoWhile.h"
+
+#include "compiler/translator/IntermNode.h"
+
+namespace
+{
+
+// An AST traverser that rewrites loops of the form
+//   do {
+//     CODE;
+//   } while (CONDITION)
+//
+// to loops of the form
+//   bool temp = false;
+//   while (true) {
+//     if (temp) {
+//       if (!CONDITION) {
+//         break;
+//       }
+//     }
+//     temp = true;
+//     CODE;
+//   }
+//
+// The reason we don't use a simpler form, with for example just (temp && !CONDITION) in the
+// while condition, is that short-circuit is often badly supported by driver shader compiler.
+// The double if has the same effect, but forces shader compilers to behave.
+//
+// TODO(cwallez) when UnfoldShortCircuitIntoIf handles loops correctly, revisit this as we might
+// be able to use while (temp || CONDITION) with temp initially set to true then run
+// UnfoldShortCircuitIntoIf
+class DoWhileRewriter : public TIntermTraverser
+{
+  public:
+    DoWhileRewriter() : TIntermTraverser(true, false, false) {}
+
+    bool visitAggregate(Visit, TIntermAggregate *node) override
+    {
+        // A well-formed AST can only have do-while in EOpSequence which represent lists of
+        // statements. By doing a prefix traversal we are able to replace the do-while in the
+        // sequence directly as the content of the do-while will be traversed later.
+        if (node->getOp() != EOpSequence)
+        {
+            return true;
+        }
+
+        TIntermSequence *statements = node->getSequence();
+
+        // The statements vector will have new statements inserted when we encounter a do-while,
+        // which prevents us from using a range-based for loop. Using the usual i++ works, as
+        // the (two) new statements inserted replace the statement at the current position.
+        for (size_t i = 0; i < statements->size(); i++)
+        {
+            TIntermNode *statement = (*statements)[i];
+            TIntermLoop *loop      = statement->getAsLoopNode();
+
+            if (loop == nullptr || loop->getType() != ELoopDoWhile)
+            {
+                continue;
+            }
+
+            TType boolType = TType(EbtBool);
+
+            // bool temp = false;
+            TIntermAggregate *tempDeclaration = nullptr;
+            {
+                TConstantUnion *falseConstant = new TConstantUnion();
+                falseConstant->setBConst(false);
+                TIntermTyped *falseValue = new TIntermConstantUnion(falseConstant, boolType);
+
+                tempDeclaration = createTempInitDeclaration(falseValue);
+            }
+
+            // temp = true;
+            TIntermBinary *assignTrue = nullptr;
+            {
+                TConstantUnion *trueConstant = new TConstantUnion();
+                trueConstant->setBConst(true);
+                TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, boolType);
+
+                assignTrue = createTempAssignment(trueValue);
+            }
+
+            // if (temp) {
+            //   if (!CONDITION) {
+            //     break;
+            //   }
+            // }
+            TIntermSelection *breakIf = nullptr;
+            {
+                TIntermBranch *breakStatement = new TIntermBranch(EOpBreak, nullptr);
+
+                TIntermAggregate *breakBlock = new TIntermAggregate(EOpSequence);
+                breakBlock->getSequence()->push_back(breakStatement);
+
+                TIntermUnary *negatedCondition = new TIntermUnary(EOpLogicalNot);
+                negatedCondition->setOperand(loop->getCondition());
+
+                TIntermSelection *innerIf =
+                    new TIntermSelection(negatedCondition, breakBlock, nullptr);
+
+                TIntermAggregate *innerIfBlock = new TIntermAggregate(EOpSequence);
+                innerIfBlock->getSequence()->push_back(innerIf);
+
+                breakIf = new TIntermSelection(createTempSymbol(boolType), innerIfBlock, nullptr);
+            }
+
+            // Assemble the replacement loops, reusing the do-while loop's body and inserting our
+            // statements at the front.
+            TIntermLoop *newLoop = nullptr;
+            {
+                TConstantUnion *trueConstant = new TConstantUnion();
+                trueConstant->setBConst(true);
+                TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, boolType);
+
+                TIntermAggregate *body = nullptr;
+                if (loop->getBody() != nullptr)
+                {
+                    body = loop->getBody()->getAsAggregate();
+                }
+                else
+                {
+                    body = new TIntermAggregate(EOpSequence);
+                }
+                auto sequence = body->getSequence();
+                sequence->insert(sequence->begin(), assignTrue);
+                sequence->insert(sequence->begin(), breakIf);
+
+                newLoop = new TIntermLoop(ELoopWhile, nullptr, trueValue, nullptr, body);
+            }
+
+            TIntermSequence replacement;
+            replacement.push_back(tempDeclaration);
+            replacement.push_back(newLoop);
+
+            node->replaceChildNodeWithMultiple(loop, replacement);
+
+            nextTemporaryIndex();
+        }
+        return true;
+    }
+};
+
+}  // anonymous namespace
+
+void RewriteDoWhile(TIntermNode *root, unsigned int *temporaryIndex)
+{
+    ASSERT(temporaryIndex != 0);
+
+    DoWhileRewriter rewriter;
+    rewriter.useTemporaryIndex(temporaryIndex);
+
+    root->traverse(&rewriter);
+}
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/compiler/translator/RewriteDoWhile.h
@@ -0,0 +1,16 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RewriteDoWhile.h: rewrite do-while loops as while loops to work around
+// driver bugs
+
+#ifndef COMPILER_TRANSLATOR_REWRITEDOWHILE_H_
+#define COMPILER_TRANSLATOR_REWRITEDOWHILE_H_
+
+class TIntermNode;
+void RewriteDoWhile(TIntermNode *root, unsigned int *temporaryIndex);
+
+#endif  // COMPILER_TRANSLATOR_REWRITEDOWHILE_H_
--- a/gfx/angle/src/compiler/translator/RewriteElseBlocks.cpp
+++ b/gfx/angle/src/compiler/translator/RewriteElseBlocks.cpp
@@ -18,17 +18,17 @@ namespace
 {
 
 class ElseBlockRewriter : public TIntermTraverser
 {
   public:
     ElseBlockRewriter();
 
   protected:
-    bool visitAggregate(Visit visit, TIntermAggregate *aggregate);
+    bool visitAggregate(Visit visit, TIntermAggregate *aggregate) override;
 
   private:
     const TType *mFunctionType;
 
     TIntermNode *rewriteSelection(TIntermSelection *selection);
 };
 
 TIntermUnary *MakeNewUnary(TOperator op, TIntermTyped *operand)
--- a/gfx/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
+++ b/gfx/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
@@ -59,17 +59,17 @@ TIntermAggregate *CopyAggregateNode(TInt
     TIntermSequence *copySeq = copyNode->getSequence();
     copySeq->insert(copySeq->begin(), node->getSequence()->begin(), node->getSequence()->end());
     copyNode->setType(node->getType());
     copyNode->setFunctionId(node->getFunctionId());
     if (node->isUserDefined())
     {
         copyNode->setUserDefined();
     }
-    copyNode->setName(node->getName());
+    copyNode->setNameObj(node->getNameObj());
     return copyNode;
 }
 
 bool SeparateExpressionsTraverser::visitBinary(Visit visit, TIntermBinary *node)
 {
     if (mFoundArrayExpression)
         return false;
 
--- a/gfx/angle/src/compiler/translator/TranslatorESSL.cpp
+++ b/gfx/angle/src/compiler/translator/TranslatorESSL.cpp
@@ -44,19 +44,17 @@ void TranslatorESSL::translate(TIntermNo
     if (precisionEmulation)
     {
         EmulatePrecision emulatePrecision(getSymbolTable(), shaderVer);
         root->traverse(&emulatePrecision);
         emulatePrecision.updateTree();
         emulatePrecision.writeEmulationHelpers(sink, SH_ESSL_OUTPUT);
     }
 
-    unsigned int temporaryIndex = 0;
-
-    RecordConstantPrecision(root, &temporaryIndex);
+    RecordConstantPrecision(root, getTemporaryIndex());
 
     // Write emulated built-in functions if needed.
     if (!getBuiltInFunctionEmulator().IsOutputEmpty())
     {
         sink << "// BEGIN: Generated code for built-in function emulation\n\n";
         if (getShaderType() == GL_FRAGMENT_SHADER)
         {
             sink << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n"
--- a/gfx/angle/src/compiler/translator/TranslatorGLSL.cpp
+++ b/gfx/angle/src/compiler/translator/TranslatorGLSL.cpp
@@ -24,17 +24,18 @@ void TranslatorGLSL::initBuiltInFunction
     {
         InitBuiltInFunctionEmulatorForGLSLWorkarounds(emu, getShaderType());
     }
 
     int targetGLSLVersion = ShaderOutputTypeToGLSLVersion(getOutputType());
     InitBuiltInFunctionEmulatorForGLSLMissingFunctions(emu, getShaderType(), targetGLSLVersion);
 }
 
-void TranslatorGLSL::translate(TIntermNode *root, int) {
+void TranslatorGLSL::translate(TIntermNode *root, int compileOptions)
+{
     TInfoSinkBase& sink = getInfoSink().obj;
 
     // Write GLSL version.
     writeVersion(root);
 
     writePragma();
 
     // Write extension behaviour as needed
--- a/gfx/angle/src/compiler/translator/TranslatorHLSL.cpp
+++ b/gfx/angle/src/compiler/translator/TranslatorHLSL.cpp
@@ -22,41 +22,39 @@ TranslatorHLSL::TranslatorHLSL(sh::GLenu
 
 void TranslatorHLSL::translate(TIntermNode *root, int compileOptions)
 {
     const ShBuiltInResources &resources = getResources();
     int numRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
 
     SeparateDeclarations(root);
 
-    unsigned int temporaryIndex = 0;
+    // Note that SeparateDeclarations needs to be run before UnfoldShortCircuitToIf.
+    UnfoldShortCircuitToIf(root, getTemporaryIndex());
 
-    // Note that SeparateDeclarations needs to be run before UnfoldShortCircuitToIf.
-    UnfoldShortCircuitToIf(root, &temporaryIndex);
-
-    SeparateExpressionsReturningArrays(root, &temporaryIndex);
+    SeparateExpressionsReturningArrays(root, getTemporaryIndex());
 
     // Note that SeparateDeclarations needs to be run before SeparateArrayInitialization.
     SeparateArrayInitialization(root);
 
     // HLSL doesn't support arrays as return values, we'll need to make functions that have an array
     // as a return value to use an out parameter to transfer the array data instead.
-    ArrayReturnValueToOutParameter(root, &temporaryIndex);
+    ArrayReturnValueToOutParameter(root, getTemporaryIndex());
 
     if (!shouldRunLoopAndIndexingValidation(compileOptions))
     {
         // HLSL doesn't support dynamic indexing of vectors and matrices.
-        RemoveDynamicIndexing(root, &temporaryIndex, getSymbolTable(), getShaderVersion());
+        RemoveDynamicIndexing(root, getTemporaryIndex(), getSymbolTable(), getShaderVersion());
     }
 
     // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which
     // use a vertex attribute as a condition, and some related computation in the else block.
     if (getOutputType() == SH_HLSL9_OUTPUT && getShaderType() == GL_VERTEX_SHADER)
     {
-        sh::RewriteElseBlocks(root, &temporaryIndex);
+        sh::RewriteElseBlocks(root, getTemporaryIndex());
     }
 
     sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(),
         getSourcePath(), getOutputType(), numRenderTargets, getUniforms(), compileOptions);
 
     outputHLSL.output(root, getInfoSink().obj);
 
     mInterfaceBlockRegisterMap = outputHLSL.getInterfaceBlockRegisterMap();
--- a/gfx/angle/src/compiler/translator/Types.cpp
+++ b/gfx/angle/src/compiler/translator/Types.cpp
@@ -218,19 +218,19 @@ bool TStructure::containsSamplers() cons
     {
         const TType *fieldType = (*mFields)[i]->type();
         if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
             return true;
     }
     return false;
 }
 
-TString TFieldListCollection::buildMangledName() const
+TString TFieldListCollection::buildMangledName(const TString &mangledNamePrefix) const
 {
-    TString mangledName(mangledNamePrefix());
+    TString mangledName(mangledNamePrefix);
     mangledName += *mName;
     for (size_t i = 0; i < mFields->size(); ++i)
     {
         mangledName += '-';
         mangledName += (*mFields)[i]->type()->getMangledName();
     }
     return mangledName;
 }
--- a/gfx/angle/src/compiler/translator/Types.h
+++ b/gfx/angle/src/compiler/translator/Types.h
@@ -68,39 +68,32 @@ class TFieldListCollection : angle::NonC
     {
         return *mName;
     }
     const TFieldList &fields() const
     {
         return *mFields;
     }
 
-    const TString &mangledName() const
-    {
-        if (mMangledName.empty())
-            mMangledName = buildMangledName();
-        return mMangledName;
-    }
     size_t objectSize() const
     {
         if (mObjectSize == 0)
             mObjectSize = calculateObjectSize();
         return mObjectSize;
     };
 
   protected:
     TFieldListCollection(const TString *name, TFieldList *fields)
         : mName(name),
           mFields(fields),
           mObjectSize(0)
     {
     }
-    TString buildMangledName() const;
+    TString buildMangledName(const TString &mangledNamePrefix) const;
     size_t calculateObjectSize() const;
-    virtual TString mangledNamePrefix() const = 0;
 
     const TString *mName;
     TFieldList *mFields;
 
     mutable TString mMangledName;
     mutable size_t mObjectSize;
 };
 
@@ -145,28 +138,34 @@ class TStructure : public TFieldListColl
         mAtGlobalScope = atGlobalScope;
     }
 
     bool atGlobalScope() const
     {
         return mAtGlobalScope;
     }
 
+    const TString &mangledName() const
+    {
+        if (mMangledName.empty())
+            mMangledName = buildMangledName("struct-");
+        return mMangledName;
+    }
+
   private:
     // TODO(zmo): Find a way to get rid of the const_cast in function
     // setName().  At the moment keep this function private so only
     // friend class RegenerateStructNames may call it.
     friend class RegenerateStructNames;
     void setName(const TString &name)
     {
         TString *mutableName = const_cast<TString *>(mName);
         *mutableName = name;
     }
 
-    TString mangledNamePrefix() const override { return "struct-"; }
     int calculateDeepestNesting() const;
 
     mutable int mDeepestNesting;
     int mUniqueId;
     bool mAtGlobalScope;
 };
 
 class TInterfaceBlock : public TFieldListCollection
@@ -202,20 +201,24 @@ class TInterfaceBlock : public TFieldLis
     TLayoutBlockStorage blockStorage() const
     {
         return mBlockStorage;
     }
     TLayoutMatrixPacking matrixPacking() const
     {
         return mMatrixPacking;
     }
+    const TString &mangledName() const
+    {
+        if (mMangledName.empty())
+            mMangledName = buildMangledName("iblock-");
+        return mMangledName;
+    }
 
   private:
-    TString mangledNamePrefix() const override { return "iblock-"; }
-
     const TString *mInstanceName; // for interface block instance names
     int mArraySize; // 0 if not an array
     TLayoutBlockStorage mBlockStorage;
     TLayoutMatrixPacking mMatrixPacking;
 };
 
 //
 // Base class for things that have a type.
@@ -267,17 +270,21 @@ class TType
     TType &operator=(const TType &) = default;
 
     TBasicType getBasicType() const
     {
         return type;
     }
     void setBasicType(TBasicType t)
     {
-        type = t;
+        if (type != t)
+        {
+            type = t;
+            invalidateMangledName();
+        }
     }
 
     TPrecision getPrecision() const
     {
         return precision;
     }
     void setPrecision(TPrecision p)
     {
@@ -322,21 +329,29 @@ class TType
     }
     int getRows() const
     {
         ASSERT(isMatrix());
         return secondarySize;
     }
     void setPrimarySize(unsigned char ps)
     {
-        primarySize = ps;
+        if (primarySize != ps)
+        {
+            primarySize = ps;
+            invalidateMangledName();
+        }
     }
     void setSecondarySize(unsigned char ss)
     {
-        secondarySize = ss;
+        if (secondarySize != ss)
+        {
+            secondarySize = ss;
+            invalidateMangledName();
+        }
     }
 
     // Full size of single instance of type
     size_t getObjectSize() const;
 
     bool isMatrix() const
     {
         return primarySize > 1 && secondarySize > 1;
@@ -354,32 +369,44 @@ class TType
         return array && arraySize == 0;
     }
     int getArraySize() const
     {
         return arraySize;
     }
     void setArraySize(int s)
     {
-        array = true;
-        arraySize = s;
+        if (!array || arraySize != s)
+        {
+            array     = true;
+            arraySize = s;
+            invalidateMangledName();
+        }
     }
     void clearArrayness()
     {
-        array = false;
-        arraySize = 0;
+        if (array)
+        {
+            array     = false;
+            arraySize = 0;
+            invalidateMangledName();
+        }
     }
 
     TInterfaceBlock *getInterfaceBlock() const
     {
         return interfaceBlock;
     }
     void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn)
     {
-        interfaceBlock = interfaceBlockIn;
+        if (interfaceBlock != interfaceBlockIn)
+        {
+            interfaceBlock = interfaceBlockIn;
+            invalidateMangledName();
+        }
     }
     bool isInterfaceBlock() const
     {
         return type == EbtInterfaceBlock;
     }
 
     bool isVector() const
     {
@@ -395,17 +422,21 @@ class TType
     }
 
     TStructure *getStruct() const
     {
         return structure;
     }
     void setStruct(TStructure *s)
     {
-        structure = s;
+        if (structure != s)
+        {
+            structure = s;
+            invalidateMangledName();
+        }
     }
 
     const TString &getMangledName() const
     {
         if (mangled.empty())
         {
             mangled = buildMangledName();
             mangled += ';';
@@ -499,17 +530,18 @@ class TType
     }
 
     // Initializes all lazily-initialized members.
     void realize()
     {
         getMangledName();
     }
 
-  protected:
+  private:
+    void invalidateMangledName() { mangled = ""; }
     TString buildMangledName() const;
     size_t getStructSize() const;
 
     TBasicType type;
     TPrecision precision;
     TQualifier qualifier;
     bool invariant;
     TLayoutQualifier layoutQualifier;
--- a/gfx/angle/src/compiler/translator/VariableInfo.cpp
+++ b/gfx/angle/src/compiler/translator/VariableInfo.cpp
@@ -146,16 +146,17 @@ CollectVariables::CollectVariables(std::
       mFrontFacingAdded(false),
       mFragCoordAdded(false),
       mInstanceIDAdded(false),
       mPositionAdded(false),
       mPointSizeAdded(false),
       mLastFragDataAdded(false),
       mFragColorAdded(false),
       mFragDataAdded(false),
+      mFragDepthEXTAdded(false),
       mFragDepthAdded(false),
       mSecondaryFragColorEXTAdded(false),
       mSecondaryFragDataEXTAdded(false),
       mHashFunction(hashFunction),
       mSymbolTable(symbolTable)
 {
 }
 
@@ -400,31 +401,46 @@ void CollectVariables::visitSymbol(TInte
                                        ->getConstPointer()
                                        ->getIConst();
                   info.precision = GL_MEDIUM_FLOAT;  // Defined by spec.
                   info.staticUse = true;
                   mOutputVariables->push_back(info);
                   mFragDataAdded = true;
               }
               return;
-          case EvqFragDepth:
-              if (!mFragDepthAdded)
+          case EvqFragDepthEXT:
+              if (!mFragDepthEXTAdded)
               {
                   OutputVariable info;
                   const char kName[] = "gl_FragDepthEXT";
                   info.name          = kName;
                   info.mappedName    = kName;
                   info.type          = GL_FLOAT;
                   info.arraySize = 0;
                   info.precision =
                       GLVariablePrecision(static_cast<const TVariable *>(
                                               mSymbolTable.findBuiltIn("gl_FragDepthEXT", 100))
                                               ->getType());
                   info.staticUse = true;
                   mOutputVariables->push_back(info);
+                  mFragDepthEXTAdded = true;
+              }
+              return;
+          case EvqFragDepth:
+              if (!mFragDepthAdded)
+              {
+                  OutputVariable info;
+                  const char kName[] = "gl_FragDepth";
+                  info.name          = kName;
+                  info.mappedName    = kName;
+                  info.type          = GL_FLOAT;
+                  info.arraySize     = 0;
+                  info.precision     = GL_HIGH_FLOAT;
+                  info.staticUse = true;
+                  mOutputVariables->push_back(info);
                   mFragDepthAdded = true;
               }
               return;
           case EvqSecondaryFragColorEXT:
               if (!mSecondaryFragColorEXTAdded)
               {
                   OutputVariable info;
                   const char kName[] = "gl_SecondaryFragColorEXT";
--- a/gfx/angle/src/compiler/translator/VariableInfo.h
+++ b/gfx/angle/src/compiler/translator/VariableInfo.h
@@ -53,16 +53,17 @@ class CollectVariables : public TIntermT
     bool mFragCoordAdded;
 
     bool mInstanceIDAdded;
     bool mPositionAdded;
     bool mPointSizeAdded;
     bool mLastFragDataAdded;
     bool mFragColorAdded;
     bool mFragDataAdded;
+    bool mFragDepthEXTAdded;
     bool mFragDepthAdded;
     bool mSecondaryFragColorEXTAdded;
     bool mSecondaryFragDataEXTAdded;
 
     ShHashFunction64 mHashFunction;
 
     const TSymbolTable &mSymbolTable;
 };
--- a/gfx/angle/src/compiler/translator/blocklayout.h
+++ b/gfx/angle/src/compiler/translator/blocklayout.h
@@ -45,16 +45,17 @@ struct COMPILER_EXPORT BlockMemberInfo
     int matrixStride;
     bool isRowMajorMatrix;
 };
 
 class COMPILER_EXPORT BlockLayoutEncoder
 {
   public:
     BlockLayoutEncoder();
+    virtual ~BlockLayoutEncoder() {}
 
     BlockMemberInfo encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix);
 
     size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; }
     size_t getCurrentRegister() const { return mCurrentOffset / ComponentsPerRegister; }
     size_t getCurrentElement() const { return mCurrentOffset % ComponentsPerRegister; }
 
     virtual void enterAggregateType() = 0;
--- a/gfx/angle/src/compiler/translator/depgraph/DependencyGraph.cpp
+++ b/gfx/angle/src/compiler/translator/depgraph/DependencyGraph.cpp
@@ -1,16 +1,14 @@
 //
 // Copyright (c) 2012 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.
 //
 
-#pragma warning(disable: 4718)
-
 #include "compiler/translator/depgraph/DependencyGraph.h"
 #include "compiler/translator/depgraph/DependencyGraphBuilder.h"
 
 TDependencyGraph::TDependencyGraph(TIntermNode* intermNode)
 {
     TDependencyGraphBuilder::build(intermNode, this);
 }
 
--- a/gfx/angle/src/compiler/translator/depgraph/DependencyGraph.h
+++ b/gfx/angle/src/compiler/translator/depgraph/DependencyGraph.h
@@ -186,16 +186,17 @@ private:
 // put their traversal specific data in it, and then pass it to a
 // traverse method.
 //
 // When using this, just fill in the methods for nodes you want visited.
 //
 class TDependencyGraphTraverser : angle::NonCopyable {
 public:
     TDependencyGraphTraverser() : mDepth(0) {}
+    virtual ~TDependencyGraphTraverser() {}
 
     virtual void visitSymbol(TGraphSymbol* symbol) {};
     virtual void visitArgument(TGraphArgument* selection) {};
     virtual void visitFunctionCall(TGraphFunctionCall* functionCall) {};
     virtual void visitSelection(TGraphSelection* selection) {};
     virtual void visitLoop(TGraphLoop* loop) {};
     virtual void visitLogicalOp(TGraphLogicalOp* logicalOp) {};
 
--- a/gfx/angle/src/compiler/translator/intermOut.cpp
+++ b/gfx/angle/src/compiler/translator/intermOut.cpp
@@ -5,16 +5,22 @@
 //
 
 #include "compiler/translator/Intermediate.h"
 #include "compiler/translator/SymbolTable.h"
 
 namespace
 {
 
+void OutputFunction(TInfoSinkBase &out, const char *str, TIntermAggregate *node)
+{
+    const char *internal = node->getNameObj().isInternal() ? " (internal function)" : "";
+    out << str << internal << ": " << node->getNameObj().getString();
+}
+
 //
 // Two purposes:
 // 1.  Show an example of how to iterate tree.  Functions can
 //     also directly call Traverse() on children themselves to
 //     have finer grained control over the process than shown here.
 //     See the last function for how to get started.
 // 2.  Print out a text based description of the tree.
 //
@@ -390,20 +396,20 @@ bool TOutputTraverser::visitAggregate(Vi
     }
 
     OutputTreeText(out, node, mDepth);
 
     switch (node->getOp())
     {
       case EOpSequence:      out << "Sequence\n"; return true;
       case EOpComma:         out << "Comma\n"; return true;
-      case EOpFunction:      out << "Function Definition: " << node->getName(); break;
-      case EOpFunctionCall:  out << "Function Call: " << node->getName(); break;
+      case EOpFunction:      OutputFunction(out, "Function Definition", node); break;
+      case EOpFunctionCall:  OutputFunction(out, "Function Call", node); break;
       case EOpParameters:    out << "Function Parameters: ";              break;
-      case EOpPrototype:     out << "Function Prototype: " << node->getName(); break;
+      case EOpPrototype:     OutputFunction(out, "Function Prototype", node); break;
 
       case EOpConstructFloat: out << "Construct float"; break;
       case EOpConstructVec2:  out << "Construct vec2";  break;
       case EOpConstructVec3:  out << "Construct vec3";  break;
       case EOpConstructVec4:  out << "Construct vec4";  break;
       case EOpConstructBool:  out << "Construct bool";  break;
       case EOpConstructBVec2: out << "Construct bvec2"; break;
       case EOpConstructBVec3: out << "Construct bvec3"; break;
--- a/gfx/angle/src/compiler/translator/util.h
+++ b/gfx/angle/src/compiler/translator/util.h
@@ -36,16 +36,17 @@ bool IsVaryingOut(TQualifier qualifier);
 bool IsVarying(TQualifier qualifier);
 InterpolationType GetInterpolationType(TQualifier qualifier);
 TString ArrayString(const TType &type);
 
 class GetVariableTraverser : angle::NonCopyable
 {
   public:
     GetVariableTraverser(const TSymbolTable &symbolTable);
+    virtual ~GetVariableTraverser() {}
 
     template <typename VarT>
     void traverse(const TType &type, const TString &name, std::vector<VarT> *output);
 
   protected:
     // May be overloaded
     virtual void visitVariable(ShaderVariable *newVar) {}
 
--- a/gfx/angle/src/libANGLE/AttributeMap.h
+++ b/gfx/angle/src/libANGLE/AttributeMap.h
@@ -10,25 +10,25 @@
 
 #include <EGL/egl.h>
 
 #include <map>
 
 namespace egl
 {
 
-class AttributeMap
+class AttributeMap final
 {
   public:
     AttributeMap();
     explicit AttributeMap(const EGLint *attributes);
 
-    virtual void insert(EGLint key, EGLint value);
-    virtual bool contains(EGLint key) const;
-    virtual EGLint get(EGLint key, EGLint defaultValue) const;
+    void insert(EGLint key, EGLint value);
+    bool contains(EGLint key) const;
+    EGLint get(EGLint key, EGLint defaultValue) const;
 
     typedef std::map<EGLint, EGLint>::const_iterator const_iterator;
 
     const_iterator begin() const;
     const_iterator end() const;
 
   private:
     std::map<EGLint, EGLint> mAttributes;
--- a/gfx/angle/src/libANGLE/BinaryStream.h
+++ b/gfx/angle/src/libANGLE/BinaryStream.h
@@ -42,30 +42,30 @@ class BinaryInputStream : angle::NonCopy
         mData = static_cast<const uint8_t*>(data);
         mLength = length;
     }
 
     // readInt will generate an error for bool types
     template <class IntT>
     IntT readInt()
     {
-        int value;
+        int value = 0;
         read(&value);
         return static_cast<IntT>(value);
     }
 
     template <class IntT>
     void readInt(IntT *outValue)
     {
         *outValue = readInt<IntT>();
     }
 
     bool readBool()
     {
-        int value;
+        int value = 0;
         read(&value);
         return (value > 0);
     }
 
     void readBool(bool *outValue)
     {
         *outValue = readBool();
     }
--- a/gfx/angle/src/libANGLE/Context.cpp
+++ b/gfx/angle/src/libANGLE/Context.cpp
@@ -61,17 +61,23 @@ Context::Context(const egl::Config *conf
                  int clientVersion,
                  const Context *shareContext,
                  rx::Renderer *renderer,
                  bool notifyResets,
                  bool robustAccess)
     : mRenderer(renderer),
       mConfig(config),
       mCurrentSurface(nullptr),
-      mData(clientVersion, mState, mCaps, mTextureCaps, mExtensions, nullptr)
+      mData(reinterpret_cast<uintptr_t>(this),
+            clientVersion,
+            mState,
+            mCaps,
+            mTextureCaps,
+            mExtensions,
+            nullptr)
 {
     ASSERT(robustAccess == false);   // Unimplemented
 
     initCaps(clientVersion);
     mState.initialize(mCaps, clientVersion);
 
     mClientVersion = clientVersion;
 
@@ -163,17 +169,20 @@ Context::~Context()
 
     for (auto fence : mFenceNVMap)
     {
         SafeDelete(fence.second);
     }
 
     for (auto query : mQueryMap)
     {
-        query.second->release();
+        if (query.second != nullptr)
+        {
+            query.second->release();
+        }
     }
 
     for (auto vertexArray : mVertexArrayMap)
     {
         SafeDelete(vertexArray.second);
     }
 
     mTransformFeedbackZero.set(NULL);
@@ -846,17 +855,17 @@ void Context::getIntegerv(GLenum pname, 
       case GL_MAX_VERTEX_UNIFORM_VECTORS:               *params = mCaps.maxVertexUniformVectors;                        break;
       case GL_MAX_VERTEX_UNIFORM_COMPONENTS:            *params = mCaps.maxVertexUniformComponents;                     break;
       case GL_MAX_VARYING_VECTORS:                      *params = mCaps.maxVaryingVectors;                              break;
       case GL_MAX_VARYING_COMPONENTS:                   *params = mCaps.maxVertexOutputComponents;                      break;
       case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:         *params = mCaps.maxCombinedTextureImageUnits;                   break;
       case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:           *params = mCaps.maxVertexTextureImageUnits;                     break;
       case GL_MAX_TEXTURE_IMAGE_UNITS:                  *params = mCaps.maxTextureImageUnits;                           break;
       case GL_MAX_FRAGMENT_UNIFORM_VECTORS:             *params = mCaps.maxFragmentUniformVectors;                      break;
-      case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:          *params = mCaps.maxFragmentInputComponents;                     break;
+      case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:          *params = mCaps.maxFragmentUniformComponents;                   break;
       case GL_MAX_RENDERBUFFER_SIZE:                    *params = mCaps.maxRenderbufferSize;                            break;
       case GL_MAX_COLOR_ATTACHMENTS_EXT:                *params = mCaps.maxColorAttachments;                            break;
       case GL_MAX_DRAW_BUFFERS_EXT:                     *params = mCaps.maxDrawBuffers;                                 break;
       //case GL_FRAMEBUFFER_BINDING:                    // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
       case GL_SUBPIXEL_BITS:                            *params = 4;                                                    break;
       case GL_MAX_TEXTURE_SIZE:                         *params = mCaps.max2DTextureSize;                               break;
       case GL_MAX_CUBE_MAP_TEXTURE_SIZE:                *params = mCaps.maxCubeMapTextureSize;                          break;
       case GL_MAX_3D_TEXTURE_SIZE:                      *params = mCaps.max3DTextureSize;                               break;
@@ -1092,27 +1101,27 @@ bool Context::getQueryParameterInfo(GLen
             {
                 return false;
             }
         }
         return true;
         case GL_PACK_ROW_LENGTH:
         case GL_PACK_SKIP_ROWS:
         case GL_PACK_SKIP_PIXELS:
-            if (!mExtensions.packSubimage)
+            if ((mClientVersion < 3) && !mExtensions.packSubimage)
             {
                 return false;
             }
             *type      = GL_INT;
             *numParams = 1;
             return true;
         case GL_UNPACK_ROW_LENGTH:
         case GL_UNPACK_SKIP_ROWS:
         case GL_UNPACK_SKIP_PIXELS:
-            if (!mExtensions.unpackSubimage)
+            if ((mClientVersion < 3) && !mExtensions.unpackSubimage)
             {
                 return false;
             }
             *type      = GL_INT;
             *numParams = 1;
             return true;
       case GL_MAX_VIEWPORT_DIMS:
         {
@@ -1223,16 +1232,18 @@ bool Context::getQueryParameterInfo(GLen
       case GL_MAX_ELEMENTS_VERTICES:
       case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:
       case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
       case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS:
       case GL_PACK_ROW_LENGTH:
       case GL_PACK_SKIP_ROWS:
       case GL_PACK_SKIP_PIXELS:
       case GL_UNPACK_ROW_LENGTH:
+      case GL_UNPACK_IMAGE_HEIGHT:
+      case GL_UNPACK_SKIP_IMAGES:
       case GL_UNPACK_SKIP_ROWS:
       case GL_UNPACK_SKIP_PIXELS:
         {
             *type = GL_INT;
             *numParams = 1;
         }
         return true;
 
--- a/gfx/angle/src/libANGLE/Data.cpp
+++ b/gfx/angle/src/libANGLE/Data.cpp
@@ -7,45 +7,29 @@
 // Data.cpp: Container class for all GL relevant state, caps and objects
 
 #include "libANGLE/Data.h"
 #include "libANGLE/ResourceManager.h"
 
 namespace gl
 {
 
-Data::Data(GLint clientVersionIn, const State &stateIn, const Caps &capsIn,
-           const TextureCapsMap &textureCapsIn, const Extensions &extensionsIn,
+Data::Data(uintptr_t contextIn,
+           GLint clientVersionIn,
+           const State &stateIn,
+           const Caps &capsIn,
+           const TextureCapsMap &textureCapsIn,
+           const Extensions &extensionsIn,
            const ResourceManager *resourceManagerIn)
-    : clientVersion(clientVersionIn),
+    : context(contextIn),
+      clientVersion(clientVersionIn),
       state(&stateIn),
       caps(&capsIn),
       textureCaps(&textureCapsIn),
       extensions(&extensionsIn),
       resourceManager(resourceManagerIn)
 {}
 
 Data::~Data()
 {
 }
 
-Data::Data(const Data &other)
-    : clientVersion(other.clientVersion),
-      state(other.state),
-      caps(other.caps),
-      textureCaps(other.textureCaps),
-      extensions(other.extensions),
-      resourceManager(other.resourceManager)
-{
 }
-
-Data &Data::operator=(const Data &other)
-{
-    clientVersion = other.clientVersion;
-    state = other.state;
-    caps = other.caps;
-    textureCaps = other.textureCaps;
-    extensions = other.extensions;
-    resourceManager = other.resourceManager;
-    return *this;
-}
-
-}
--- a/gfx/angle/src/libANGLE/Data.h
+++ b/gfx/angle/src/libANGLE/Data.h
@@ -4,32 +4,35 @@
 // found in the LICENSE file.
 //
 
 // Data.h: Container class for all GL relevant state, caps and objects
 
 #ifndef LIBANGLE_DATA_H_
 #define LIBANGLE_DATA_H_
 
+#include "common/angleutils.h"
 #include "libANGLE/State.h"
 
 namespace gl
 {
 
-struct Data final
+struct Data final : public angle::NonCopyable
 {
   public:
-    Data(GLint clientVersion, const State &state, const Caps &caps,
-         const TextureCapsMap &textureCaps, const Extensions &extensions,
+    Data(uintptr_t context,
+         GLint clientVersion,
+         const State &state,
+         const Caps &caps,
+         const TextureCapsMap &textureCaps,
+         const Extensions &extensions,
          const ResourceManager *resourceManager);
     ~Data();
 
-    Data(const Data &other);
-    Data &operator=(const Data &other);
-
+    uintptr_t context;
     GLint clientVersion;
     const State *state;
     const Caps *caps;
     const TextureCapsMap *textureCaps;
     const Extensions *extensions;
     const ResourceManager *resourceManager;
 };
 
--- a/gfx/angle/src/libANGLE/Display.cpp
+++ b/gfx/angle/src/libANGLE/Display.cpp
@@ -71,29 +71,16 @@ void InitDefaultPlatformImpl()
         {
             defaultPlatform = new DefaultPlatform();
         }
 
         ANGLEPlatformInitialize(defaultPlatform);
     }
 }
 
-void DeinitDefaultPlatformImpl()
-{
-    if (defaultPlatform != nullptr)
-    {
-        if (ANGLEPlatformCurrent() == defaultPlatform)
-        {
-            ANGLEPlatformShutdown();
-        }
-
-        SafeDelete(defaultPlatform);
-    }
-}
-
 typedef std::map<EGLNativeWindowType, Surface*> WindowSurfaceMap;
 // Get a map of all EGL window surfaces to validate that no window has more than one EGL surface
 // associated with it.
 static WindowSurfaceMap *GetWindowSurfaces()
 {
     static WindowSurfaceMap windowSurfaces;
     return &windowSurfaces;
 }
--- a/gfx/angle/src/libANGLE/Framebuffer.cpp
+++ b/gfx/angle/src/libANGLE/Framebuffer.cpp
@@ -606,19 +606,27 @@ Error Framebuffer::readPixels(Context *c
     if (unpackBuffer)
     {
         unpackBuffer->onPixelUnpack();
     }
 
     return Error(GL_NO_ERROR);
 }
 
-Error Framebuffer::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
-                        GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
+Error Framebuffer::blit(Context *context,
+                        const gl::Rectangle &sourceArea,
+                        const gl::Rectangle &destArea,
+                        GLbitfield mask,
+                        GLenum filter,
+                        const gl::Framebuffer *sourceFramebuffer)
 {
+    // Sync blit state
+    const State &state = context->getState();
+    context->syncRendererState(state.blitStateBitMask());
+
     return mImpl->blit(state, sourceArea, destArea, mask, filter, sourceFramebuffer);
 }
 
 int Framebuffer::getSamples(const gl::Data &data) const
 {
     if (checkStatus(data) == GL_FRAMEBUFFER_COMPLETE)
     {
         // for a complete framebuffer, all attachments must have the same sample count
--- a/gfx/angle/src/libANGLE/Framebuffer.h
+++ b/gfx/angle/src/libANGLE/Framebuffer.h
@@ -139,18 +139,22 @@ class Framebuffer
     GLenum getImplementationColorReadFormat() const;
     GLenum getImplementationColorReadType() const;
     Error readPixels(Context *context,
                      const gl::Rectangle &area,
                      GLenum format,
                      GLenum type,
                      GLvoid *pixels) const;
 
-    Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
-               GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer);
+    Error blit(Context *context,
+               const gl::Rectangle &sourceArea,
+               const gl::Rectangle &destArea,
+               GLbitfield mask,
+               GLenum filter,
+               const gl::Framebuffer *sourceFramebuffer);
 
   protected:
     void detachResourceById(GLenum resourceType, GLuint resourceId);
 
     Data mData;
     rx::FramebufferImpl *mImpl;
     GLuint mId;
 };
--- a/gfx/angle/src/libANGLE/FramebufferAttachment.h
+++ b/gfx/angle/src/libANGLE/FramebufferAttachment.h
@@ -141,16 +141,17 @@ class FramebufferAttachment final
     FramebufferAttachmentObject *mResource;
 };
 
 // A base class for objects that FBO Attachments may point to.
 class FramebufferAttachmentObject
 {
   public:
     FramebufferAttachmentObject() {}
+    virtual ~FramebufferAttachmentObject() {}
 
     virtual GLsizei getAttachmentWidth(const FramebufferAttachment::Target &target) const = 0;
     virtual GLsizei getAttachmentHeight(const FramebufferAttachment::Target &target) const = 0;
     virtual GLenum getAttachmentInternalFormat(const FramebufferAttachment::Target &target) const = 0;
     virtual GLsizei getAttachmentSamples(const FramebufferAttachment::Target &target) const = 0;
 
     virtual void onAttach() = 0;
     virtual void onDetach() = 0;
--- a/gfx/angle/src/libANGLE/Program.cpp
+++ b/gfx/angle/src/libANGLE/Program.cpp
@@ -21,37 +21,20 @@
 #include "libANGLE/ResourceManager.h"
 #include "libANGLE/features.h"
 #include "libANGLE/renderer/Renderer.h"
 #include "libANGLE/renderer/ProgramImpl.h"
 #include "libANGLE/queryconversions.h"
 
 namespace gl
 {
-const char * const g_fakepath = "C:\\fakepath";
 
 namespace
 {
 
-unsigned int ParseAndStripArrayIndex(std::string* name)
-{
-    unsigned int subscript = GL_INVALID_INDEX;
-
-    // Strip any trailing array operator and retrieve the subscript
-    size_t open = name->find_last_of('[');
-    size_t close = name->find_last_of(']');
-    if (open != std::string::npos && close == name->length() - 1)
-    {
-        subscript = atoi(name->substr(open + 1).c_str());
-        name->erase(open);
-    }
-
-    return subscript;
-}
-
 void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
 {
     stream->writeInt(var.type);
     stream->writeInt(var.precision);
     stream->writeString(var.name);
     stream->writeString(var.mappedName);
     stream->writeInt(var.arraySize);
     stream->writeInt(var.staticUse);
@@ -65,50 +48,16 @@ void LoadShaderVar(BinaryInputStream *st
     var->precision  = stream->readInt<GLenum>();
     var->name       = stream->readString();
     var->mappedName = stream->readString();
     var->arraySize  = stream->readInt<unsigned int>();
     var->staticUse  = stream->readBool();
     var->structName = stream->readString();
 }
 
-template <typename VarT>
-void DefineUniformBlockMembers(const std::vector<VarT> &fields,
-                               const std::string &prefix,
-                               int blockIndex,
-                               std::vector<LinkedUniform> *uniformsOut)
-{
-    for (const VarT &field : fields)
-    {
-        const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
-
-        if (field.isStruct())
-        {
-            for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
-            {
-                const std::string uniformElementName =
-                    fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
-                DefineUniformBlockMembers(field.fields, uniformElementName, blockIndex,
-                                          uniformsOut);
-            }
-        }
-        else
-        {
-            // TODO(jmadill): record row-majorness?
-            // Block layout is recorded in the Impl.
-            LinkedUniform newUniform(field.type, field.precision, fieldName, field.arraySize,
-                                     blockIndex, sh::BlockMemberInfo::getDefaultBlockInfo());
-
-            // Since block uniforms have no location, we don't need to store them in the uniform
-            // locations list.
-            uniformsOut->push_back(newUniform);
-        }
-    }
-}
-
 // This simplified cast function doesn't need to worry about advanced concepts like
 // depth range values, or casting to bool.
 template <typename DestT, typename SrcT>
 DestT UniformStateQueryCast(SrcT value);
 
 // From-Float-To-Integer Casts
 template <>
 GLint UniformStateQueryCast(GLfloat value)
@@ -182,16 +131,18 @@ bool UniformInList(const std::vector<Lin
             return true;
     }
 
     return false;
 }
 
 }  // anonymous namespace
 
+const char *const g_fakepath = "C:\\fakepath";
+
 AttributeBindings::AttributeBindings()
 {
 }
 
 AttributeBindings::~AttributeBindings()
 {
 }
 
@@ -204,17 +155,17 @@ InfoLog::~InfoLog()
 }
 
 size_t InfoLog::getLength() const
 {
     const std::string &logString = mStream.str();
     return logString.empty() ? 0 : logString.length() + 1;
 }
 
-void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog)
+void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
 {
     size_t index = 0;
 
     if (bufSize > 0)
     {
         const std::string str(mStream.str());
 
         if (!str.empty())
@@ -516,17 +467,17 @@ Error Program::link(const gl::Data &data
 
     rx::LinkResult result = mProgram->link(data, mInfoLog);
     if (result.error.isError() || !result.linkSuccess)
     {
         return result.error;
     }
 
     gatherTransformFeedbackVaryings(mergedVaryings);
-    mProgram->gatherUniformBlockInfo(&mData.mUniformBlocks, &mData.mUniforms);
+    gatherInterfaceBlockInfo();
 
     mLinked = true;
     return gl::Error(GL_NO_ERROR);
 }
 
 int AttributeBindings::getAttributeBinding(const std::string &name) const
 {
     for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
@@ -566,39 +517,37 @@ void Program::unlink(bool destroy)
     mData.mUniformBlocks.clear();
     mData.mOutputVariables.clear();
 
     mValidated = false;
 
     mLinked = false;
 }
 
-bool Program::isLinked()
+bool Program::isLinked() const
 {
     return mLinked;
 }
 
 Error Program::loadBinary(GLenum binaryFormat, const void *binary, GLsizei length)
 {
     unlink(false);
 
 #if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED
     return Error(GL_NO_ERROR);
 #else
-    ASSERT(binaryFormat == mProgram->getBinaryFormat());
-
-    BinaryInputStream stream(binary, length);
-
-    GLenum format = stream.readInt<GLenum>();
-    if (format != mProgram->getBinaryFormat())
+    ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
+    if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
     {
         mInfoLog << "Invalid program binary format.";
         return Error(GL_NO_ERROR);
     }
 
+    BinaryInputStream stream(binary, length);
+
     int majorVersion = stream.readInt<int>();
     int minorVersion = stream.readInt<int>();
     if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION)
     {
         mInfoLog << "Invalid program binary version.";
         return Error(GL_NO_ERROR);
     }
 
@@ -667,21 +616,31 @@ Error Program::loadBinary(GLenum binaryF
         stream.readBool(&uniformBlock.fragmentStaticUse);
 
         unsigned int numMembers = stream.readInt<unsigned int>();
         for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
         {
             uniformBlock.memberUniformIndexes.push_back(stream.readInt<unsigned int>());
         }
 
-        // TODO(jmadill): Make D3D-only
-        stream.readInt(&uniformBlock.psRegisterIndex);
-        stream.readInt(&uniformBlock.vsRegisterIndex);
+        mData.mUniformBlocks.push_back(uniformBlock);
+    }
 
-        mData.mUniformBlocks.push_back(uniformBlock);
+    unsigned int transformFeedbackVaryingCount = stream.readInt<unsigned int>();
+    ASSERT(mData.mTransformFeedbackVaryingVars.empty());
+    for (unsigned int transformFeedbackVaryingIndex = 0;
+        transformFeedbackVaryingIndex < transformFeedbackVaryingCount;
+        ++transformFeedbackVaryingIndex)
+    {
+        sh::Varying varying;
+        stream.readInt(&varying.arraySize);
+        stream.readInt(&varying.type);
+        stream.readString(&varying.name);
+
+        mData.mTransformFeedbackVaryingVars.push_back(varying);
     }
 
     stream.readInt(&mData.mTransformFeedbackBufferMode);
 
     unsigned int outputVarCount = stream.readInt<unsigned int>();
     for (unsigned int outputIndex = 0; outputIndex < outputVarCount; ++outputIndex)
     {
         int locationIndex = stream.readInt<int>();
@@ -705,22 +664,21 @@ Error Program::loadBinary(GLenum binaryF
     return Error(GL_NO_ERROR);
 #endif // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED
 }
 
 Error Program::saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const
 {
     if (binaryFormat)
     {
-        *binaryFormat = mProgram->getBinaryFormat();
+        *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
     }
 
     BinaryOutputStream stream;
 
-    stream.writeInt(mProgram->getBinaryFormat());
     stream.writeInt(ANGLE_MAJOR_VERSION);
     stream.writeInt(ANGLE_MINOR_VERSION);
     stream.writeBytes(reinterpret_cast<const unsigned char*>(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE);
 
     stream.writeInt(mData.mActiveAttribLocationsMask.to_ulong());
 
     stream.writeInt(mData.mAttributes.size());
     for (const sh::Attribute &attrib : mData.mAttributes)
@@ -762,20 +720,24 @@ Error Program::saveBinary(GLenum *binary
         stream.writeInt(uniformBlock.vertexStaticUse);
         stream.writeInt(uniformBlock.fragmentStaticUse);
 
         stream.writeInt(uniformBlock.memberUniformIndexes.size());
         for (unsigned int memberUniformIndex : uniformBlock.memberUniformIndexes)
         {
             stream.writeInt(memberUniformIndex);
         }
+    }
 
-        // TODO(jmadill): make D3D-only
-        stream.writeInt(uniformBlock.psRegisterIndex);
-        stream.writeInt(uniformBlock.vsRegisterIndex);
+    stream.writeInt(mData.mTransformFeedbackVaryingVars.size());
+    for (const sh::Varying &varying : mData.mTransformFeedbackVaryingVars)
+    {
+        stream.writeInt(varying.arraySize);
+        stream.writeInt(varying.type);
+        stream.writeString(varying.name);
     }
 
     stream.writeInt(mData.mTransformFeedbackBufferMode);
 
     stream.writeInt(mData.mOutputVariables.size());
     for (const auto &outputPair : mData.mOutputVariables)
     {
         stream.writeInt(outputPair.first);
@@ -859,22 +821,22 @@ unsigned int Program::getRefCount() cons
     return mRefCount;
 }
 
 int Program::getInfoLogLength() const
 {
     return static_cast<int>(mInfoLog.getLength());
 }
 
-void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
+void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
 {
     return mInfoLog.getLog(bufSize, length, infoLog);
 }
 
-void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
+void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) const
 {
     int total = 0;
 
     if (mData.mAttachedVertexShader)
     {
         if (total < maxCount)
         {
             shaders[total] = mData.mAttachedVertexShader->getHandle();
@@ -894,17 +856,17 @@ void Program::getAttachedShaders(GLsizei
     }
 
     if (count)
     {
         *count = total;
     }
 }
 
-GLuint Program::getAttributeLocation(const std::string &name)
+GLuint Program::getAttributeLocation(const std::string &name) const
 {
     for (const sh::Attribute &attribute : mData.mAttributes)
     {
         if (attribute.name == name && attribute.staticUse)
         {
             return attribute.location;
         }
     }
@@ -968,34 +930,34 @@ void Program::getActiveAttribute(GLuint 
         }
     }
 
     // Always a single 'type' instance
     *size = 1;
     *type = attrib.type;
 }
 
-GLint Program::getActiveAttributeCount()
+GLint Program::getActiveAttributeCount() const
 {
     if (!mLinked)
     {
         return 0;
     }
 
     GLint count = 0;
 
     for (const sh::Attribute &attrib : mData.mAttributes)
     {
         count += (attrib.staticUse ? 1 : 0);
     }
 
     return count;
 }
 
-GLint Program::getActiveAttributeMaxLength()
+GLint Program::getActiveAttributeMaxLength() const
 {
     if (!mLinked)
     {
         return 0;
     }
 
     size_t maxLength = 0;
 
@@ -1020,17 +982,22 @@ GLint Program::getFragDataLocation(const
         if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element))
         {
             return static_cast<GLint>(outputPair.first);
         }
     }
     return -1;
 }
 
-void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+void Program::getActiveUniform(GLuint index,
+                               GLsizei bufsize,
+                               GLsizei *length,
+                               GLint *size,
+                               GLenum *type,
+                               GLchar *name) const
 {
     if (mLinked)
     {
         // index must be smaller than getActiveUniformCount()
         ASSERT(index < mData.mUniforms.size());
         const LinkedUniform &uniform = mData.mUniforms[index];
 
         if (bufsize > 0)
@@ -1065,29 +1032,29 @@ void Program::getActiveUniform(GLuint in
             *length = 0;
         }
 
         *size = 0;
         *type = GL_NONE;
     }
 }
 
-GLint Program::getActiveUniformCount()
+GLint Program::getActiveUniformCount() const
 {
     if (mLinked)
     {
         return static_cast<GLint>(mData.mUniforms.size());
     }
     else
     {
         return 0;
     }
 }
 
-GLint Program::getActiveUniformMaxLength()
+GLint Program::getActiveUniformMaxLength() const
 {
     size_t maxLength = 0;
 
     if (mLinked)
     {
         for (const LinkedUniform &uniform : mData.mUniforms)
         {
             if (!uniform.name.empty())
@@ -1269,27 +1236,27 @@ void Program::setUniformMatrix4x2fv(GLin
 }
 
 void Program::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
 {
     setMatrixUniformInternal<4, 3>(location, count, transpose, v);
     mProgram->setUniformMatrix4x3fv(location, count, transpose, v);
 }
 
-void Program::getUniformfv(GLint location, GLfloat *v)
+void Program::getUniformfv(GLint location, GLfloat *v) const
 {
     getUniformInternal(location, v);
 }
 
-void Program::getUniformiv(GLint location, GLint *v)
+void Program::getUniformiv(GLint location, GLint *v) const
 {
     getUniformInternal(location, v);
 }
 
-void Program::getUniformuiv(GLint location, GLuint *v)
+void Program::getUniformuiv(GLint location, GLuint *v) const
 {
     getUniformInternal(location, v);
 }
 
 void Program::flagForDeletion()
 {
     mDeleteStatus = true;
 }
@@ -1389,17 +1356,17 @@ bool Program::validateSamplers(InfoLog *
     return true;
 }
 
 bool Program::isValidated() const
 {
     return mValidated;
 }
 
-GLuint Program::getActiveUniformBlockCount()
+GLuint Program::getActiveUniformBlockCount() const
 {
     return static_cast<GLuint>(mData.mUniformBlocks.size());
 }
 
 void Program::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const
 {
     ASSERT(uniformBlockIndex <
            mData.mUniformBlocks.size());  // index must be smaller than getActiveUniformBlockCount()
@@ -1457,17 +1424,17 @@ void Program::getActiveUniformBlockiv(GL
         break;
       case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
           *params = static_cast<GLint>(uniformBlock.fragmentStaticUse);
         break;
       default: UNREACHABLE();
     }
 }
 
-GLint Program::getActiveUniformBlockMaxLength()
+GLint Program::getActiveUniformBlockMaxLength() const
 {
     int maxLength = 0;
 
     if (mLinked)
     {
         unsigned int numUniformBlocks = static_cast<unsigned int>(mData.mUniformBlocks.size());
         for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
         {
@@ -1482,17 +1449,17 @@ GLint Program::getActiveUniformBlockMaxL
                 maxLength = std::max(length + arrayLength, maxLength);
             }
         }
     }
 
     return maxLength;
 }
 
-GLuint Program::getUniformBlockIndex(const std::string &name)
+GLuint Program::getUniformBlockIndex(const std::string &name) const
 {
     size_t subscript     = GL_INVALID_INDEX;
     std::string baseName = gl::ParseUniformName(name, &subscript);
 
     unsigned int numUniformBlocks = static_cast<unsigned int>(mData.mUniformBlocks.size());
     for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
     {
         const gl::UniformBlock &uniformBlock = mData.mUniformBlocks[blockIndex];
@@ -1515,29 +1482,31 @@ const UniformBlock &Program::getUniformB
 {
     ASSERT(index < static_cast<GLuint>(mData.mUniformBlocks.size()));
     return mData.mUniformBlocks[index];
 }
 
 void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
 {
     mData.mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding;
+    mProgram->setUniformBlockBinding(uniformBlockIndex, uniformBlockBinding);
 }
 
 GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
 {
     return mData.getUniformBlockBinding(uniformBlockIndex);
 }
 
 void Program::resetUniformBlockBindings()
 {
     for (unsigned int blockId = 0; blockId < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; blockId++)
     {
         mData.mUniformBlockBindings[blockId] = 0;
     }
+    mData.mActiveUniformBlockBindings.reset();
 }
 
 void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode)
 {
     mData.mTransformFeedbackVaryingNames.resize(count);
     for (GLsizei i = 0; i < count; i++)
     {
         mData.mTransformFeedbackVaryingNames[i] = varyings[i];
@@ -1885,18 +1854,16 @@ bool Program::linkUniformBlocks(InfoLog 
                 infoLog
                     << "Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS ("
                     << caps.maxFragmentUniformBlocks << ")";
                 return false;
             }
         }
     }
 
-    gatherInterfaceBlockInfo();
-
     return true;
 }
 
 bool Program::areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock,
                                          const sh::InterfaceBlock &fragmentInterfaceBlock)
 {
     const char* blockName = vertexInterfaceBlock.name.c_str();
     // validate blocks for the same member types
@@ -2325,21 +2292,68 @@ void Program::gatherInterfaceBlockInfo()
             continue;
         }
 
         defineUniformBlock(fragmentBlock, GL_FRAGMENT_SHADER);
         visitedList.insert(fragmentBlock.name);
     }
 }
 
+template <typename VarT>
+void Program::defineUniformBlockMembers(const std::vector<VarT> &fields,
+                                        const std::string &prefix,
+                                        int blockIndex)
+{
+    for (const VarT &field : fields)
+    {
+        const std::string &fullName = (prefix.empty() ? field.name : prefix + "." + field.name);
+
+        if (field.isStruct())
+        {
+            for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
+            {
+                const std::string uniformElementName =
+                    fullName + (field.isArray() ? ArrayString(arrayElement) : "");
+                defineUniformBlockMembers(field.fields, uniformElementName, blockIndex);
+            }
+        }
+        else
+        {
+            // If getBlockMemberInfo returns false, the uniform is optimized out.
+            sh::BlockMemberInfo memberInfo;
+            if (!mProgram->getUniformBlockMemberInfo(fullName, &memberInfo))
+            {
+                continue;
+            }
+
+            LinkedUniform newUniform(field.type, field.precision, fullName, field.arraySize,
+                                     blockIndex, memberInfo);
+
+            // Since block uniforms have no location, we don't need to store them in the uniform
+            // locations list.
+            mData.mUniforms.push_back(newUniform);
+        }
+    }
+}
+
 void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType)
 {
-    int blockIndex                = static_cast<int>(mData.mUniformBlocks.size());
+    int blockIndex   = static_cast<int>(mData.mUniformBlocks.size());
+    size_t blockSize = 0;
+
+    // Don't define this block at all if it's not active in the implementation.
+    if (!mProgram->getUniformBlockSize(interfaceBlock.name, &blockSize))
+    {
+        return;
+    }
+
+    // Track the first and last uniform index to determine the range of active uniforms in the
+    // block.
     size_t firstBlockUniformIndex = mData.mUniforms.size();
-    DefineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, &mData.mUniforms);
+    defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex);
     size_t lastBlockUniformIndex = mData.mUniforms.size();
 
     std::vector<unsigned int> blockUniformIndexes;
     for (size_t blockUniformIndex = firstBlockUniformIndex;
          blockUniformIndex < lastBlockUniformIndex; ++blockUniformIndex)
     {
         blockUniformIndexes.push_back(static_cast<unsigned int>(blockUniformIndex));
     }
@@ -2356,16 +2370,25 @@ void Program::defineUniformBlock(const s
                 block.vertexStaticUse = interfaceBlock.staticUse;
             }
             else
             {
                 ASSERT(shaderType == GL_FRAGMENT_SHADER);
                 block.fragmentStaticUse = interfaceBlock.staticUse;
             }
 
+            // TODO(jmadill): Determine if we can ever have an inactive array element block.
+            size_t blockElementSize = 0;
+            if (!mProgram->getUniformBlockSize(block.nameWithArrayIndex(), &blockElementSize))
+            {
+                continue;
+            }
+
+            ASSERT(blockElementSize == blockSize);
+            block.dataSize = static_cast<unsigned int>(blockElementSize);
             mData.mUniformBlocks.push_back(block);
         }
     }
     else
     {
         UniformBlock block(interfaceBlock.name, false, 0);
         block.memberUniformIndexes = blockUniformIndexes;
 
@@ -2374,16 +2397,17 @@ void Program::defineUniformBlock(const s
             block.vertexStaticUse = interfaceBlock.staticUse;
         }
         else
         {
             ASSERT(shaderType == GL_FRAGMENT_SHADER);
             block.fragmentStaticUse = interfaceBlock.staticUse;
         }
 
+        block.dataSize = static_cast<unsigned int>(blockSize);
         mData.mUniformBlocks.push_back(block);
     }
 }
 
 template <typename T>
 void Program::setUniformInternal(GLint location, GLsizei count, const T *v)
 {
     const VariableLocation &locationInfo = mData.mUniformLocations[location];
--- a/gfx/angle/src/libANGLE/Program.h
+++ b/gfx/angle/src/libANGLE/Program.h
@@ -64,17 +64,17 @@ class AttributeBindings
 
 class InfoLog : angle::NonCopyable
 {
   public:
     InfoLog();
     ~InfoLog();
 
     size_t getLength() const;
-    void getLog(GLsizei bufSize, GLsizei *length, char *infoLog);
+    void getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
 
     void appendSanitized(const char *message);
     void reset();
 
     // This helper class ensures we append a newline after writing a line.
     class StreamHelper : angle::NonCopyable
     {
       public:
@@ -177,16 +177,20 @@ class Program : angle::NonCopyable
             return mTransformFeedbackVaryingNames;
         }
         GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; }
         GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const
         {
             ASSERT(uniformBlockIndex < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS);
             return mUniformBlockBindings[uniformBlockIndex];
         }
+        const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const
+        {
+            return mActiveUniformBlockBindings;
+        }
         const std::vector<sh::Attribute> &getAttributes() const { return mAttributes; }
         const AttributesMask &getActiveAttribLocationsMask() const
         {
             return mActiveAttribLocationsMask;
         }
         const std::map<int, VariableLocation> &getOutputVariables() const
         {
             return mOutputVariables;
@@ -208,16 +212,17 @@ class Program : angle::NonCopyable
         Shader *mAttachedFragmentShader;
         Shader *mAttachedVertexShader;
 
         std::vector<std::string> mTransformFeedbackVaryingNames;
         std::vector<sh::Varying> mTransformFeedbackVaryingVars;
         GLenum mTransformFeedbackBufferMode;
 
         GLuint mUniformBlockBindings[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS];
+        UniformBlockBindingMask mActiveUniformBlockBindings;
 
         std::vector<sh::Attribute> mAttributes;
         std::bitset<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
 
         // Uniforms are sorted in order:
         //  1. Non-sampler uniforms
         //  2. Sampler uniforms
         //  3. Uniform block uniforms
@@ -240,39 +245,44 @@ class Program : angle::NonCopyable
 
     bool attachShader(Shader *shader);
     bool detachShader(Shader *shader);
     int getAttachedShadersCount() const;
 
     void bindAttributeLocation(GLuint index, const char *name);
 
     Error link(const gl::Data &data);
-    bool isLinked();
+    bool isLinked() const;
 
     Error loadBinary(GLenum binaryFormat, const void *binary, GLsizei length);
     Error saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const;
     GLint getBinaryLength() const;
 
     int getInfoLogLength() const;
-    void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
-    void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
+    void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
+    void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) const;
 
-    GLuint getAttributeLocation(const std::string &name);
+    GLuint getAttributeLocation(const std::string &name) const;
     bool isAttribLocationActive(size_t attribLocation) const;
 
     void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
-    GLint getActiveAttributeCount();
-    GLint getActiveAttributeMaxLength();
+    GLint getActiveAttributeCount() const;
+    GLint getActiveAttributeMaxLength() const;
     const std::vector<sh::Attribute> &getAttributes() const { return mData.mAttributes; }
 
     GLint getFragDataLocation(const std::string &name) const;
 
-    void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
-    GLint getActiveUniformCount();
-    GLint getActiveUniformMaxLength();
+    void getActiveUniform(GLuint index,
+                          GLsizei bufsize,
+                          GLsizei *length,
+                          GLint *size,
+                          GLenum *type,
+                          GLchar *name) const;
+    GLint getActiveUniformCount() const;
+    GLint getActiveUniformMaxLength() const;
     GLint getActiveUniformi(GLuint index, GLenum pname) const;
     bool isValidUniformLocation(GLint location) const;
     const LinkedUniform &getUniformByLocation(GLint location) const;
 
     GLint getUniformLocation(const std::string &name) const;
     GLuint getUniformIndex(const std::string &name) const;
     void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
     void setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
@@ -291,26 +301,26 @@ class Program : angle::NonCopyable
     void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
     void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
     void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
     void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
     void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
     void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
     void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 
-    void getUniformfv(GLint location, GLfloat *params);
-    void getUniformiv(GLint location, GLint *params);
-    void getUniformuiv(GLint location, GLuint *params);
+    void getUniformfv(GLint location, GLfloat *params) const;
+    void getUniformiv(GLint location, GLint *params) const;
+    void getUniformuiv(GLint location, GLuint *params) const;
 
     void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const;
     void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const;
-    GLuint getActiveUniformBlockCount();
-    GLint getActiveUniformBlockMaxLength();
+    GLuint getActiveUniformBlockCount() const;
+    GLint getActiveUniformBlockMaxLength() const;
 
-    GLuint getUniformBlockIndex(const std::string &name);
+    GLuint getUniformBlockIndex(const std::string &name) const;
 
     void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding);
     GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
 
     const UniformBlock &getUniformBlockByIndex(GLuint index) const;
 
     void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode);
     void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const;
@@ -390,16 +400,21 @@ class Program : angle::NonCopyable
         unsigned int samplerCount;
     };
 
     VectorAndSamplerCount flattenUniform(const sh::ShaderVariable &uniform,
                                          const std::string &fullName,
                                          std::vector<LinkedUniform> *samplerUniforms);
 
     void gatherInterfaceBlockInfo();
+    template <typename VarT>
+    void defineUniformBlockMembers(const std::vector<VarT> &fields,
+                                   const std::string &prefix,
+                                   int blockIndex);
+
     void defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType);
 
     template <typename T>
     void setUniformInternal(GLint location, GLsizei count, const T *v);
 
     template <size_t cols, size_t rows, typename T>
     void setMatrixUniformInternal(GLint location, GLsizei count, GLboolean transpose, const T *v);
 
--- a/gfx/angle/src/libANGLE/Query.cpp
+++ b/gfx/angle/src/libANGLE/Query.cpp
@@ -42,9 +42,18 @@ Error Query::isResultAvailable(GLuint *a
     return mQuery->isResultAvailable(available);
 }
 
 GLenum Query::getType() const
 {
     return mQuery->getType();
 }
 
+rx::QueryImpl *Query::getImplementation()
+{
+    return mQuery;
 }
+
+const rx::QueryImpl *Query::getImplementation() const
+{
+    return mQuery;
+}
+}
--- a/gfx/angle/src/libANGLE/Query.h
+++ b/gfx/angle/src/libANGLE/Query.h
@@ -33,15 +33,18 @@ class Query : public RefCountObject
     Error begin();
     Error end();
 
     Error getResult(GLuint *params);
     Error isResultAvailable(GLuint *available);
 
     GLenum getType() const;
 
+    rx::QueryImpl *getImplementation();
+    const rx::QueryImpl *getImplementation() const;
+
   private:
     rx::QueryImpl *mQuery;
 };
 
 }
 
 #endif   // LIBANGLE_QUERY_H_
--- a/gfx/angle/src/libANGLE/ResourceManager.cpp
+++ b/gfx/angle/src/libANGLE/ResourceManager.cpp
@@ -436,17 +436,17 @@ void ResourceManager::checkRenderbufferA
         }
     }
 }
 
 void ResourceManager::checkSamplerAllocation(GLuint sampler)
 {
     if (sampler != 0 && !getSampler(sampler))
     {
-        Sampler *samplerObject = new Sampler(sampler);
+        Sampler *samplerObject = new Sampler(mFactory, sampler);
         mSamplerMap[sampler] = samplerObject;
         samplerObject->addRef();
         // Samplers cannot be created via Bind
     }
 }
 
 bool ResourceManager::isSampler(GLuint sampler)
 {
--- a/gfx/angle/src/libANGLE/Sampler.cpp
+++ b/gfx/angle/src/libANGLE/Sampler.cpp
@@ -4,24 +4,32 @@
 // found in the LICENSE file.
 //
 
 // Sampler.cpp : Implements the Sampler class, which represents a GLES 3
 // sampler object. Sampler objects store some state needed to sample textures.
 
 #include "libANGLE/Sampler.h"
 #include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/ImplFactory.h"
+#include "libANGLE/renderer/SamplerImpl.h"
 
 namespace gl
 {
 
-Sampler::Sampler(GLuint id) : RefCountObject(id), mSamplerState()
+Sampler::Sampler(rx::ImplFactory *factory, GLuint id)
+    : RefCountObject(id), mImpl(factory->createSampler()), mSamplerState()
 {
 }
 
+Sampler::~Sampler()
+{
+    SafeDelete(mImpl);
+}
+
 void Sampler::setMinFilter(GLenum minFilter)
 {
     mSamplerState.minFilter = minFilter;
 }
 
 GLenum Sampler::getMinFilter() const
 {
     return mSamplerState.minFilter;
@@ -117,9 +125,18 @@ GLenum Sampler::getCompareFunc() const
     return mSamplerState.compareFunc;
 }
 
 const SamplerState &Sampler::getSamplerState() const
 {
     return mSamplerState;
 }
 
+const rx::SamplerImpl *Sampler::getImplementation() const
+{
+    return mImpl;
 }
+
+rx::SamplerImpl *Sampler::getImplementation()
+{
+    return mImpl;
+}
+}
--- a/gfx/angle/src/libANGLE/Sampler.h
+++ b/gfx/angle/src/libANGLE/Sampler.h
@@ -8,23 +8,30 @@
 // sampler object. Sampler objects store some state needed to sample textures.
 
 #ifndef LIBANGLE_SAMPLER_H_
 #define LIBANGLE_SAMPLER_H_
 
 #include "libANGLE/angletypes.h"
 #include "libANGLE/RefCountObject.h"
 
+namespace rx
+{
+class ImplFactory;
+class SamplerImpl;
+}
+
 namespace gl
 {
 
-class Sampler : public RefCountObject
+class Sampler final : public RefCountObject
 {
   public:
-    Sampler(GLuint id);
+    Sampler(rx::ImplFactory *factory, GLuint id);
+    ~Sampler() override;
 
     void setMinFilter(GLenum minFilter);
     GLenum getMinFilter() const;
 
     void setMagFilter(GLenum magFilter);
     GLenum getMagFilter() const;
 
     void setWrapS(GLenum wrapS);
@@ -48,15 +55,20 @@ class Sampler : public RefCountObject
     void setCompareMode(GLenum compareMode);
     GLenum getCompareMode() const;
 
     void setCompareFunc(GLenum compareFunc);
     GLenum getCompareFunc() const;
 
     const SamplerState &getSamplerState() const;
 
+    const rx::SamplerImpl *getImplementation() const;
+    rx::SamplerImpl *getImplementation();
+
   private:
+    rx::SamplerImpl *mImpl;
+
     SamplerState mSamplerState;
 };
 
 }
 
 #endif // LIBANGLE_SAMPLER_H_
--- a/gfx/angle/src/libANGLE/State.cpp
+++ b/gfx/angle/src/libANGLE/State.cpp
@@ -23,29 +23,41 @@ State::State()
 {
     mMaxDrawBuffers = 0;
     mMaxCombinedTextureImageUnits = 0;
 
     // Initialize dirty bit masks
     // TODO(jmadill): additional ES3 state
     mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_ALIGNMENT);
     mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_ROW_LENGTH);
+    mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_IMAGE_HEIGHT);
+    mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_SKIP_IMAGES);
+    mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_SKIP_ROWS);
+    mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_SKIP_PIXELS);
+
     mPackStateBitMask.set(DIRTY_BIT_PACK_ALIGNMENT);
     mPackStateBitMask.set(DIRTY_BIT_PACK_REVERSE_ROW_ORDER);
+    mPackStateBitMask.set(DIRTY_BIT_PACK_ROW_LENGTH);
+    mPackStateBitMask.set(DIRTY_BIT_PACK_SKIP_ROWS);
+    mPackStateBitMask.set(DIRTY_BIT_PACK_SKIP_PIXELS);
+
     mClearStateBitMask.set(DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
     mClearStateBitMask.set(DIRTY_BIT_SCISSOR_TEST_ENABLED);
     mClearStateBitMask.set(DIRTY_BIT_SCISSOR);
     mClearStateBitMask.set(DIRTY_BIT_VIEWPORT);
     mClearStateBitMask.set(DIRTY_BIT_CLEAR_COLOR);
     mClearStateBitMask.set(DIRTY_BIT_CLEAR_DEPTH);
     mClearStateBitMask.set(DIRTY_BIT_CLEAR_STENCIL);
     mClearStateBitMask.set(DIRTY_BIT_COLOR_MASK);
     mClearStateBitMask.set(DIRTY_BIT_DEPTH_MASK);
     mClearStateBitMask.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
     mClearStateBitMask.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+
+    mBlitStateBitMask.set(DIRTY_BIT_SCISSOR_TEST_ENABLED);
+    mBlitStateBitMask.set(DIRTY_BIT_SCISSOR);
 }
 
 State::~State()
 {
     reset();
 }
 
 void State::initialize(const Caps &caps, GLuint clientVersion)
@@ -985,42 +997,20 @@ void State::setGenericUniformBufferBindi
     mGenericUniformBuffer.set(buffer);
 }
 
 void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size)
 {
     mUniformBuffers[index].set(buffer, offset, size);
 }
 
-GLuint State::getIndexedUniformBufferId(GLuint index) const
-{
-    ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
-
-    return mUniformBuffers[index].id();
-}
-
-Buffer *State::getIndexedUniformBuffer(GLuint index) const
+const OffsetBindingPointer<Buffer> &State::getIndexedUniformBuffer(size_t index) const
 {
     ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
-
-    return mUniformBuffers[index].get();
-}
-
-GLintptr State::getIndexedUniformBufferOffset(GLuint index) const
-{
-    ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
-
-    return mUniformBuffers[index].getOffset();
-}
-
-GLsizeiptr State::getIndexedUniformBufferSize(GLuint index) const
-{
-    ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
-
-    return mUniformBuffers[index].getSize();
+    return mUniformBuffers[index];
 }
 
 void State::setCopyReadBufferBinding(Buffer *buffer)
 {
     mCopyReadBuffer.set(buffer);
 }
 
 void State::setCopyWriteBufferBinding(Buffer *buffer)
@@ -1128,16 +1118,49 @@ void State::setPackReverseRowOrder(bool 
     mDirtyBits.set(DIRTY_BIT_PACK_REVERSE_ROW_ORDER);
 }
 
 bool State::getPackReverseRowOrder() const
 {
     return mPack.reverseRowOrder;
 }
 
+void State::setPackRowLength(GLint rowLength)
+{
+    mPack.rowLength = rowLength;
+    mDirtyBits.set(DIRTY_BIT_PACK_ROW_LENGTH);
+}
+
+GLint State::getPackRowLength() const
+{
+    return mPack.rowLength;
+}
+
+void State::setPackSkipRows(GLint skipRows)
+{
+    mPack.skipRows = skipRows;
+    mDirtyBits.set(DIRTY_BIT_PACK_SKIP_ROWS);
+}
+
+GLint State::getPackSkipRows() const
+{
+    return mPack.skipRows;
+}
+
+void State::setPackSkipPixels(GLint skipPixels)
+{
+    mPack.skipPixels = skipPixels;
+    mDirtyBits.set(DIRTY_BIT_PACK_SKIP_PIXELS);
+}
+
+GLint State::getPackSkipPixels() const
+{
+    return mPack.skipPixels;
+}
+
 const PixelPackState &State::getPackState() const
 {
     return mPack;
 }
 
 PixelPackState &State::getPackState()
 {
     return mPack;
@@ -1160,16 +1183,60 @@ void State::setUnpackRowLength(GLint row
     mDirtyBits.set(DIRTY_BIT_UNPACK_ROW_LENGTH);
 }
 
 GLint State::getUnpackRowLength() const
 {
     return mUnpack.rowLength;
 }
 
+void State::setUnpackImageHeight(GLint imageHeight)
+{
+    mUnpack.imageHeight = imageHeight;
+    mDirtyBits.set(DIRTY_BIT_UNPACK_IMAGE_HEIGHT);
+}
+
+GLint State::getUnpackImageHeight() const
+{
+    return mUnpack.imageHeight;
+}
+
+void State::setUnpackSkipImages(GLint skipImages)
+{
+    mUnpack.skipImages = skipImages;
+    mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_IMAGES);
+}
+
+GLint State::getUnpackSkipImages() const
+{
+    return mUnpack.skipImages;
+}
+
+void State::setUnpackSkipRows(GLint skipRows)
+{
+    mUnpack.skipRows = skipRows;
+    mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_ROWS);
+}
+
+GLint State::getUnpackSkipRows() const
+{
+    return mUnpack.skipRows;
+}
+
+void State::setUnpackSkipPixels(GLint skipPixels)
+{
+    mUnpack.skipPixels = skipPixels;
+    mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_PIXELS);
+}
+
+GLint State::getUnpackSkipPixels() const
+{
+    return mUnpack.skipPixels;
+}
+
 const PixelUnpackState &State::getUnpackState() const
 {
     return mUnpack;
 }
 
 PixelUnpackState &State::getUnpackState()
 {
     return mUnpack;
@@ -1262,18 +1329,39 @@ void State::getIntegerv(const gl::Data &
         //case GL_FRAMEBUFFER_BINDING:                    // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
       case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE:           *params = mDrawFramebuffer->id();                         break;
       case GL_READ_FRAMEBUFFER_BINDING_ANGLE:           *params = mReadFramebuffer->id();                         break;
       case GL_RENDERBUFFER_BINDING:                     *params = mRenderbuffer.id();                             break;
       case GL_VERTEX_ARRAY_BINDING:                     *params = mVertexArray->id();                             break;
       case GL_CURRENT_PROGRAM:                          *params = mProgram ? mProgram->id() : 0;                  break;
       case GL_PACK_ALIGNMENT:                           *params = mPack.alignment;                                break;
       case GL_PACK_REVERSE_ROW_ORDER_ANGLE:             *params = mPack.reverseRowOrder;                          break;
+      case GL_PACK_ROW_LENGTH:
+          *params = mPack.rowLength;
+          break;
+      case GL_PACK_SKIP_ROWS:
+          *params = mPack.skipRows;
+          break;
+      case GL_PACK_SKIP_PIXELS:
+          *params = mPack.skipPixels;
+          break;
       case GL_UNPACK_ALIGNMENT:                         *params = mUnpack.alignment;                              break;
       case GL_UNPACK_ROW_LENGTH:                        *params = mUnpack.rowLength;                              break;
+      case GL_UNPACK_IMAGE_HEIGHT:
+          *params = mUnpack.imageHeight;
+          break;
+      case GL_UNPACK_SKIP_IMAGES:
+          *params = mUnpack.skipImages;
+          break;
+      case GL_UNPACK_SKIP_ROWS:
+          *params = mUnpack.skipRows;
+          break;
+      case GL_UNPACK_SKIP_PIXELS:
+          *params = mUnpack.skipPixels;
+          break;
       case GL_GENERATE_MIPMAP_HINT:                     *params = mGenerateMipmapHint;                            break;
       case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:      *params = mFragmentShaderDerivativeHint;                  break;
       case GL_ACTIVE_TEXTURE:
           *params = (static_cast<GLint>(mActiveSampler) + GL_TEXTURE0);
           break;
       case GL_STENCIL_FUNC:                             *params = mDepthStencil.stencilFunc;                      break;
       case GL_STENCIL_REF:                              *params = mStencilRef;                                    break;
       case GL_STENCIL_VALUE_MASK:                       *params = clampToInt(mDepthStencil.stencilMask);          break;
--- a/gfx/angle/src/libANGLE/State.h
+++ b/gfx/angle/src/libANGLE/State.h
@@ -198,20 +198,17 @@ class State : angle::NonCopyable
     // GL_ARRAY_BUFFER
     void setArrayBufferBinding(Buffer *buffer);
     GLuint getArrayBufferId() const;
     bool removeArrayBufferBinding(GLuint buffer);
 
     // GL_UNIFORM_BUFFER - Both indexed and generic targets
     void setGenericUniformBufferBinding(Buffer *buffer);
     void setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size);
-    GLuint getIndexedUniformBufferId(GLuint index) const;
-    Buffer *getIndexedUniformBuffer(GLuint index) const;
-    GLintptr getIndexedUniformBufferOffset(GLuint index) const;
-    GLsizeiptr getIndexedUniformBufferSize(GLuint index) const;
+    const OffsetBindingPointer<Buffer> &getIndexedUniformBuffer(size_t index) const;
 
     // GL_COPY_[READ/WRITE]_BUFFER
     void setCopyReadBufferBinding(Buffer *buffer);
     void setCopyWriteBufferBinding(Buffer *buffer);
 
     // GL_PIXEL[PACK/UNPACK]_BUFFER
     void setPixelPackBufferBinding(Buffer *buffer);
     void setPixelUnpackBufferBinding(Buffer *buffer);
@@ -230,24 +227,38 @@ class State : angle::NonCopyable
     const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const;
     const void *getVertexAttribPointer(unsigned int attribNum) const;
 
     // Pixel pack state manipulation
     void setPackAlignment(GLint alignment);
     GLint getPackAlignment() const;
     void setPackReverseRowOrder(bool reverseRowOrder);
     bool getPackReverseRowOrder() const;
+    void setPackRowLength(GLint rowLength);
+    GLint getPackRowLength() const;
+    void setPackSkipRows(GLint skipRows);
+    GLint getPackSkipRows() const;
+    void setPackSkipPixels(GLint skipPixels);
+    GLint getPackSkipPixels() const;
     const PixelPackState &getPackState() const;
     PixelPackState &getPackState();
 
     // Pixel unpack state manipulation
     void setUnpackAlignment(GLint alignment);
     GLint getUnpackAlignment() const;
     void setUnpackRowLength(GLint rowLength);
     GLint getUnpackRowLength() const;
+    void setUnpackImageHeight(GLint imageHeight);
+    GLint getUnpackImageHeight() const;
+    void setUnpackSkipImages(GLint skipImages);
+    GLint getUnpackSkipImages() const;
+    void setUnpackSkipRows(GLint skipRows);
+    GLint getUnpackSkipRows() const;
+    void setUnpackSkipPixels(GLint skipPixels);
+    GLint getUnpackSkipPixels() const;
     const PixelUnpackState &getUnpackState() const;
     PixelUnpackState &getUnpackState();
 
     // State query functions
     void getBooleanv(GLenum pname, GLboolean *params);
     void getFloatv(GLenum pname, GLfloat *params);
     void getIntegerv(const gl::Data &data, GLenum pname, GLint *params);
     bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data);
@@ -287,18 +298,25 @@ class State : angle::NonCopyable
         DIRTY_BIT_RASTERIZER_DISCARD_ENABLED,
         DIRTY_BIT_LINE_WIDTH,
         DIRTY_BIT_PRIMITIVE_RESTART_ENABLED,
         DIRTY_BIT_CLEAR_COLOR,
         DIRTY_BIT_CLEAR_DEPTH,
         DIRTY_BIT_CLEAR_STENCIL,
         DIRTY_BIT_UNPACK_ALIGNMENT,
         DIRTY_BIT_UNPACK_ROW_LENGTH,
+        DIRTY_BIT_UNPACK_IMAGE_HEIGHT,
+        DIRTY_BIT_UNPACK_SKIP_IMAGES,
+        DIRTY_BIT_UNPACK_SKIP_ROWS,
+        DIRTY_BIT_UNPACK_SKIP_PIXELS,
         DIRTY_BIT_PACK_ALIGNMENT,
         DIRTY_BIT_PACK_REVERSE_ROW_ORDER,
+        DIRTY_BIT_PACK_ROW_LENGTH,
+        DIRTY_BIT_PACK_SKIP_ROWS,
+        DIRTY_BIT_PACK_SKIP_PIXELS,
         DIRTY_BIT_DITHER_ENABLED,
         DIRTY_BIT_GENERATE_MIPMAP_HINT,
         DIRTY_BIT_SHADER_DERIVATIVE_HINT,
         DIRTY_BIT_READ_FRAMEBUFFER_BINDING,
         DIRTY_BIT_READ_FRAMEBUFFER_OBJECT,
         DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING,
         DIRTY_BIT_DRAW_FRAMEBUFFER_OBJECT,
         DIRTY_BIT_RENDERBUFFER_BINDING,
@@ -317,16 +335,17 @@ class State : angle::NonCopyable
     void clearDirtyBits() { mDirtyBits.reset(); }
     void clearDirtyBits(const DirtyBits &bitset) { mDirtyBits &= ~bitset; }
     void setAllDirtyBits() { mDirtyBits.set(); }
 
     // Dirty bit masks
     const DirtyBits &unpackStateBitMask() const { return mUnpackStateBitMask; }
     const DirtyBits &packStateBitMask() const { return mPackStateBitMask; }
     const DirtyBits &clearStateBitMask() const { return mClearStateBitMask; }
+    const DirtyBits &blitStateBitMask() const { return mBlitStateBitMask; }
 
   private:
     // Cached values from Context's caps
     GLuint mMaxDrawBuffers;
     GLuint mMaxCombinedTextureImageUnits;
 
     ColorF mColorClearValue;
     GLclampf mDepthClearValue;
@@ -391,14 +410,15 @@ class State : angle::NonCopyable
     PixelPackState mPack;
 
     bool mPrimitiveRestart;
 
     DirtyBits mDirtyBits;
     DirtyBits mUnpackStateBitMask;
     DirtyBits mPackStateBitMask;
     DirtyBits mClearStateBitMask;
+    DirtyBits mBlitStateBitMask;
 };
 
 }
 
 #endif // LIBANGLE_STATE_H_
 
--- a/gfx/angle/src/libANGLE/Uniform.cpp
+++ b/gfx/angle/src/libANGLE/Uniform.cpp
@@ -116,31 +116,34 @@ uint8_t *LinkedUniform::getDataPtrToElem
 }
 
 const uint8_t *LinkedUniform::getDataPtrToElement(size_t elementIndex) const
 {
     return const_cast<LinkedUniform *>(this)->getDataPtrToElement(elementIndex);
 }
 
 UniformBlock::UniformBlock()
-    : isArray(false),
-      arrayElement(0),
-      dataSize(0),
-      vertexStaticUse(false),
-      fragmentStaticUse(false),
-      psRegisterIndex(GL_INVALID_INDEX),
-      vsRegisterIndex(GL_INVALID_INDEX)
+    : isArray(false), arrayElement(0), dataSize(0), vertexStaticUse(false), fragmentStaticUse(false)
 {
 }
 
 UniformBlock::UniformBlock(const std::string &nameIn, bool isArrayIn, unsigned int arrayElementIn)
     : name(nameIn),
       isArray(isArrayIn),
       arrayElement(arrayElementIn),
       dataSize(0),
       vertexStaticUse(false),
-      fragmentStaticUse(false),
-      psRegisterIndex(GL_INVALID_INDEX),
-      vsRegisterIndex(GL_INVALID_INDEX)
+      fragmentStaticUse(false)
 {
 }
 
+std::string UniformBlock::nameWithArrayIndex() const
+{
+    std::stringstream fullNameStr;
+    fullNameStr << name;
+    if (isArray)
+    {
+        fullNameStr << "[" << arrayElement << "]";
+    }
+
+    return fullNameStr.str();
 }
+}
--- a/gfx/angle/src/libANGLE/Uniform.h
+++ b/gfx/angle/src/libANGLE/Uniform.h
@@ -49,26 +49,24 @@ struct LinkedUniform : public sh::Unifor
 // Helper struct representing a single shader uniform block
 struct UniformBlock
 {
     UniformBlock();
     UniformBlock(const std::string &nameIn, bool isArrayIn, unsigned int arrayElementIn);
     UniformBlock(const UniformBlock &other) = default;
     UniformBlock &operator=(const UniformBlock &other) = default;
 
+    std::string nameWithArrayIndex() const;
+
     std::string name;
     bool isArray;
     unsigned int arrayElement;
     unsigned int dataSize;
 
     bool vertexStaticUse;
     bool fragmentStaticUse;
 
     std::vector<unsigned int> memberUniformIndexes;
-
-    // TODO(jmadill): Make D3D-only.
-    unsigned int psRegisterIndex;
-    unsigned int vsRegisterIndex;
 };
 
 }
 
 #endif   // LIBANGLE_UNIFORM_H_
--- a/gfx/angle/src/libANGLE/angletypes.h
+++ b/gfx/angle/src/libANGLE/angletypes.h
@@ -268,16 +268,19 @@ struct PixelPackState
           rowLength(0),
           skipRows(0),
           skipPixels(0)
     {}
 };
 
 // Used in Program and VertexArray.
 typedef std::bitset<MAX_VERTEX_ATTRIBS> AttributesMask;
+
+// Use in Program
+typedef std::bitset<IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS> UniformBlockBindingMask;
 }
 
 namespace rx
 {
 enum VendorID : uint32_t
 {
     VENDOR_ID_UNKNOWN = 0x0,
     VENDOR_ID_AMD     = 0x1002,
--- a/gfx/angle/src/libANGLE/formatutils.cpp
+++ b/gfx/angle/src/libANGLE/formatutils.cpp
@@ -584,19 +584,33 @@ GLuint InternalFormat::computeRowPitch(G
     }
     else
     {
         rowBytes = computeBlockSize(formatType, width, 1);
     }
     return rx::roundUp(rowBytes, static_cast<GLuint>(alignment));
 }
 
-GLuint InternalFormat::computeDepthPitch(GLenum formatType, GLsizei width, GLsizei height, GLint alignment, GLint rowLength) const
+GLuint InternalFormat::computeDepthPitch(GLenum formatType,
+                                         GLsizei width,
+                                         GLsizei height,
+                                         GLint alignment,
+                                         GLint rowLength,
+                                         GLint imageHeight) const
 {
-    return computeRowPitch(formatType, width, alignment, rowLength) * height;
+    GLuint rows;
+    if (imageHeight > 0)
+    {
+        rows = imageHeight;
+    }
+    else
+    {
+        rows = height;
+    }
+    return computeRowPitch(formatType, width, alignment, rowLength) * rows;
 }
 
 GLuint InternalFormat::computeBlockSize(GLenum formatType, GLsizei width, GLsizei height) const
 {
     if (compressed)
     {
         GLsizei numBlocksWide = (width + compressedBlockWidth - 1) / compressedBlockWidth;
         GLsizei numBlocksHight = (height + compressedBlockHeight - 1) / compressedBlockHeight;
@@ -611,16 +625,25 @@ GLuint InternalFormat::computeBlockSize(
         }
         else
         {
             return componentCount * typeInfo.bytes * width * height;
         }
     }
 }
 
+GLuint InternalFormat::computeSkipPixels(GLint rowPitch,
+                                         GLint depthPitch,
+                                         GLint skipImages,
+                                         GLint skipRows,
+                                         GLint skipPixels) const
+{
+    return skipImages * depthPitch + skipRows * rowPitch + skipPixels * pixelBytes;
+}
+
 GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type)
 {
     const InternalFormat& formatInfo = GetInternalFormatInfo(internalFormat);
     if (formatInfo.pixelBytes > 0)
     {
         return internalFormat;
     }
     else
--- a/gfx/angle/src/libANGLE/formatutils.h
+++ b/gfx/angle/src/libANGLE/formatutils.h
@@ -61,18 +61,28 @@ struct InternalFormat
     GLenum colorEncoding;
 
     typedef bool (*SupportCheckFunction)(GLuint, const Extensions &);
     SupportCheckFunction textureSupport;
     SupportCheckFunction renderSupport;
     SupportCheckFunction filterSupport;
 
     GLuint computeRowPitch(GLenum formatType, GLsizei width, GLint alignment, GLint rowLength) const;
-    GLuint computeDepthPitch(GLenum formatType, GLsizei width, GLsizei height, GLint alignment, GLint rowLength) const;
+    GLuint computeDepthPitch(GLenum formatType,
+                             GLsizei width,
+                             GLsizei height,
+                             GLint alignment,
+                             GLint rowLength,
+                             GLint imageHeight) const;
     GLuint computeBlockSize(GLenum formatType, GLsizei width, GLsizei height) const;
+    GLuint computeSkipPixels(GLint rowPitch,
+                             GLint depthPitch,
+                             GLint skipImages,
+                             GLint skipRows,
+                             GLint skipPixels) const;
 };
 const InternalFormat &GetInternalFormatInfo(GLenum internalFormat);
 
 GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type);
 
 typedef std::set<GLenum> FormatSet;
 const FormatSet &GetAllSizedInternalFormats();
 
--- a/gfx/angle/src/libANGLE/moz.build
+++ b/gfx/angle/src/libANGLE/moz.build
@@ -68,16 +68,17 @@ UNIFIED_SOURCES += [
     '../compiler/translator/ParseContext.cpp',
     '../compiler/translator/PoolAlloc.cpp',
     '../compiler/translator/PruneEmptyDeclarations.cpp',
     '../compiler/translator/RecordConstantPrecision.cpp',
     '../compiler/translator/RegenerateStructNames.cpp',
     '../compiler/translator/RemoveDynamicIndexing.cpp',
     '../compiler/translator/RemovePow.cpp',
     '../compiler/translator/RemoveSwitchFallThrough.cpp',
+    '../compiler/translator/RewriteDoWhile.cpp',
     '../compiler/translator/RewriteElseBlocks.cpp',
     '../compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp',
     '../compiler/translator/SearchSymbol.cpp',
     '../compiler/translator/SeparateArrayInitialization.cpp',
     '../compiler/translator/SeparateDeclarations.cpp',
     '../compiler/translator/SeparateExpressionsReturningArrays.cpp',
     '../compiler/translator/ShaderLang.cpp',
     '../compiler/translator/ShaderVars.cpp',
@@ -180,16 +181,17 @@ UNIFIED_SOURCES += [
     'renderer/gl/formatutilsgl.cpp',
     'renderer/gl/FramebufferGL.cpp',
     'renderer/gl/FunctionsGL.cpp',
     'renderer/gl/ProgramGL.cpp',
     'renderer/gl/QueryGL.cpp',
     'renderer/gl/RenderbufferGL.cpp',
     'renderer/gl/RendererGL.cpp',
     'renderer/gl/renderergl_utils.cpp',
+    'renderer/gl/SamplerGL.cpp',
     'renderer/gl/ShaderGL.cpp',
     'renderer/gl/StateManagerGL.cpp',
     'renderer/gl/SurfaceGL.cpp',
     'renderer/gl/TextureGL.cpp',
     'renderer/gl/TransformFeedbackGL.cpp',
     'renderer/gl/VertexArrayGL.cpp',
     'renderer/gl/wgl/DisplayWGL.cpp',
     'renderer/gl/wgl/FunctionsWGL.cpp',
@@ -236,16 +238,19 @@ if CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
         'renderer/d3d/d3d11/InputLayoutCache.cpp',
         'renderer/d3d/d3d11/PixelTransfer11.cpp',
         'renderer/d3d/d3d11/Query11.cpp',
         'renderer/d3d/d3d11/Renderer11.cpp',
         'renderer/d3d/d3d11/renderer11_utils.cpp',
         'renderer/d3d/d3d11/RenderStateCache.cpp',
         'renderer/d3d/d3d11/RenderTarget11.cpp',
         'renderer/d3d/d3d11/ShaderExecutable11.cpp',
+        'renderer/d3d/d3d11/swizzle_format_info.cpp',
+        'renderer/d3d/d3d11/texture_format_table.cpp',
+        'renderer/d3d/d3d11/texture_format_util.cpp',
         'renderer/d3d/d3d11/TextureStorage11.cpp',
         'renderer/d3d/d3d11/Trim11.cpp',
         'renderer/d3d/d3d11/VertexBuffer11.cpp',
         'renderer/d3d/d3d11/win32/NativeWindow.cpp',
     ]
 if CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
     SOURCES += [
         'renderer/d3d/d3d11/SwapChain11.cpp',
--- a/gfx/angle/src/libANGLE/renderer/ImplFactory.h
+++ b/gfx/angle/src/libANGLE/renderer/ImplFactory.h
@@ -20,16 +20,17 @@ namespace rx
 class BufferImpl;
 class CompilerImpl;
 class FenceNVImpl;
 class FenceSyncImpl;
 class FramebufferImpl;
 class ProgramImpl;
 class QueryImpl;
 class RenderbufferImpl;
+class SamplerImpl;
 class ShaderImpl;
 class TextureImpl;
 class TransformFeedbackImpl;
 class VertexArrayImpl;
 
 class ImplFactory : angle::NonCopyable
 {
   public:
@@ -58,13 +59,16 @@ class ImplFactory : angle::NonCopyable
 
     // Query and Fence creation
     virtual QueryImpl *createQuery(GLenum type) = 0;
     virtual FenceNVImpl *createFenceNV() = 0;
     virtual FenceSyncImpl *createFenceSync() = 0;
 
     // Transform Feedback creation
     virtual TransformFeedbackImpl *createTransformFeedback() = 0;
+
+    // Sampler object creation
+    virtual SamplerImpl *createSampler() = 0;
 };
 
 }
 
 #endif // LIBANGLE_RENDERER_IMPLFACTORY_H_
--- a/gfx/angle/src/libANGLE/renderer/ProgramImpl.h
+++ b/gfx/angle/src/libANGLE/renderer/ProgramImpl.h
@@ -30,19 +30,16 @@ struct LinkResult
 };
 
 class ProgramImpl : angle::NonCopyable
 {
   public:
     ProgramImpl(const gl::Program::Data &data) : mData(data) {}
     virtual ~ProgramImpl() {}
 
-    virtual int getShaderVersion() const = 0;
-
-    virtual GLenum getBinaryFormat() = 0;
     virtual LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
     virtual gl::Error save(gl::BinaryOutputStream *stream) = 0;
 
     virtual LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) = 0;
     virtual GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) = 0;
 
     virtual void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) = 0;
     virtual void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) = 0;
@@ -61,19 +58,27 @@ class ProgramImpl : angle::NonCopyable
     virtual void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
     virtual void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
     virtual void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
     virtual void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
     virtual void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
     virtual void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
     virtual void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
 
-    // Gather uniform block active uniform indices, and uniform block offset info.
-    virtual void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
-                                        std::vector<gl::LinkedUniform> *uniforms) = 0;
+    // TODO: synchronize in syncState when dirty bits exist.
+    virtual void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) = 0;
+
+    // May only be called after a successful link operation.
+    // Return false for inactive blocks.
+    virtual bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const = 0;
+
+    // May only be called after a successful link operation.
+    // Returns false for inactive members.
+    virtual bool getUniformBlockMemberInfo(const std::string &memberUniformName,
+                                           sh::BlockMemberInfo *memberInfoOut) const = 0;
 
   protected:
     const gl::Program::Data &mData;
 };
 
 }
 
 #endif // LIBANGLE_RENDERER_PROGRAMIMPL_H_
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/SamplerImpl.h
@@ -0,0 +1,25 @@
+//
+// Copyright 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.
+//
+
+// SamplerImpl.h: Defines the abstract rx::SamplerImpl class.
+
+#ifndef LIBANGLE_RENDERER_SAMPLERIMPL_H_
+#define LIBANGLE_RENDERER_SAMPLERIMPL_H_
+
+#include "common/angleutils.h"
+
+namespace rx
+{
+
+class SamplerImpl : public angle::NonCopyable
+{
+  public:
+    SamplerImpl() {}
+    virtual ~SamplerImpl() {}
+};
+}
+
+#endif  // LIBANGLE_RENDERER_SAMPLERIMPL_H_
--- a/gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
@@ -245,27 +245,25 @@ GLenum FramebufferD3D::getImplementation
 
     return implementationFormatInfo.type;
 }
 
 gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
 {
     const gl::PixelPackState &packState = state.getPackState();
 
-    if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0)
-    {
-        UNIMPLEMENTED();
-        return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels");
-    }
-
     GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
     const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
-    GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, 0);
+    GLuint outputPitch =
+        sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, packState.rowLength);
+    GLsizei outputSkipBytes = sizedFormatInfo.computeSkipPixels(
+        outputPitch, 0, 0, packState.skipRows, packState.skipPixels);
 
-    return readPixels(area, format, type, outputPitch, packState, reinterpret_cast<uint8_t*>(pixels));
+    return readPixelsImpl(area, format, type, outputPitch, packState,
+                          reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes);
 }
 
 gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
                                GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
 {
     bool blitRenderTarget = false;
     if ((mask & GL_COLOR_BUFFER_BIT) &&
         sourceFramebuffer->getReadColorbuffer() != nullptr &&
--- a/gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h
+++ b/gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h
@@ -86,18 +86,22 @@ class FramebufferD3D : public Framebuffe
   protected:
     // Cache variable
     mutable gl::AttachmentList mColorAttachmentsForRender;
     mutable bool mInvalidateColorAttachmentCache;
 
   private:
     virtual gl::Error clear(const gl::State &state, const ClearParameters &clearParams) = 0;
 
-    virtual gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch,
-                                 const gl::PixelPackState &pack, uint8_t *pixels) const = 0;
+    virtual gl::Error readPixelsImpl(const gl::Rectangle &area,
+                                     GLenum format,
+                                     GLenum type,
+                                     size_t outputPitch,
+                                     const gl::PixelPackState &pack,
+                                     uint8_t *pixels) const = 0;
 
     virtual gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor,
                            bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter,
                            const gl::Framebuffer *sourceFramebuffer) = 0;
 
     virtual GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const = 0;
 };
 
--- a/gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -303,17 +303,16 @@ ProgramD3D::ProgramD3D(const gl::Program
       mDynamicHLSL(NULL),
       mGeometryExecutable(NULL),
       mUsesPointSize(false),
       mVertexUniformStorage(NULL),
       mFragmentUniformStorage(NULL),
       mUsedVertexSamplerRange(0),
       mUsedPixelSamplerRange(0),
       mDirtySamplerMapping(true),
-      mShaderVersion(100),
       mSerial(issueSerial())
 {
     mDynamicHLSL = new DynamicHLSL(renderer);
 }
 
 ProgramD3D::~ProgramD3D()
 {
     reset();
@@ -471,18 +470,16 @@ LinkResult ProgramD3D::load(gl::InfoLog 
 
     int compileFlags = stream->readInt<int>();
     if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
     {
         infoLog << "Mismatched compilation flags.";
         return LinkResult(false, gl::Error(GL_NO_ERROR));
     }
 
-    stream->readInt(&mShaderVersion);
-
     // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
     for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
     {
         stream->readInt(&mSemanticIndexes[i]);
     }
 
     const unsigned int psSamplerCount = stream->readInt<unsigned int>();
     for (unsigned int i = 0; i < psSamplerCount; ++i)
@@ -525,16 +522,32 @@ LinkResult ProgramD3D::load(gl::InfoLog 
         stream->readInt(&d3dUniform->psRegisterIndex);
         stream->readInt(&d3dUniform->vsRegisterIndex);
         stream->readInt(&d3dUniform->registerCount);
         stream->readInt(&d3dUniform->registerElement);
 
         mD3DUniforms.push_back(d3dUniform);
     }
 
+    const unsigned int blockCount = stream->readInt<unsigned int>();
+    if (stream->error())
+    {
+        infoLog << "Invalid program binary.";
+        return LinkResult(false, gl::Error(GL_NO_ERROR));
+    }
+
+    ASSERT(mD3DUniformBlocks.empty());
+    for (unsigned int blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+    {
+        D3DUniformBlock uniformBlock;
+        stream->readInt(&uniformBlock.psRegisterIndex);
+        stream->readInt(&uniformBlock.vsRegisterIndex);
+        mD3DUniformBlocks.push_back(uniformBlock);
+    }
+
     const unsigned int transformFeedbackVaryingCount = stream->readInt<unsigned int>();
     mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount);
     for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++)
     {
         gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex];
 
         stream->readString(&varying.name);
         stream->readInt(&varying.type);
@@ -669,18 +682,16 @@ gl::Error ProgramD3D::save(gl::BinaryOut
 {
     // Output the DeviceIdentifier before we output any shader code
     // When we load the binary again later, we can validate the device identifier before trying to compile any HLSL
     DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier();
     stream->writeBytes(reinterpret_cast<unsigned char*>(&binaryIdentifier), sizeof(DeviceIdentifier));
 
     stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
 
-    stream->writeInt(mShaderVersion);
-
     // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
     for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
     {
         stream->writeInt(mSemanticIndexes[i]);
     }
 
     stream->writeInt(mSamplersPS.size());
     for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
@@ -697,25 +708,30 @@ gl::Error ProgramD3D::save(gl::BinaryOut
         stream->writeInt(mSamplersVS[i].logicalTextureUnit);
         stream->writeInt(mSamplersVS[i].textureType);
     }
 
     stream->writeInt(mUsedVertexSamplerRange);
     stream->writeInt(mUsedPixelSamplerRange);
 
     stream->writeInt(mD3DUniforms.size());
-    for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
+    for (const D3DUniform *uniform : mD3DUniforms)
     {
-        const D3DUniform &uniform = *mD3DUniforms[uniformIndex];
-
         // Type, name and arraySize are redundant, so aren't stored in the binary.
-        stream->writeInt(uniform.psRegisterIndex);
-        stream->writeInt(uniform.vsRegisterIndex);
-        stream->writeInt(uniform.registerCount);
-        stream->writeInt(uniform.registerElement);
+        stream->writeInt(uniform->psRegisterIndex);
+        stream->writeInt(uniform->vsRegisterIndex);
+        stream->writeInt(uniform->registerCount);
+        stream->writeInt(uniform->registerElement);
+    }
+
+    stream->writeInt(mD3DUniformBlocks.size());
+    for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks)
+    {
+        stream->writeInt(uniformBlock.psRegisterIndex);
+        stream->writeInt(uniformBlock.vsRegisterIndex);
     }
 
     stream->writeInt(mTransformFeedbackLinkedVaryings.size());
     for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
     {
         const gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
 
         stream->writeString(varying.name);
@@ -999,17 +1015,16 @@ LinkResult ProgramD3D::link(const gl::Da
     const ShaderD3D *vertexShaderD3D   = GetImplAs<ShaderD3D>(vertexShader);
     const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
 
     mSamplersVS.resize(data.caps->maxVertexTextureImageUnits);
     mSamplersPS.resize(data.caps->maxTextureImageUnits);
 
     mVertexHLSL = vertexShader->getTranslatedSource();
     vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
-    mShaderVersion = vertexShader->getShaderVersion();
 
     mPixelHLSL = fragmentShader->getTranslatedSource();
     fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
 
     if (mRenderer->getRendererLimitations().noFrontFacingSupport)
     {
         if (fragmentShaderD3D->usesFrontFacing())
         {
@@ -1048,94 +1063,87 @@ LinkResult ProgramD3D::link(const gl::Da
 
     LinkResult result = compileProgramExecutables(infoLog, registers, packedVaryings);
     if (result.error.isError() || !result.linkSuccess)
     {
         infoLog << "Failed to create D3D shaders.";
         return result;
     }
 
+    initUniformBlockInfo();
+
     return LinkResult(true, gl::Error(GL_NO_ERROR));
 }
 
 GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
 {
     // TODO(jmadill): Do something useful here?
     return GL_TRUE;
 }
 
-void ProgramD3D::gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
-                                        std::vector<gl::LinkedUniform> *uniforms)
+void ProgramD3D::initUniformBlockInfo()
 {
     const gl::Shader *vertexShader = mData.getAttachedVertexShader();
 
-    BlockInfoMap blockInfo;
-    std::map<std::string, size_t> blockDataSizes;
-
     for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
     {
         if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
             continue;
 
-        if (blockDataSizes.count(vertexBlock.name) > 0)
+        if (mBlockDataSizes.count(vertexBlock.name) > 0)
             continue;
 
-        size_t dataSize                  = defineUniformBlock(vertexBlock, &blockInfo);
-        blockDataSizes[vertexBlock.name] = dataSize;
+        size_t dataSize                   = getUniformBlockInfo(vertexBlock);
+        mBlockDataSizes[vertexBlock.name] = dataSize;
     }
 
     const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
 
     for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
     {
         if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
             continue;
 
-        if (blockDataSizes.count(fragmentBlock.name) > 0)
+        if (mBlockDataSizes.count(fragmentBlock.name) > 0)
             continue;
 
-        size_t dataSize                    = defineUniformBlock(fragmentBlock, &blockInfo);
-        blockDataSizes[fragmentBlock.name] = dataSize;
+        size_t dataSize                     = getUniformBlockInfo(fragmentBlock);
+        mBlockDataSizes[fragmentBlock.name] = dataSize;
     }
+}
 
-    // Copy block info out to uniforms.
-    for (gl::LinkedUniform &linkedUniform : *uniforms)
-    {
-        const auto &infoEntry = blockInfo.find(linkedUniform.name);
-
-        if (infoEntry != blockInfo.end())
-        {
-            linkedUniform.blockInfo = infoEntry->second;
-        }
-    }
+void ProgramD3D::assignUniformBlockRegisters()
+{
+    mD3DUniformBlocks.clear();
 
     // Assign registers and update sizes.
-    const ShaderD3D *vertexShaderD3D   = GetImplAs<ShaderD3D>(vertexShader);
-    const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
+    const ShaderD3D *vertexShaderD3D   = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
+    const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
 
-    for (gl::UniformBlock &uniformBlock : *uniformBlocks)
+    for (const gl::UniformBlock &uniformBlock : mData.getUniformBlocks())
     {
         unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
 
+        D3DUniformBlock d3dUniformBlock;
+
         if (uniformBlock.vertexStaticUse)
         {
             unsigned int baseRegister =
                 vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
-            uniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
+            d3dUniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
         }
 
         if (uniformBlock.fragmentStaticUse)
         {
             unsigned int baseRegister =
                 fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
-            uniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
+            d3dUniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
         }
 
-        ASSERT(blockDataSizes.count(uniformBlock.name) == 1);
-        uniformBlock.dataSize = static_cast<unsigned int>(blockDataSizes[uniformBlock.name]);
+        mD3DUniformBlocks.push_back(d3dUniformBlock);
     }
 }
 
 void ProgramD3D::initializeUniformStorage()
 {
     // Compute total default block size
     unsigned int vertexRegisters = 0;
     unsigned int fragmentRegisters = 0;
@@ -1175,50 +1183,60 @@ gl::Error ProgramD3D::applyUniforms()
         d3dUniform->dirty = false;
     }
 
     return gl::Error(GL_NO_ERROR);
 }
 
 gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
 {
+    if (mData.getUniformBlocks().empty())
+    {
+        return gl::Error(GL_NO_ERROR);
+    }
+
+    // Lazy init.
+    if (mD3DUniformBlocks.empty())
+    {
+        assignUniformBlockRegisters();
+    }
+
     mVertexUBOCache.clear();
     mFragmentUBOCache.clear();
 
     const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
     const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
 
-    const auto &uniformBlocks = mData.getUniformBlocks();
-    for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlocks.size();
+    for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
          uniformBlockIndex++)
     {
-        const gl::UniformBlock &uniformBlock = uniformBlocks[uniformBlockIndex];
-        GLuint blockBinding            = mData.getUniformBlockBinding(uniformBlockIndex);
+        const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
+        GLuint blockBinding                 = mData.getUniformBlockBinding(uniformBlockIndex);
 
         // Unnecessary to apply an unreferenced standard or shared UBO
-        if (!uniformBlock.vertexStaticUse && !uniformBlock.fragmentStaticUse)
+        if (!uniformBlock.vertexStaticUse() && !uniformBlock.fragmentStaticUse())
         {
             continue;
         }
 
-        if (uniformBlock.vertexStaticUse)
+        if (uniformBlock.vertexStaticUse())
         {
             unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS;
             ASSERT(registerIndex < data.caps->maxVertexUniformBlocks);
 
             if (mVertexUBOCache.size() <= registerIndex)
             {
                 mVertexUBOCache.resize(registerIndex + 1, -1);
             }
 
             ASSERT(mVertexUBOCache[registerIndex] == -1);
             mVertexUBOCache[registerIndex] = blockBinding;
         }
 
-        if (uniformBlock.fragmentStaticUse)
+        if (uniformBlock.fragmentStaticUse())
         {
             unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS;
             ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks);
 
             if (mFragmentUBOCache.size() <= registerIndex)
             {
                 mFragmentUBOCache.resize(registerIndex + 1, -1);
             }
@@ -1339,16 +1357,21 @@ void ProgramD3D::setUniform3uiv(GLint lo
     setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
 }
 
 void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
 {
     setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
 }
 
+void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/,
+                                        GLuint /*uniformBlockBinding*/)
+{
+}
+
 void ProgramD3D::defineUniformsAndAssignRegisters()
 {
     D3DUniformMap uniformMap;
     const gl::Shader *vertexShader   = mData.getAttachedVertexShader();
     for (const sh::Uniform &vertexUniform : vertexShader->getUniforms())
 
     {
         if (vertexUniform.staticUse)
@@ -1674,18 +1697,17 @@ void ProgramD3D::setUniformMatrixfv(GLin
         {
             targetUniform->dirty = expandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
         }
         target += targetMatrixStride;
         value += cols * rows;
     }
 }
 
-size_t ProgramD3D::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock,
-                                      BlockInfoMap *blockInfoOut)
+size_t ProgramD3D::getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock)
 {
     ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
 
     // define member uniforms
     sh::Std140BlockEncoder std140Encoder;
     sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
     sh::BlockLayoutEncoder *encoder = nullptr;
 
@@ -1694,17 +1716,17 @@ size_t ProgramD3D::defineUniformBlock(co
         encoder = &std140Encoder;
     }
     else
     {
         encoder = &hlslEncoder;
     }
 
     GetUniformBlockInfo(interfaceBlock.fields, "", encoder, interfaceBlock.isRowMajorLayout,
-                        blockInfoOut);
+                        &mBlockInfo);
 
     return encoder->getBlockSize();
 }
 
 void ProgramD3D::assignAllSamplerRegisters()
 {
     for (const D3DUniform *d3dUniform : mD3DUniforms)
     {
@@ -1758,25 +1780,25 @@ void ProgramD3D::AssignSamplers(unsigned
 void ProgramD3D::reset()
 {
     SafeDeleteContainer(mVertexExecutables);
     SafeDeleteContainer(mPixelExecutables);
     SafeDelete(mGeometryExecutable);
 
     mVertexHLSL.clear();
     mVertexWorkarounds = D3DCompilerWorkarounds();
-    mShaderVersion = 100;
 
     mPixelHLSL.clear();
     mPixelWorkarounds = D3DCompilerWorkarounds();
     mUsesFragDepth = false;
     mPixelShaderKey.clear();
     mUsesPointSize = false;
 
     SafeDeleteContainer(mD3DUniforms);
+    mD3DUniformBlocks.clear();
 
     SafeDelete(mVertexUniformStorage);
     SafeDelete(mFragmentUniformStorage);
 
     mSamplersPS.clear();
     mSamplersVS.clear();
 
     mUsedVertexSamplerRange = 0;
@@ -1882,9 +1904,39 @@ void ProgramD3D::gatherTransformFeedback
         }
     }
 }
 
 D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
 {
     return mD3DUniforms[mData.getUniformLocations()[location].index];
 }
+
+bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
+{
+    std::string baseName = blockName;
+    gl::ParseAndStripArrayIndex(&baseName);
+
+    auto sizeIter = mBlockDataSizes.find(baseName);
+    if (sizeIter == mBlockDataSizes.end())
+    {
+        *sizeOut = 0;
+        return false;
+    }
+
+    *sizeOut = sizeIter->second;
+    return true;
 }
+
+bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName,
+                                           sh::BlockMemberInfo *memberInfoOut) const
+{
+    auto infoIter = mBlockInfo.find(memberUniformName);
+    if (infoIter == mBlockInfo.end())
+    {
+        *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
+        return false;
+    }
+
+    *memberInfoOut = infoIter->second;
+    return true;
+}
+}
--- a/gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
+++ b/gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
@@ -63,51 +63,62 @@ struct D3DUniform : angle::NonCopyable
     unsigned int registerCount;
 
     // Register "elements" are used for uniform structs in ES3, to appropriately identify single
     // uniforms
     // inside aggregate types, which are packed according C-like structure rules.
     unsigned int registerElement;
 };
 
+struct D3DUniformBlock
+{
+    D3DUniformBlock() : vsRegisterIndex(GL_INVALID_INDEX), psRegisterIndex(GL_INVALID_INDEX) {}
+
+    bool vertexStaticUse() const { return vsRegisterIndex != GL_INVALID_INDEX; }
+
+    bool fragmentStaticUse() const { return psRegisterIndex != GL_INVALID_INDEX; }
+
+    unsigned int vsRegisterIndex;
+    unsigned int psRegisterIndex;
+};
+
 class ProgramD3D : public ProgramImpl
 {
   public:
     typedef int SemanticIndexArray[gl::MAX_VERTEX_ATTRIBS];
 
     ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer);
     virtual ~ProgramD3D();
 
     const std::vector<PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; }
-    int getShaderVersion() const { return mShaderVersion; }
 
     GLint getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const;
     GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const;
     GLint getUsedSamplerRange(gl::SamplerType type) const;
     void updateSamplerMapping();
 
     bool usesPointSize() const { return mUsesPointSize; }
     bool usesPointSpriteEmulation() const;
     bool usesGeometryShader() const;
     bool usesInstancedPointSpriteEmulation() const;
 
-    GLenum getBinaryFormat() { return GL_PROGRAM_BINARY_ANGLE; }
     LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream);
     gl::Error save(gl::BinaryOutputStream *stream);
 
     gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutableD3D **outExectuable);
     gl::Error getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout, ShaderExecutableD3D **outExectuable, gl::InfoLog *infoLog);
     gl::Error getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout, ShaderExecutableD3D **outExectuable, gl::InfoLog *infoLog);
     ShaderExecutableD3D *getGeometryExecutable() const { return mGeometryExecutable; }
 
     LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override;
     GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
 
-    void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
-                                std::vector<gl::LinkedUniform> *uniforms) override;
+    bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override;
+    bool getUniformBlockMemberInfo(const std::string &memberUniformName,
+                                   sh::BlockMemberInfo *memberInfoOut) const override;
 
     void initializeUniformStorage();
     gl::Error applyUniforms();
     gl::Error applyUniformBuffers(const gl::Data &data);
     void dirtyAllUniforms();
 
     void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
     void setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
@@ -126,16 +137,18 @@ class ProgramD3D : public ProgramImpl
     void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
     void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
     void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
     void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
     void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
     void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
     void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 
+    void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
+
     const UniformStorageD3D &getVertexUniformStorage() const { return *mVertexUniformStorage; }
     const UniformStorageD3D &getFragmentUniformStorage() const { return *mFragmentUniformStorage; }
 
     unsigned int getSerial() const;
 
     void sortAttributesByLayout(const std::vector<TranslatedAttribute> &unsortedAttributes,
                                 int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS],
                                 const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const;
@@ -192,17 +205,16 @@ class ProgramD3D : public ProgramImpl
         Sampler();
 
         bool active;
         GLint logicalTextureUnit;
         GLenum textureType;
     };
 
     typedef std::map<std::string, D3DUniform *> D3DUniformMap;
-    typedef std::map<std::string, sh::BlockMemberInfo> BlockInfoMap;
 
     void defineUniformsAndAssignRegisters();
     void defineUniformBase(const gl::Shader *shader,
                            const sh::Uniform &uniform,
                            D3DUniformMap *uniformMap);
     void defineUniform(GLenum shaderType,
                        const sh::ShaderVariable &uniform,
                        const std::string &fullName,
@@ -212,18 +224,16 @@ class ProgramD3D : public ProgramImpl
     void assignSamplerRegisters(const D3DUniform *d3dUniform);
 
     static void AssignSamplers(unsigned int startSamplerIndex,
                                GLenum samplerType,
                                unsigned int samplerCount,
                                std::vector<Sampler> &outSamplers,
                                GLuint *outUsedRange);
 
-    size_t defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, BlockInfoMap *blockInfoOut);
-
     template <typename T>
     void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType);
 
     template <int cols, int rows>
     void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType);
 
     LinkResult compileProgramExecutables(gl::InfoLog &infoLog,
                                          int registers,
@@ -232,16 +242,20 @@ class ProgramD3D : public ProgramImpl
     void gatherTransformFeedbackVaryings(const std::vector<gl::LinkedVarying> &varyings);
     D3DUniform *getD3DUniformByName(const std::string &name);
     D3DUniform *getD3DUniformFromLocation(GLint location);
 
     void initSemanticIndex();
     void initAttributesByLayout();
 
     void reset();
+    void assignUniformBlockRegisters();
+
+    void initUniformBlockInfo();
+    size_t getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock);
 
     RendererD3D *mRenderer;
     DynamicHLSL *mDynamicHLSL;
 
     std::vector<VertexExecutable *> mVertexExecutables;
     std::vector<PixelExecutable *> mPixelExecutables;
     ShaderExecutableD3D *mGeometryExecutable;
 
@@ -262,30 +276,32 @@ class ProgramD3D : public ProgramImpl
     std::vector<Sampler> mSamplersVS;
     GLuint mUsedVertexSamplerRange;
     GLuint mUsedPixelSamplerRange;
     bool mDirtySamplerMapping;
 
     // Cache for getPixelExecutableForFramebuffer
     std::vector<GLenum> mPixelShaderOutputFormatCache;
 
-    int mShaderVersion;
-
     SemanticIndexArray mSemanticIndexes;
     SemanticIndexArray mAttributesByLayout;
 
     unsigned int mSerial;
 
     std::vector<GLint> mVertexUBOCache;
     std::vector<GLint> mFragmentUBOCache;
     VertexExecutable::Signature mCachedVertexSignature;
     gl::InputLayout mCachedInputLayout;
 
     std::vector<gl::LinkedVarying> mTransformFeedbackLinkedVaryings;
     std::vector<D3DUniform *> mD3DUniforms;
+    std::vector<D3DUniformBlock> mD3DUniformBlocks;
+
+    std::map<std::string, sh::BlockMemberInfo> mBlockInfo;
+    std::map<std::string, size_t> mBlockDataSizes;
 
     static unsigned int issueSerial();
     static unsigned int mCurrentSerial;
 };
 
 }
 
 #endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_
--- a/gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
@@ -18,16 +18,17 @@
 #include "libANGLE/State.h"
 #include "libANGLE/VertexArray.h"
 #include "libANGLE/formatutils.h"
 #include "libANGLE/renderer/d3d/BufferD3D.h"
 #include "libANGLE/renderer/d3d/CompilerD3D.h"
 #include "libANGLE/renderer/d3d/DisplayD3D.h"
 #include "libANGLE/renderer/d3d/IndexDataManager.h"
 #include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/SamplerD3D.h"
 
 namespace rx
 {
 
 namespace
 {
 // If we request a scratch buffer requesting a smaller size this many times,
 // release and recreate the scratch buffer. This ensures we don't have a
@@ -68,16 +69,21 @@ void RendererD3D::cleanup()
     }
 }
 
 CompilerImpl *RendererD3D::createCompiler()
 {
     return new CompilerD3D(getRendererClass());
 }
 
+SamplerImpl *RendererD3D::createSampler()
+{
+    return new SamplerD3D();
+}
+
 gl::Error RendererD3D::drawArrays(const gl::Data &data, GLenum mode, GLint first, GLsizei count)
 {
     return genericDrawArrays(data, mode, first, count, 0);
 }
 
 gl::Error RendererD3D::drawArraysInstanced(const gl::Data &data,
                                            GLenum mode,
                                            GLint first,
--- a/gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.h
+++ b/gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.h
@@ -126,16 +126,18 @@ class RendererD3D : public Renderer, pub
                                 const GLvoid *indices,
                                 const gl::IndexRange &indexRange) override;
 
     bool isDeviceLost() const override;
     std::string getVendorString() const override;
 
     CompilerImpl *createCompiler() override;
 
+    SamplerImpl *createSampler() override;
+
     virtual int getMinorShaderModel() const = 0;
     virtual std::string getShaderModelSuffix() const = 0;
 
     // Direct3D Specific methods
     virtual DeviceIdentifier getAdapterIdentifier() const = 0;
 
     virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0;
 
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/SamplerD3D.h
@@ -0,0 +1,25 @@
+//
+// Copyright 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.
+//
+
+// SamplerD3D.h: Defines the rx::SamplerD3D class, an implementation of SamplerImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_SAMPLERD3D_H_
+#define LIBANGLE_RENDERER_D3D_SAMPLERD3D_H_
+
+#include "libANGLE/renderer/SamplerImpl.h"
+
+namespace rx
+{
+
+class SamplerD3D : public SamplerImpl
+{
+  public:
+    SamplerD3D() {}
+    ~SamplerD3D() override {}
+};
+}
+
+#endif  // LIBANGLE_RENDERER_D3D_SAMPLERD3D_H_
--- a/gfx/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp
@@ -118,27 +118,28 @@ ShShaderOutput ShaderD3D::getCompilerOut
 }
 
 int ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *shaderSourceStream)
 {
     uncompile();
 
     int additionalOptions = 0;
 
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
     const std::string &source = mData.getSource();
 
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
     if (gl::DebugAnnotationsActive())
     {
         std::string sourcePath = getTempPath();
         writeFile(sourcePath.c_str(), source.c_str(), source.length());
         additionalOptions |= SH_LINE_DIRECTIVES | SH_SOURCE_PATH;
         *shaderSourceStream << sourcePath;
     }
 #endif
+
     *shaderSourceStream << source;
     return additionalOptions;
 }
 
 bool ShaderD3D::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog)
 {
     // TODO(jmadill): We shouldn't need to cache this.
     mCompilerOutputType = compiler->getShaderOutputType();
--- a/gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
@@ -160,24 +160,16 @@ bool TextureD3D::shouldUseSetData(const 
 }
 
 gl::Error TextureD3D::setImageImpl(const gl::ImageIndex &index,
                                    GLenum type,
                                    const gl::PixelUnpackState &unpack,
                                    const uint8_t *pixels,
                                    ptrdiff_t layerOffset)
 {
-    if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0)
-    {
-        // TODO(jmadill): additional unpack parameters
-        // return no error here to work around dEQP-GLES3 failing to state reset.
-        UNIMPLEMENTED();
-        return gl::Error(GL_NO_ERROR);
-    }
-
     ImageD3D *image = getImage(index);
     ASSERT(image);
 
     // No-op
     if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0)
     {
         return gl::Error(GL_NO_ERROR);
     }
@@ -253,22 +245,16 @@ gl::Error TextureD3D::subImage(const gl:
     return gl::Error(GL_NO_ERROR);
 }
 
 gl::Error TextureD3D::setCompressedImageImpl(const gl::ImageIndex &index,
                                              const gl::PixelUnpackState &unpack,
                                              const uint8_t *pixels,
                                              ptrdiff_t layerOffset)
 {
-    if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0)
-    {
-        UNIMPLEMENTED();
-        return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state");
-    }
-
     // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains.
     // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components.
     const uint8_t *pixelData = NULL;
     gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData);
     if (error.isError())
     {
         return error;
     }
@@ -290,22 +276,16 @@ gl::Error TextureD3D::setCompressedImage
 
     return gl::Error(GL_NO_ERROR);
 }
 
 gl::Error TextureD3D::subImageCompressed(const gl::ImageIndex &index, const gl::Box &area, GLenum format,
                                          const gl::PixelUnpackState &unpack, const uint8_t *pixels,
                                          ptrdiff_t layerOffset)
 {
-    if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0)
-    {
-        UNIMPLEMENTED();
-        return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state");
-    }
-
     const uint8_t *pixelData = NULL;
     gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData);
     if (error.isError())
     {
         return error;
     }
 
     if (pixelData != NULL)
@@ -328,16 +308,25 @@ gl::Error TextureD3D::subImageCompressed
 bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat)
 {
     return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat);
 }
 
 gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const uint8_t *pixels, const gl::Box &destArea,
                                        GLenum sizedInternalFormat, GLenum type, RenderTargetD3D *destRenderTarget)
 {
+    if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 ||
+        unpack.skipImages != 0)
+    {
+        // TODO(jmadill): additional unpack parameters
+        UNIMPLEMENTED();
+        return gl::Error(GL_INVALID_OPERATION,
+                         "Unimplemented pixel store parameters in fastUnpackPixels");
+    }
+
     // No-op
     if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0)
     {
         return gl::Error(GL_NO_ERROR);
     }
 
     // In order to perform the fast copy through the shader, we must have the right format, and be able
     // to create a render target.
@@ -760,22 +749,16 @@ gl::Error TextureD3D_2D::setSubImage(GLe
                                      const gl::Box &area,
                                      GLenum format,
                                      GLenum type,
                                      const gl::PixelUnpackState &unpack,
                                      const uint8_t *pixels)
 {
     ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0);
 
-    if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0)
-    {
-        UNIMPLEMENTED();
-        return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state");
-    }
-
     GLint level          = static_cast<GLint>(imageLevel);
     gl::ImageIndex index = gl::ImageIndex::Make2D(level);
     if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
     {
         RenderTargetD3D *renderTarget = NULL;
         gl::Error error = getRenderTarget(index, &renderTarget);
         if (error.isError())
         {
@@ -2558,17 +2541,18 @@ gl::Error TextureD3D_2DArray::setImage(G
     ASSERT(target == GL_TEXTURE_2D_ARRAY);
 
     GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
 
     GLint level = static_cast<GLint>(imageLevel);
     redefineImage(level, sizedInternalFormat, size);
 
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
-    GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, size.width, size.height, unpack.alignment, unpack.rowLength);
+    GLsizei inputDepthPitch = formatInfo.computeDepthPitch(
+        type, size.width, size.height, unpack.alignment, unpack.rowLength, unpack.imageHeight);
 
     for (int i = 0; i < size.depth; i++)
     {
         const ptrdiff_t layerOffset = (inputDepthPitch * i);
         gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i);
         gl::Error error = setImageImpl(index, type, unpack, pixels, layerOffset);
         if (error.isError())
         {
@@ -2585,17 +2569,18 @@ gl::Error TextureD3D_2DArray::setSubImag
                                           GLenum format,
                                           GLenum type,
                                           const gl::PixelUnpackState &unpack,
                                           const uint8_t *pixels)
 {
     ASSERT(target == GL_TEXTURE_2D_ARRAY);
     GLint level                          = static_cast<GLint>(imageLevel);
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(level));
-    GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment, unpack.rowLength);
+    GLsizei inputDepthPitch = formatInfo.computeDepthPitch(
+        type, area.width, area.height, unpack.alignment, unpack.rowLength, unpack.imageHeight);
 
     for (int i = 0; i < area.depth; i++)
     {
         int layer = area.z + i;
         const ptrdiff_t layerOffset = (inputDepthPitch * i);
 
         gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1);
 
@@ -2620,17 +2605,18 @@ gl::Error TextureD3D_2DArray::setCompres
 {
     ASSERT(target == GL_TEXTURE_2D_ARRAY);
 
     GLint level = static_cast<GLint>(imageLevel);
     // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
     redefineImage(level, internalFormat, size);
 
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
-    GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0);
+    GLsizei inputDepthPitch =
+        formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0, 0);
 
     for (int i = 0; i < size.depth; i++)
     {
         const ptrdiff_t layerOffset = (inputDepthPitch * i);
 
         gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i);
         gl::Error error = setCompressedImageImpl(index, unpack, pixels, layerOffset);
         if (error.isError())
@@ -2643,17 +2629,18 @@ gl::Error TextureD3D_2DArray::setCompres
 }
 
 gl::Error TextureD3D_2DArray::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
                                                     const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels)
 {
     ASSERT(target == GL_TEXTURE_2D_ARRAY);
 
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
-    GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0);
+    GLsizei inputDepthPitch =
+        formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0);
 
     for (int i = 0; i < area.depth; i++)
     {
         int layer = area.z + i;
         const ptrdiff_t layerOffset = (inputDepthPitch * i);
 
         gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1);
 
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
@@ -284,33 +284,45 @@ gl::Error Framebuffer11::invalidateBase(
 }
 
 gl::Error Framebuffer11::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
 {
     // A no-op implementation conforms to the spec, so don't call UNIMPLEMENTED()
     return gl::Error(GL_NO_ERROR);
 }
 
-gl::Error Framebuffer11::readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) const
+gl::Error Framebuffer11::readPixelsImpl(const gl::Rectangle &area,
+                                        GLenum format,
+                                        GLenum type,
+                                        size_t outputPitch,
+                                        const gl::PixelPackState &pack,
+                                        uint8_t *pixels) const
 {
     ID3D11Texture2D *colorBufferTexture = nullptr;
     unsigned int subresourceIndex = 0;
 
     const gl::FramebufferAttachment *colorbuffer = mData.getReadAttachment();
     ASSERT(colorbuffer);
 
     gl::Error error = getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture);
     if (error.isError())
     {
         return error;
     }
 
     gl::Buffer *packBuffer = pack.pixelBuffer.get();
     if (packBuffer != nullptr)
     {
+        if (pack.rowLength != 0 || pack.skipRows != 0 || pack.skipPixels != 0)
+        {
+            UNIMPLEMENTED();
+            return gl::Error(GL_INVALID_OPERATION,
+                             "Unimplemented pixel store parameters in readPixelsImpl");
+        }
+
         Buffer11 *packBufferStorage = GetImplAs<Buffer11>(packBuffer);
         PackPixelsParams packParams(area, format, type, static_cast<GLuint>(outputPitch), pack,
                                     reinterpret_cast<ptrdiff_t>(pixels));
 
         error = packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams);
         if (error.isError())
         {
             SafeRelease(colorBufferTexture);
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
@@ -26,18 +26,22 @@ class Framebuffer11 : public Framebuffer
     gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
 
     // Invalidate the cached swizzles of all bound texture attachments.
     gl::Error invalidateSwizzles() const;
 
   private:
     gl::Error clear(const gl::State &state, const ClearParameters &clearParams) override;
 
-    gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch,
-                         const gl::PixelPackState &pack, uint8_t *pixels) const override;
+    gl::Error readPixelsImpl(const gl::Rectangle &area,
+                             GLenum format,
+                             GLenum type,
+                             size_t outputPitch,
+                             const gl::PixelPackState &pack,
+                             uint8_t *pixels) const override;
 
     gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor,
                    bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter,
                    const gl::Framebuffer *sourceFramebuffer) override;
 
     gl::Error invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const;
 
     GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override;
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
@@ -2,27 +2,28 @@
 // Copyright (c) 2012 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.
 //
 
 // Image11.h: Implements the rx::Image11 class, which acts as the interface to
 // the actual underlying resources of a Texture
 
-#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
 #include "libANGLE/renderer/d3d/d3d11/Image11.h"
-#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
-#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
-#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
-#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+#include "common/utilities.h"
+#include "libANGLE/formatutils.h"
 #include "libANGLE/Framebuffer.h"
 #include "libANGLE/FramebufferAttachment.h"
-#include "libANGLE/formatutils.h"
-
-#include "common/utilities.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
 
 namespace rx
 {
 
 Image11::Image11(Renderer11 *renderer)
     : mRenderer(renderer),
       mDXGIFormat(DXGI_FORMAT_UNKNOWN),
       mStagingTexture(NULL),
@@ -241,46 +242,50 @@ DXGI_FORMAT Image11::getDXGIFormat() con
 }
 
 // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
 // into the target pixel rectangle.
 gl::Error Image11::loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input)
 {
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
     GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength);
-    GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment, unpack.rowLength);
+    GLsizei inputDepthPitch = formatInfo.computeDepthPitch(
+        type, area.width, area.height, unpack.alignment, unpack.rowLength, unpack.imageHeight);
+    GLsizei inputSkipBytes = formatInfo.computeSkipPixels(
+        inputRowPitch, inputDepthPitch, unpack.skipImages, unpack.skipRows, unpack.skipPixels);
 
     const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat);
     GLuint outputPixelSize = dxgiFormatInfo.pixelBytes;
 
     const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, mRenderer->getRenderer11DeviceCaps());
     LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(type);
 
     D3D11_MAPPED_SUBRESOURCE mappedImage;
     gl::Error error = map(D3D11_MAP_WRITE, &mappedImage);
     if (error.isError())
     {
         return error;
     }
 
     uint8_t *offsetMappedData = (reinterpret_cast<uint8_t*>(mappedImage.pData) + (area.y * mappedImage.RowPitch + area.x * outputPixelSize + area.z * mappedImage.DepthPitch));
     loadFunction(area.width, area.height, area.depth,
-                 reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch,
-                 offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch);
+                 reinterpret_cast<const uint8_t *>(input) + inputSkipBytes, inputRowPitch,
+                 inputDepthPitch, offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch);
 
     unmap();
 
     return gl::Error(GL_NO_ERROR);
 }
 
 gl::Error Image11::loadCompressedData(const gl::Box &area, const void *input)
 {
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
     GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0);
-    GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0);
+    GLsizei inputDepthPitch =
+        formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0);
 
     const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat);
     GLuint outputPixelSize = dxgiFormatInfo.pixelBytes;
     GLuint outputBlockWidth = dxgiFormatInfo.blockWidth;
     GLuint outputBlockHeight = dxgiFormatInfo.blockHeight;
 
     ASSERT(area.x % outputBlockWidth == 0);
     ASSERT(area.y % outputBlockHeight == 0);
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
@@ -5,33 +5,35 @@
 //
 
 // PixelTransfer11.cpp:
 //   Implementation for buffer-to-texture and texture-to-buffer copies.
 //   Used to implement pixel transfers from unpack and to pack buffers.
 //
 
 #include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
-#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
-#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
 #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
-#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
-#include "libANGLE/formatutils.h"
 #include "libANGLE/Texture.h"
-#include "libANGLE/Buffer.h"
-#include "libANGLE/Context.h"
 
 // Precompiled shaders
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h"
 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h"
 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h"
 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h"
 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h"
 
 namespace rx
 {
 
 PixelTransfer11::PixelTransfer11(Renderer11 *renderer)
     : mRenderer(renderer),
       mResourcesLoaded(false),
       mBufferToTextureVS(NULL),
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp
@@ -3,20 +3,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
 // RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers
 // retained by Renderbuffers.
 
 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
 #include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
-#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
 
 namespace rx
 {
 
 static bool getTextureProperties(ID3D11Resource *resource, unsigned int *mipLevels, unsigned int *samples)
 {
     ID3D11Texture1D *texture1D = d3d11::DynamicCastComObject<ID3D11Texture1D>(resource);
     if (texture1D)
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
@@ -3,68 +3,69 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
 // Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer.
 
 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
 
+#include <EGL/eglext.h>
 #include <sstream>
-#include <EGL/eglext.h>
-
+
+#include "common/tls.h"
 #include "common/utilities.h"
-#include "common/tls.h"
 #include "libANGLE/Buffer.h"
 #include "libANGLE/Display.h"
+#include "libANGLE/formatutils.h"
 #include "libANGLE/Framebuffer.h"
 #include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/histogram_macros.h"
 #include "libANGLE/Program.h"
-#include "libANGLE/State.h"
-#include "libANGLE/Surface.h"
-#include "libANGLE/formatutils.h"
-#include "libANGLE/histogram_macros.h"
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Clear11.h"
+#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
+#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Image11.h"
+#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Query11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libANGLE/renderer/d3d/d3d11/Trim11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
 #include "libANGLE/renderer/d3d/FramebufferD3D.h"
 #include "libANGLE/renderer/d3d/IndexDataManager.h"
 #include "libANGLE/renderer/d3d/ProgramD3D.h"
 #include "libANGLE/renderer/d3d/RenderbufferD3D.h"
 #include "libANGLE/renderer/d3d/ShaderD3D.h"
 #include "libANGLE/renderer/d3d/SurfaceD3D.h"
 #include "libANGLE/renderer/d3d/TextureD3D.h"
 #include "libANGLE/renderer/d3d/TransformFeedbackD3D.h"
 #include "libANGLE/renderer/d3d/VertexDataManager.h"
-#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
-#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
-#include "libANGLE/renderer/d3d/d3d11/Clear11.h"
-#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
-#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
-#include "libANGLE/renderer/d3d/d3d11/Image11.h"
-#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
-#include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h"
-#include "libANGLE/renderer/d3d/d3d11/Query11.h"
-#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
-#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
-#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
-#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
-#include "libANGLE/renderer/d3d/d3d11/Trim11.h"
-#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
-#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
-#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
-#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
-#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/State.h"
+#include "libANGLE/Surface.h"
+#include "third_party/trace_event/trace_event.h"
 
 // Include the D3D9 debug annotator header for use by the desktop D3D11 renderer
 // because the D3D11 interface method ID3DUserDefinedAnnotation::GetStatus
 // doesn't work with the Graphics Diagnostics tools in Visual Studio 2013.
 #ifdef ANGLE_ENABLE_D3D9
 #include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h"
 #endif
 
-#include "third_party/trace_event/trace_event.h"
-
 // Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process
 // HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed.
 #ifndef ANGLE_SKIP_DXGI_1_2_CHECK
 #define ANGLE_SKIP_DXGI_1_2_CHECK 0
 #endif
 
 #ifdef _DEBUG
 // this flag enables suppressing some spurious warnings that pop up in certain WebGL samples
@@ -1002,23 +1003,24 @@ gl::Error Renderer11::setUniformBuffers(
     {
         GLint binding = vertexUniformBuffers[uniformBufferIndex];
 
         if (binding == -1)
         {
             continue;
         }
 
-        gl::Buffer *uniformBuffer = data.state->getIndexedUniformBuffer(binding);
-        GLintptr uniformBufferOffset = data.state->getIndexedUniformBufferOffset(binding);
-        GLsizeiptr uniformBufferSize = data.state->getIndexedUniformBufferSize(binding);
-
-        if (uniformBuffer)
+        const OffsetBindingPointer<gl::Buffer> &uniformBuffer =
+            data.state->getIndexedUniformBuffer(binding);
+        GLintptr uniformBufferOffset = uniformBuffer.getOffset();
+        GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
+
+        if (uniformBuffer.get() != nullptr)
         {
-            Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer);
+            Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get());
             ID3D11Buffer *constantBuffer;
 
             if (mRenderer11DeviceCaps.supportsConstantBufferOffsets)
             {
                 constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM);
             }
             else
             {
@@ -1062,23 +1064,24 @@ gl::Error Renderer11::setUniformBuffers(
     {
         GLint binding = fragmentUniformBuffers[uniformBufferIndex];
 
         if (binding == -1)
         {
             continue;
         }
 
-        gl::Buffer *uniformBuffer = data.state->getIndexedUniformBuffer(binding);
-        GLintptr uniformBufferOffset = data.state->getIndexedUniformBufferOffset(binding);
-        GLsizeiptr uniformBufferSize = data.state->getIndexedUniformBufferSize(binding);
-
-        if (uniformBuffer)
+        const OffsetBindingPointer<gl::Buffer> &uniformBuffer =
+            data.state->getIndexedUniformBuffer(binding);
+        GLintptr uniformBufferOffset = uniformBuffer.getOffset();
+        GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
+
+        if (uniformBuffer.get() != nullptr)
         {
-            Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer);
+            Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get());
             ID3D11Buffer *constantBuffer;
 
             if (mRenderer11DeviceCaps.supportsConstantBufferOffsets)
             {
                 constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM);
             }
             else
             {
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
@@ -4,20 +4,21 @@
 // found in the LICENSE file.
 //
 
 // SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain.
 
 #include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
 
 #include "libANGLE/features.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
 #include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
-#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
 #include "third_party/trace_event/trace_event.h"
 
 // Precompiled shaders
 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h"
 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h"
 
 #ifdef ANGLE_ENABLE_KEYEDMUTEX
 #define ANGLE_RESOURCE_SHARE_TYPE D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
@@ -8,27 +8,28 @@
 // classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture.
 
 #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
 
 #include <tuple>
 
 #include "common/MemoryBuffer.h"
 #include "common/utilities.h"
+#include "libANGLE/formatutils.h"
 #include "libANGLE/ImageIndex.h"
-#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/Image11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
 #include "libANGLE/renderer/d3d/EGLImageD3D.h"
 #include "libANGLE/renderer/d3d/TextureD3D.h"
-#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
-#include "libANGLE/renderer/d3d/d3d11/Image11.h"
-#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
-#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
-#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
-#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
-#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
 
 namespace rx
 {
 
 TextureStorage11::SwizzleCacheValue::SwizzleCacheValue()
     : swizzleRed(GL_NONE), swizzleGreen(GL_NONE), swizzleBlue(GL_NONE), swizzleAlpha(GL_NONE)
 {
 }
@@ -643,17 +644,20 @@ gl::Error TextureStorage11::setData(cons
     // different logic. Will implemnent this in a follow-up patch, and ensure we do not use SetData
     // with compressed formats in the calling logic.
     ASSERT(!internalFormatInfo.compressed);
 
     int width = destBox ? destBox->width : static_cast<int>(image->getWidth());
     int height = destBox ? destBox->height : static_cast<int>(image->getHeight());
     int depth = destBox ? destBox->depth : static_cast<int>(image->getDepth());
     UINT srcRowPitch = internalFormatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength);
-    UINT srcDepthPitch = internalFormatInfo.computeDepthPitch(type, width, height, unpack.alignment, unpack.rowLength);
+    UINT srcDepthPitch = internalFormatInfo.computeDepthPitch(type, width, height, unpack.alignment,
+                                                              unpack.rowLength, unpack.imageHeight);
+    GLsizei srcSkipBytes = internalFormatInfo.computeSkipPixels(
+        srcRowPitch, srcDepthPitch, unpack.skipImages, unpack.skipRows, unpack.skipPixels);
 
     const d3d11::TextureFormat &d3d11Format = d3d11::GetTextureFormatInfo(image->getInternalFormat(), mRenderer->getRenderer11DeviceCaps());
     const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11Format.texFormat);
 
     size_t outputPixelSize = dxgiFormatInfo.pixelBytes;
 
     UINT bufferRowPitch   = static_cast<unsigned int>(outputPixelSize) * width;
     UINT bufferDepthPitch = bufferRowPitch * height;
@@ -663,18 +667,17 @@ gl::Error TextureStorage11::setData(cons
     error = mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer);
     if (error.isError())
     {
         return error;
     }
 
     // TODO: fast path
     LoadImageFunction loadFunction = d3d11Format.loadFunctions.at(type);
-    loadFunction(width, height, depth,
-                 pixelData, srcRowPitch, srcDepthPitch,
+    loadFunction(width, height, depth, pixelData + srcSkipBytes, srcRowPitch, srcDepthPitch,
                  conversionBuffer->data(), bufferRowPitch, bufferDepthPitch);
 
     ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
 
     if (!fullUpdate)
     {
         ASSERT(destBox);
 
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp
@@ -3,24 +3,25 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
 // formatutils11.cpp: Queries for GL image formats and their translations to D3D11
 // formats.
 
 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+
 #include "libANGLE/formatutils.h"
-#include "libANGLE/renderer/Renderer.h"
 #include "libANGLE/renderer/d3d/copyimage.h"
+#include "libANGLE/renderer/d3d/d3d11/copyvertex.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
 #include "libANGLE/renderer/d3d/generatemip.h"
 #include "libANGLE/renderer/d3d/loadimage.h"
-#include "libANGLE/renderer/d3d/d3d11/copyvertex.h"
-#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
-#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/Renderer.h"
 
 namespace rx
 {
 
 namespace d3d11
 {
 
 typedef std::map<DXGI_FORMAT, GLenum> DXGIToESFormatMap;
@@ -298,83 +299,16 @@ static bool NeverSupported(D3D_FEATURE_L
 }
 
 template <D3D_FEATURE_LEVEL requiredFeatureLevel>
 static bool RequiresFeatureLevel(D3D_FEATURE_LEVEL featureLevel)
 {
     return featureLevel >= requiredFeatureLevel;
 }
 
-typedef bool(*FormatSupportFunction)(const Renderer11DeviceCaps&);
-
-static bool AnyDevice(const Renderer11DeviceCaps &deviceCaps)
-{
-    return true;
-}
-
-static bool OnlyFL10Plus(const Renderer11DeviceCaps &deviceCaps)
-{
-    return (deviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0);
-}
-
-static bool OnlyFL9_3(const Renderer11DeviceCaps &deviceCaps)
-{
-    return (deviceCaps.featureLevel == D3D_FEATURE_LEVEL_9_3);
-}
-
-template <DXGI_FORMAT format, bool requireSupport>
-static bool SupportsFormat(const Renderer11DeviceCaps &deviceCaps)
-{
-    // Must support texture, SRV and RTV support
-    UINT mustSupport = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE |
-                       D3D11_FORMAT_SUPPORT_SHADER_SAMPLE | D3D11_FORMAT_SUPPORT_MIP | D3D11_FORMAT_SUPPORT_RENDER_TARGET;
-
-    if (d3d11_gl::GetMaximumClientVersion(deviceCaps.featureLevel) > 2)
-    {
-        mustSupport |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
-    }
-
-    bool fullSupport = false;
-    if (format == DXGI_FORMAT_B5G6R5_UNORM)
-    {
-        // All hardware that supports DXGI_FORMAT_B5G6R5_UNORM should support autogen mipmaps, but check anyway.
-        mustSupport |= D3D11_FORMAT_SUPPORT_MIP_AUTOGEN;
-        fullSupport = ((deviceCaps.B5G6R5support & mustSupport) == mustSupport);
-    }
-    else if (format == DXGI_FORMAT_B4G4R4A4_UNORM)
-    {
-        fullSupport = ((deviceCaps.B4G4R4A4support & mustSupport) == mustSupport);
-    }
-    else if (format == DXGI_FORMAT_B5G5R5A1_UNORM)
-    {
-        fullSupport = ((deviceCaps.B5G5R5A1support & mustSupport) == mustSupport);
-    }
-    else
-    {
-        UNREACHABLE();
-        return false;
-    }
-
-    // This 'SupportsFormat' function is used by individual entries in the D3D11 Format Map below, which maps GL formats to DXGI formats.
-    if (requireSupport)
-    {
-        // This means that ANGLE would like to use the entry in the map if the inputted DXGI format *IS* supported.
-        // e.g. the entry might map GL_RGB5_A1 to DXGI_FORMAT_B5G5R5A1, which should only be used if DXGI_FORMAT_B5G5R5A1 is supported.
-        // In this case, we should only return 'true' if the format *IS* supported.
-        return fullSupport;
-    }
-    else
-    {
-        // This means that ANGLE would like to use the entry in the map if the inputted DXGI format *ISN'T* supported.
-        // This might be a fallback entry. e.g. for ANGLE to use DXGI_FORMAT_R8G8B8A8_UNORM if DXGI_FORMAT_B5G5R5A1 isn't supported.
-        // In this case, we should only return 'true' if the format *ISN'T* supported.
-        return !fullSupport;
-    }
-}
-
 ColorCopyFunction DXGIFormat::getFastCopyFunction(GLenum format, GLenum type) const
 {
     FastCopyFunctionMap::const_iterator iter = fastCopyFunctions.find(std::make_pair(format, type));
     return (iter != fastCopyFunctions.end()) ? iter->second : NULL;
 }
 
 void AddDXGIFormat(DXGIFormatInfoMap *map, DXGI_FORMAT dxgiFormat, GLuint pixelBits, GLuint blockWidth, GLuint blockHeight,
                    GLenum componentType, MipGenerationFunction mipFunc, ColorReadFunction readFunc, NativeMipmapGenerationSupportFunction nativeMipmapSupport)
@@ -527,584 +461,16 @@ const DXGIFormat &GetDXGIFormatInfo(DXGI
     }
     else
     {
         static DXGIFormat defaultInfo;
         return defaultInfo;
     }
 }
 
-struct SwizzleSizeType
-{
-    size_t maxComponentSize;
-    GLenum componentType;
-
-    SwizzleSizeType()
-        : maxComponentSize(0), componentType(GL_NONE)
-    { }
-
-    SwizzleSizeType(size_t maxComponentSize, GLenum componentType)
-        : maxComponentSize(maxComponentSize), componentType(componentType)
-    { }
-
-    bool operator<(const SwizzleSizeType& other) const
-    {
-        return (maxComponentSize != other.maxComponentSize) ? (maxComponentSize < other.maxComponentSize)
-                                                            : (componentType < other.componentType);
-    }
-};
-
-struct SwizzleFormatInfo
-{
-    DXGI_FORMAT mTexFormat;
-    DXGI_FORMAT mSRVFormat;
-    DXGI_FORMAT mRTVFormat;
-
-    SwizzleFormatInfo()
-        : mTexFormat(DXGI_FORMAT_UNKNOWN), mSRVFormat(DXGI_FORMAT_UNKNOWN), mRTVFormat(DXGI_FORMAT_UNKNOWN)
-    { }
-
-    SwizzleFormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat)
-        : mTexFormat(texFormat), mSRVFormat(srvFormat), mRTVFormat(rtvFormat)
-    { }
-};
-
-typedef std::map<SwizzleSizeType, SwizzleFormatInfo> SwizzleInfoMap;
-typedef std::pair<SwizzleSizeType, SwizzleFormatInfo> SwizzleInfoPair;
-
-static SwizzleInfoMap BuildSwizzleInfoMap()
-{
-    SwizzleInfoMap map;
-
-    map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_R8G8B8A8_UNORM    )));
-    map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM)));
-    map.insert(SwizzleInfoPair(SwizzleSizeType(24, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT)));
-    map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT)));
-
-    map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_SIGNED_NORMALIZED  ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SNORM,     DXGI_FORMAT_R8G8B8A8_SNORM,     DXGI_FORMAT_R8G8B8A8_SNORM    )));
-
-    map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_FLOAT              ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT)));
-    map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_FLOAT              ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT)));
-
-    map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_UNSIGNED_INT       ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UINT,      DXGI_FORMAT_R8G8B8A8_UINT,      DXGI_FORMAT_R8G8B8A8_UINT     )));
-    map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_UNSIGNED_INT       ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UINT,  DXGI_FORMAT_R16G16B16A16_UINT,  DXGI_FORMAT_R16G16B16A16_UINT )));
-    map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_UNSIGNED_INT       ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_UINT,  DXGI_FORMAT_R32G32B32A32_UINT,  DXGI_FORMAT_R32G32B32A32_UINT )));
-
-    map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_INT                ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SINT,      DXGI_FORMAT_R8G8B8A8_SINT,      DXGI_FORMAT_R8G8B8A8_SINT     )));
-    map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_INT                ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_SINT,  DXGI_FORMAT_R16G16B16A16_SINT,  DXGI_FORMAT_R16G16B16A16_SINT )));
-    map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_INT                ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_SINT,  DXGI_FORMAT_R32G32B32A32_SINT,  DXGI_FORMAT_R32G32B32A32_SINT )));
-
-    return map;
-}
-
-typedef std::pair<GLint, DXGI_FORMAT> InitializeTextureFormatPair;
-typedef std::pair<InitializeTextureFormatPair, InitializeTextureDataFunction> InternalFormatInitializerPair;
-typedef std::map<InitializeTextureFormatPair, InitializeTextureDataFunction> InternalFormatInitializerMap;
-
-static InternalFormatInitializerMap BuildInternalFormatInitializerMap()
-{
-    InternalFormatInitializerMap map;
-
-    map.insert(InternalFormatInitializerPair(InitializeTextureFormatPair(GL_RGB8,    DXGI_FORMAT_R8G8B8A8_UNORM     ), Initialize4ComponentData<GLubyte,  0x00,       0x00,       0x00,       0xFF>));
-    map.insert(InternalFormatInitializerPair(InitializeTextureFormatPair(GL_RGB565,  DXGI_FORMAT_R8G8B8A8_UNORM     ), Initialize4ComponentData<GLubyte,  0x00,       0x00,       0x00,       0xFF>));
-    map.insert(InternalFormatInitializerPair(InitializeTextureFormatPair(GL_SRGB8,   DXGI_FORMAT_R8G8B8A8_UNORM_SRGB), Initialize4ComponentData<GLubyte,  0x00,       0x00,       0x00,       0xFF>));
-    map.insert(InternalFormatInitializerPair(InitializeTextureFormatPair(GL_RGB16F,  DXGI_FORMAT_R16G16B16A16_FLOAT ), Initialize4ComponentData<GLhalf,   0x0000,     0x0000,     0x0000,     gl::Float16One>));
-    map.insert(InternalFormatInitializerPair(InitializeTextureFormatPair(GL_RGB32F,  DXGI_FORMAT_R32G32B32A32_FLOAT ), Initialize4ComponentData<GLfloat,  0x00000000, 0x00000000, 0x00000000, gl::Float32One>));
-    map.insert(InternalFormatInitializerPair(InitializeTextureFormatPair(GL_RGB8UI,  DXGI_FORMAT_R8G8B8A8_UINT      ), Initialize4ComponentData<GLubyte,  0x00,       0x00,       0x00,       0x01>));
-    map.insert(InternalFormatInitializerPair(InitializeTextureFormatPair(GL_RGB8I,   DXGI_FORMAT_R8G8B8A8_SINT      ), Initialize4ComponentData<GLbyte,   0x00,       0x00,       0x00,       0x01>));
-    map.insert(InternalFormatInitializerPair(InitializeTextureFormatPair(GL_RGB16UI, DXGI_FORMAT_R16G16B16A16_UINT  ), Initialize4ComponentData<GLushort, 0x0000,     0x0000,     0x0000,     0x0001>));
-    map.insert(InternalFormatInitializerPair(InitializeTextureFormatPair(GL_RGB16I,  DXGI_FORMAT_R16G16B16A16_SINT  ), Initialize4ComponentData<GLshort,  0x0000,     0x0000,     0x0000,     0x0001>));
-    map.insert(InternalFormatInitializerPair(InitializeTextureFormatPair(GL_RGB32UI, DXGI_FORMAT_R32G32B32A32_UINT  ), Initialize4ComponentData<GLuint,   0x00000000, 0x00000000, 0x00000000, 0x00000001>));
-    map.insert(InternalFormatInitializerPair(InitializeTextureFormatPair(GL_RGB32I,  DXGI_FORMAT_R32G32B32A32_SINT  ), Initialize4ComponentData<GLint,    0x00000000, 0x00000000, 0x00000000, 0x00000001>));
-
-    return map;
-}
-
-// ES3 image loading functions vary based on:
-//    - the GL internal format (supplied to glTex*Image*D)
-//    - the GL data type given (supplied to glTex*Image*D)
-//    - the target DXGI_FORMAT that the image will be loaded into (which is chosen based on the D3D device's capabilities)
-// This map type determines which loading function to use, based on these three parameters.
-// Source formats and types are taken from Tables 3.2 and 3.3 of the ES 3 spec.
-typedef std::pair<DXGI_FORMAT, LoadImageFunction> DxgiFormatLoadFunctionPair;
-typedef std::pair<GLenum, DxgiFormatLoadFunctionPair> GLTypeDXGIFunctionPair;
-typedef std::map<GLenum, std::vector<GLTypeDXGIFunctionPair> > D3D11LoadFunctionMap;
-
-static void UnimplementedLoadFunction(size_t width, size_t height, size_t depth,
-                                      const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
-                                      uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
-    UNIMPLEMENTED();
-}
-
-static void UnreachableLoadFunction(size_t width, size_t height, size_t depth,
-                                    const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
-                                    uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
-    UNREACHABLE();
-}
-
-// A helper function to insert data into the D3D11LoadFunctionMap with fewer characters.
-static inline void InsertLoadFunction(D3D11LoadFunctionMap *map, GLenum internalFormat, GLenum type,
-                                      DXGI_FORMAT dxgiFormat, LoadImageFunction loadFunc)
-{
-    (*map)[internalFormat].push_back(GLTypeDXGIFunctionPair(type, DxgiFormatLoadFunctionPair(dxgiFormat, loadFunc)));
-}
-
-D3D11LoadFunctionMap BuildD3D11LoadFunctionMap()
-{
-    D3D11LoadFunctionMap map;
-
-    //                      | Internal format      | Type                             | Target DXGI Format              | Load function                       |
-    InsertLoadFunction(&map, GL_RGBA8,              GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8B8A8_UNORM,       LoadToNative<GLubyte, 4>             );
-    InsertLoadFunction(&map, GL_RGB5_A1,            GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8B8A8_UNORM,       LoadToNative<GLubyte, 4>             );
-    InsertLoadFunction(&map, GL_RGBA4,              GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8B8A8_UNORM,       LoadToNative<GLubyte, 4>             );
-    InsertLoadFunction(&map, GL_SRGB8_ALPHA8,       GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,  LoadToNative<GLubyte, 4>             );
-    InsertLoadFunction(&map, GL_RGBA8_SNORM,        GL_BYTE,                           DXGI_FORMAT_R8G8B8A8_SNORM,       LoadToNative<GLbyte, 4>              );
-    InsertLoadFunction(&map, GL_RGBA4,              GL_UNSIGNED_SHORT_4_4_4_4,         DXGI_FORMAT_R8G8B8A8_UNORM,       LoadRGBA4ToRGBA8                     );
-    InsertLoadFunction(&map, GL_RGBA4,              GL_UNSIGNED_SHORT_4_4_4_4,         DXGI_FORMAT_B4G4R4A4_UNORM,       LoadRGBA4ToARGB4                     );
-    InsertLoadFunction(&map, GL_RGB10_A2,           GL_UNSIGNED_INT_2_10_10_10_REV,    DXGI_FORMAT_R10G10B10A2_UNORM,    LoadToNative<GLuint, 1>              );
-    InsertLoadFunction(&map, GL_RGB5_A1,            GL_UNSIGNED_SHORT_5_5_5_1,         DXGI_FORMAT_R8G8B8A8_UNORM,       LoadRGB5A1ToRGBA8                    );
-    InsertLoadFunction(&map, GL_RGB5_A1,            GL_UNSIGNED_SHORT_5_5_5_1,         DXGI_FORMAT_B5G5R5A1_UNORM,       LoadRGB5A1ToA1RGB5                   );
-    InsertLoadFunction(&map, GL_RGB5_A1,            GL_UNSIGNED_INT_2_10_10_10_REV,    DXGI_FORMAT_R8G8B8A8_UNORM,       LoadRGB10A2ToRGBA8                   );
-    InsertLoadFunction(&map, GL_RGBA16F,            GL_HALF_FLOAT,                     DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadToNative<GLhalf, 4>              );
-    InsertLoadFunction(&map, GL_RGBA16F,            GL_HALF_FLOAT_OES,                 DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadToNative<GLhalf, 4>              );
-    InsertLoadFunction(&map, GL_RGBA32F,            GL_FLOAT,                          DXGI_FORMAT_R32G32B32A32_FLOAT,   LoadToNative<GLfloat, 4>             );
-    InsertLoadFunction(&map, GL_RGBA16F,            GL_FLOAT,                          DXGI_FORMAT_R16G16B16A16_FLOAT,   Load32FTo16F<4>                      );
-    InsertLoadFunction(&map, GL_RGBA8UI,            GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8B8A8_UINT,        LoadToNative<GLubyte, 4>             );
-    InsertLoadFunction(&map, GL_RGBA8I,             GL_BYTE,                           DXGI_FORMAT_R8G8B8A8_SINT,        LoadToNative<GLbyte, 4>              );
-    InsertLoadFunction(&map, GL_RGBA16UI,           GL_UNSIGNED_SHORT,                 DXGI_FORMAT_R16G16B16A16_UINT,    LoadToNative<GLushort, 4>            );
-    InsertLoadFunction(&map, GL_RGBA16I,            GL_SHORT,                          DXGI_FORMAT_R16G16B16A16_SINT,    LoadToNative<GLshort, 4>             );
-    InsertLoadFunction(&map, GL_RGBA32UI,           GL_UNSIGNED_INT,                   DXGI_FORMAT_R32G32B32A32_UINT,    LoadToNative<GLuint, 4>              );
-    InsertLoadFunction(&map, GL_RGBA32I,            GL_INT,                            DXGI_FORMAT_R32G32B32A32_SINT,    LoadToNative<GLint, 4>               );
-    InsertLoadFunction(&map, GL_RGB10_A2UI,         GL_UNSIGNED_INT_2_10_10_10_REV,    DXGI_FORMAT_R10G10B10A2_UINT,     LoadToNative<GLuint, 1>              );
-    InsertLoadFunction(&map, GL_RGB8,               GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8B8A8_UNORM,       LoadToNative3To4<GLubyte, 0xFF>      );
-    InsertLoadFunction(&map, GL_RGB565,             GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8B8A8_UNORM,       LoadToNative3To4<GLubyte, 0xFF>      );
-    InsertLoadFunction(&map, GL_SRGB8,              GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,  LoadToNative3To4<GLubyte, 0xFF>      );
-    InsertLoadFunction(&map, GL_RGB8_SNORM,         GL_BYTE,                           DXGI_FORMAT_R8G8B8A8_SNORM,       LoadToNative3To4<GLbyte, 0x7F>       );
-    InsertLoadFunction(&map, GL_RGB565,             GL_UNSIGNED_SHORT_5_6_5,           DXGI_FORMAT_R8G8B8A8_UNORM,       LoadR5G6B5ToRGBA8                    );
-    InsertLoadFunction(&map, GL_RGB565,             GL_UNSIGNED_SHORT_5_6_5,           DXGI_FORMAT_B5G6R5_UNORM,         LoadToNative<GLushort, 1>            );
-    InsertLoadFunction(&map, GL_R11F_G11F_B10F,     GL_UNSIGNED_INT_10F_11F_11F_REV,   DXGI_FORMAT_R11G11B10_FLOAT,      LoadToNative<GLuint, 1>              );
-    InsertLoadFunction(&map, GL_RGB9_E5,            GL_UNSIGNED_INT_5_9_9_9_REV,       DXGI_FORMAT_R9G9B9E5_SHAREDEXP,   LoadToNative<GLuint, 1>              );
-    InsertLoadFunction(&map, GL_RGB16F,             GL_HALF_FLOAT,                     DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadToNative3To4<GLhalf, gl::Float16One>);
-    InsertLoadFunction(&map, GL_RGB16F,             GL_HALF_FLOAT_OES,                 DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadToNative3To4<GLhalf, gl::Float16One>);
-    InsertLoadFunction(&map, GL_R11F_G11F_B10F,     GL_HALF_FLOAT,                     DXGI_FORMAT_R11G11B10_FLOAT,      LoadRGB16FToRG11B10F                 );
-    InsertLoadFunction(&map, GL_R11F_G11F_B10F,     GL_HALF_FLOAT_OES,                 DXGI_FORMAT_R11G11B10_FLOAT,      LoadRGB16FToRG11B10F                 );
-    InsertLoadFunction(&map, GL_RGB9_E5,            GL_HALF_FLOAT,                     DXGI_FORMAT_R9G9B9E5_SHAREDEXP,   LoadRGB16FToRGB9E5                   );
-    InsertLoadFunction(&map, GL_RGB9_E5,            GL_HALF_FLOAT_OES,                 DXGI_FORMAT_R9G9B9E5_SHAREDEXP,   LoadRGB16FToRGB9E5                   );
-    InsertLoadFunction(&map, GL_RGB32F,             GL_FLOAT,                          DXGI_FORMAT_R32G32B32A32_FLOAT,   LoadToNative3To4<GLfloat, gl::Float32One>);
-    InsertLoadFunction(&map, GL_RGB16F,             GL_FLOAT,                          DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadRGB32FToRGBA16F                  );
-    InsertLoadFunction(&map, GL_R11F_G11F_B10F,     GL_FLOAT,                          DXGI_FORMAT_R11G11B10_FLOAT,      LoadRGB32FToRG11B10F                 );
-    InsertLoadFunction(&map, GL_RGB9_E5,            GL_FLOAT,                          DXGI_FORMAT_R9G9B9E5_SHAREDEXP,   LoadRGB32FToRGB9E5                   );
-    InsertLoadFunction(&map, GL_RGB8UI,             GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8B8A8_UINT,        LoadToNative3To4<GLubyte, 0x01>      );
-    InsertLoadFunction(&map, GL_RGB8I,              GL_BYTE,                           DXGI_FORMAT_R8G8B8A8_SINT,        LoadToNative3To4<GLbyte, 0x01>       );
-    InsertLoadFunction(&map, GL_RGB16UI,            GL_UNSIGNED_SHORT,                 DXGI_FORMAT_R16G16B16A16_UINT,    LoadToNative3To4<GLushort, 0x0001>   );
-    InsertLoadFunction(&map, GL_RGB16I,             GL_SHORT,                          DXGI_FORMAT_R16G16B16A16_SINT,    LoadToNative3To4<GLshort, 0x0001>    );
-    InsertLoadFunction(&map, GL_RGB32UI,            GL_UNSIGNED_INT,                   DXGI_FORMAT_R32G32B32A32_UINT,    LoadToNative3To4<GLuint, 0x00000001> );
-    InsertLoadFunction(&map, GL_RGB32I,             GL_INT,                            DXGI_FORMAT_R32G32B32A32_SINT,    LoadToNative3To4<GLint, 0x00000001>  );
-    InsertLoadFunction(&map, GL_RG8,                GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8_UNORM,           LoadToNative<GLubyte, 2>             );
-    InsertLoadFunction(&map, GL_RG8_SNORM,          GL_BYTE,                           DXGI_FORMAT_R8G8_SNORM,           LoadToNative<GLbyte, 2>              );
-    InsertLoadFunction(&map, GL_RG16F,              GL_HALF_FLOAT,                     DXGI_FORMAT_R16G16_FLOAT,         LoadToNative<GLhalf, 2>              );
-    InsertLoadFunction(&map, GL_RG16F,              GL_HALF_FLOAT_OES,                 DXGI_FORMAT_R16G16_FLOAT,         LoadToNative<GLhalf, 2>              );
-    InsertLoadFunction(&map, GL_RG32F,              GL_FLOAT,                          DXGI_FORMAT_R32G32_FLOAT,         LoadToNative<GLfloat, 2>             );
-    InsertLoadFunction(&map, GL_RG16F,              GL_FLOAT,                          DXGI_FORMAT_R16G16_FLOAT,         Load32FTo16F<2>                      );
-    InsertLoadFunction(&map, GL_RG8UI,              GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8_UINT,            LoadToNative<GLubyte, 2>             );
-    InsertLoadFunction(&map, GL_RG8I,               GL_BYTE,                           DXGI_FORMAT_R8G8_SINT,            LoadToNative<GLbyte, 2>              );
-    InsertLoadFunction(&map, GL_RG16UI,             GL_UNSIGNED_SHORT,                 DXGI_FORMAT_R16G16_UINT,          LoadToNative<GLushort, 2>            );
-    InsertLoadFunction(&map, GL_RG16I,              GL_SHORT,                          DXGI_FORMAT_R16G16_SINT,          LoadToNative<GLshort, 2>             );
-    InsertLoadFunction(&map, GL_RG32UI,             GL_UNSIGNED_INT,                   DXGI_FORMAT_R32G32_UINT,          LoadToNative<GLuint, 2>              );
-    InsertLoadFunction(&map, GL_RG32I,              GL_INT,                            DXGI_FORMAT_R32G32_SINT,          LoadToNative<GLint, 2>               );
-    InsertLoadFunction(&map, GL_R8,                 GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8_UNORM,             LoadToNative<GLubyte, 1>             );
-    InsertLoadFunction(&map, GL_R8_SNORM,           GL_BYTE,                           DXGI_FORMAT_R8_SNORM,             LoadToNative<GLbyte, 1>              );
-    InsertLoadFunction(&map, GL_R16F,               GL_HALF_FLOAT,                     DXGI_FORMAT_R16_FLOAT,            LoadToNative<GLhalf, 1>              );
-    InsertLoadFunction(&map, GL_R16F,               GL_HALF_FLOAT_OES,                 DXGI_FORMAT_R16_FLOAT,            LoadToNative<GLhalf, 1>              );
-    InsertLoadFunction(&map, GL_R32F,               GL_FLOAT,                          DXGI_FORMAT_R32_FLOAT,            LoadToNative<GLfloat, 1>             );
-    InsertLoadFunction(&map, GL_R16F,               GL_FLOAT,                          DXGI_FORMAT_R16_FLOAT,            Load32FTo16F<1>                      );
-    InsertLoadFunction(&map, GL_R8UI,               GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8_UINT,              LoadToNative<GLubyte, 1>             );
-    InsertLoadFunction(&map, GL_R8I,                GL_BYTE,                           DXGI_FORMAT_R8_SINT,              LoadToNative<GLbyte, 1>              );
-    InsertLoadFunction(&map, GL_R16UI,              GL_UNSIGNED_SHORT,                 DXGI_FORMAT_R16_UINT,             LoadToNative<GLushort, 1>            );
-    InsertLoadFunction(&map, GL_R16I,               GL_SHORT,                          DXGI_FORMAT_R16_SINT,             LoadToNative<GLshort, 1>             );
-    InsertLoadFunction(&map, GL_R32UI,              GL_UNSIGNED_INT,                   DXGI_FORMAT_R32_UINT,             LoadToNative<GLuint, 1>              );
-    InsertLoadFunction(&map, GL_R32I,               GL_INT,                            DXGI_FORMAT_R32_SINT,             LoadToNative<GLint, 1>               );
-
-    InsertLoadFunction(&map, GL_DEPTH_COMPONENT16,  GL_UNSIGNED_SHORT,                 DXGI_FORMAT_R16_TYPELESS,         LoadToNative<GLushort, 1>            );
-    InsertLoadFunction(&map, GL_DEPTH_COMPONENT16,  GL_UNSIGNED_SHORT,                 DXGI_FORMAT_D16_UNORM,            LoadToNative<GLushort, 1>            );
-    InsertLoadFunction(&map, GL_DEPTH_COMPONENT24,  GL_UNSIGNED_INT,                   DXGI_FORMAT_R24G8_TYPELESS,       LoadR32ToR24G8                       );
-    InsertLoadFunction(&map, GL_DEPTH_COMPONENT24,  GL_UNSIGNED_INT,                   DXGI_FORMAT_D24_UNORM_S8_UINT,    LoadR32ToR24G8                       );
-    InsertLoadFunction(&map, GL_DEPTH_COMPONENT16,  GL_UNSIGNED_INT,                   DXGI_FORMAT_R16_TYPELESS,         LoadR32ToR16                         );
-    InsertLoadFunction(&map, GL_DEPTH_COMPONENT32F, GL_FLOAT,                          DXGI_FORMAT_R32_TYPELESS,         LoadToNative<GLfloat, 1>             );
-    InsertLoadFunction(&map, GL_DEPTH_COMPONENT32F, GL_FLOAT,                          DXGI_FORMAT_UNKNOWN,              UnimplementedLoadFunction            );
-    InsertLoadFunction(&map, GL_DEPTH24_STENCIL8,   GL_UNSIGNED_INT_24_8,              DXGI_FORMAT_R24G8_TYPELESS,       LoadR32ToR24G8                       );
-    InsertLoadFunction(&map, GL_DEPTH24_STENCIL8,   GL_UNSIGNED_INT_24_8,              DXGI_FORMAT_D24_UNORM_S8_UINT,    LoadR32ToR24G8                       );
-    InsertLoadFunction(&map, GL_DEPTH32F_STENCIL8,  GL_FLOAT_32_UNSIGNED_INT_24_8_REV, DXGI_FORMAT_R32G8X24_TYPELESS,    LoadToNative<GLuint, 2>              );
-    InsertLoadFunction(&map, GL_DEPTH32F_STENCIL8,  GL_FLOAT_32_UNSIGNED_INT_24_8_REV, DXGI_FORMAT_UNKNOWN,              UnimplementedLoadFunction            );
-    InsertLoadFunction(&map, GL_STENCIL_INDEX8,     DXGI_FORMAT_R24G8_TYPELESS,        DXGI_FORMAT_UNKNOWN,              UnimplementedLoadFunction            );
-    InsertLoadFunction(&map, GL_STENCIL_INDEX8,     DXGI_FORMAT_D24_UNORM_S8_UINT,     DXGI_FORMAT_UNKNOWN,              UnimplementedLoadFunction            );
-
-    // Unsized formats
-    // Load functions are unreachable because they are converted to sized internal formats based on
-    // the format and type before loading takes place.
-    InsertLoadFunction(&map, GL_RGBA,               GL_UNSIGNED_BYTE,                  DXGI_FORMAT_UNKNOWN,              UnreachableLoadFunction              );
-    InsertLoadFunction(&map, GL_RGBA,               GL_UNSIGNED_SHORT_4_4_4_4,         DXGI_FORMAT_UNKNOWN,              UnreachableLoadFunction              );
-    InsertLoadFunction(&map, GL_RGBA,               GL_UNSIGNED_SHORT_5_5_5_1,         DXGI_FORMAT_UNKNOWN,              UnreachableLoadFunction              );
-    InsertLoadFunction(&map, GL_RGB,                GL_UNSIGNED_BYTE,                  DXGI_FORMAT_UNKNOWN,              UnreachableLoadFunction              );
-    InsertLoadFunction(&map, GL_RGB,                GL_UNSIGNED_SHORT_5_6_5,           DXGI_FORMAT_UNKNOWN,              UnreachableLoadFunction              );
-    InsertLoadFunction(&map, GL_LUMINANCE_ALPHA,    GL_UNSIGNED_BYTE,                  DXGI_FORMAT_UNKNOWN,              UnreachableLoadFunction              );
-    InsertLoadFunction(&map, GL_LUMINANCE,          GL_UNSIGNED_BYTE,                  DXGI_FORMAT_UNKNOWN,              UnreachableLoadFunction              );
-    InsertLoadFunction(&map, GL_ALPHA,              GL_UNSIGNED_BYTE,                  DXGI_FORMAT_UNKNOWN,              UnreachableLoadFunction              );
-    InsertLoadFunction(&map, GL_BGRA_EXT,           GL_UNSIGNED_BYTE,                  DXGI_FORMAT_UNKNOWN,              UnreachableLoadFunction              );
-
-    // From GL_OES_texture_float
-    InsertLoadFunction(&map, GL_LUMINANCE_ALPHA,    GL_FLOAT,                          DXGI_FORMAT_R32G32B32A32_FLOAT,   LoadLA32FToRGBA32F                   );
-    InsertLoadFunction(&map, GL_LUMINANCE,          GL_FLOAT,                          DXGI_FORMAT_R32G32B32A32_FLOAT,   LoadL32FToRGBA32F                    );
-    InsertLoadFunction(&map, GL_ALPHA,              GL_FLOAT,                          DXGI_FORMAT_R32G32B32A32_FLOAT,   LoadA32FToRGBA32F                    );
-
-    // From GL_OES_texture_half_float
-    InsertLoadFunction(&map, GL_LUMINANCE_ALPHA,    GL_HALF_FLOAT,                     DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadLA16FToRGBA16F                   );
-    InsertLoadFunction(&map, GL_LUMINANCE_ALPHA,    GL_HALF_FLOAT_OES,                 DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadLA16FToRGBA16F                   );
-    InsertLoadFunction(&map, GL_LUMINANCE,          GL_HALF_FLOAT,                     DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadL16FToRGBA16F                    );
-    InsertLoadFunction(&map, GL_LUMINANCE,          GL_HALF_FLOAT_OES,                 DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadL16FToRGBA16F                    );
-    InsertLoadFunction(&map, GL_ALPHA,              GL_HALF_FLOAT,                     DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadA16FToRGBA16F                    );
-    InsertLoadFunction(&map, GL_ALPHA,              GL_HALF_FLOAT_OES,                 DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadA16FToRGBA16F                    );
-
-    // From GL_EXT_texture_storage
-    InsertLoadFunction(&map, GL_ALPHA8_EXT,             GL_UNSIGNED_BYTE,              DXGI_FORMAT_A8_UNORM,             LoadToNative<GLubyte, 1>             );
-    InsertLoadFunction(&map, GL_ALPHA8_EXT,             GL_UNSIGNED_BYTE,              DXGI_FORMAT_R8G8B8A8_UNORM,       LoadA8ToRGBA8                        );
-    InsertLoadFunction(&map, GL_LUMINANCE8_EXT,         GL_UNSIGNED_BYTE,              DXGI_FORMAT_UNKNOWN,              LoadL8ToRGBA8                        );
-    InsertLoadFunction(&map, GL_LUMINANCE8_ALPHA8_EXT,  GL_UNSIGNED_BYTE,              DXGI_FORMAT_UNKNOWN,              LoadLA8ToRGBA8                       );
-    InsertLoadFunction(&map, GL_ALPHA32F_EXT,           GL_FLOAT,                      DXGI_FORMAT_UNKNOWN,              LoadA32FToRGBA32F                    );
-    InsertLoadFunction(&map, GL_LUMINANCE32F_EXT,       GL_FLOAT,                      DXGI_FORMAT_UNKNOWN,              LoadL32FToRGBA32F                    );
-    InsertLoadFunction(&map, GL_LUMINANCE_ALPHA32F_EXT, GL_FLOAT,                      DXGI_FORMAT_UNKNOWN,              LoadLA32FToRGBA32F                   );
-    InsertLoadFunction(&map, GL_ALPHA16F_EXT,           GL_HALF_FLOAT,                 DXGI_FORMAT_UNKNOWN,              LoadA16FToRGBA16F                    );
-    InsertLoadFunction(&map, GL_ALPHA16F_EXT,           GL_HALF_FLOAT_OES,             DXGI_FORMAT_UNKNOWN,              LoadA16FToRGBA16F                    );
-    InsertLoadFunction(&map, GL_LUMINANCE16F_EXT,       GL_HALF_FLOAT,                 DXGI_FORMAT_UNKNOWN,              LoadL16FToRGBA16F                    );
-    InsertLoadFunction(&map, GL_LUMINANCE16F_EXT,       GL_HALF_FLOAT_OES,             DXGI_FORMAT_UNKNOWN,              LoadL16FToRGBA16F                    );
-    InsertLoadFunction(&map, GL_LUMINANCE_ALPHA16F_EXT, GL_HALF_FLOAT,                 DXGI_FORMAT_UNKNOWN,              LoadLA16FToRGBA16F                   );
-    InsertLoadFunction(&map, GL_LUMINANCE_ALPHA16F_EXT, GL_HALF_FLOAT_OES,             DXGI_FORMAT_UNKNOWN,              LoadLA16FToRGBA16F                   );
-
-    // From GL_ANGLE_depth_texture
-    InsertLoadFunction(&map, GL_DEPTH_COMPONENT32_OES,  GL_UNSIGNED_INT,               DXGI_FORMAT_UNKNOWN,              LoadR32ToR24G8                       );
-
-    // From GL_EXT_texture_format_BGRA8888
-    InsertLoadFunction(&map, GL_BGRA8_EXT,              GL_UNSIGNED_BYTE,                  DXGI_FORMAT_UNKNOWN,          LoadToNative<GLubyte, 4>             );
-    InsertLoadFunction(&map, GL_BGRA4_ANGLEX,           GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, DXGI_FORMAT_UNKNOWN,          LoadRGBA4ToRGBA8                     );
-    InsertLoadFunction(&map, GL_BGRA4_ANGLEX,           GL_UNSIGNED_BYTE,                  DXGI_FORMAT_UNKNOWN,          LoadToNative<GLubyte, 4>             );
-    InsertLoadFunction(&map, GL_BGR5_A1_ANGLEX,         GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, DXGI_FORMAT_UNKNOWN,          LoadRGB5A1ToRGBA8                    );
-    InsertLoadFunction(&map, GL_BGR5_A1_ANGLEX,         GL_UNSIGNED_BYTE,                  DXGI_FORMAT_UNKNOWN,          LoadToNative<GLubyte, 4>             );
-
-    // Compressed formats
-    // From ES 3.0.1 spec, table 3.16
-    //                      | Internal format                             | Type            | Load function                |
-    InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC,                        GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
-    InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC,                        GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
-    InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_R11_EAC,                 GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
-    InsertLoadFunction(&map, GL_COMPRESSED_RG11_EAC,                       GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
-    InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_RG11_EAC,                GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
-    InsertLoadFunction(&map, GL_COMPRESSED_RGB8_ETC2,                      GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
-    InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ETC2,                     GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
-    InsertLoadFunction(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,  GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
-    InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
-    InsertLoadFunction(&map, GL_COMPRESSED_RGBA8_ETC2_EAC,                 GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
-    InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,          GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
-
-    // From GL_EXT_texture_compression_dxt1
-    InsertLoadFunction(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,              GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        LoadCompressedToNative<4, 4,  8>     );
-    InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,             GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        LoadCompressedToNative<4, 4,  8>     );
-
-    // From GL_ANGLE_texture_compression_dxt3
-    InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,           GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        LoadCompressedToNative<4, 4, 16>     );
-
-    // From GL_ANGLE_texture_compression_dxt5
-    InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,           GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        LoadCompressedToNative<4, 4, 16>     );
-
-    return map;
-}
-
-// For sized GL internal formats, there are several possible corresponding D3D11 formats depending on device capabilities.
-// This map type allows querying for the DXGI texture formats to use for textures, SRVs, RTVs and DSVs given a GL internal format.
-typedef std::pair<FormatSupportFunction, TextureFormat> TextureFormatWithSupportFunction;
-typedef std::map<GLenum, std::vector<TextureFormatWithSupportFunction>> D3D11ES3FormatMap;
-
-TextureFormat::TextureFormat()
-    : texFormat(DXGI_FORMAT_UNKNOWN),
-      srvFormat(DXGI_FORMAT_UNKNOWN),
-      rtvFormat(DXGI_FORMAT_UNKNOWN),
-      dsvFormat(DXGI_FORMAT_UNKNOWN),
-      renderFormat(DXGI_FORMAT_UNKNOWN),
-      swizzleTexFormat(DXGI_FORMAT_UNKNOWN),
-      swizzleSRVFormat(DXGI_FORMAT_UNKNOWN),
-      swizzleRTVFormat(DXGI_FORMAT_UNKNOWN),
-      dataInitializerFunction(NULL),
-      loadFunctions()
-{
-}
-
-static inline void InsertD3D11FormatInfo(D3D11ES3FormatMap *formatMap, GLenum internalFormat, DXGI_FORMAT texFormat,
-                                         DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat,
-                                         FormatSupportFunction formatSupportFunction)
-{
-    TextureFormat info;
-    info.texFormat = texFormat;
-    info.srvFormat = srvFormat;
-    info.rtvFormat = rtvFormat;
-    info.dsvFormat = dsvFormat;
-
-    // Given a GL internal format, the renderFormat is the DSV format if it is depth- or stencil-renderable,
-    // the RTV format if it is color-renderable, and the (nonrenderable) texture format otherwise.
-    if (dsvFormat != DXGI_FORMAT_UNKNOWN)
-    {
-        info.renderFormat = dsvFormat;
-    }
-    else if (rtvFormat != DXGI_FORMAT_UNKNOWN)
-    {
-        info.renderFormat = rtvFormat;
-    }
-    else if (texFormat != DXGI_FORMAT_UNKNOWN)
-    {
-        info.renderFormat = texFormat;
-    }
-    else
-    {
-        info.renderFormat = DXGI_FORMAT_UNKNOWN;
-    }
-
-    // Compute the swizzle formats
-    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
-    if (internalFormat != GL_NONE && formatInfo.pixelBytes > 0)
-    {
-        if (formatInfo.componentCount != 4 || texFormat == DXGI_FORMAT_UNKNOWN ||
-            srvFormat == DXGI_FORMAT_UNKNOWN || rtvFormat == DXGI_FORMAT_UNKNOWN)
-        {
-            // Get the maximum sized component
-            unsigned int maxBits = 1;
-            if (formatInfo.compressed)
-            {
-                unsigned int compressedBitsPerBlock = formatInfo.pixelBytes * 8;
-                unsigned int blockSize = formatInfo.compressedBlockWidth * formatInfo.compressedBlockHeight;
-                maxBits = std::max(compressedBitsPerBlock / blockSize, maxBits);
-            }
-            else
-            {
-                maxBits = std::max(maxBits, formatInfo.alphaBits);
-                maxBits = std::max(maxBits, formatInfo.redBits);
-                maxBits = std::max(maxBits, formatInfo.greenBits);
-                maxBits = std::max(maxBits, formatInfo.blueBits);
-                maxBits = std::max(maxBits, formatInfo.luminanceBits);
-                maxBits = std::max(maxBits, formatInfo.depthBits);
-            }
-
-            maxBits = roundUp(maxBits, 8U);
-
-            static const SwizzleInfoMap swizzleMap = BuildSwizzleInfoMap();
-            SwizzleInfoMap::const_iterator swizzleIter = swizzleMap.find(SwizzleSizeType(maxBits, formatInfo.componentType));
-            ASSERT(swizzleIter != swizzleMap.end());
-
-            const SwizzleFormatInfo &swizzleInfo = swizzleIter->second;
-            info.swizzleTexFormat = swizzleInfo.mTexFormat;
-            info.swizzleSRVFormat = swizzleInfo.mSRVFormat;
-            info.swizzleRTVFormat = swizzleInfo.mRTVFormat;
-        }
-        else
-        {
-            // The original texture format is suitable for swizzle operations
-            info.swizzleTexFormat = texFormat;
-            info.swizzleSRVFormat = srvFormat;
-            info.swizzleRTVFormat = rtvFormat;
-        }
-    }
-    else
-    {
-        // Not possible to swizzle with this texture format since it is either unsized or GL_NONE
-        info.swizzleTexFormat = DXGI_FORMAT_UNKNOWN;
-        info.swizzleSRVFormat = DXGI_FORMAT_UNKNOWN;
-        info.swizzleRTVFormat = DXGI_FORMAT_UNKNOWN;
-    }
-
-    // Check if there is an initialization function for this texture format
-    static const InternalFormatInitializerMap initializerMap = BuildInternalFormatInitializerMap();
-    InternalFormatInitializerMap::const_iterator initializerIter = initializerMap.find(InitializeTextureFormatPair(internalFormat, texFormat));
-    info.dataInitializerFunction = (initializerIter != initializerMap.end()) ? initializerIter->second : NULL;
-
-    // Gather all the load functions for this internal format
-    static const D3D11LoadFunctionMap loadFunctions = BuildD3D11LoadFunctionMap();
-    D3D11LoadFunctionMap::const_iterator loadFunctionIter = loadFunctions.find(internalFormat);
-    if (loadFunctionIter != loadFunctions.end())
-    {
-        const std::vector<GLTypeDXGIFunctionPair> &loadFunctionVector = loadFunctionIter->second;
-        for (size_t i = 0; i < loadFunctionVector.size(); i++)
-        {
-            DxgiFormatLoadFunctionPair formatFuncPair = loadFunctionVector[i].second;
-            GLenum type = loadFunctionVector[i].first;
-            DXGI_FORMAT dxgiFormat = formatFuncPair.first;
-            rx::LoadImageFunction loadFunc = formatFuncPair.second;
-
-            if (dxgiFormat == texFormat || dxgiFormat == DXGI_FORMAT_UNKNOWN)
-            {
-                info.loadFunctions.insert(std::make_pair(type, loadFunc));
-            }
-        }
-    }
-
-    ASSERT(info.loadFunctions.size() != 0 || internalFormat == GL_NONE);
-
-    (*formatMap)[internalFormat].push_back(std::make_pair(formatSupportFunction, info));
-}
-
-static D3D11ES3FormatMap BuildD3D11FormatMap()
-{
-    D3D11ES3FormatMap map;
-
-    //                         | GL internal format  | D3D11 texture format            | D3D11 SRV format               | D3D11 RTV format               | D3D11 DSV format     | Requirements
-    InsertD3D11FormatInfo(&map, GL_NONE,              DXGI_FORMAT_UNKNOWN,              DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_R8,                DXGI_FORMAT_R8_UNORM,             DXGI_FORMAT_R8_UNORM,            DXGI_FORMAT_R8_UNORM,            DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_R8_SNORM,          DXGI_FORMAT_R8_SNORM,             DXGI_FORMAT_R8_SNORM,            DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RG8,               DXGI_FORMAT_R8G8_UNORM,           DXGI_FORMAT_R8G8_UNORM,          DXGI_FORMAT_R8G8_UNORM,          DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RG8_SNORM,         DXGI_FORMAT_R8G8_SNORM,           DXGI_FORMAT_R8G8_SNORM,          DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGB8,              DXGI_FORMAT_R8G8B8A8_UNORM,       DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGB8_SNORM,        DXGI_FORMAT_R8G8B8A8_SNORM,       DXGI_FORMAT_R8G8B8A8_SNORM,      DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGB565,            DXGI_FORMAT_R8G8B8A8_UNORM,       DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,   SupportsFormat<DXGI_FORMAT_B5G6R5_UNORM, false>);
-    InsertD3D11FormatInfo(&map, GL_RGB565,            DXGI_FORMAT_B5G6R5_UNORM,         DXGI_FORMAT_B5G6R5_UNORM,        DXGI_FORMAT_B5G6R5_UNORM,        DXGI_FORMAT_UNKNOWN,   SupportsFormat<DXGI_FORMAT_B5G6R5_UNORM, true> );
-    InsertD3D11FormatInfo(&map, GL_RGBA4,             DXGI_FORMAT_R8G8B8A8_UNORM,       DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,   SupportsFormat<DXGI_FORMAT_B4G4R4A4_UNORM, false>);
-    InsertD3D11FormatInfo(&map, GL_RGBA4,             DXGI_FORMAT_B4G4R4A4_UNORM,       DXGI_FORMAT_B4G4R4A4_UNORM,      DXGI_FORMAT_B4G4R4A4_UNORM,      DXGI_FORMAT_UNKNOWN,   SupportsFormat<DXGI_FORMAT_B4G4R4A4_UNORM, true> );
-    InsertD3D11FormatInfo(&map, GL_RGB5_A1,           DXGI_FORMAT_R8G8B8A8_UNORM,       DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,   SupportsFormat<DXGI_FORMAT_B5G5R5A1_UNORM, false>);
-    InsertD3D11FormatInfo(&map, GL_RGB5_A1,           DXGI_FORMAT_B5G5R5A1_UNORM,       DXGI_FORMAT_B5G5R5A1_UNORM,      DXGI_FORMAT_B5G5R5A1_UNORM,      DXGI_FORMAT_UNKNOWN,   SupportsFormat<DXGI_FORMAT_B5G5R5A1_UNORM, true> );
-    InsertD3D11FormatInfo(&map, GL_RGBA8,             DXGI_FORMAT_R8G8B8A8_UNORM,       DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGBA8_SNORM,       DXGI_FORMAT_R8G8B8A8_SNORM,       DXGI_FORMAT_R8G8B8A8_SNORM,      DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGB10_A2,          DXGI_FORMAT_R10G10B10A2_UNORM,    DXGI_FORMAT_R10G10B10A2_UNORM,   DXGI_FORMAT_R10G10B10A2_UNORM,   DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGB10_A2UI,        DXGI_FORMAT_R10G10B10A2_UINT,     DXGI_FORMAT_R10G10B10A2_UINT,    DXGI_FORMAT_R10G10B10A2_UINT,    DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_SRGB8,             DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,  DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_SRGB8_ALPHA8,      DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,  DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_R16F,              DXGI_FORMAT_R16_FLOAT,            DXGI_FORMAT_R16_FLOAT,           DXGI_FORMAT_R16_FLOAT,           DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RG16F,             DXGI_FORMAT_R16G16_FLOAT,         DXGI_FORMAT_R16G16_FLOAT,        DXGI_FORMAT_R16G16_FLOAT,        DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGB16F,            DXGI_FORMAT_R16G16B16A16_FLOAT,   DXGI_FORMAT_R16G16B16A16_FLOAT,  DXGI_FORMAT_R16G16B16A16_FLOAT,  DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGBA16F,           DXGI_FORMAT_R16G16B16A16_FLOAT,   DXGI_FORMAT_R16G16B16A16_FLOAT,  DXGI_FORMAT_R16G16B16A16_FLOAT,  DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_R32F,              DXGI_FORMAT_R32_FLOAT,            DXGI_FORMAT_R32_FLOAT,           DXGI_FORMAT_R32_FLOAT,           DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RG32F,             DXGI_FORMAT_R32G32_FLOAT,         DXGI_FORMAT_R32G32_FLOAT,        DXGI_FORMAT_R32G32_FLOAT,        DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGB32F,            DXGI_FORMAT_R32G32B32A32_FLOAT,   DXGI_FORMAT_R32G32B32A32_FLOAT,  DXGI_FORMAT_R32G32B32A32_FLOAT,  DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGBA32F,           DXGI_FORMAT_R32G32B32A32_FLOAT,   DXGI_FORMAT_R32G32B32A32_FLOAT,  DXGI_FORMAT_R32G32B32A32_FLOAT,  DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_R11F_G11F_B10F,    DXGI_FORMAT_R11G11B10_FLOAT,      DXGI_FORMAT_R11G11B10_FLOAT,     DXGI_FORMAT_R11G11B10_FLOAT,     DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGB9_E5,           DXGI_FORMAT_R9G9B9E5_SHAREDEXP,   DXGI_FORMAT_R9G9B9E5_SHAREDEXP,  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_R8I,               DXGI_FORMAT_R8_SINT,              DXGI_FORMAT_R8_SINT,             DXGI_FORMAT_R8_SINT,             DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_R8UI,              DXGI_FORMAT_R8_UINT,              DXGI_FORMAT_R8_UINT,             DXGI_FORMAT_R8_UINT,             DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_R16I,              DXGI_FORMAT_R16_SINT,             DXGI_FORMAT_R16_SINT,            DXGI_FORMAT_R16_SINT,            DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_R16UI,             DXGI_FORMAT_R16_UINT,             DXGI_FORMAT_R16_UINT,            DXGI_FORMAT_R16_UINT,            DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_R32I,              DXGI_FORMAT_R32_SINT,             DXGI_FORMAT_R32_SINT,            DXGI_FORMAT_R32_SINT,            DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_R32UI,             DXGI_FORMAT_R32_UINT,             DXGI_FORMAT_R32_UINT,            DXGI_FORMAT_R32_UINT,            DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RG8I,              DXGI_FORMAT_R8G8_SINT,            DXGI_FORMAT_R8G8_SINT,           DXGI_FORMAT_R8G8_SINT,           DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RG8UI,             DXGI_FORMAT_R8G8_UINT,            DXGI_FORMAT_R8G8_UINT,           DXGI_FORMAT_R8G8_UINT,           DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RG16I,             DXGI_FORMAT_R16G16_SINT,          DXGI_FORMAT_R16G16_SINT,         DXGI_FORMAT_R16G16_SINT,         DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RG16UI,            DXGI_FORMAT_R16G16_UINT,          DXGI_FORMAT_R16G16_UINT,         DXGI_FORMAT_R16G16_UINT,         DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RG32I,             DXGI_FORMAT_R32G32_SINT,          DXGI_FORMAT_R32G32_SINT,         DXGI_FORMAT_R32G32_SINT,         DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RG32UI,            DXGI_FORMAT_R32G32_UINT,          DXGI_FORMAT_R32G32_UINT,         DXGI_FORMAT_R32G32_UINT,         DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGB8I,             DXGI_FORMAT_R8G8B8A8_SINT,        DXGI_FORMAT_R8G8B8A8_SINT,       DXGI_FORMAT_R8G8B8A8_SINT,       DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGB8UI,            DXGI_FORMAT_R8G8B8A8_UINT,        DXGI_FORMAT_R8G8B8A8_UINT,       DXGI_FORMAT_R8G8B8A8_UINT,       DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGB16I,            DXGI_FORMAT_R16G16B16A16_SINT,    DXGI_FORMAT_R16G16B16A16_SINT,   DXGI_FORMAT_R16G16B16A16_SINT,   DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGB16UI,           DXGI_FORMAT_R16G16B16A16_UINT,    DXGI_FORMAT_R16G16B16A16_UINT,   DXGI_FORMAT_R16G16B16A16_UINT,   DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGB32I,            DXGI_FORMAT_R32G32B32A32_SINT,    DXGI_FORMAT_R32G32B32A32_SINT,   DXGI_FORMAT_R32G32B32A32_SINT,   DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGB32UI,           DXGI_FORMAT_R32G32B32A32_UINT,    DXGI_FORMAT_R32G32B32A32_UINT,   DXGI_FORMAT_R32G32B32A32_UINT,   DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGBA8I,            DXGI_FORMAT_R8G8B8A8_SINT,        DXGI_FORMAT_R8G8B8A8_SINT,       DXGI_FORMAT_R8G8B8A8_SINT,       DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGBA8UI,           DXGI_FORMAT_R8G8B8A8_UINT,        DXGI_FORMAT_R8G8B8A8_UINT,       DXGI_FORMAT_R8G8B8A8_UINT,       DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGBA16I,           DXGI_FORMAT_R16G16B16A16_SINT,    DXGI_FORMAT_R16G16B16A16_SINT,   DXGI_FORMAT_R16G16B16A16_SINT,   DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGBA16UI,          DXGI_FORMAT_R16G16B16A16_UINT,    DXGI_FORMAT_R16G16B16A16_UINT,   DXGI_FORMAT_R16G16B16A16_UINT,   DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGBA32I,           DXGI_FORMAT_R32G32B32A32_SINT,    DXGI_FORMAT_R32G32B32A32_SINT,   DXGI_FORMAT_R32G32B32A32_SINT,   DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-    InsertD3D11FormatInfo(&map, GL_RGBA32UI,          DXGI_FORMAT_R32G32B32A32_UINT,    DXGI_FORMAT_R32G32B32A32_UINT,   DXGI_FORMAT_R32G32B32A32_UINT,   DXGI_FORMAT_UNKNOWN,   AnyDevice  );
-
-    // Unsized formats, TODO: Are types of float and half float allowed for the unsized types? Would it change the DXGI format?
-    InsertD3D11FormatInfo(&map, GL_ALPHA,             DXGI_FORMAT_A8_UNORM,             DXGI_FORMAT_A8_UNORM,            DXGI_FORMAT_A8_UNORM,            DXGI_FORMAT_UNKNOWN,   OnlyFL10Plus );
-    InsertD3D11FormatInfo(&map, GL_ALPHA,             DXGI_FORMAT_R8G8B8A8_UNORM,       DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,   OnlyFL9_3    );
-    InsertD3D11FormatInfo(&map, GL_LUMINANCE,         DXGI_FORMAT_R8G8B8A8_UNORM,       DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,   AnyDevice    );
-    InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA,   DXGI_FORMAT_R8G8B8A8_UNORM,       DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,   AnyDevice    );
-    InsertD3D11FormatInfo(&map, GL_RGB,               DXGI_FORMAT_R8G8B8A8_UNORM,       DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,   AnyDevice    );
-    InsertD3D11FormatInfo(&map, GL_RGBA,              DXGI_FORMAT_R8G8B8A8_UNORM,       DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,   AnyDevice    );
-    InsertD3D11FormatInfo(&map, GL_BGRA_EXT,          DXGI_FORMAT_B8G8R8A8_UNORM,       DXGI_FORMAT_B8G8R8A8_UNORM,      DXGI_FORMAT_B8G8R8A8_UNORM,      DXGI_FORMAT_UNKNOWN,   AnyDevice    );
-
-    // From GL_EXT_texture_storage
-    //                           | GL internal format     | D3D11 texture format          | D3D11 SRV format                    | D3D11 RTV format              | D3D11 DSV format    | Requirements
-    InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT,             DXGI_FORMAT_A8_UNORM,           DXGI_FORMAT_A8_UNORM,                 DXGI_FORMAT_A8_UNORM,           DXGI_FORMAT_UNKNOWN,   OnlyFL10Plus);
-    InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT,             DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_UNKNOWN,   OnlyFL9_3   );
-    InsertD3D11FormatInfo(&map, GL_LUMINANCE8_EXT,         DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_UNKNOWN,   AnyDevice   );
-    InsertD3D11FormatInfo(&map, GL_ALPHA32F_EXT,           DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT,       DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN,   AnyDevice   );
-    InsertD3D11FormatInfo(&map, GL_LUMINANCE32F_EXT,       DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT,       DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN,   AnyDevice   );
-    InsertD3D11FormatInfo(&map, GL_ALPHA16F_EXT,           DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT,       DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN,   AnyDevice   );
-    InsertD3D11FormatInfo(&map, GL_LUMINANCE16F_EXT,       DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT,       DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN,   AnyDevice   );
-    InsertD3D11FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT,  DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_UNKNOWN,   AnyDevice   );
-    InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT,       DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN,   AnyDevice   );
-    InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA16F_EXT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT,       DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN,   AnyDevice   );
-    InsertD3D11FormatInfo(&map, GL_BGRA8_EXT,              DXGI_FORMAT_B8G8R8A8_UNORM,     DXGI_FORMAT_B8G8R8A8_UNORM,           DXGI_FORMAT_B8G8R8A8_UNORM,     DXGI_FORMAT_UNKNOWN,   AnyDevice   );
-    InsertD3D11FormatInfo(&map, GL_BGRA4_ANGLEX,           DXGI_FORMAT_B8G8R8A8_UNORM,     DXGI_FORMAT_B8G8R8A8_UNORM,           DXGI_FORMAT_B8G8R8A8_UNORM,     DXGI_FORMAT_UNKNOWN,   AnyDevice   );
-    InsertD3D11FormatInfo(&map, GL_BGR5_A1_ANGLEX,         DXGI_FORMAT_B8G8R8A8_UNORM,     DXGI_FORMAT_B8G8R8A8_UNORM,           DXGI_FORMAT_B8G8R8A8_UNORM,     DXGI_FORMAT_UNKNOWN,   AnyDevice   );
-
-    // Depth stencil formats
-    InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT16,     DXGI_FORMAT_R16_TYPELESS,        DXGI_FORMAT_R16_UNORM,                DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_D16_UNORM,            OnlyFL10Plus);
-    InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT16,     DXGI_FORMAT_D16_UNORM,           DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_D16_UNORM,            OnlyFL9_3   );
-    InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT24,     DXGI_FORMAT_R24G8_TYPELESS,      DXGI_FORMAT_R24_UNORM_X8_TYPELESS,    DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_D24_UNORM_S8_UINT,    OnlyFL10Plus);
-    InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT24,     DXGI_FORMAT_D24_UNORM_S8_UINT,   DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_D24_UNORM_S8_UINT,    OnlyFL9_3   );
-    InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT32F,    DXGI_FORMAT_R32_TYPELESS,        DXGI_FORMAT_R32_FLOAT,                DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_D32_FLOAT,            OnlyFL10Plus);
-    InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT32F,    DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,              OnlyFL9_3   );
-    InsertD3D11FormatInfo(&map, GL_DEPTH24_STENCIL8,      DXGI_FORMAT_R24G8_TYPELESS,      DXGI_FORMAT_R24_UNORM_X8_TYPELESS,    DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_D24_UNORM_S8_UINT,    OnlyFL10Plus);
-    InsertD3D11FormatInfo(&map, GL_DEPTH24_STENCIL8,      DXGI_FORMAT_D24_UNORM_S8_UINT,   DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_D24_UNORM_S8_UINT,    OnlyFL9_3   );
-    InsertD3D11FormatInfo(&map, GL_DEPTH32F_STENCIL8,     DXGI_FORMAT_R32G8X24_TYPELESS,   DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_D32_FLOAT_S8X24_UINT, OnlyFL10Plus);
-    InsertD3D11FormatInfo(&map, GL_DEPTH32F_STENCIL8,     DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,              OnlyFL9_3   );
-    InsertD3D11FormatInfo(&map, GL_STENCIL_INDEX8,        DXGI_FORMAT_R24G8_TYPELESS,      DXGI_FORMAT_X24_TYPELESS_G8_UINT,     DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_D24_UNORM_S8_UINT,    OnlyFL10Plus);
-    InsertD3D11FormatInfo(&map, GL_STENCIL_INDEX8,        DXGI_FORMAT_D24_UNORM_S8_UINT,   DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_D24_UNORM_S8_UINT,    OnlyFL9_3   );
-
-    // From GL_ANGLE_depth_texture
-    // Since D3D11 doesn't have a D32_UNORM format, use D24S8 which has comparable precision and matches the ES3 format.
-    InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT32_OES, DXGI_FORMAT_R24G8_TYPELESS,      DXGI_FORMAT_R24_UNORM_X8_TYPELESS,    DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_D24_UNORM_S8_UINT,    OnlyFL10Plus);
-
-    // Compressed formats, From ES 3.0.1 spec, table 3.16
-    //                           | GL internal format                        | D3D11 texture format | D3D11 SRV format     | D3D11 RTV format    | D3D11 DSV format    | Requirements
-    InsertD3D11FormatInfo(&map, GL_COMPRESSED_R11_EAC,                        DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,  DXGI_FORMAT_UNKNOWN,  OnlyFL10Plus);
-    InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_R11_EAC,                 DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,  DXGI_FORMAT_UNKNOWN,  OnlyFL10Plus);
-    InsertD3D11FormatInfo(&map, GL_COMPRESSED_RG11_EAC,                       DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,  DXGI_FORMAT_UNKNOWN,  OnlyFL10Plus);
-    InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_RG11_EAC,                DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,  DXGI_FORMAT_UNKNOWN,  OnlyFL10Plus);
-    InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_ETC2,                      DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,  DXGI_FORMAT_UNKNOWN,  OnlyFL10Plus);
-    InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ETC2,                     DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,  DXGI_FORMAT_UNKNOWN,  OnlyFL10Plus);
-    InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,  DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,  DXGI_FORMAT_UNKNOWN,  OnlyFL10Plus);
-    InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,  DXGI_FORMAT_UNKNOWN,  OnlyFL10Plus);
-    InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA8_ETC2_EAC,                 DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,  DXGI_FORMAT_UNKNOWN,  OnlyFL10Plus);
-    InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,          DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,   DXGI_FORMAT_UNKNOWN,  DXGI_FORMAT_UNKNOWN,  OnlyFL10Plus);
-
-    // From GL_EXT_texture_compression_dxt1
-    InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,              DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN,  DXGI_FORMAT_UNKNOWN,  AnyDevice);
-    InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,             DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN,  DXGI_FORMAT_UNKNOWN,  AnyDevice);
-
-    // From GL_ANGLE_texture_compression_dxt3
-    InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,           DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_UNKNOWN,  DXGI_FORMAT_UNKNOWN,  AnyDevice);
-
-    // From GL_ANGLE_texture_compression_dxt5
-    InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,           DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_UNKNOWN,  DXGI_FORMAT_UNKNOWN,  AnyDevice);
-
-    return map;
-}
-
-const TextureFormat &GetTextureFormatInfo(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps)
-{
-    static const D3D11ES3FormatMap formatMap = BuildD3D11FormatMap();
-
-    D3D11ES3FormatMap::const_iterator iter = formatMap.find(internalFormat);
-    if (iter != formatMap.end())
-    {
-        const std::vector<TextureFormatWithSupportFunction> &formatVector = iter->second;
-        for (size_t i = 0; i < formatVector.size(); i++)
-        {
-            const FormatSupportFunction supportFunction = formatVector[i].first;
-            const TextureFormat &textureFormat = formatVector[i].second;
-
-            if (supportFunction(renderer11DeviceCaps))
-            {
-                return textureFormat;
-            }
-        }
-    }
-
-    static const TextureFormat defaultInfo;
-    return defaultInfo;
-}
-
 typedef std::map<gl::VertexFormatType, VertexFormat> D3D11VertexFormatInfoMap;
 typedef std::pair<gl::VertexFormatType, VertexFormat> D3D11VertexFormatPair;
 
 VertexFormat::VertexFormat()
     : conversionType(VERTEX_CONVERT_NONE),
       nativeFormat(DXGI_FORMAT_UNKNOWN),
       copyFunction(NULL)
 {
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h
@@ -55,47 +55,27 @@ struct DXGIFormat
     FastCopyFunctionMap fastCopyFunctions;
 
     NativeMipmapGenerationSupportFunction nativeMipmapSupport;
 
     ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const;
 };
 const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format);
 
-struct TextureFormat
-{
-    TextureFormat();
-
-    DXGI_FORMAT texFormat;
-    DXGI_FORMAT srvFormat;
-    DXGI_FORMAT rtvFormat;
-    DXGI_FORMAT dsvFormat;
-    DXGI_FORMAT renderFormat;
-
-    DXGI_FORMAT swizzleTexFormat;
-    DXGI_FORMAT swizzleSRVFormat;
-    DXGI_FORMAT swizzleRTVFormat;
-
-    InitializeTextureDataFunction dataInitializerFunction;
-
-    typedef std::map<GLenum, LoadImageFunction> LoadFunctionMap;
-    LoadFunctionMap loadFunctions;
-};
-const TextureFormat &GetTextureFormatInfo(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps);
-
 struct VertexFormat
 {
     VertexFormat();
     VertexFormat(VertexConversionType conversionType,
                  DXGI_FORMAT nativeFormat,
                  VertexCopyFunction copyFunction);
 
     VertexConversionType conversionType;
     DXGI_FORMAT nativeFormat;
     VertexCopyFunction copyFunction;
 };
-const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType, D3D_FEATURE_LEVEL featureLevel);
+const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType,
+                                        D3D_FEATURE_LEVEL featureLevel);
 
-}
+}  // namespace d3d11
 
-}
+}  // namespace rx
 
 #endif // LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -7,25 +7,26 @@
 // renderer11_utils.cpp: Conversion functions and other utility routines
 // specific to the D3D11 renderer.
 
 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
 
 #include <algorithm>
 
 #include "common/debug.h"
+#include "libANGLE/formatutils.h"
 #include "libANGLE/Framebuffer.h"
 #include "libANGLE/Program.h"
-#include "libANGLE/formatutils.h"
-#include "libANGLE/renderer/d3d/WorkaroundsD3D.h"
-#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
-#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
-#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/WorkaroundsD3D.h"
 
 namespace rx
 {
 
 namespace gl_d3d11
 {
 
 D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha)
@@ -1207,16 +1208,18 @@ void GenerateCaps(ID3D11Device *device, 
     extensions->shaderTextureLOD = GetShaderTextureLODSupport(featureLevel);
     extensions->fragDepth = true;
     extensions->textureUsage = true; // This could be false since it has no effect in D3D11
     extensions->discardFramebuffer = false; // TODO: enable this once BUG:497445 is fixed (Chrome WebGL video tests fail with this extension active)
     extensions->translatedShaderSource = true;
     extensions->fboRenderMipmap = false;
     extensions->debugMarker = true;
     extensions->eglImage                 = true;
+    extensions->unpackSubimage           = true;
+    extensions->packSubimage             = true;
 
     // D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing.
     // D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't support gl_FrontFacing.
     limitations->noFrontFacingSupport = (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
 
     // D3D11 Feature Level 9_3 doesn't support alpha-to-coverage
     limitations->noSampleAlphaToCoverageSupport = (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
 
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.cpp
@@ -0,0 +1,118 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// swizzle_format_info:
+//   Provides information for swizzle format and a map from type->formatinfo
+//
+
+#include "libANGLE/renderer/d3d/d3d11/swizzle_format_info.h"
+
+#include <GLES3/gl3.h>
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+SwizzleSizeType::SwizzleSizeType() : maxComponentSize(0), componentType(GL_NONE)
+{
+}
+
+SwizzleSizeType::SwizzleSizeType(size_t maxComponentSize, GLenum componentType)
+    : maxComponentSize(maxComponentSize), componentType(componentType)
+{
+}
+
+bool SwizzleSizeType::operator<(const SwizzleSizeType &other) const
+{
+    return (maxComponentSize != other.maxComponentSize)
+               ? (maxComponentSize < other.maxComponentSize)
+               : (componentType < other.componentType);
+}
+
+SwizzleFormatInfo::SwizzleFormatInfo()
+    : mTexFormat(DXGI_FORMAT_UNKNOWN),
+      mSRVFormat(DXGI_FORMAT_UNKNOWN),
+      mRTVFormat(DXGI_FORMAT_UNKNOWN)
+{
+}
+
+SwizzleFormatInfo::SwizzleFormatInfo(DXGI_FORMAT texFormat,
+                                     DXGI_FORMAT srvFormat,
+                                     DXGI_FORMAT rtvFormat)
+    : mTexFormat(texFormat), mSRVFormat(srvFormat), mRTVFormat(rtvFormat)
+{
+}
+
+typedef std::pair<SwizzleSizeType, SwizzleFormatInfo> SwizzleInfoPair;
+
+const SwizzleInfoMap &BuildSwizzleInfoMap()
+{
+    static SwizzleInfoMap map;
+
+    map.insert(
+        SwizzleInfoPair(SwizzleSizeType(8, GL_UNSIGNED_NORMALIZED),
+                        SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM,
+                                          DXGI_FORMAT_R8G8B8A8_UNORM)));
+    map.insert(SwizzleInfoPair(
+        SwizzleSizeType(16, GL_UNSIGNED_NORMALIZED),
+        SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM,
+                          DXGI_FORMAT_R16G16B16A16_UNORM)));
+    map.insert(SwizzleInfoPair(
+        SwizzleSizeType(24, GL_UNSIGNED_NORMALIZED),
+        SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT,
+                          DXGI_FORMAT_R32G32B32A32_FLOAT)));
+    map.insert(SwizzleInfoPair(
+        SwizzleSizeType(32, GL_UNSIGNED_NORMALIZED),
+        SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT,
+                          DXGI_FORMAT_R32G32B32A32_FLOAT)));
+
+    map.insert(
+        SwizzleInfoPair(SwizzleSizeType(8, GL_SIGNED_NORMALIZED),
+                        SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM,
+                                          DXGI_FORMAT_R8G8B8A8_SNORM)));
+
+    map.insert(SwizzleInfoPair(
+        SwizzleSizeType(16, GL_FLOAT),
+        SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT,
+                          DXGI_FORMAT_R16G16B16A16_FLOAT)));
+    map.insert(SwizzleInfoPair(
+        SwizzleSizeType(32, GL_FLOAT),
+        SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT,
+                          DXGI_FORMAT_R32G32B32A32_FLOAT)));
+
+    map.insert(
+        SwizzleInfoPair(SwizzleSizeType(8, GL_UNSIGNED_INT),
+                        SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT,
+                                          DXGI_FORMAT_R8G8B8A8_UINT)));
+    map.insert(SwizzleInfoPair(
+        SwizzleSizeType(16, GL_UNSIGNED_INT),
+        SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT,
+                          DXGI_FORMAT_R16G16B16A16_UINT)));
+    map.insert(SwizzleInfoPair(
+        SwizzleSizeType(32, GL_UNSIGNED_INT),
+        SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT,
+                          DXGI_FORMAT_R32G32B32A32_UINT)));
+
+    map.insert(
+        SwizzleInfoPair(SwizzleSizeType(8, GL_INT),
+                        SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT,
+                                          DXGI_FORMAT_R8G8B8A8_SINT)));
+    map.insert(SwizzleInfoPair(
+        SwizzleSizeType(16, GL_INT),
+        SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT,
+                          DXGI_FORMAT_R16G16B16A16_SINT)));
+    map.insert(SwizzleInfoPair(
+        SwizzleSizeType(32, GL_INT),
+        SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT,
+                          DXGI_FORMAT_R32G32B32A32_SINT)));
+
+    return map;
+}
+
+}  // namespace d3d11
+
+}  // namespace rx
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h
@@ -0,0 +1,53 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// swizzle_format_info:
+//   Provides information for swizzle format and a map from type->formatinfo
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_SWIZZLEFORMATINFO_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_SWIZZLEFORMATINFO_H_
+
+#include <GLES2/gl2.h>
+#include <map>
+
+#include "common/platform.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+struct SwizzleSizeType
+{
+    size_t maxComponentSize;
+    GLenum componentType;
+
+    SwizzleSizeType();
+    SwizzleSizeType(size_t maxComponentSize, GLenum componentType);
+
+    bool operator<(const SwizzleSizeType &other) const;
+};
+
+struct SwizzleFormatInfo
+{
+    DXGI_FORMAT mTexFormat;
+    DXGI_FORMAT mSRVFormat;
+    DXGI_FORMAT mRTVFormat;
+
+    SwizzleFormatInfo();
+    SwizzleFormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat);
+};
+
+typedef std::map<SwizzleSizeType, SwizzleFormatInfo> SwizzleInfoMap;
+
+const SwizzleInfoMap &BuildSwizzleInfoMap();
+
+}  // namespace d3d11
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_D3D11_SWIZZLEFORMATINFO_H_
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp
@@ -0,0 +1,411 @@
+
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// texture_format_table:
+//   Queries for full textureFormat information based in internalFormat
+//
+
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/swizzle_format_info.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_util.h"
+#include "libANGLE/renderer/d3d/loadimage.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+namespace
+{
+
+typedef bool (*FormatSupportFunction)(const Renderer11DeviceCaps &);
+
+bool AnyDevice(const Renderer11DeviceCaps &deviceCaps)
+{
+    return true;
+}
+
+bool OnlyFL10Plus(const Renderer11DeviceCaps &deviceCaps)
+{
+    return (deviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0);
+}
+
+bool OnlyFL9_3(const Renderer11DeviceCaps &deviceCaps)
+{
+    return (deviceCaps.featureLevel == D3D_FEATURE_LEVEL_9_3);
+}
+
+template <DXGI_FORMAT format, bool requireSupport>
+bool SupportsFormat(const Renderer11DeviceCaps &deviceCaps)
+{
+    // Must support texture, SRV and RTV support
+    UINT mustSupport = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE |
+                       D3D11_FORMAT_SUPPORT_SHADER_SAMPLE | D3D11_FORMAT_SUPPORT_MIP |
+                       D3D11_FORMAT_SUPPORT_RENDER_TARGET;
+
+    if (d3d11_gl::GetMaximumClientVersion(deviceCaps.featureLevel) > 2)
+    {
+        mustSupport |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
+    }
+
+    bool fullSupport = false;
+    if (format == DXGI_FORMAT_B5G6R5_UNORM)
+    {
+        // All hardware that supports DXGI_FORMAT_B5G6R5_UNORM should support autogen mipmaps, but
+        // check anyway.
+        mustSupport |= D3D11_FORMAT_SUPPORT_MIP_AUTOGEN;
+        fullSupport = ((deviceCaps.B5G6R5support & mustSupport) == mustSupport);
+    }
+    else if (format == DXGI_FORMAT_B4G4R4A4_UNORM)
+    {
+        fullSupport = ((deviceCaps.B4G4R4A4support & mustSupport) == mustSupport);
+    }
+    else if (format == DXGI_FORMAT_B5G5R5A1_UNORM)
+    {
+        fullSupport = ((deviceCaps.B5G5R5A1support & mustSupport) == mustSupport);
+    }
+    else
+    {
+        UNREACHABLE();
+        return false;
+    }
+
+    // This 'SupportsFormat' function is used by individual entries in the D3D11 Format Map below,
+    // which maps GL formats to DXGI formats.
+    if (requireSupport)
+    {
+        // This means that ANGLE would like to use the entry in the map if the inputted DXGI format
+        // *IS* supported.
+        // e.g. the entry might map GL_RGB5_A1 to DXGI_FORMAT_B5G5R5A1, which should only be used if
+        // DXGI_FORMAT_B5G5R5A1 is supported.
+        // In this case, we should only return 'true' if the format *IS* supported.
+        return fullSupport;
+    }
+    else
+    {
+        // This means that ANGLE would like to use the entry in the map if the inputted DXGI format
+        // *ISN'T* supported.
+        // This might be a fallback entry. e.g. for ANGLE to use DXGI_FORMAT_R8G8B8A8_UNORM if
+        // DXGI_FORMAT_B5G5R5A1 isn't supported.
+        // In this case, we should only return 'true' if the format *ISN'T* supported.
+        return !fullSupport;
+    }
+}
+
+// End Format Support Functions
+
+// For sized GL internal formats, there are several possible corresponding D3D11 formats depending
+// on device capabilities.
+// This map type allows querying for the DXGI texture formats to use for textures, SRVs, RTVs and
+// DSVs given a GL internal format.
+typedef std::pair<FormatSupportFunction, TextureFormat> TextureFormatWithSupportFunction;
+typedef std::map<GLenum, std::vector<TextureFormatWithSupportFunction>> D3D11ES3FormatMap;
+
+inline void InsertD3D11FormatInfo(D3D11ES3FormatMap *formatMap,
+                                  GLenum internalFormat,
+                                  DXGI_FORMAT texFormat,
+                                  DXGI_FORMAT srvFormat,
+                                  DXGI_FORMAT rtvFormat,
+                                  DXGI_FORMAT dsvFormat,
+                                  FormatSupportFunction formatSupportFunction)
+{
+    TextureFormat info;
+    info.texFormat = texFormat;
+    info.srvFormat = srvFormat;
+    info.rtvFormat = rtvFormat;
+    info.dsvFormat = dsvFormat;
+
+    // Given a GL internal format, the renderFormat is the DSV format if it is depth- or
+    // stencil-renderable,
+    // the RTV format if it is color-renderable, and the (nonrenderable) texture format otherwise.
+    if (dsvFormat != DXGI_FORMAT_UNKNOWN)
+    {
+        info.renderFormat = dsvFormat;
+    }
+    else if (rtvFormat != DXGI_FORMAT_UNKNOWN)
+    {
+        info.renderFormat = rtvFormat;
+    }
+    else if (texFormat != DXGI_FORMAT_UNKNOWN)
+    {
+        info.renderFormat = texFormat;
+    }
+    else
+    {
+        info.renderFormat = DXGI_FORMAT_UNKNOWN;
+    }
+
+    // Compute the swizzle formats
+    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+    if (internalFormat != GL_NONE && formatInfo.pixelBytes > 0)
+    {
+        if (formatInfo.componentCount != 4 || texFormat == DXGI_FORMAT_UNKNOWN ||
+            srvFormat == DXGI_FORMAT_UNKNOWN || rtvFormat == DXGI_FORMAT_UNKNOWN)
+        {
+            // Get the maximum sized component
+            unsigned int maxBits = 1;
+            if (formatInfo.compressed)
+            {
+                unsigned int compressedBitsPerBlock = formatInfo.pixelBytes * 8;
+                unsigned int blockSize =
+                    formatInfo.compressedBlockWidth * formatInfo.compressedBlockHeight;
+                maxBits = std::max(compressedBitsPerBlock / blockSize, maxBits);
+            }
+            else
+            {
+                maxBits = std::max(maxBits, formatInfo.alphaBits);
+                maxBits = std::max(maxBits, formatInfo.redBits);
+                maxBits = std::max(maxBits, formatInfo.greenBits);
+                maxBits = std::max(maxBits, formatInfo.blueBits);
+                maxBits = std::max(maxBits, formatInfo.luminanceBits);
+                maxBits = std::max(maxBits, formatInfo.depthBits);
+            }
+
+            maxBits = roundUp(maxBits, 8U);
+
+            static const SwizzleInfoMap &swizzleMap = BuildSwizzleInfoMap();
+            SwizzleInfoMap::const_iterator swizzleIter =
+                swizzleMap.find(SwizzleSizeType(maxBits, formatInfo.componentType));
+
+            // Handle the odd case where we might find an invalid swizzle key.
+            // This should never happen, but it's hard to prove, so add a fail-safe.
+            ASSERT(swizzleIter != swizzleMap.end());
+            if (swizzleIter != swizzleMap.end())
+            {
+                const SwizzleFormatInfo &swizzleInfo = swizzleIter->second;
+                info.swizzleTexFormat                = swizzleInfo.mTexFormat;
+                info.swizzleSRVFormat                = swizzleInfo.mSRVFormat;
+                info.swizzleRTVFormat                = swizzleInfo.mRTVFormat;
+            }
+        }
+        else
+        {
+            // The original texture format is suitable for swizzle operations
+            info.swizzleTexFormat = texFormat;
+            info.swizzleSRVFormat = srvFormat;
+            info.swizzleRTVFormat = rtvFormat;
+        }
+    }
+    else
+    {
+        // Not possible to swizzle with this texture format since it is either unsized or GL_NONE
+        info.swizzleTexFormat = DXGI_FORMAT_UNKNOWN;
+        info.swizzleSRVFormat = DXGI_FORMAT_UNKNOWN;
+        info.swizzleRTVFormat = DXGI_FORMAT_UNKNOWN;
+    }
+
+    // Check if there is an initialization function for this texture format
+    static const InternalFormatInitializerMap &initializerMap = BuildInternalFormatInitializerMap();
+    auto initializerIter =
+        initializerMap.find(InitializeTextureFormatPair(internalFormat, texFormat));
+    info.dataInitializerFunction =
+        (initializerIter != initializerMap.end()) ? initializerIter->second : NULL;
+
+    // Gather all the load functions for this internal format
+    static const D3D11LoadFunctionMap &loadFunctions = BuildD3D11LoadFunctionMap();
+    auto loadFunctionIter = loadFunctions.find(internalFormat);
+    if (loadFunctionIter != loadFunctions.end())
+    {
+        const std::vector<GLTypeDXGIFunctionPair> &loadFunctionVector = loadFunctionIter->second;
+        for (size_t i = 0; i < loadFunctionVector.size(); i++)
+        {
+            DxgiFormatLoadFunctionPair formatFuncPair = loadFunctionVector[i].second;
+            GLenum type                               = loadFunctionVector[i].first;
+            DXGI_FORMAT dxgiFormat                    = formatFuncPair.first;
+            rx::LoadImageFunction loadFunc            = formatFuncPair.second;
+
+            if (dxgiFormat == texFormat || dxgiFormat == DXGI_FORMAT_UNKNOWN)
+            {
+                info.loadFunctions.insert(std::make_pair(type, loadFunc));
+            }
+        }
+    }
+
+    ASSERT(info.loadFunctions.size() != 0 || internalFormat == GL_NONE);
+
+    (*formatMap)[internalFormat].push_back(std::make_pair(formatSupportFunction, info));
+}
+
+const D3D11ES3FormatMap &BuildD3D11FormatMap()
+{
+    static D3D11ES3FormatMap map;
+
+    // clang-format off
+    //                         | GL internal format                          | D3D11 texture format           | D3D11 SRV format                    | D3D11 RTV format               | D3D11 DSV format                | Requirements
+    InsertD3D11FormatInfo(&map, GL_NONE,                                      DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_R8,                                        DXGI_FORMAT_R8_UNORM,            DXGI_FORMAT_R8_UNORM,                 DXGI_FORMAT_R8_UNORM,            DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_R8_SNORM,                                  DXGI_FORMAT_R8_SNORM,            DXGI_FORMAT_R8_SNORM,                 DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RG8,                                       DXGI_FORMAT_R8G8_UNORM,          DXGI_FORMAT_R8G8_UNORM,               DXGI_FORMAT_R8G8_UNORM,          DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RG8_SNORM,                                 DXGI_FORMAT_R8G8_SNORM,          DXGI_FORMAT_R8G8_SNORM,               DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGB8,                                      DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGB8_SNORM,                                DXGI_FORMAT_R8G8B8A8_SNORM,      DXGI_FORMAT_R8G8B8A8_SNORM,           DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGB565,                                    DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,              SupportsFormat<DXGI_FORMAT_B5G6R5_UNORM, false>);
+    InsertD3D11FormatInfo(&map, GL_RGB565,                                    DXGI_FORMAT_B5G6R5_UNORM,        DXGI_FORMAT_B5G6R5_UNORM,             DXGI_FORMAT_B5G6R5_UNORM,        DXGI_FORMAT_UNKNOWN,              SupportsFormat<DXGI_FORMAT_B5G6R5_UNORM, true>);
+    InsertD3D11FormatInfo(&map, GL_RGBA4,                                     DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,              SupportsFormat<DXGI_FORMAT_B4G4R4A4_UNORM, false>);
+    InsertD3D11FormatInfo(&map, GL_RGBA4,                                     DXGI_FORMAT_B4G4R4A4_UNORM,      DXGI_FORMAT_B4G4R4A4_UNORM,           DXGI_FORMAT_B4G4R4A4_UNORM,      DXGI_FORMAT_UNKNOWN,              SupportsFormat<DXGI_FORMAT_B4G4R4A4_UNORM, true>);
+    InsertD3D11FormatInfo(&map, GL_RGB5_A1,                                   DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,              SupportsFormat<DXGI_FORMAT_B5G5R5A1_UNORM, false>);
+    InsertD3D11FormatInfo(&map, GL_RGB5_A1,                                   DXGI_FORMAT_B5G5R5A1_UNORM,      DXGI_FORMAT_B5G5R5A1_UNORM,           DXGI_FORMAT_B5G5R5A1_UNORM,      DXGI_FORMAT_UNKNOWN,              SupportsFormat<DXGI_FORMAT_B5G5R5A1_UNORM, true>);
+    InsertD3D11FormatInfo(&map, GL_RGBA8,                                     DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGBA8_SNORM,                               DXGI_FORMAT_R8G8B8A8_SNORM,      DXGI_FORMAT_R8G8B8A8_SNORM,           DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGB10_A2,                                  DXGI_FORMAT_R10G10B10A2_UNORM,   DXGI_FORMAT_R10G10B10A2_UNORM,        DXGI_FORMAT_R10G10B10A2_UNORM,   DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGB10_A2UI,                                DXGI_FORMAT_R10G10B10A2_UINT,    DXGI_FORMAT_R10G10B10A2_UINT,         DXGI_FORMAT_R10G10B10A2_UINT,    DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_SRGB8,                                     DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,      DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_SRGB8_ALPHA8,                              DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,      DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_R16F,                                      DXGI_FORMAT_R16_FLOAT,           DXGI_FORMAT_R16_FLOAT,                DXGI_FORMAT_R16_FLOAT,           DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RG16F,                                     DXGI_FORMAT_R16G16_FLOAT,        DXGI_FORMAT_R16G16_FLOAT,             DXGI_FORMAT_R16G16_FLOAT,        DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGB16F,                                    DXGI_FORMAT_R16G16B16A16_FLOAT,  DXGI_FORMAT_R16G16B16A16_FLOAT,       DXGI_FORMAT_R16G16B16A16_FLOAT,  DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGBA16F,                                   DXGI_FORMAT_R16G16B16A16_FLOAT,  DXGI_FORMAT_R16G16B16A16_FLOAT,       DXGI_FORMAT_R16G16B16A16_FLOAT,  DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_R32F,                                      DXGI_FORMAT_R32_FLOAT,           DXGI_FORMAT_R32_FLOAT,                DXGI_FORMAT_R32_FLOAT,           DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RG32F,                                     DXGI_FORMAT_R32G32_FLOAT,        DXGI_FORMAT_R32G32_FLOAT,             DXGI_FORMAT_R32G32_FLOAT,        DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGB32F,                                    DXGI_FORMAT_R32G32B32A32_FLOAT,  DXGI_FORMAT_R32G32B32A32_FLOAT,       DXGI_FORMAT_R32G32B32A32_FLOAT,  DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGBA32F,                                   DXGI_FORMAT_R32G32B32A32_FLOAT,  DXGI_FORMAT_R32G32B32A32_FLOAT,       DXGI_FORMAT_R32G32B32A32_FLOAT,  DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_R11F_G11F_B10F,                            DXGI_FORMAT_R11G11B10_FLOAT,     DXGI_FORMAT_R11G11B10_FLOAT,          DXGI_FORMAT_R11G11B10_FLOAT,     DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGB9_E5,                                   DXGI_FORMAT_R9G9B9E5_SHAREDEXP,  DXGI_FORMAT_R9G9B9E5_SHAREDEXP,       DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_R8I,                                       DXGI_FORMAT_R8_SINT,             DXGI_FORMAT_R8_SINT,                  DXGI_FORMAT_R8_SINT,             DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_R8UI,                                      DXGI_FORMAT_R8_UINT,             DXGI_FORMAT_R8_UINT,                  DXGI_FORMAT_R8_UINT,             DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_R16I,                                      DXGI_FORMAT_R16_SINT,            DXGI_FORMAT_R16_SINT,                 DXGI_FORMAT_R16_SINT,            DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_R16UI,                                     DXGI_FORMAT_R16_UINT,            DXGI_FORMAT_R16_UINT,                 DXGI_FORMAT_R16_UINT,            DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_R32I,                                      DXGI_FORMAT_R32_SINT,            DXGI_FORMAT_R32_SINT,                 DXGI_FORMAT_R32_SINT,            DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_R32UI,                                     DXGI_FORMAT_R32_UINT,            DXGI_FORMAT_R32_UINT,                 DXGI_FORMAT_R32_UINT,            DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RG8I,                                      DXGI_FORMAT_R8G8_SINT,           DXGI_FORMAT_R8G8_SINT,                DXGI_FORMAT_R8G8_SINT,           DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RG8UI,                                     DXGI_FORMAT_R8G8_UINT,           DXGI_FORMAT_R8G8_UINT,                DXGI_FORMAT_R8G8_UINT,           DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RG16I,                                     DXGI_FORMAT_R16G16_SINT,         DXGI_FORMAT_R16G16_SINT,              DXGI_FORMAT_R16G16_SINT,         DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RG16UI,                                    DXGI_FORMAT_R16G16_UINT,         DXGI_FORMAT_R16G16_UINT,              DXGI_FORMAT_R16G16_UINT,         DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RG32I,                                     DXGI_FORMAT_R32G32_SINT,         DXGI_FORMAT_R32G32_SINT,              DXGI_FORMAT_R32G32_SINT,         DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RG32UI,                                    DXGI_FORMAT_R32G32_UINT,         DXGI_FORMAT_R32G32_UINT,              DXGI_FORMAT_R32G32_UINT,         DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGB8I,                                     DXGI_FORMAT_R8G8B8A8_SINT,       DXGI_FORMAT_R8G8B8A8_SINT,            DXGI_FORMAT_R8G8B8A8_SINT,       DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGB8UI,                                    DXGI_FORMAT_R8G8B8A8_UINT,       DXGI_FORMAT_R8G8B8A8_UINT,            DXGI_FORMAT_R8G8B8A8_UINT,       DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGB16I,                                    DXGI_FORMAT_R16G16B16A16_SINT,   DXGI_FORMAT_R16G16B16A16_SINT,        DXGI_FORMAT_R16G16B16A16_SINT,   DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGB16UI,                                   DXGI_FORMAT_R16G16B16A16_UINT,   DXGI_FORMAT_R16G16B16A16_UINT,        DXGI_FORMAT_R16G16B16A16_UINT,   DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGB32I,                                    DXGI_FORMAT_R32G32B32A32_SINT,   DXGI_FORMAT_R32G32B32A32_SINT,        DXGI_FORMAT_R32G32B32A32_SINT,   DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGB32UI,                                   DXGI_FORMAT_R32G32B32A32_UINT,   DXGI_FORMAT_R32G32B32A32_UINT,        DXGI_FORMAT_R32G32B32A32_UINT,   DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGBA8I,                                    DXGI_FORMAT_R8G8B8A8_SINT,       DXGI_FORMAT_R8G8B8A8_SINT,            DXGI_FORMAT_R8G8B8A8_SINT,       DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGBA8UI,                                   DXGI_FORMAT_R8G8B8A8_UINT,       DXGI_FORMAT_R8G8B8A8_UINT,            DXGI_FORMAT_R8G8B8A8_UINT,       DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGBA16I,                                   DXGI_FORMAT_R16G16B16A16_SINT,   DXGI_FORMAT_R16G16B16A16_SINT,        DXGI_FORMAT_R16G16B16A16_SINT,   DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGBA16UI,                                  DXGI_FORMAT_R16G16B16A16_UINT,   DXGI_FORMAT_R16G16B16A16_UINT,        DXGI_FORMAT_R16G16B16A16_UINT,   DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGBA32I,                                   DXGI_FORMAT_R32G32B32A32_SINT,   DXGI_FORMAT_R32G32B32A32_SINT,        DXGI_FORMAT_R32G32B32A32_SINT,   DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGBA32UI,                                  DXGI_FORMAT_R32G32B32A32_UINT,   DXGI_FORMAT_R32G32B32A32_UINT,        DXGI_FORMAT_R32G32B32A32_UINT,   DXGI_FORMAT_UNKNOWN,              AnyDevice);
+
+    // Unsized formats, TODO: Are types of float and half float allowed for the unsized types? Would
+    // it change the DXGI format?
+    InsertD3D11FormatInfo(&map, GL_ALPHA,                                     DXGI_FORMAT_A8_UNORM,            DXGI_FORMAT_A8_UNORM,                 DXGI_FORMAT_A8_UNORM,            DXGI_FORMAT_UNKNOWN,              OnlyFL10Plus);
+    InsertD3D11FormatInfo(&map, GL_ALPHA,                                     DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,              OnlyFL9_3);
+    InsertD3D11FormatInfo(&map, GL_LUMINANCE,                                 DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA,                           DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGB,                                       DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_RGBA,                                      DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_BGRA_EXT,                                  DXGI_FORMAT_B8G8R8A8_UNORM,      DXGI_FORMAT_B8G8R8A8_UNORM,           DXGI_FORMAT_B8G8R8A8_UNORM,      DXGI_FORMAT_UNKNOWN,              AnyDevice);
+
+    // From GL_EXT_texture_storage
+    //                           | GL internal format                         | D3D11 texture format          | D3D11 SRV format                    | D3D11 RTV format                | D3D11 DSV format               | Requirements
+    InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT,                                DXGI_FORMAT_A8_UNORM,            DXGI_FORMAT_A8_UNORM,                 DXGI_FORMAT_A8_UNORM,            DXGI_FORMAT_UNKNOWN,              OnlyFL10Plus);
+    InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT,                                DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,              OnlyFL9_3);
+    InsertD3D11FormatInfo(&map, GL_LUMINANCE8_EXT,                            DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_ALPHA32F_EXT,                              DXGI_FORMAT_R32G32B32A32_FLOAT,  DXGI_FORMAT_R32G32B32A32_FLOAT,       DXGI_FORMAT_R32G32B32A32_FLOAT,  DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_LUMINANCE32F_EXT,                          DXGI_FORMAT_R32G32B32A32_FLOAT,  DXGI_FORMAT_R32G32B32A32_FLOAT,       DXGI_FORMAT_R32G32B32A32_FLOAT,  DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_ALPHA16F_EXT,                              DXGI_FORMAT_R16G16B16A16_FLOAT,  DXGI_FORMAT_R16G16B16A16_FLOAT,       DXGI_FORMAT_R16G16B16A16_FLOAT,  DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_LUMINANCE16F_EXT,                          DXGI_FORMAT_R16G16B16A16_FLOAT,  DXGI_FORMAT_R16G16B16A16_FLOAT,       DXGI_FORMAT_R16G16B16A16_FLOAT,  DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT,                     DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,      DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA32F_EXT,                    DXGI_FORMAT_R32G32B32A32_FLOAT,  DXGI_FORMAT_R32G32B32A32_FLOAT,       DXGI_FORMAT_R32G32B32A32_FLOAT,  DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA16F_EXT,                    DXGI_FORMAT_R16G16B16A16_FLOAT,  DXGI_FORMAT_R16G16B16A16_FLOAT,       DXGI_FORMAT_R16G16B16A16_FLOAT,  DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_BGRA8_EXT,                                 DXGI_FORMAT_B8G8R8A8_UNORM,      DXGI_FORMAT_B8G8R8A8_UNORM,           DXGI_FORMAT_B8G8R8A8_UNORM,      DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_BGRA4_ANGLEX,                              DXGI_FORMAT_B8G8R8A8_UNORM,      DXGI_FORMAT_B8G8R8A8_UNORM,           DXGI_FORMAT_B8G8R8A8_UNORM,      DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_BGR5_A1_ANGLEX,                            DXGI_FORMAT_B8G8R8A8_UNORM,      DXGI_FORMAT_B8G8R8A8_UNORM,           DXGI_FORMAT_B8G8R8A8_UNORM,      DXGI_FORMAT_UNKNOWN,              AnyDevice);
+
+    // Depth stencil formats
+    InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT16,                         DXGI_FORMAT_R16_TYPELESS,        DXGI_FORMAT_R16_UNORM,                DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_D16_UNORM,            OnlyFL10Plus);
+    InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT16,                         DXGI_FORMAT_D16_UNORM,           DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_D16_UNORM,            OnlyFL9_3);
+    InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT24,                         DXGI_FORMAT_R24G8_TYPELESS,      DXGI_FORMAT_R24_UNORM_X8_TYPELESS,    DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_D24_UNORM_S8_UINT,    OnlyFL10Plus);
+    InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT24,                         DXGI_FORMAT_D24_UNORM_S8_UINT,   DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_D24_UNORM_S8_UINT,    OnlyFL9_3);
+    InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT32F,                        DXGI_FORMAT_R32_TYPELESS,        DXGI_FORMAT_R32_FLOAT,                DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_D32_FLOAT,            OnlyFL10Plus);
+    InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT32F,                        DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              OnlyFL9_3);
+    InsertD3D11FormatInfo(&map, GL_DEPTH24_STENCIL8,                          DXGI_FORMAT_R24G8_TYPELESS,      DXGI_FORMAT_R24_UNORM_X8_TYPELESS,    DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_D24_UNORM_S8_UINT,    OnlyFL10Plus);
+    InsertD3D11FormatInfo(&map, GL_DEPTH24_STENCIL8,                          DXGI_FORMAT_D24_UNORM_S8_UINT,   DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_D24_UNORM_S8_UINT,    OnlyFL9_3);
+    InsertD3D11FormatInfo(&map, GL_DEPTH32F_STENCIL8,                         DXGI_FORMAT_R32G8X24_TYPELESS,   DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_D32_FLOAT_S8X24_UINT, OnlyFL10Plus);
+    InsertD3D11FormatInfo(&map, GL_DEPTH32F_STENCIL8,                         DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              OnlyFL9_3);
+    InsertD3D11FormatInfo(&map, GL_STENCIL_INDEX8,                            DXGI_FORMAT_R24G8_TYPELESS,      DXGI_FORMAT_X24_TYPELESS_G8_UINT,     DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_D24_UNORM_S8_UINT,    OnlyFL10Plus);
+    InsertD3D11FormatInfo(&map, GL_STENCIL_INDEX8,                            DXGI_FORMAT_D24_UNORM_S8_UINT,   DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_D24_UNORM_S8_UINT,    OnlyFL9_3);
+
+    // From GL_ANGLE_depth_texture
+    // Since D3D11 doesn't have a D32_UNORM format, use D24S8 which has comparable precision and
+    // matches the ES3 format.
+    InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT32_OES,                     DXGI_FORMAT_R24G8_TYPELESS,      DXGI_FORMAT_R24_UNORM_X8_TYPELESS,    DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_D24_UNORM_S8_UINT,    OnlyFL10Plus);
+
+    // Compressed formats, From ES 3.0.1 spec, table 3.16
+    //                           | GL internal format                        | D3D11 texture format           | D3D11 SRV format                    | D3D11 RTV format               | D3D11 DSV format                | Requirements
+    InsertD3D11FormatInfo(&map, GL_COMPRESSED_R11_EAC,                        DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              OnlyFL10Plus);
+    InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_R11_EAC,                 DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              OnlyFL10Plus);
+    InsertD3D11FormatInfo(&map, GL_COMPRESSED_RG11_EAC,                       DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              OnlyFL10Plus);
+    InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_RG11_EAC,                DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              OnlyFL10Plus);
+    InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_ETC2,                      DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              OnlyFL10Plus);
+    InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ETC2,                     DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              OnlyFL10Plus);
+    InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              OnlyFL10Plus);
+    InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              OnlyFL10Plus);
+    InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA8_ETC2_EAC,                 DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              OnlyFL10Plus);
+    InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,          DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,                  DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              OnlyFL10Plus);
+
+    // From GL_EXT_texture_compression_dxt1
+    InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,              DXGI_FORMAT_BC1_UNORM,           DXGI_FORMAT_BC1_UNORM,                DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,             DXGI_FORMAT_BC1_UNORM,           DXGI_FORMAT_BC1_UNORM,                DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              AnyDevice);
+
+    // From GL_ANGLE_texture_compression_dxt3
+    InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,           DXGI_FORMAT_BC2_UNORM,           DXGI_FORMAT_BC2_UNORM,                DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              AnyDevice);
+
+    // From GL_ANGLE_texture_compression_dxt5
+    InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,           DXGI_FORMAT_BC3_UNORM,           DXGI_FORMAT_BC3_UNORM,                DXGI_FORMAT_UNKNOWN,             DXGI_FORMAT_UNKNOWN,              AnyDevice);
+    // clang-format on
+
+    return map;
+}
+
+}  // namespace
+
+TextureFormat::TextureFormat()
+    : texFormat(DXGI_FORMAT_UNKNOWN),
+      srvFormat(DXGI_FORMAT_UNKNOWN),
+      rtvFormat(DXGI_FORMAT_UNKNOWN),
+      dsvFormat(DXGI_FORMAT_UNKNOWN),
+      renderFormat(DXGI_FORMAT_UNKNOWN),
+      swizzleTexFormat(DXGI_FORMAT_UNKNOWN),
+      swizzleSRVFormat(DXGI_FORMAT_UNKNOWN),
+      swizzleRTVFormat(DXGI_FORMAT_UNKNOWN),
+      dataInitializerFunction(NULL),
+      loadFunctions()
+{
+}
+
+const TextureFormat &GetTextureFormatInfo(GLenum internalFormat,
+                                          const Renderer11DeviceCaps &renderer11DeviceCaps)
+{
+    static const D3D11ES3FormatMap &formatMap = BuildD3D11FormatMap();
+
+    D3D11ES3FormatMap::const_iterator iter = formatMap.find(internalFormat);
+    if (iter != formatMap.end())
+    {
+        const std::vector<TextureFormatWithSupportFunction> &formatVector = iter->second;
+        for (size_t i = 0; i < formatVector.size(); i++)
+        {
+            const FormatSupportFunction supportFunction = formatVector[i].first;
+            const TextureFormat &textureFormat          = formatVector[i].second;
+
+            if (supportFunction(renderer11DeviceCaps))
+            {
+                return textureFormat;
+            }
+        }
+    }
+
+    static const TextureFormat defaultInfo;
+    return defaultInfo;
+}
+
+}  // namespace d3d11
+
+}  // namespace rx
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h
@@ -0,0 +1,52 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// texture_format_table:
+//   Queries for full textureFormat information based on internalFormat
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATTABLE_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATTABLE_H_
+
+#include <map>
+
+#include "common/platform.h"
+#include "libANGLE/renderer/d3d/formatutilsD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+struct TextureFormat
+{
+    TextureFormat();
+
+    DXGI_FORMAT texFormat;
+    DXGI_FORMAT srvFormat;
+    DXGI_FORMAT rtvFormat;
+    DXGI_FORMAT dsvFormat;
+    DXGI_FORMAT renderFormat;
+
+    DXGI_FORMAT swizzleTexFormat;
+    DXGI_FORMAT swizzleSRVFormat;
+    DXGI_FORMAT swizzleRTVFormat;
+
+    InitializeTextureDataFunction dataInitializerFunction;
+    typedef std::map<GLenum, LoadImageFunction> LoadFunctionMap;
+
+    LoadFunctionMap loadFunctions;
+};
+
+const TextureFormat &GetTextureFormatInfo(GLenum internalformat,
+                                          const Renderer11DeviceCaps &renderer11DeviceCaps);
+
+}  // namespace d3d11
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATTABLE_H_
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.cpp
@@ -0,0 +1,281 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// texture_format_util:
+//   Contains helper functions for texture_format_table
+//
+
+#include "libANGLE/renderer/d3d/d3d11/texture_format_util.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/loadimage.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+namespace
+{
+
+// ES3 image loading functions vary based on:
+//    - the GL internal format (supplied to glTex*Image*D)
+//    - the GL data type given (supplied to glTex*Image*D)
+//    - the target DXGI_FORMAT that the image will be loaded into (which is chosen based on the D3D
+//    device's capabilities)
+// This map type determines which loading function to use, based on these three parameters.
+// Source formats and types are taken from Tables 3.2 and 3.3 of the ES 3 spec.
+void UnimplementedLoadFunction(size_t width,
+                               size_t height,
+                               size_t depth,
+                               const uint8_t *input,
+                               size_t inputRowPitch,
+                               size_t inputDepthPitch,
+                               uint8_t *output,
+                               size_t outputRowPitch,
+                               size_t outputDepthPitch)
+{
+    UNIMPLEMENTED();
+}
+
+void UnreachableLoadFunction(size_t width,
+                             size_t height,
+                             size_t depth,
+                             const uint8_t *input,
+                             size_t inputRowPitch,
+                             size_t inputDepthPitch,
+                             uint8_t *output,
+                             size_t outputRowPitch,
+                             size_t outputDepthPitch)
+{
+    UNREACHABLE();
+}
+
+// A helper function to insert data into the D3D11LoadFunctionMap with fewer characters.
+inline void InsertLoadFunction(D3D11LoadFunctionMap *map, GLenum internalFormat, GLenum type,
+    DXGI_FORMAT dxgiFormat, LoadImageFunction loadFunc)
+{
+    (*map)[internalFormat].push_back(GLTypeDXGIFunctionPair(type, DxgiFormatLoadFunctionPair(dxgiFormat, loadFunc)));
+}
+
+}  // namespace
+
+// TODO: This will be generated by a JSON file
+const D3D11LoadFunctionMap &BuildD3D11LoadFunctionMap()
+{
+    static D3D11LoadFunctionMap map;
+
+    //                      | Internal format      | Type                             | Target DXGI Format              | Load function                       |
+    InsertLoadFunction(&map, GL_RGBA8,              GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8B8A8_UNORM,       LoadToNative<GLubyte, 4>             );
+    InsertLoadFunction(&map, GL_RGB5_A1,            GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8B8A8_UNORM,       LoadToNative<GLubyte, 4>             );
+    InsertLoadFunction(&map, GL_RGBA4,              GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8B8A8_UNORM,       LoadToNative<GLubyte, 4>             );
+    InsertLoadFunction(&map, GL_SRGB8_ALPHA8,       GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,  LoadToNative<GLubyte, 4>             );
+    InsertLoadFunction(&map, GL_RGBA8_SNORM,        GL_BYTE,                           DXGI_FORMAT_R8G8B8A8_SNORM,       LoadToNative<GLbyte, 4>              );
+    InsertLoadFunction(&map, GL_RGBA4,              GL_UNSIGNED_SHORT_4_4_4_4,         DXGI_FORMAT_R8G8B8A8_UNORM,       LoadRGBA4ToRGBA8                     );
+    InsertLoadFunction(&map, GL_RGBA4,              GL_UNSIGNED_SHORT_4_4_4_4,         DXGI_FORMAT_B4G4R4A4_UNORM,       LoadRGBA4ToARGB4                     );
+    InsertLoadFunction(&map, GL_RGB10_A2,           GL_UNSIGNED_INT_2_10_10_10_REV,    DXGI_FORMAT_R10G10B10A2_UNORM,    LoadToNative<GLuint, 1>              );
+    InsertLoadFunction(&map, GL_RGB5_A1,            GL_UNSIGNED_SHORT_5_5_5_1,         DXGI_FORMAT_R8G8B8A8_UNORM,       LoadRGB5A1ToRGBA8                    );
+    InsertLoadFunction(&map, GL_RGB5_A1,            GL_UNSIGNED_SHORT_5_5_5_1,         DXGI_FORMAT_B5G5R5A1_UNORM,       LoadRGB5A1ToA1RGB5                   );
+    InsertLoadFunction(&map, GL_RGB5_A1,            GL_UNSIGNED_INT_2_10_10_10_REV,    DXGI_FORMAT_R8G8B8A8_UNORM,       LoadRGB10A2ToRGBA8                   );
+    InsertLoadFunction(&map, GL_RGBA16F,            GL_HALF_FLOAT,                     DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadToNative<GLhalf, 4>              );
+    InsertLoadFunction(&map, GL_RGBA16F,            GL_HALF_FLOAT_OES,                 DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadToNative<GLhalf, 4>              );
+    InsertLoadFunction(&map, GL_RGBA32F,            GL_FLOAT,                          DXGI_FORMAT_R32G32B32A32_FLOAT,   LoadToNative<GLfloat, 4>             );
+    InsertLoadFunction(&map, GL_RGBA16F,            GL_FLOAT,                          DXGI_FORMAT_R16G16B16A16_FLOAT,   Load32FTo16F<4>                      );
+    InsertLoadFunction(&map, GL_RGBA8UI,            GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8B8A8_UINT,        LoadToNative<GLubyte, 4>             );
+    InsertLoadFunction(&map, GL_RGBA8I,             GL_BYTE,                           DXGI_FORMAT_R8G8B8A8_SINT,        LoadToNative<GLbyte, 4>              );
+    InsertLoadFunction(&map, GL_RGBA16UI,           GL_UNSIGNED_SHORT,                 DXGI_FORMAT_R16G16B16A16_UINT,    LoadToNative<GLushort, 4>            );
+    InsertLoadFunction(&map, GL_RGBA16I,            GL_SHORT,                          DXGI_FORMAT_R16G16B16A16_SINT,    LoadToNative<GLshort, 4>             );
+    InsertLoadFunction(&map, GL_RGBA32UI,           GL_UNSIGNED_INT,                   DXGI_FORMAT_R32G32B32A32_UINT,    LoadToNative<GLuint, 4>              );
+    InsertLoadFunction(&map, GL_RGBA32I,            GL_INT,                            DXGI_FORMAT_R32G32B32A32_SINT,    LoadToNative<GLint, 4>               );
+    InsertLoadFunction(&map, GL_RGB10_A2UI,         GL_UNSIGNED_INT_2_10_10_10_REV,    DXGI_FORMAT_R10G10B10A2_UINT,     LoadToNative<GLuint, 1>              );
+    InsertLoadFunction(&map, GL_RGB8,               GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8B8A8_UNORM,       LoadToNative3To4<GLubyte, 0xFF>      );
+    InsertLoadFunction(&map, GL_RGB565,             GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8B8A8_UNORM,       LoadToNative3To4<GLubyte, 0xFF>      );
+    InsertLoadFunction(&map, GL_SRGB8,              GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,  LoadToNative3To4<GLubyte, 0xFF>      );
+    InsertLoadFunction(&map, GL_RGB8_SNORM,         GL_BYTE,                           DXGI_FORMAT_R8G8B8A8_SNORM,       LoadToNative3To4<GLbyte, 0x7F>       );
+    InsertLoadFunction(&map, GL_RGB565,             GL_UNSIGNED_SHORT_5_6_5,           DXGI_FORMAT_R8G8B8A8_UNORM,       LoadR5G6B5ToRGBA8                    );
+    InsertLoadFunction(&map, GL_RGB565,             GL_UNSIGNED_SHORT_5_6_5,           DXGI_FORMAT_B5G6R5_UNORM,         LoadToNative<GLushort, 1>            );
+    InsertLoadFunction(&map, GL_R11F_G11F_B10F,     GL_UNSIGNED_INT_10F_11F_11F_REV,   DXGI_FORMAT_R11G11B10_FLOAT,      LoadToNative<GLuint, 1>              );
+    InsertLoadFunction(&map, GL_RGB9_E5,            GL_UNSIGNED_INT_5_9_9_9_REV,       DXGI_FORMAT_R9G9B9E5_SHAREDEXP,   LoadToNative<GLuint, 1>              );
+    InsertLoadFunction(&map, GL_RGB16F,             GL_HALF_FLOAT,                     DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadToNative3To4<GLhalf, gl::Float16One>);
+    InsertLoadFunction(&map, GL_RGB16F,             GL_HALF_FLOAT_OES,                 DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadToNative3To4<GLhalf, gl::Float16One>);
+    InsertLoadFunction(&map, GL_R11F_G11F_B10F,     GL_HALF_FLOAT,                     DXGI_FORMAT_R11G11B10_FLOAT,      LoadRGB16FToRG11B10F                 );
+    InsertLoadFunction(&map, GL_R11F_G11F_B10F,     GL_HALF_FLOAT_OES,                 DXGI_FORMAT_R11G11B10_FLOAT,      LoadRGB16FToRG11B10F                 );
+    InsertLoadFunction(&map, GL_RGB9_E5,            GL_HALF_FLOAT,                     DXGI_FORMAT_R9G9B9E5_SHAREDEXP,   LoadRGB16FToRGB9E5                   );
+    InsertLoadFunction(&map, GL_RGB9_E5,            GL_HALF_FLOAT_OES,                 DXGI_FORMAT_R9G9B9E5_SHAREDEXP,   LoadRGB16FToRGB9E5                   );
+    InsertLoadFunction(&map, GL_RGB32F,             GL_FLOAT,                          DXGI_FORMAT_R32G32B32A32_FLOAT,   LoadToNative3To4<GLfloat, gl::Float32One>);
+    InsertLoadFunction(&map, GL_RGB16F,             GL_FLOAT,                          DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadRGB32FToRGBA16F                  );
+    InsertLoadFunction(&map, GL_R11F_G11F_B10F,     GL_FLOAT,                          DXGI_FORMAT_R11G11B10_FLOAT,      LoadRGB32FToRG11B10F                 );
+    InsertLoadFunction(&map, GL_RGB9_E5,            GL_FLOAT,                          DXGI_FORMAT_R9G9B9E5_SHAREDEXP,   LoadRGB32FToRGB9E5                   );
+    InsertLoadFunction(&map, GL_RGB8UI,             GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8B8A8_UINT,        LoadToNative3To4<GLubyte, 0x01>      );
+    InsertLoadFunction(&map, GL_RGB8I,              GL_BYTE,                           DXGI_FORMAT_R8G8B8A8_SINT,        LoadToNative3To4<GLbyte, 0x01>       );
+    InsertLoadFunction(&map, GL_RGB16UI,            GL_UNSIGNED_SHORT,                 DXGI_FORMAT_R16G16B16A16_UINT,    LoadToNative3To4<GLushort, 0x0001>   );
+    InsertLoadFunction(&map, GL_RGB16I,             GL_SHORT,                          DXGI_FORMAT_R16G16B16A16_SINT,    LoadToNative3To4<GLshort, 0x0001>    );
+    InsertLoadFunction(&map, GL_RGB32UI,            GL_UNSIGNED_INT,                   DXGI_FORMAT_R32G32B32A32_UINT,    LoadToNative3To4<GLuint, 0x00000001> );
+    InsertLoadFunction(&map, GL_RGB32I,             GL_INT,                            DXGI_FORMAT_R32G32B32A32_SINT,    LoadToNative3To4<GLint, 0x00000001>  );
+    InsertLoadFunction(&map, GL_RG8,                GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8_UNORM,           LoadToNative<GLubyte, 2>             );
+    InsertLoadFunction(&map, GL_RG8_SNORM,          GL_BYTE,                           DXGI_FORMAT_R8G8_SNORM,           LoadToNative<GLbyte, 2>              );
+    InsertLoadFunction(&map, GL_RG16F,              GL_HALF_FLOAT,                     DXGI_FORMAT_R16G16_FLOAT,         LoadToNative<GLhalf, 2>              );
+    InsertLoadFunction(&map, GL_RG16F,              GL_HALF_FLOAT_OES,                 DXGI_FORMAT_R16G16_FLOAT,         LoadToNative<GLhalf, 2>              );
+    InsertLoadFunction(&map, GL_RG32F,              GL_FLOAT,                          DXGI_FORMAT_R32G32_FLOAT,         LoadToNative<GLfloat, 2>             );
+    InsertLoadFunction(&map, GL_RG16F,              GL_FLOAT,                          DXGI_FORMAT_R16G16_FLOAT,         Load32FTo16F<2>                      );
+    InsertLoadFunction(&map, GL_RG8UI,              GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8G8_UINT,            LoadToNative<GLubyte, 2>             );
+    InsertLoadFunction(&map, GL_RG8I,               GL_BYTE,                           DXGI_FORMAT_R8G8_SINT,            LoadToNative<GLbyte, 2>              );
+    InsertLoadFunction(&map, GL_RG16UI,             GL_UNSIGNED_SHORT,                 DXGI_FORMAT_R16G16_UINT,          LoadToNative<GLushort, 2>            );
+    InsertLoadFunction(&map, GL_RG16I,              GL_SHORT,                          DXGI_FORMAT_R16G16_SINT,          LoadToNative<GLshort, 2>             );
+    InsertLoadFunction(&map, GL_RG32UI,             GL_UNSIGNED_INT,                   DXGI_FORMAT_R32G32_UINT,          LoadToNative<GLuint, 2>              );
+    InsertLoadFunction(&map, GL_RG32I,              GL_INT,                            DXGI_FORMAT_R32G32_SINT,          LoadToNative<GLint, 2>               );
+    InsertLoadFunction(&map, GL_R8,                 GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8_UNORM,             LoadToNative<GLubyte, 1>             );
+    InsertLoadFunction(&map, GL_R8_SNORM,           GL_BYTE,                           DXGI_FORMAT_R8_SNORM,             LoadToNative<GLbyte, 1>              );
+    InsertLoadFunction(&map, GL_R16F,               GL_HALF_FLOAT,                     DXGI_FORMAT_R16_FLOAT,            LoadToNative<GLhalf, 1>              );
+    InsertLoadFunction(&map, GL_R16F,               GL_HALF_FLOAT_OES,                 DXGI_FORMAT_R16_FLOAT,            LoadToNative<GLhalf, 1>              );
+    InsertLoadFunction(&map, GL_R32F,               GL_FLOAT,                          DXGI_FORMAT_R32_FLOAT,            LoadToNative<GLfloat, 1>             );
+    InsertLoadFunction(&map, GL_R16F,               GL_FLOAT,                          DXGI_FORMAT_R16_FLOAT,            Load32FTo16F<1>                      );
+    InsertLoadFunction(&map, GL_R8UI,               GL_UNSIGNED_BYTE,                  DXGI_FORMAT_R8_UINT,              LoadToNative<GLubyte, 1>             );
+    InsertLoadFunction(&map, GL_R8I,                GL_BYTE,                           DXGI_FORMAT_R8_SINT,              LoadToNative<GLbyte, 1>              );
+    InsertLoadFunction(&map, GL_R16UI,              GL_UNSIGNED_SHORT,                 DXGI_FORMAT_R16_UINT,             LoadToNative<GLushort, 1>            );
+    InsertLoadFunction(&map, GL_R16I,               GL_SHORT,                          DXGI_FORMAT_R16_SINT,             LoadToNative<GLshort, 1>             );
+    InsertLoadFunction(&map, GL_R32UI,              GL_UNSIGNED_INT,                   DXGI_FORMAT_R32_UINT,             LoadToNative<GLuint, 1>              );
+    InsertLoadFunction(&map, GL_R32I,               GL_INT,                            DXGI_FORMAT_R32_SINT,             LoadToNative<GLint, 1>               );
+
+    InsertLoadFunction(&map, GL_DEPTH_COMPONENT16,  GL_UNSIGNED_SHORT,                 DXGI_FORMAT_R16_TYPELESS,         LoadToNative<GLushort, 1>            );
+    InsertLoadFunction(&map, GL_DEPTH_COMPONENT16,  GL_UNSIGNED_SHORT,                 DXGI_FORMAT_D16_UNORM,            LoadToNative<GLushort, 1>            );
+    InsertLoadFunction(&map, GL_DEPTH_COMPONENT24,  GL_UNSIGNED_INT,                   DXGI_FORMAT_R24G8_TYPELESS,       LoadR32ToR24G8                       );
+    InsertLoadFunction(&map, GL_DEPTH_COMPONENT24,  GL_UNSIGNED_INT,                   DXGI_FORMAT_D24_UNORM_S8_UINT,    LoadR32ToR24G8                       );
+    InsertLoadFunction(&map, GL_DEPTH_COMPONENT16,  GL_UNSIGNED_INT,                   DXGI_FORMAT_R16_TYPELESS,         LoadR32ToR16                         );
+    InsertLoadFunction(&map, GL_DEPTH_COMPONENT32F, GL_FLOAT,                          DXGI_FORMAT_R32_TYPELESS,         LoadToNative<GLfloat, 1>             );
+    InsertLoadFunction(&map, GL_DEPTH_COMPONENT32F, GL_FLOAT,                          DXGI_FORMAT_UNKNOWN,              UnimplementedLoadFunction            );
+    InsertLoadFunction(&map, GL_DEPTH24_STENCIL8,   GL_UNSIGNED_INT_24_8,              DXGI_FORMAT_R24G8_TYPELESS,       LoadR32ToR24G8                       );
+    InsertLoadFunction(&map, GL_DEPTH24_STENCIL8,   GL_UNSIGNED_INT_24_8,              DXGI_FORMAT_D24_UNORM_S8_UINT,    LoadR32ToR24G8                       );
+    InsertLoadFunction(&map, GL_DEPTH32F_STENCIL8,  GL_FLOAT_32_UNSIGNED_INT_24_8_REV, DXGI_FORMAT_R32G8X24_TYPELESS,    LoadToNative<GLuint, 2>              );
+    InsertLoadFunction(&map, GL_DEPTH32F_STENCIL8,  GL_FLOAT_32_UNSIGNED_INT_24_8_REV, DXGI_FORMAT_UNKNOWN,              UnimplementedLoadFunction            );
+    InsertLoadFunction(&map, GL_STENCIL_INDEX8,     DXGI_FORMAT_R24G8_TYPELESS,        DXGI_FORMAT_UNKNOWN,              UnimplementedLoadFunction            );
+    InsertLoadFunction(&map, GL_STENCIL_INDEX8,     DXGI_FORMAT_D24_UNORM_S8_UINT,     DXGI_FORMAT_UNKNOWN,              UnimplementedLoadFunction            );
+
+    // Unsized formats
+    // Load functions are unreachable because they are converted to sized internal formats based on
+    // the format and type before loading takes place.
+    InsertLoadFunction(&map, GL_RGBA,               GL_UNSIGNED_BYTE,                  DXGI_FORMAT_UNKNOWN,              UnreachableLoadFunction              );
+    InsertLoadFunction(&map, GL_RGBA,               GL_UNSIGNED_SHORT_4_4_4_4,         DXGI_FORMAT_UNKNOWN,              UnreachableLoadFunction              );
+    InsertLoadFunction(&map, GL_RGBA,               GL_UNSIGNED_SHORT_5_5_5_1,         DXGI_FORMAT_UNKNOWN,              UnreachableLoadFunction              );
+    InsertLoadFunction(&map, GL_RGB,                GL_UNSIGNED_BYTE,                  DXGI_FORMAT_UNKNOWN,              UnreachableLoadFunction              );
+    InsertLoadFunction(&map, GL_RGB,                GL_UNSIGNED_SHORT_5_6_5,           DXGI_FORMAT_UNKNOWN,              UnreachableLoadFunction              );
+    InsertLoadFunction(&map, GL_LUMINANCE_ALPHA,    GL_UNSIGNED_BYTE,                  DXGI_FORMAT_UNKNOWN,              UnreachableLoadFunction              );
+    InsertLoadFunction(&map, GL_LUMINANCE,          GL_UNSIGNED_BYTE,                  DXGI_FORMAT_UNKNOWN,              UnreachableLoadFunction              );
+    InsertLoadFunction(&map, GL_ALPHA,              GL_UNSIGNED_BYTE,                  DXGI_FORMAT_UNKNOWN,              UnreachableLoadFunction              );
+    InsertLoadFunction(&map, GL_BGRA_EXT,           GL_UNSIGNED_BYTE,                  DXGI_FORMAT_UNKNOWN,              UnreachableLoadFunction              );
+
+    // From GL_OES_texture_float
+    InsertLoadFunction(&map, GL_LUMINANCE_ALPHA,    GL_FLOAT,                          DXGI_FORMAT_R32G32B32A32_FLOAT,   LoadLA32FToRGBA32F                   );
+    InsertLoadFunction(&map, GL_LUMINANCE,          GL_FLOAT,                          DXGI_FORMAT_R32G32B32A32_FLOAT,   LoadL32FToRGBA32F                    );
+    InsertLoadFunction(&map, GL_ALPHA,              GL_FLOAT,                          DXGI_FORMAT_R32G32B32A32_FLOAT,   LoadA32FToRGBA32F                    );
+
+    // From GL_OES_texture_half_float
+    InsertLoadFunction(&map, GL_LUMINANCE_ALPHA,    GL_HALF_FLOAT,                     DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadLA16FToRGBA16F                   );
+    InsertLoadFunction(&map, GL_LUMINANCE_ALPHA,    GL_HALF_FLOAT_OES,                 DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadLA16FToRGBA16F                   );
+    InsertLoadFunction(&map, GL_LUMINANCE,          GL_HALF_FLOAT,                     DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadL16FToRGBA16F                    );
+    InsertLoadFunction(&map, GL_LUMINANCE,          GL_HALF_FLOAT_OES,                 DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadL16FToRGBA16F                    );
+    InsertLoadFunction(&map, GL_ALPHA,              GL_HALF_FLOAT,                     DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadA16FToRGBA16F                    );
+    InsertLoadFunction(&map, GL_ALPHA,              GL_HALF_FLOAT_OES,                 DXGI_FORMAT_R16G16B16A16_FLOAT,   LoadA16FToRGBA16F                    );
+
+    // From GL_EXT_texture_storage
+    InsertLoadFunction(&map, GL_ALPHA8_EXT,             GL_UNSIGNED_BYTE,              DXGI_FORMAT_A8_UNORM,             LoadToNative<GLubyte, 1>             );
+    InsertLoadFunction(&map, GL_ALPHA8_EXT,             GL_UNSIGNED_BYTE,              DXGI_FORMAT_R8G8B8A8_UNORM,       LoadA8ToRGBA8                        );
+    InsertLoadFunction(&map, GL_LUMINANCE8_EXT,         GL_UNSIGNED_BYTE,              DXGI_FORMAT_UNKNOWN,              LoadL8ToRGBA8                        );
+    InsertLoadFunction(&map, GL_LUMINANCE8_ALPHA8_EXT,  GL_UNSIGNED_BYTE,              DXGI_FORMAT_UNKNOWN,              LoadLA8ToRGBA8                       );
+    InsertLoadFunction(&map, GL_ALPHA32F_EXT,           GL_FLOAT,                      DXGI_FORMAT_UNKNOWN,              LoadA32FToRGBA32F                    );
+    InsertLoadFunction(&map, GL_LUMINANCE32F_EXT,       GL_FLOAT,                      DXGI_FORMAT_UNKNOWN,              LoadL32FToRGBA32F                    );
+    InsertLoadFunction(&map, GL_LUMINANCE_ALPHA32F_EXT, GL_FLOAT,                      DXGI_FORMAT_UNKNOWN,              LoadLA32FToRGBA32F                   );
+    InsertLoadFunction(&map, GL_ALPHA16F_EXT,           GL_HALF_FLOAT,                 DXGI_FORMAT_UNKNOWN,              LoadA16FToRGBA16F                    );
+    InsertLoadFunction(&map, GL_ALPHA16F_EXT,           GL_HALF_FLOAT_OES,             DXGI_FORMAT_UNKNOWN,              LoadA16FToRGBA16F                    );
+    InsertLoadFunction(&map, GL_LUMINANCE16F_EXT,       GL_HALF_FLOAT,                 DXGI_FORMAT_UNKNOWN,              LoadL16FToRGBA16F                    );
+    InsertLoadFunction(&map, GL_LUMINANCE16F_EXT,       GL_HALF_FLOAT_OES,             DXGI_FORMAT_UNKNOWN,              LoadL16FToRGBA16F                    );
+    InsertLoadFunction(&map, GL_LUMINANCE_ALPHA16F_EXT, GL_HALF_FLOAT,                 DXGI_FORMAT_UNKNOWN,              LoadLA16FToRGBA16F                   );
+    InsertLoadFunction(&map, GL_LUMINANCE_ALPHA16F_EXT, GL_HALF_FLOAT_OES,             DXGI_FORMAT_UNKNOWN,              LoadLA16FToRGBA16F                   );
+
+    // From GL_ANGLE_depth_texture
+    InsertLoadFunction(&map, GL_DEPTH_COMPONENT32_OES,  GL_UNSIGNED_INT,               DXGI_FORMAT_UNKNOWN,              LoadR32ToR24G8                       );
+
+    // From GL_EXT_texture_format_BGRA8888
+    InsertLoadFunction(&map, GL_BGRA8_EXT,              GL_UNSIGNED_BYTE,                  DXGI_FORMAT_UNKNOWN,          LoadToNative<GLubyte, 4>             );
+    InsertLoadFunction(&map, GL_BGRA4_ANGLEX,           GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, DXGI_FORMAT_UNKNOWN,          LoadRGBA4ToRGBA8                     );
+    InsertLoadFunction(&map, GL_BGRA4_ANGLEX,           GL_UNSIGNED_BYTE,                  DXGI_FORMAT_UNKNOWN,          LoadToNative<GLubyte, 4>             );
+    InsertLoadFunction(&map, GL_BGR5_A1_ANGLEX,         GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, DXGI_FORMAT_UNKNOWN,          LoadRGB5A1ToRGBA8                    );
+    InsertLoadFunction(&map, GL_BGR5_A1_ANGLEX,         GL_UNSIGNED_BYTE,                  DXGI_FORMAT_UNKNOWN,          LoadToNative<GLubyte, 4>             );
+    // Compressed formats
+    // From ES 3.0.1 spec, table 3.16
+    //                      | Internal format                             | Type            | Load function                |
+    InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC,                        GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
+    InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC,                        GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
+    InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_R11_EAC,                 GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
+    InsertLoadFunction(&map, GL_COMPRESSED_RG11_EAC,                       GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
+    InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_RG11_EAC,                GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
+    InsertLoadFunction(&map, GL_COMPRESSED_RGB8_ETC2,                      GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
+    InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ETC2,                     GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
+    InsertLoadFunction(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,  GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
+    InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
+    InsertLoadFunction(&map, GL_COMPRESSED_RGBA8_ETC2_EAC,                 GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
+    InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,          GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        UnimplementedLoadFunction            );
+
+    // From GL_EXT_texture_compression_dxt1
+    InsertLoadFunction(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,              GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        LoadCompressedToNative<4, 4,  8>     );
+    InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,             GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        LoadCompressedToNative<4, 4,  8>     );
+
+    // From GL_ANGLE_texture_compression_dxt3
+    InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,           GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        LoadCompressedToNative<4, 4, 16>     );
+
+    // From GL_ANGLE_texture_compression_dxt5
+    InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,           GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN,        LoadCompressedToNative<4, 4, 16>     );
+
+    return map;
+}
+
+typedef std::pair<InitializeTextureFormatPair, InitializeTextureDataFunction>
+    InternalFormatInitializerPair;
+
+// TODO: This should be generated by a JSON file
+const InternalFormatInitializerMap &BuildInternalFormatInitializerMap()
+{
+    static InternalFormatInitializerMap map;
+
+    map.insert(InternalFormatInitializerPair(
+        InitializeTextureFormatPair(GL_RGB8, DXGI_FORMAT_R8G8B8A8_UNORM),
+        Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>));
+    map.insert(InternalFormatInitializerPair(
+        InitializeTextureFormatPair(GL_RGB565, DXGI_FORMAT_R8G8B8A8_UNORM),
+        Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>));
+    map.insert(InternalFormatInitializerPair(
+        InitializeTextureFormatPair(GL_SRGB8, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB),
+        Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>));
+    map.insert(InternalFormatInitializerPair(
+        InitializeTextureFormatPair(GL_RGB16F, DXGI_FORMAT_R16G16B16A16_FLOAT),
+        Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>));
+    map.insert(InternalFormatInitializerPair(
+        InitializeTextureFormatPair(GL_RGB32F, DXGI_FORMAT_R32G32B32A32_FLOAT),
+        Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>));
+    map.insert(InternalFormatInitializerPair(
+        InitializeTextureFormatPair(GL_RGB8UI, DXGI_FORMAT_R8G8B8A8_UINT),
+        Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0x01>));
+    map.insert(InternalFormatInitializerPair(
+        InitializeTextureFormatPair(GL_RGB8I, DXGI_FORMAT_R8G8B8A8_SINT),
+        Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x01>));
+    map.insert(InternalFormatInitializerPair(
+        InitializeTextureFormatPair(GL_RGB16UI, DXGI_FORMAT_R16G16B16A16_UINT),
+        Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x0001>));
+    map.insert(InternalFormatInitializerPair(
+        InitializeTextureFormatPair(GL_RGB16I, DXGI_FORMAT_R16G16B16A16_SINT),
+        Initialize4ComponentData<GLshort, 0x0000, 0x0000, 0x0000, 0x0001>));
+    map.insert(InternalFormatInitializerPair(
+        InitializeTextureFormatPair(GL_RGB32UI, DXGI_FORMAT_R32G32B32A32_UINT),
+        Initialize4ComponentData<GLuint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>));
+    map.insert(InternalFormatInitializerPair(
+        InitializeTextureFormatPair(GL_RGB32I, DXGI_FORMAT_R32G32B32A32_SINT),
+        Initialize4ComponentData<GLint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>));
+
+    return map;
+}
+
+}  // namespace d3d11
+
+}  // namespace rx
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.h
@@ -0,0 +1,39 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// texture_format_util:
+//   Contains helper functions for texture_format_table
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATUTIL_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATUTIL_H_
+
+#include <map>
+
+#include "libANGLE/renderer/d3d/d3d11/renderer11.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+typedef std::pair<DXGI_FORMAT, LoadImageFunction> DxgiFormatLoadFunctionPair;
+typedef std::pair<GLenum, DxgiFormatLoadFunctionPair> GLTypeDXGIFunctionPair;
+typedef std::map<GLenum, std::vector<GLTypeDXGIFunctionPair>> D3D11LoadFunctionMap;
+
+const D3D11LoadFunctionMap &BuildD3D11LoadFunctionMap();
+
+typedef std::pair<GLint, DXGI_FORMAT> InitializeTextureFormatPair;
+typedef std::map<InitializeTextureFormatPair, InitializeTextureDataFunction>
+    InternalFormatInitializerMap;
+
+const InternalFormatInitializerMap &BuildInternalFormatInitializerMap();
+
+}  // namespace d3d11
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATUTIL_H_
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
@@ -68,17 +68,22 @@ gl::Error Framebuffer9::clear(const gl::
     float farZ = state.getFarPlane();
     mRenderer->setViewport(state.getViewport(), nearZ, farZ, GL_TRIANGLES, state.getRasterizerState().frontFace, true);
 
     mRenderer->setScissorRectangle(state.getScissor(), state.isScissorTestEnabled());
 
     return mRenderer->clear(clearParams, colorAttachment, depthStencilAttachment);
 }
 
-gl::Error Framebuffer9::readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) const
+gl::Error Framebuffer9::readPixelsImpl(const gl::Rectangle &area,
+                                       GLenum format,
+                                       GLenum type,
+                                       size_t outputPitch,
+                                       const gl::PixelPackState &pack,
+                                       uint8_t *pixels) const
 {
     ASSERT(pack.pixelBuffer.get() == nullptr);
 
     const gl::FramebufferAttachment *colorbuffer = mData.getColorAttachment(0);
     ASSERT(colorbuffer);
 
     RenderTarget9 *renderTarget = nullptr;
     gl::Error error = colorbuffer->getRenderTarget(&renderTarget);
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
@@ -23,18 +23,22 @@ class Framebuffer9 : public FramebufferD
 
     gl::Error discard(size_t count, const GLenum *attachments) override;
     gl::Error invalidate(size_t count, const GLenum *attachments) override;
     gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
 
   private:
     gl::Error clear(const gl::State &state, const ClearParameters &clearParams) override;
 
-    gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch,
-                         const gl::PixelPackState &pack, uint8_t *pixels) const override;
+    gl::Error readPixelsImpl(const gl::Rectangle &area,
+                             GLenum format,
+                             GLenum type,
+                             size_t outputPitch,
+                             const gl::PixelPackState &pack,
+                             uint8_t *pixels) const override;
 
     gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor,
                    bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter,
                    const gl::Framebuffer *sourceFramebuffer) override;
 
     GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override;
 
     Renderer9 *const mRenderer;
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
@@ -475,16 +475,18 @@ gl::Error Image9::copyToSurface(IDirect3
 // into the target pixel rectangle.
 gl::Error Image9::loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input)
 {
     // 3D textures are not supported by the D3D9 backend.
     ASSERT(area.z == 0 && area.depth == 1);
 
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
     GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength);
+    GLsizei inputSkipBytes = formatInfo.computeSkipPixels(inputRowPitch, 0, unpack.skipImages,
+                                                          unpack.skipRows, unpack.skipPixels);
 
     const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
     ASSERT(d3dFormatInfo.loadFunction != NULL);
 
     RECT lockRect =
     {
         area.x, area.y,
         area.x + area.width, area.y + area.height
@@ -493,32 +495,34 @@ gl::Error Image9::loadData(const gl::Box
     D3DLOCKED_RECT locked;
     gl::Error error = lock(&locked, lockRect);
     if (error.isError())
     {
         return error;
     }
 
     d3dFormatInfo.loadFunction(area.width, area.height, area.depth,
-                               reinterpret_cast<const uint8_t*>(input), inputRowPitch, 0,
-                               reinterpret_cast<uint8_t*>(locked.pBits), locked.Pitch, 0);
+                               reinterpret_cast<const uint8_t *>(input) + inputSkipBytes,
+                               inputRowPitch, 0, reinterpret_cast<uint8_t *>(locked.pBits),
+                               locked.Pitch, 0);
 
     unlock();
 
     return gl::Error(GL_NO_ERROR);
 }
 
 gl::Error Image9::loadCompressedData(const gl::Box &area, const void *input)
 {
     // 3D textures are not supported by the D3D9 backend.
     ASSERT(area.z == 0 && area.depth == 1);
 
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
     GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0);
-    GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0);
+    GLsizei inputDepthPitch =
+        formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0);
 
     const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
 
     ASSERT(area.x % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockWidth == 0);
     ASSERT(area.y % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockHeight == 0);
 
     ASSERT(d3d9FormatInfo.loadFunction != NULL);
 
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
@@ -569,16 +569,18 @@ void GenerateCaps(IDirect3D9 *d3d9,
     extensions->fragDepth = true;
     extensions->textureUsage = true;
     extensions->translatedShaderSource = true;
     extensions->fboRenderMipmap = false;
     extensions->discardFramebuffer = false; // It would be valid to set this to true, since glDiscardFramebufferEXT is just a hint
     extensions->colorBufferFloat = false;
     extensions->debugMarker = true;
     extensions->eglImage               = true;
+    extensions->unpackSubimage         = true;
+    extensions->packSubimage           = true;
 
     // D3D9 has no concept of separate masks and refs for front and back faces in the depth stencil
     // state.
     limitations->noSeparateStencilRefsAndMasks = true;
 
     // D3D9 shader models have limited support for looping, so the Appendix A
     // index/loop limitations are necessary. Workarounds that are needed to
     // support dynamic indexing of vectors on HLSL also don't work on D3D9.
--- a/gfx/angle/src/libANGLE/renderer/gl/CompilerGL.h
+++ b/gfx/angle/src/libANGLE/renderer/gl/CompilerGL.h
@@ -17,17 +17,17 @@ class FunctionsGL;
 
 class CompilerGL : public CompilerImpl
 {
   public:
     CompilerGL(const FunctionsGL *functions);
     ~CompilerGL() override {}
 
     gl::Error release() override { return gl::Error(GL_NO_ERROR); }
-    ShShaderOutput getTranslatorOutputType() const { return mTranslatorOutputType; }
+    ShShaderOutput getTranslatorOutputType() const override { return mTranslatorOutputType; }
 
   private:
     ShShaderOutput mTranslatorOutputType;
 };
 
 }
 
 #endif // LIBANGLE_RENDERER_GL_COMPILERGL_H_
--- a/gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
+++ b/gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
@@ -13,40 +13,48 @@
 #include "libANGLE/State.h"
 #include "libANGLE/FramebufferAttachment.h"
 #include "libANGLE/angletypes.h"
 #include "libANGLE/formatutils.h"
 #include "libANGLE/renderer/gl/FunctionsGL.h"
 #include "libANGLE/renderer/gl/RenderbufferGL.h"
 #include "libANGLE/renderer/gl/StateManagerGL.h"
 #include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
 
 namespace rx
 {
 
-FramebufferGL::FramebufferGL(const gl::Framebuffer::Data &data, const FunctionsGL *functions, StateManagerGL *stateManager, bool isDefault)
+FramebufferGL::FramebufferGL(const gl::Framebuffer::Data &data,
+                             const FunctionsGL *functions,
+                             StateManagerGL *stateManager,
+                             const WorkaroundsGL &workarounds,
+                             bool isDefault)
     : FramebufferImpl(data),
       mFunctions(functions),
       mStateManager(stateManager),
+      mWorkarounds(workarounds),
       mFramebufferID(0),
       mIsDefault(isDefault)
 {
     if (!mIsDefault)
     {
         mFunctions->genFramebuffers(1, &mFramebufferID);
     }
 }
 
 FramebufferGL::FramebufferGL(GLuint id,
                              const gl::Framebuffer::Data &data,
                              const FunctionsGL *functions,
+                             const WorkaroundsGL &workarounds,
                              StateManagerGL *stateManager)
     : FramebufferImpl(data),
       mFunctions(functions),
       mStateManager(stateManager),
+      mWorkarounds(workarounds),
       mFramebufferID(id),
       mIsDefault(true)
 {
 }
 
 FramebufferGL::~FramebufferGL()
 {
     mStateManager->deleteFramebuffer(mFramebufferID);
@@ -192,48 +200,53 @@ gl::Error FramebufferGL::invalidateSub(s
                                              attachments, area.x, area.y, area.width, area.height);
     }
 
     return gl::Error(GL_NO_ERROR);
 }
 
 gl::Error FramebufferGL::clear(const gl::Data &data, GLbitfield mask)
 {
+    syncClearState(mask);
     mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
     mFunctions->clear(mask);
 
     return gl::Error(GL_NO_ERROR);
 }
 
 gl::Error FramebufferGL::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
 {
+    syncClearBufferState(buffer, drawbuffer);
     mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
     mFunctions->clearBufferfv(buffer, drawbuffer, values);
 
     return gl::Error(GL_NO_ERROR);
 }
 
 gl::Error FramebufferGL::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
 {
+    syncClearBufferState(buffer, drawbuffer);
     mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
     mFunctions->clearBufferuiv(buffer, drawbuffer, values);
 
     return gl::Error(GL_NO_ERROR);
 }
 
 gl::Error FramebufferGL::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
 {
+    syncClearBufferState(buffer, drawbuffer);
     mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
     mFunctions->clearBufferiv(buffer, drawbuffer, values);
 
     return gl::Error(GL_NO_ERROR);
 }
 
 gl::Error FramebufferGL::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
 {
+    syncClearBufferState(buffer, drawbuffer);
     mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
     mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
 
     return gl::Error(GL_NO_ERROR);
 }
 
 GLenum FramebufferGL::getImplementationColorReadFormat() const
 {
@@ -285,9 +298,77 @@ GLenum FramebufferGL::checkStatus() cons
     return mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
 }
 
 GLuint FramebufferGL::getFramebufferID() const
 {
     return mFramebufferID;
 }
 
+void FramebufferGL::syncDrawState() const
+{
+    if (mFunctions->standard == STANDARD_GL_DESKTOP)
+    {
+        // Enable SRGB blending for all framebuffers except the default framebuffer on Desktop
+        // OpenGL.
+        // When SRGB blending is enabled, only SRGB capable formats will use it but the default
+        // framebuffer will always use it if it is enabled.
+        // TODO(geofflang): Update this when the framebuffer binding dirty changes, when it exists.
+        mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
+    }
 }
+
+void FramebufferGL::syncClearState(GLbitfield mask)
+{
+    if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
+        (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
+    {
+        bool hasSRBAttachment = false;
+        for (const auto &attachment : mData.getColorAttachments())
+        {
+            if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
+            {
+                hasSRBAttachment = true;
+                break;
+            }
+        }
+
+        mStateManager->setFramebufferSRGBEnabled(hasSRBAttachment);
+    }
+    else
+    {
+        mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
+    }
+}
+
+void FramebufferGL::syncClearBufferState(GLenum buffer, GLint drawBuffer)
+{
+    if (mFunctions->standard == STANDARD_GL_DESKTOP)
+    {
+        if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
+            !mIsDefault)
+        {
+            // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
+            // is an SRGB format.
+            const auto &drawbufferState  = mData.getDrawBufferStates();
+            const auto &colorAttachments = mData.getColorAttachments();
+
+            const gl::FramebufferAttachment *attachment = nullptr;
+            if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
+                drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
+            {
+                size_t attachmentIdx =
+                    static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
+                attachment = &colorAttachments[attachmentIdx];
+            }
+
+            if (attachment != nullptr)
+            {
+                mStateManager->setFramebufferSRGBEnabled(attachment->getColorEncoding() == GL_SRGB);
+            }
+        }
+        else
+        {
+            mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
+        }
+    }
+}
+}
--- a/gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.h
+++ b/gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.h
@@ -11,27 +11,33 @@
 
 #include "libANGLE/renderer/FramebufferImpl.h"
 
 namespace rx
 {
 
 class FunctionsGL;
 class StateManagerGL;
+struct WorkaroundsGL;
 
 class FramebufferGL : public FramebufferImpl
 {
   public:
-    FramebufferGL(const gl::Framebuffer::Data &data, const FunctionsGL *functions, StateManagerGL *stateManager, bool isDefault);
+    FramebufferGL(const gl::Framebuffer::Data &data,
+                  const FunctionsGL *functions,
+                  StateManagerGL *stateManager,
+                  const WorkaroundsGL &workarounds,
+                  bool isDefault);
     // Constructor called when we need to create a FramebufferGL from an
     // existing framebuffer name, for example for the default framebuffer
     // on the Mac EGL CGL backend.
     FramebufferGL(GLuint id,
                   const gl::Framebuffer::Data &data,
                   const FunctionsGL *functions,
+                  const WorkaroundsGL &workarounds,
                   StateManagerGL *stateManager);
     ~FramebufferGL() override;
 
     void onUpdateColorAttachment(size_t index) override;
     void onUpdateDepthAttachment() override;
     void onUpdateStencilAttachment() override;
     void onUpdateDepthStencilAttachment() override;
 
@@ -52,21 +58,27 @@ class FramebufferGL : public Framebuffer
     GLenum getImplementationColorReadType() const override;
     gl::Error readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const override;
 
     gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
                    GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) override;
 
     GLenum checkStatus() const override;
 
+    void syncDrawState() const;
+
     GLuint getFramebufferID() const;
 
   private:
+    void syncClearState(GLbitfield mask);
+    void syncClearBufferState(GLenum buffer, GLint drawBuffer);
+
     const FunctionsGL *mFunctions;
     StateManagerGL *mStateManager;
+    const WorkaroundsGL &mWorkarounds;
 
     GLuint mFramebufferID;
     bool mIsDefault;
 };
 
 }
 
 #endif // LIBANGLE_RENDERER_GL_FRAMEBUFFERGL_H_
--- a/gfx/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp
+++ b/gfx/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp
@@ -887,16 +887,42 @@ void FunctionsGL::initialize()
     // GL_EXT_draw_instanced
     AssignGLExtensionEntryPoint(extensions, "GL_EXT_draw_instanced", loadProcAddress("glDrawArraysInstancedEXT"), &drawArraysInstanced);
     AssignGLExtensionEntryPoint(extensions, "GL_EXT_draw_instanced", loadProcAddress("glDrawElementsInstancedEXT"), &drawElementsInstanced);
 
     // GL_ARB_draw_instanced
     AssignGLExtensionEntryPoint(extensions, "GL_ARB_draw_instanced", loadProcAddress("glDrawArraysInstancedARB"), &drawArraysInstanced);
     AssignGLExtensionEntryPoint(extensions, "GL_ARB_draw_instanced", loadProcAddress("glDrawElementsInstancedARB"), &drawElementsInstanced);
 
+    // GL_ARB_sampler_objects
+    AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glGenSamplers"), &genSamplers);
+    AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glDeleteSamplers"), &deleteSamplers);
+    AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glIsSampler"), &isSampler);
+    AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glBindSampler"), &bindSampler);
+    AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glSample