Vulkan: Introduce vk::Format.

BUG=angleproject:1319

Change-Id: I88bcc6caa5d29565728848bada1563e47e383b29
Reviewed-on: https://chromium-review.googlesource.com/367753
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/angle_format.py b/src/libANGLE/renderer/angle_format.py
index e46bc7d..43ca684 100644
--- a/src/libANGLE/renderer/angle_format.py
+++ b/src/libANGLE/renderer/angle_format.py
@@ -8,6 +8,7 @@
 
 import json
 import os
+import re
 
 def reject_duplicate_keys(pairs):
     found_keys = {}
@@ -34,12 +35,136 @@
     reject_duplicate_keys(pairs)
     return { angle: gl for gl, angle in pairs }
 
-def load_with_override(override_path):
+def load_without_override():
     map_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'angle_format_map.json')
-    results = load_forward_table(map_path)
+    return load_forward_table(map_path)
+
+def load_with_override(override_path):
+    results = load_without_override()
     overrides = load_json(override_path)
 
     for k, v in overrides.iteritems():
         results[k] = v
 
     return results
+
+def get_component_type(format_id):
+    if "SNORM" in format_id:
+        return "snorm"
+    elif "UNORM" in format_id:
+        return "unorm"
+    elif "FLOAT" in format_id:
+        return "float"
+    elif "UINT" in format_id:
+        return "uint"
+    elif "SINT" in format_id:
+        return "int"
+    elif format_id == "NONE":
+        return "none"
+    elif "SRGB" in format_id:
+        return "unorm"
+    elif format_id == "R9G9B9E5_SHAREDEXP":
+        return "float"
+    else:
+        raise ValueError("Unknown component type for " + format_id)
+
+def get_channel_tokens(format_id):
+    r = re.compile(r'([ABDGLRS][\d]+)')
+    return filter(r.match, r.split(format_id))
+
+def get_channels(format_id):
+    channels = ''
+    tokens = get_channel_tokens(format_id)
+    if len(tokens) == 0:
+        return None
+    for token in tokens:
+        channels += token[0].lower()
+
+    return channels
+
+def get_bits(format_id):
+    bits = {}
+    tokens = get_channel_tokens(format_id)
+    if len(tokens) == 0:
+        return None
+    for token in tokens:
+        bits[token[0]] = int(token[1:])
+    return bits
+
+def get_format_info(format_id):
+    return get_component_type(format_id), get_bits(format_id), get_channels(format_id)
+
+# TODO(oetuaho): Expand this code so that it could generate the gl format info tables as well.
+def gl_format_channels(internal_format):
+    if internal_format == 'GL_BGR5_A1_ANGLEX':
+        return 'bgra'
+    if internal_format == 'GL_R11F_G11F_B10F':
+        return 'rgb'
+    if internal_format == 'GL_RGB5_A1':
+        return 'rgba'
+    if internal_format.find('GL_RGB10_A2') == 0:
+        return 'rgba'
+
+    channels_pattern = re.compile('GL_(COMPRESSED_)?(SIGNED_)?(ETC\d_)?([A-Z]+)')
+    match = re.search(channels_pattern, internal_format)
+    channels_string = match.group(4)
+
+    if channels_string == 'ALPHA':
+        return 'a'
+    if channels_string == 'LUMINANCE':
+        if (internal_format.find('ALPHA') >= 0):
+            return 'la'
+        return 'l'
+    if channels_string == 'SRGB':
+        if (internal_format.find('ALPHA') >= 0):
+            return 'rgba'
+        return 'rgb'
+    if channels_string == 'DEPTH':
+        if (internal_format.find('STENCIL') >= 0):
+            return 'ds'
+        return 'd'
+    if channels_string == 'STENCIL':
+        return 's'
+    return channels_string.lower()
+
+def get_internal_format_initializer(internal_format, format_id):
+    gl_channels = gl_format_channels(internal_format)
+    gl_format_no_alpha = gl_channels == 'rgb' or gl_channels == 'l'
+    component_type, bits, channels = get_format_info(format_id)
+
+    if not gl_format_no_alpha or channels != 'rgba':
+        return 'nullptr'
+
+    elif 'BC1_' in format_id:
+        # BC1 is a special case since the texture data determines whether each block has an alpha channel or not.
+        # This if statement is hit by COMPRESSED_RGB_S3TC_DXT1, which is a bit of a mess.
+        # TODO(oetuaho): Look into whether COMPRESSED_RGB_S3TC_DXT1 works right in general.
+        # Reference: https://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt
+        return 'nullptr'
+
+    elif component_type == 'uint' and bits['R'] == 8:
+        return 'Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0x01>'
+    elif component_type == 'unorm' and bits['R'] == 8:
+        return 'Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>'
+    elif component_type == 'unorm' and bits['R'] == 16:
+        return 'Initialize4ComponentData<GLubyte, 0x0000, 0x0000, 0x0000, 0xFFFF>'
+    elif component_type == 'int' and bits['R'] == 8:
+        return 'Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x01>'
+    elif component_type == 'snorm' and bits['R'] == 8:
+        return 'Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x7F>'
+    elif component_type == 'snorm' and bits['R'] == 16:
+        return 'Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x7FFF>'
+    elif component_type == 'float' and bits['R'] == 16:
+        return 'Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>'
+    elif component_type == 'uint' and bits['R'] == 16:
+        return 'Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x0001>'
+    elif component_type == 'int' and bits['R'] == 16:
+        return 'Initialize4ComponentData<GLshort, 0x0000, 0x0000, 0x0000, 0x0001>'
+    elif component_type == 'float' and bits['R'] == 32:
+        return 'Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>'
+    elif component_type == 'int' and bits['R'] == 32:
+        return 'Initialize4ComponentData<GLint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>'
+    elif component_type == 'uint' and bits['R'] == 32:
+        return 'Initialize4ComponentData<GLuint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>'
+    else:
+        raise ValueError('warning: internal format initializer could not be generated and may be needed for ' + internal_format)
diff --git a/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py b/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py
index db6a44b..02c600b 100644
--- a/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py
+++ b/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py
@@ -12,7 +12,6 @@
 import math
 import pprint
 import os
-import re
 import sys
 
 sys.path.append('../..')
@@ -69,81 +68,6 @@
 }}  // namespace rx
 """
 
-# TODO(oetuaho): Expand this code so that it could generate the gl format info tables as well.
-def gl_format_channels(internal_format):
-    if internal_format == 'GL_BGR5_A1_ANGLEX':
-        return 'bgra'
-    if internal_format == 'GL_R11F_G11F_B10F':
-        return 'rgb'
-    if internal_format == 'GL_RGB5_A1':
-        return 'rgba'
-    if internal_format.find('GL_RGB10_A2') == 0:
-        return 'rgba'
-
-    channels_pattern = re.compile('GL_(COMPRESSED_)?(SIGNED_)?(ETC\d_)?([A-Z]+)')
-    match = re.search(channels_pattern, internal_format)
-    channels_string = match.group(4)
-
-    if channels_string == 'ALPHA':
-        return 'a'
-    if channels_string == 'LUMINANCE':
-        if (internal_format.find('ALPHA') >= 0):
-            return 'la'
-        return 'l'
-    if channels_string == 'SRGB':
-        if (internal_format.find('ALPHA') >= 0):
-            return 'rgba'
-        return 'rgb'
-    if channels_string == 'DEPTH':
-        if (internal_format.find('STENCIL') >= 0):
-            return 'ds'
-        return 'd'
-    if channels_string == 'STENCIL':
-        return 's'
-    return channels_string.lower()
-
-def get_internal_format_initializer(internal_format, angle_format):
-    internal_format_initializer = 'nullptr'
-    gl_channels = gl_format_channels(internal_format)
-    gl_format_no_alpha = gl_channels == 'rgb' or gl_channels == 'l'
-    if gl_format_no_alpha and angle_format['channels'] == 'rgba':
-        if angle_format['texFormat'].startswith('DXGI_FORMAT_BC1_UNORM'):
-            # BC1 is a special case since the texture data determines whether each block has an alpha channel or not.
-            # This if statement is hit by COMPRESSED_RGB_S3TC_DXT1, which is a bit of a mess.
-            # TODO(oetuaho): Look into whether COMPRESSED_RGB_S3TC_DXT1 works right in general.
-            # Reference: https://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt
-            pass
-        elif 'componentType' not in angle_format:
-            raise ValueError('warning: internal format initializer could not be generated and may be needed for ' + internal_format)
-        elif angle_format['componentType'] == 'uint' and angle_format['bits']['red'] == 8:
-            internal_format_initializer = 'Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0x01>'
-        elif angle_format['componentType'] == 'unorm' and angle_format['bits']['red'] == 8:
-            internal_format_initializer = 'Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>'
-        elif angle_format['componentType'] == 'unorm' and angle_format['bits']['red'] == 16:
-            internal_format_initializer = 'Initialize4ComponentData<GLubyte, 0x0000, 0x0000, 0x0000, 0xFFFF>'
-        elif angle_format['componentType'] == 'int' and angle_format['bits']['red'] == 8:
-            internal_format_initializer = 'Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x01>'
-        elif angle_format['componentType'] == 'snorm' and angle_format['bits']['red'] == 8:
-            internal_format_initializer = 'Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x7F>'
-        elif angle_format['componentType'] == 'snorm' and angle_format['bits']['red'] == 16:
-            internal_format_initializer = 'Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x7FFF>'
-        elif angle_format['componentType'] == 'float' and angle_format['bits']['red'] == 16:
-            internal_format_initializer = 'Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>'
-        elif angle_format['componentType'] == 'uint' and angle_format['bits']['red'] == 16:
-            internal_format_initializer = 'Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x0001>'
-        elif angle_format['componentType'] == 'int' and angle_format['bits']['red'] == 16:
-            internal_format_initializer = 'Initialize4ComponentData<GLshort, 0x0000, 0x0000, 0x0000, 0x0001>'
-        elif angle_format['componentType'] == 'float' and angle_format['bits']['red'] == 32:
-            internal_format_initializer = 'Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>'
-        elif angle_format['componentType'] == 'int' and angle_format['bits']['red'] == 32:
-            internal_format_initializer = 'Initialize4ComponentData<GLint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>'
-        elif angle_format['componentType'] == 'uint' and angle_format['bits']['red'] == 32:
-            internal_format_initializer = 'Initialize4ComponentData<GLuint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>'
-        else:
-            raise ValueError('warning: internal format initializer could not be generated and may be needed for ' + internal_format)
-
-    return internal_format_initializer
-
 def get_swizzle_format_id(internal_format, angle_format):
     angle_format_id = angle_format["formatName"]
     if (internal_format == 'GL_NONE') or (angle_format_id == 'NONE'):
@@ -265,7 +189,8 @@
     # Derived values.
     parsed["blitSRVFormat"] = get_blit_srv_format(parsed)
     parsed["swizzleFormat"] = get_swizzle_format_id(internal_format, parsed)
-    parsed["initializer"]   = get_internal_format_initializer(internal_format, json)
+    parsed["initializer"]   = angle_format.get_internal_format_initializer(
+        internal_format, parsed["formatName"])
 
     if len(prefix) > 0:
         return split_format_entry_template.format(**parsed)
@@ -332,29 +257,16 @@
 
     return table_data
 
-def reject_duplicate_keys(pairs):
-    found_keys = {}
-    for key, value in pairs:
-        if key in found_keys:
-           raise ValueError("duplicate key: %r" % (key,))
-        else:
-           found_keys[key] = value
-    return found_keys
-
 json_map = angle_format.load_with_override(os.path.abspath('texture_format_map.json'))
 data_source_name = 'texture_format_data.json'
+json_data = angle_format.load_json(data_source_name)
 
-with open(data_source_name) as texture_format_json_file:
-    texture_format_data = texture_format_json_file.read()
-    texture_format_json_file.close()
-    json_data = json.loads(texture_format_data, object_pairs_hook=angle_format.reject_duplicate_keys)
-
-    angle_format_cases = parse_json_into_switch_angle_format_string(json_map, json_data)
-    output_cpp = template_texture_format_table_autogen_cpp.format(
-        script_name = sys.argv[0],
-        copyright_year = date.today().year,
-        angle_format_info_cases = angle_format_cases,
-        data_source_name = data_source_name)
-    with open('texture_format_table_autogen.cpp', 'wt') as out_file:
-        out_file.write(output_cpp)
-        out_file.close()
+angle_format_cases = parse_json_into_switch_angle_format_string(json_map, json_data)
+output_cpp = template_texture_format_table_autogen_cpp.format(
+    script_name = sys.argv[0],
+    copyright_year = date.today().year,
+    angle_format_info_cases = angle_format_cases,
+    data_source_name = data_source_name)
+with open('texture_format_table_autogen.cpp', 'wt') as out_file:
+    out_file.write(output_cpp)
+    out_file.close()
diff --git a/src/libANGLE/renderer/d3d/formatutilsD3D.h b/src/libANGLE/renderer/d3d/formatutilsD3D.h
index 4893beb..a245a04 100644
--- a/src/libANGLE/renderer/d3d/formatutilsD3D.h
+++ b/src/libANGLE/renderer/d3d/formatutilsD3D.h
@@ -24,9 +24,6 @@
 
 namespace rx
 {
-typedef void (*InitializeTextureDataFunction)(size_t width, size_t height, size_t depth,
-                                              uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
 typedef void (*VertexCopyFunction)(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
 
 enum VertexConversionType
diff --git a/src/libANGLE/renderer/gen_angle_format_table.py b/src/libANGLE/renderer/gen_angle_format_table.py
index 6b56bb4..f47a024 100644
--- a/src/libANGLE/renderer/gen_angle_format_table.py
+++ b/src/libANGLE/renderer/gen_angle_format_table.py
@@ -126,47 +126,6 @@
 format_entry_template = """    {{ Format::ID::{id}, {glInternalFormat}, {fboImplementationInternalFormat}, {mipGenerationFunction}, {fastCopyFunctions}, {colorReadFunction}, {namedComponentType}, {R}, {G}, {B}, {A}, {D}, {S} }},
 """
 
-def get_component_type(format_id):
-    if "SNORM" in format_id:
-        return "snorm"
-    elif "UNORM" in format_id:
-        return "unorm"
-    elif "FLOAT" in format_id:
-        return "float"
-    elif "UINT" in format_id:
-        return "uint"
-    elif "SINT" in format_id:
-        return "int"
-    elif format_id == "NONE":
-        return "none"
-    elif "SRGB" in format_id:
-        return "unorm"
-    else:
-        raise ValueError("Unknown component type for " + format_id)
-
-def get_channel_tokens(format_id):
-    r = re.compile(r'([ABDGLRS][\d]+)')
-    return filter(r.match, r.split(format_id))
-
-def get_channels(format_id):
-    channels = ''
-    tokens = get_channel_tokens(format_id)
-    if len(tokens) == 0:
-        return None
-    for token in tokens:
-        channels += token[0].lower()
-
-    return channels
-
-def get_bits(format_id):
-    bits = {}
-    tokens = get_channel_tokens(format_id)
-    if len(tokens) == 0:
-        return None
-    for token in tokens:
-        bits[token[0]] = int(token[1:])
-    return bits
-
 def get_named_component_type(component_type):
     if component_type == "snorm":
         return "GL_SIGNED_NORMALIZED"
@@ -202,13 +161,13 @@
         parsed["fboImplementationInternalFormat"] = parsed["glInternalFormat"]
 
     if "componentType" not in parsed:
-        parsed["componentType"] = get_component_type(format_id)
+        parsed["componentType"] = angle_format.get_component_type(format_id)
 
     if "channels" not in parsed:
-        parsed["channels"] = get_channels(format_id)
+        parsed["channels"] = angle_format.get_channels(format_id)
 
     if "bits" not in parsed:
-        parsed["bits"] = get_bits(format_id)
+        parsed["bits"] = angle_format.get_bits(format_id)
 
     # Derived values.
     parsed["mipGenerationFunction"] = get_mip_generation_function(parsed)
diff --git a/src/libANGLE/renderer/renderer_utils.h b/src/libANGLE/renderer/renderer_utils.h
index 440548e..803c8c2 100644
--- a/src/libANGLE/renderer/renderer_utils.h
+++ b/src/libANGLE/renderer/renderer_utils.h
@@ -95,6 +95,13 @@
 ColorCopyFunction GetFastCopyFunction(const FastCopyFunctionMap &fastCopyFunctions,
                                       const gl::FormatType &formatType);
 
+using InitializeTextureDataFunction = void (*)(size_t width,
+                                               size_t height,
+                                               size_t depth,
+                                               uint8_t *output,
+                                               size_t outputRowPitch,
+                                               size_t outputDepthPitch);
+
 using LoadImageFunction = void (*)(size_t width,
                                    size_t height,
                                    size_t depth,
diff --git a/src/libANGLE/renderer/vulkan/SurfaceVk.cpp b/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
index 2b433bd..bad05e3 100644
--- a/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
+++ b/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
@@ -14,6 +14,7 @@
 #include "libANGLE/renderer/vulkan/DisplayVk.h"
 #include "libANGLE/renderer/vulkan/FramebufferVk.h"
 #include "libANGLE/renderer/vulkan/RendererVk.h"
+#include "libANGLE/renderer/vulkan/formatutilsvk.h"
 
 namespace rx
 {
@@ -21,10 +22,10 @@
 namespace
 {
 
-VkFormat GetVkFormatFromConfig(const egl::Config &config)
+const vk::Format &GetVkFormatFromConfig(const egl::Config &config)
 {
     // TODO(jmadill): Properly handle format interpretation.
-    return VK_FORMAT_B8G8R8A8_UNORM;
+    return vk::Format::Get(GL_BGRA8_EXT);
 }
 
 }  // namespace
@@ -239,7 +240,7 @@
         preTransform = surfaceCaps.currentTransform;
     }
 
-    VkFormat configSurfaceFormat = GetVkFormatFromConfig(*mState.config);
+    const vk::Format &configSurfaceFormat = GetVkFormatFromConfig(*mState.config);
 
     uint32_t surfaceFormatCount = 0;
     ANGLE_VK_TRY(vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, mSurface, &surfaceFormatCount,
@@ -258,7 +259,7 @@
         bool foundFormat = false;
         for (const auto &surfaceFormat : surfaceFormats)
         {
-            if (surfaceFormat.format == configSurfaceFormat)
+            if (surfaceFormat.format == configSurfaceFormat.native)
             {
                 foundFormat = true;
                 break;
@@ -274,7 +275,7 @@
     swapchainInfo.flags                 = 0;
     swapchainInfo.surface               = mSurface;
     swapchainInfo.minImageCount         = minImageCount;
-    swapchainInfo.imageFormat           = configSurfaceFormat;
+    swapchainInfo.imageFormat           = configSurfaceFormat.native;
     swapchainInfo.imageColorSpace       = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
     swapchainInfo.imageExtent.width     = mWidth;
     swapchainInfo.imageExtent.height    = mHeight;
@@ -311,7 +312,7 @@
         imageViewInfo.flags                           = 0;
         imageViewInfo.image                           = swapchainImage;
         imageViewInfo.viewType                        = VK_IMAGE_VIEW_TYPE_2D;
-        imageViewInfo.format                          = configSurfaceFormat;
+        imageViewInfo.format                          = configSurfaceFormat.native;
         imageViewInfo.components.r                    = VK_COMPONENT_SWIZZLE_R;
         imageViewInfo.components.g                    = VK_COMPONENT_SWIZZLE_G;
         imageViewInfo.components.b                    = VK_COMPONENT_SWIZZLE_B;
diff --git a/src/libANGLE/renderer/vulkan/formatutilsvk.cpp b/src/libANGLE/renderer/vulkan/formatutilsvk.cpp
new file mode 100644
index 0000000..a858284
--- /dev/null
+++ b/src/libANGLE/renderer/vulkan/formatutilsvk.cpp
@@ -0,0 +1,31 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// formatutilsvk:
+//   Helper for Vulkan format code.
+
+#include "libANGLE/renderer/vulkan/formatutilsvk.h"
+
+#include "libANGLE/renderer/load_functions_table.h"
+
+namespace rx
+{
+
+namespace vk
+{
+
+const angle::Format &Format::format() const
+{
+    return angle::Format::Get(formatID);
+}
+
+LoadFunctionMap Format::getLoadFunctions() const
+{
+    return GetLoadFunctionsMap(internalFormat, formatID);
+}
+
+}  // namespace vk
+
+}  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/formatutilsvk.h b/src/libANGLE/renderer/vulkan/formatutilsvk.h
new file mode 100644
index 0000000..48d1e14
--- /dev/null
+++ b/src/libANGLE/renderer/vulkan/formatutilsvk.h
@@ -0,0 +1,56 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Vk::Format:
+//   Vulkan implementation of a storage format.
+
+#ifndef LIBANGLE_RENDERER_VULKAN_FORMAT_H_
+#define LIBANGLE_RENDERER_VULKAN_FORMAT_H_
+
+#include <vulkan/vulkan.h>
+
+#include "libANGLE/renderer/Format.h"
+#include "libANGLE/renderer/renderer_utils.h"
+
+namespace rx
+{
+
+namespace vk
+{
+
+struct Format final : angle::NonCopyable
+{
+    constexpr Format(GLenum internalFormat,
+                     angle::Format::ID formatID,
+                     VkFormat native,
+                     InitializeTextureDataFunction initFunction);
+
+    static const Format &Get(GLenum internalFormat);
+
+    const angle::Format &format() const;
+    LoadFunctionMap getLoadFunctions() const;
+
+    GLenum internalFormat;
+    angle::Format::ID formatID;
+    VkFormat native;
+    InitializeTextureDataFunction dataInitializerFunction;
+};
+
+constexpr Format::Format(GLenum internalFormat,
+                         angle::Format::ID formatID,
+                         VkFormat native,
+                         InitializeTextureDataFunction initFunction)
+    : internalFormat(internalFormat),
+      formatID(formatID),
+      native(native),
+      dataInitializerFunction(initFunction)
+{
+}
+
+}  // namespace vk
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_FORMAT_H_
diff --git a/src/libANGLE/renderer/vulkan/gen_vk_format_table.py b/src/libANGLE/renderer/vulkan/gen_vk_format_table.py
new file mode 100644
index 0000000..38e7c58
--- /dev/null
+++ b/src/libANGLE/renderer/vulkan/gen_vk_format_table.py
@@ -0,0 +1,123 @@
+#!/usr/bin/python
+# Copyright 2016 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# gen_vk_format_table.py:
+#  Code generation for vk format map
+
+from datetime import date
+import json
+import math
+import pprint
+import os
+import re
+import sys
+
+sys.path.append('..')
+import angle_format
+
+template_table_autogen_cpp = """// GENERATED FILE - DO NOT EDIT.
+// Generated by {script_name} using data from {input_file_name}
+//
+// Copyright {copyright_year} 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.
+//
+// {out_file_name}:
+//   Queries for full Vulkan format information based on GL format.
+
+#include "libANGLE/renderer/vulkan/formatutilsvk.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+using namespace angle;
+
+namespace rx
+{{
+
+namespace vk
+{{
+
+// static
+const Format &Format::Get(GLenum internalFormat)
+{{
+    // clang-format off
+    switch (internalFormat)
+    {{
+{format_case_data}
+        default:
+            break;
+    }}
+    // clang-format on
+
+    UNREACHABLE();
+    static const Format noInfo(GL_NONE, angle::Format::ID::NONE, VK_FORMAT_UNDEFINED, nullptr);
+    return noInfo;
+}}
+
+}}  // namespace vk
+
+}}  // namespace rx
+"""
+
+format_entry_template = """{space}{{
+{space}    static constexpr Format info({internalFormat},
+{space}                                 angle::Format::ID::{formatName},
+{space}                                 {vkFormat},
+{space}                                 {initializer});
+{space}    return info;
+{space}}}
+"""
+
+def parse_format_case(internal_format, format_name, native_format):
+
+    table_data = ""
+
+    parsed = {
+        "space": "        ",
+        "internalFormat": internal_format,
+        "formatName": format_name,
+        "vkFormat": native_format,
+    }
+
+    # Derived values.
+    parsed["initializer"] = angle_format.get_internal_format_initializer(
+        internal_format, format_name)
+
+    return format_entry_template.format(**parsed)
+
+def parse_json_into_cases(json_map, vk_map):
+    table_data = ''
+
+    for internal_format, format_name in sorted(json_map.iteritems()):
+
+        if format_name not in vk_map:
+            continue
+
+        native_format = vk_map[format_name]
+
+        table_data += '        case ' + internal_format + ':\n'
+        table_data += parse_format_case(internal_format, format_name, native_format)
+
+    return table_data
+
+input_file_name = 'vk_format_map.json'
+out_file_name = 'vk_format_table'
+
+json_map = angle_format.load_without_override()
+vk_map = angle_format.load_json(input_file_name)
+
+format_case_data = parse_json_into_cases(json_map, vk_map)
+output_cpp = template_table_autogen_cpp.format(
+    copyright_year = date.today().year,
+    format_case_data = format_case_data,
+    script_name = __file__,
+    out_file_name = out_file_name,
+    input_file_name = input_file_name)
+
+with open(out_file_name + '_autogen.cpp', 'wt') as out_file:
+    out_file.write(output_cpp)
+    out_file.close()
diff --git a/src/libANGLE/renderer/vulkan/vk_format_map.json b/src/libANGLE/renderer/vulkan/vk_format_map.json
new file mode 100644
index 0000000..dce60b7
--- /dev/null
+++ b/src/libANGLE/renderer/vulkan/vk_format_map.json
@@ -0,0 +1,161 @@
+{
+    "NONE": "VK_FORMAT_UNDEFINED",
+    "R4G4B4A4_UNORM": "VK_FORMAT_R4G4B4A4_UNORM_PACK16",
+    "B4G4R4A4_UNORM": "VK_FORMAT_B4G4R4A4_UNORM_PACK16",
+    "R5G6B5_UNORM": "VK_FORMAT_R5G6B5_UNORM_PACK16",
+    "B5G6R5_UNORM": "VK_FORMAT_B5G6R5_UNORM_PACK16",
+    "R5G5B5A1_UNORM": "VK_FORMAT_R5G5B5A1_UNORM_PACK16",
+    "B5G5R5A1_UNORM": "VK_FORMAT_B5G5R5A1_UNORM_PACK16",
+    "A1R5G5B5_UNORM": "VK_FORMAT_A1R5G5B5_UNORM_PACK16",
+    "R8_UNORM": "VK_FORMAT_R8_UNORM",
+    "R8_SNORM": "VK_FORMAT_R8_SNORM",
+    "R8_UINT": "VK_FORMAT_R8_UINT",
+    "R8_SINT": "VK_FORMAT_R8_SINT",
+    "R8_SRGB": "VK_FORMAT_R8_SRGB",
+    "R8G8_UNORM": "VK_FORMAT_R8G8_UNORM",
+    "R8G8_SNORM": "VK_FORMAT_R8G8_SNORM",
+    "R8G8_UINT": "VK_FORMAT_R8G8_UINT",
+    "R8G8_SINT": "VK_FORMAT_R8G8_SINT",
+    "R8G8_SRGB": "VK_FORMAT_R8G8_SRGB",
+    "R8G8B8_UNORM": "VK_FORMAT_R8G8B8_UNORM",
+    "R8G8B8_SNORM": "VK_FORMAT_R8G8B8_SNORM",
+    "R8G8B8_UINT": "VK_FORMAT_R8G8B8_UINT",
+    "R8G8B8_SINT": "VK_FORMAT_R8G8B8_SINT",
+    "R8G8B8_SRGB": "VK_FORMAT_R8G8B8_SRGB",
+    "B8G8R8_UNORM": "VK_FORMAT_B8G8R8_UNORM",
+    "B8G8R8_SNORM": "VK_FORMAT_B8G8R8_SNORM",
+    "B8G8R8_UINT": "VK_FORMAT_B8G8R8_UINT",
+    "B8G8R8_SINT": "VK_FORMAT_B8G8R8_SINT",
+    "B8G8R8_SRGB": "VK_FORMAT_B8G8R8_SRGB",
+    "R8G8B8A8_UNORM": "VK_FORMAT_R8G8B8A8_UNORM",
+    "R8G8B8A8_SNORM": "VK_FORMAT_R8G8B8A8_SNORM",
+    "R8G8B8A8_UINT": "VK_FORMAT_R8G8B8A8_UINT",
+    "R8G8B8A8_SINT": "VK_FORMAT_R8G8B8A8_SINT",
+    "R8G8B8A8_SRGB": "VK_FORMAT_R8G8B8A8_SRGB",
+    "B8G8R8A8_UNORM": "VK_FORMAT_B8G8R8A8_UNORM",
+    "B8G8R8A8_SNORM": "VK_FORMAT_B8G8R8A8_SNORM",
+    "B8G8R8A8_USCALED": "VK_FORMAT_B8G8R8A8_USCALED",
+    "B8G8R8A8_SSCALED": "VK_FORMAT_B8G8R8A8_SSCALED",
+    "B8G8R8A8_UINT": "VK_FORMAT_B8G8R8A8_UINT",
+    "B8G8R8A8_SINT": "VK_FORMAT_B8G8R8A8_SINT",
+    "B8G8R8A8_SRGB": "VK_FORMAT_B8G8R8A8_SRGB",
+    "A2R10G10B10_UNORM_PACK32": "VK_FORMAT_A2R10G10B10_UNORM_PACK32",
+    "A2R10G10B10_SNORM_PACK32": "VK_FORMAT_A2R10G10B10_SNORM_PACK32",
+    "A2R10G10B10_USCALED_PACK32": "VK_FORMAT_A2R10G10B10_USCALED_PACK32",
+    "A2R10G10B10_SSCALED_PACK32": "VK_FORMAT_A2R10G10B10_SSCALED_PACK32",
+    "A2R10G10B10_UINT_PACK32": "VK_FORMAT_A2R10G10B10_UINT_PACK32",
+    "A2R10G10B10_SINT_PACK32": "VK_FORMAT_A2R10G10B10_SINT_PACK32",
+    "A2B10G10R10_UNORM_PACK32": "VK_FORMAT_A2B10G10R10_UNORM_PACK32",
+    "A2B10G10R10_SNORM_PACK32": "VK_FORMAT_A2B10G10R10_SNORM_PACK32",
+    "A2B10G10R10_USCALED_PACK32": "VK_FORMAT_A2B10G10R10_USCALED_PACK32",
+    "A2B10G10R10_SSCALED_PACK32": "VK_FORMAT_A2B10G10R10_SSCALED_PACK32",
+    "A2B10G10R10_UINT_PACK32": "VK_FORMAT_A2B10G10R10_UINT_PACK32",
+    "A2B10G10R10_SINT_PACK32": "VK_FORMAT_A2B10G10R10_SINT_PACK32",
+    "R16_UNORM": "VK_FORMAT_R16_UNORM",
+    "R16_SNORM": "VK_FORMAT_R16_SNORM",
+    "R16_UINT": "VK_FORMAT_R16_UINT",
+    "R16_SINT": "VK_FORMAT_R16_SINT",
+    "R16_FLOAT": "VK_FORMAT_R16_SFLOAT",
+    "R16G16_UNORM": "VK_FORMAT_R16G16_UNORM",
+    "R16G16_SNORM": "VK_FORMAT_R16G16_SNORM",
+    "R16G16_UINT": "VK_FORMAT_R16G16_UINT",
+    "R16G16_SINT": "VK_FORMAT_R16G16_SINT",
+    "R16G16_FLOAT": "VK_FORMAT_R16G16_SFLOAT",
+    "R16G16B16_UNORM": "VK_FORMAT_R16G16B16_UNORM",
+    "R16G16B16_SNORM": "VK_FORMAT_R16G16B16_SNORM",
+    "R16G16B16_UINT": "VK_FORMAT_R16G16B16_UINT",
+    "R16G16B16_SINT": "VK_FORMAT_R16G16B16_SINT",
+    "R16G16B16_FLOAT": "VK_FORMAT_R16G16B16_SFLOAT",
+    "R16G16B16A16_UNORM": "VK_FORMAT_R16G16B16A16_UNORM",
+    "R16G16B16A16_SNORM": "VK_FORMAT_R16G16B16A16_SNORM",
+    "R16G16B16A16_UINT": "VK_FORMAT_R16G16B16A16_UINT",
+    "R16G16B16A16_SINT": "VK_FORMAT_R16G16B16A16_SINT",
+    "R16G16B16A16_FLOAT": "VK_FORMAT_R16G16B16A16_SFLOAT",
+    "R32_UINT": "VK_FORMAT_R32_UINT",
+    "R32_SINT": "VK_FORMAT_R32_SINT",
+    "R32_FLOAT": "VK_FORMAT_R32_SFLOAT",
+    "R32G32_UINT": "VK_FORMAT_R32G32_UINT",
+    "R32G32_SINT": "VK_FORMAT_R32G32_SINT",
+    "R32G32_FLOAT": "VK_FORMAT_R32G32_SFLOAT",
+    "R32G32B32_UINT": "VK_FORMAT_R32G32B32_UINT",
+    "R32G32B32_SINT": "VK_FORMAT_R32G32B32_SINT",
+    "R32G32B32_FLOAT": "VK_FORMAT_R32G32B32_SFLOAT",
+    "R32G32B32A32_UINT": "VK_FORMAT_R32G32B32A32_UINT",
+    "R32G32B32A32_SINT": "VK_FORMAT_R32G32B32A32_SINT",
+    "R32G32B32A32_FLOAT": "VK_FORMAT_R32G32B32A32_SFLOAT",
+    "R64_UINT": "VK_FORMAT_R64_UINT",
+    "R64_SINT": "VK_FORMAT_R64_SINT",
+    "R64_FLOAT": "VK_FORMAT_R64_SFLOAT",
+    "R64G64_UINT": "VK_FORMAT_R64G64_UINT",
+    "R64G64_SINT": "VK_FORMAT_R64G64_SINT",
+    "R64G64_FLOAT": "VK_FORMAT_R64G64_SFLOAT",
+    "R64G64B64_UINT": "VK_FORMAT_R64G64B64_UINT",
+    "R64G64B64_SINT": "VK_FORMAT_R64G64B64_SINT",
+    "R64G64B64_FLOAT": "VK_FORMAT_R64G64B64_SFLOAT",
+    "R64G64B64A64_UINT": "VK_FORMAT_R64G64B64A64_UINT",
+    "R64G64B64A64_SINT": "VK_FORMAT_R64G64B64A64_SINT",
+    "R64G64B64A64_FLOAT": "VK_FORMAT_R64G64B64A64_SFLOAT",
+    "B10G11R11_UFLOAT_PACK32": "VK_FORMAT_B10G11R11_UFLOAT_PACK32",
+    "E5B9G9R9_UFLOAT_PACK32": "VK_FORMAT_E5B9G9R9_UFLOAT_PACK32",
+    "D16_UNORM": "VK_FORMAT_D16_UNORM",
+    "X8_D24_UNORM_PACK32": "VK_FORMAT_X8_D24_UNORM_PACK32",
+    "D32_FLOAT": "VK_FORMAT_D32_SFLOAT",
+    "S8_UINT": "VK_FORMAT_S8_UINT",
+    "D16_UNORM_S8_UINT": "VK_FORMAT_D16_UNORM_S8_UINT",
+    "D24_UNORM_S8_UINT": "VK_FORMAT_D24_UNORM_S8_UINT",
+    "D32_SFLOAT_S8_UINT": "VK_FORMAT_D32_SFLOAT_S8_UINT",
+    "BC1_RGB_UNORM_BLOCK": "VK_FORMAT_BC1_RGB_UNORM_BLOCK",
+    "BC1_RGB_SRGB_BLOCK": "VK_FORMAT_BC1_RGB_SRGB_BLOCK",
+    "BC1_RGBA_UNORM_BLOCK": "VK_FORMAT_BC1_RGBA_UNORM_BLOCK",
+    "BC1_RGBA_SRGB_BLOCK": "VK_FORMAT_BC1_RGBA_SRGB_BLOCK",
+    "BC2_UNORM_BLOCK": "VK_FORMAT_BC2_UNORM_BLOCK",
+    "BC2_SRGB_BLOCK": "VK_FORMAT_BC2_SRGB_BLOCK",
+    "BC3_UNORM_BLOCK": "VK_FORMAT_BC3_UNORM_BLOCK",
+    "BC3_SRGB_BLOCK": "VK_FORMAT_BC3_SRGB_BLOCK",
+    "BC4_UNORM_BLOCK": "VK_FORMAT_BC4_UNORM_BLOCK",
+    "BC4_SNORM_BLOCK": "VK_FORMAT_BC4_SNORM_BLOCK",
+    "BC5_UNORM_BLOCK": "VK_FORMAT_BC5_UNORM_BLOCK",
+    "BC5_SNORM_BLOCK": "VK_FORMAT_BC5_SNORM_BLOCK",
+    "BC6H_UFLOAT_BLOCK": "VK_FORMAT_BC6H_UFLOAT_BLOCK",
+    "BC6H_SFLOAT_BLOCK": "VK_FORMAT_BC6H_SFLOAT_BLOCK",
+    "BC7_UNORM_BLOCK": "VK_FORMAT_BC7_UNORM_BLOCK",
+    "BC7_SRGB_BLOCK": "VK_FORMAT_BC7_SRGB_BLOCK",
+    "ETC2_R8G8B8_UNORM_BLOCK": "VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK",
+    "ETC2_R8G8B8_SRGB_BLOCK": "VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK",
+    "ETC2_R8G8B8A1_UNORM_BLOCK": "VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK",
+    "ETC2_R8G8B8A1_SRGB_BLOCK": "VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK",
+    "ETC2_R8G8B8A8_UNORM_BLOCK": "VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK",
+    "ETC2_R8G8B8A8_SRGB_BLOCK": "VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK",
+    "EAC_R11_UNORM_BLOCK": "VK_FORMAT_EAC_R11_UNORM_BLOCK",
+    "EAC_R11_SNORM_BLOCK": "VK_FORMAT_EAC_R11_SNORM_BLOCK",
+    "EAC_R11G11_UNORM_BLOCK": "VK_FORMAT_EAC_R11G11_UNORM_BLOCK",
+    "EAC_R11G11_SNORM_BLOCK": "VK_FORMAT_EAC_R11G11_SNORM_BLOCK",
+    "ASTC_4x4_UNORM_BLOCK": "VK_FORMAT_ASTC_4x4_UNORM_BLOCK",
+    "ASTC_4x4_SRGB_BLOCK": "VK_FORMAT_ASTC_4x4_SRGB_BLOCK",
+    "ASTC_5x4_UNORM_BLOCK": "VK_FORMAT_ASTC_5x4_UNORM_BLOCK",
+    "ASTC_5x4_SRGB_BLOCK": "VK_FORMAT_ASTC_5x4_SRGB_BLOCK",
+    "ASTC_5x5_UNORM_BLOCK": "VK_FORMAT_ASTC_5x5_UNORM_BLOCK",
+    "ASTC_5x5_SRGB_BLOCK": "VK_FORMAT_ASTC_5x5_SRGB_BLOCK",
+    "ASTC_6x5_UNORM_BLOCK": "VK_FORMAT_ASTC_6x5_UNORM_BLOCK",
+    "ASTC_6x5_SRGB_BLOCK": "VK_FORMAT_ASTC_6x5_SRGB_BLOCK",
+    "ASTC_6x6_UNORM_BLOCK": "VK_FORMAT_ASTC_6x6_UNORM_BLOCK",
+    "ASTC_6x6_SRGB_BLOCK": "VK_FORMAT_ASTC_6x6_SRGB_BLOCK",
+    "ASTC_8x5_UNORM_BLOCK": "VK_FORMAT_ASTC_8x5_UNORM_BLOCK",
+    "ASTC_8x5_SRGB_BLOCK": "VK_FORMAT_ASTC_8x5_SRGB_BLOCK",
+    "ASTC_8x6_UNORM_BLOCK": "VK_FORMAT_ASTC_8x6_UNORM_BLOCK",
+    "ASTC_8x6_SRGB_BLOCK": "VK_FORMAT_ASTC_8x6_SRGB_BLOCK",
+    "ASTC_8x8_UNORM_BLOCK": "VK_FORMAT_ASTC_8x8_UNORM_BLOCK",
+    "ASTC_8x8_SRGB_BLOCK": "VK_FORMAT_ASTC_8x8_SRGB_BLOCK",
+    "ASTC_10x5_UNORM_BLOCK": "VK_FORMAT_ASTC_10x5_UNORM_BLOCK",
+    "ASTC_10x5_SRGB_BLOCK": "VK_FORMAT_ASTC_10x5_SRGB_BLOCK",
+    "ASTC_10x6_UNORM_BLOCK": "VK_FORMAT_ASTC_10x6_UNORM_BLOCK",
+    "ASTC_10x6_SRGB_BLOCK": "VK_FORMAT_ASTC_10x6_SRGB_BLOCK",
+    "ASTC_10x8_UNORM_BLOCK": "VK_FORMAT_ASTC_10x8_UNORM_BLOCK",
+    "ASTC_10x8_SRGB_BLOCK": "VK_FORMAT_ASTC_10x8_SRGB_BLOCK",
+    "ASTC_10x10_UNORM_BLOCK": "VK_FORMAT_ASTC_10x10_UNORM_BLOCK",
+    "ASTC_10x10_SRGB_BLOCK": "VK_FORMAT_ASTC_10x10_SRGB_BLOCK",
+    "ASTC_12x10_UNORM_BLOCK": "VK_FORMAT_ASTC_12x10_UNORM_BLOCK",
+    "ASTC_12x10_SRGB_BLOCK": "VK_FORMAT_ASTC_12x10_SRGB_BLOCK",
+    "ASTC_12x12_UNORM_BLOCK": "VK_FORMAT_ASTC_12x12_UNORM_BLOCK",
+    "ASTC_12x12_SRGB_BLOC": "VK_FORMAT_ASTC_12x12_SRGB_BLOCK"
+}
diff --git a/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp b/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp
new file mode 100644
index 0000000..40778d2
--- /dev/null
+++ b/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp
@@ -0,0 +1,868 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_vk_format_table.py using data from vk_format_map.json
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// vk_format_table:
+//   Queries for full Vulkan format information based on GL format.
+
+#include "libANGLE/renderer/vulkan/formatutilsvk.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+using namespace angle;
+
+namespace rx
+{
+
+namespace vk
+{
+
+// static
+const Format &Format::Get(GLenum internalFormat)
+{
+    // clang-format off
+    switch (internalFormat)
+    {
+        case GL_BGR565_ANGLEX:
+        {
+            static constexpr Format info(GL_BGR565_ANGLEX,
+                                         angle::Format::ID::B5G6R5_UNORM,
+                                         VK_FORMAT_B5G6R5_UNORM_PACK16,
+                                         nullptr);
+            return info;
+        }
+        case GL_BGR5_A1_ANGLEX:
+        {
+            static constexpr Format info(GL_BGR5_A1_ANGLEX,
+                                         angle::Format::ID::B5G5R5A1_UNORM,
+                                         VK_FORMAT_B5G5R5A1_UNORM_PACK16,
+                                         nullptr);
+            return info;
+        }
+        case GL_BGRA4_ANGLEX:
+        {
+            static constexpr Format info(GL_BGRA4_ANGLEX,
+                                         angle::Format::ID::B4G4R4A4_UNORM,
+                                         VK_FORMAT_B4G4R4A4_UNORM_PACK16,
+                                         nullptr);
+            return info;
+        }
+        case GL_BGRA8_EXT:
+        {
+            static constexpr Format info(GL_BGRA8_EXT,
+                                         angle::Format::ID::B8G8R8A8_UNORM,
+                                         VK_FORMAT_B8G8R8A8_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_R11_EAC:
+        {
+            static constexpr Format info(GL_COMPRESSED_R11_EAC,
+                                         angle::Format::ID::EAC_R11_UNORM_BLOCK,
+                                         VK_FORMAT_EAC_R11_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RG11_EAC:
+        {
+            static constexpr Format info(GL_COMPRESSED_RG11_EAC,
+                                         angle::Format::ID::EAC_R11G11_UNORM_BLOCK,
+                                         VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGB8_ETC2:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGB8_ETC2,
+                                         angle::Format::ID::ETC2_R8G8B8_UNORM_BLOCK,
+                                         VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+                                         angle::Format::ID::ETC2_R8G8B8A1_UNORM_BLOCK,
+                                         VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
+                                         Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA8_ETC2_EAC:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA8_ETC2_EAC,
+                                         angle::Format::ID::ETC2_R8G8B8A8_UNORM_BLOCK,
+                                         VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x10_KHR,
+                                         angle::Format::ID::ASTC_10x10_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x5_KHR,
+                                         angle::Format::ID::ASTC_10x5_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x6_KHR,
+                                         angle::Format::ID::ASTC_10x6_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x8_KHR,
+                                         angle::Format::ID::ASTC_10x8_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_12x10_KHR,
+                                         angle::Format::ID::ASTC_12x10_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_12x12_KHR,
+                                         angle::Format::ID::ASTC_12x12_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_4x4_KHR,
+                                         angle::Format::ID::ASTC_4x4_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_5x4_KHR,
+                                         angle::Format::ID::ASTC_5x4_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_5x5_KHR,
+                                         angle::Format::ID::ASTC_5x5_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_6x5_KHR,
+                                         angle::Format::ID::ASTC_6x5_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_6x6_KHR,
+                                         angle::Format::ID::ASTC_6x6_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x5_KHR,
+                                         angle::Format::ID::ASTC_8x5_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x6_KHR,
+                                         angle::Format::ID::ASTC_8x6_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x8_KHR,
+                                         angle::Format::ID::ASTC_8x8_UNORM_BLOCK,
+                                         VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
+                                         angle::Format::ID::BC1_RGBA_UNORM_BLOCK,
+                                         VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+        {
+            static constexpr Format info(GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
+                                         angle::Format::ID::BC1_RGB_UNORM_BLOCK,
+                                         VK_FORMAT_BC1_RGB_UNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SIGNED_R11_EAC:
+        {
+            static constexpr Format info(GL_COMPRESSED_SIGNED_R11_EAC,
+                                         angle::Format::ID::EAC_R11_SNORM_BLOCK,
+                                         VK_FORMAT_EAC_R11_SNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SIGNED_RG11_EAC:
+        {
+            static constexpr Format info(GL_COMPRESSED_SIGNED_RG11_EAC,
+                                         angle::Format::ID::EAC_R11G11_SNORM_BLOCK,
+                                         VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR,
+                                         angle::Format::ID::ASTC_10x10_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR,
+                                         angle::Format::ID::ASTC_10x5_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR,
+                                         angle::Format::ID::ASTC_10x6_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR,
+                                         angle::Format::ID::ASTC_10x8_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR,
+                                         angle::Format::ID::ASTC_12x10_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR,
+                                         angle::Format::ID::ASTC_4x4_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR,
+                                         angle::Format::ID::ASTC_5x4_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR,
+                                         angle::Format::ID::ASTC_5x5_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR,
+                                         angle::Format::ID::ASTC_6x5_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR,
+                                         angle::Format::ID::ASTC_6x6_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR,
+                                         angle::Format::ID::ASTC_8x5_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR,
+                                         angle::Format::ID::ASTC_8x6_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR,
+                                         angle::Format::ID::ASTC_8x8_SRGB_BLOCK,
+                                         VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
+                                         angle::Format::ID::ETC2_R8G8B8A8_SRGB_BLOCK,
+                                         VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_ETC2:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_ETC2,
+                                         angle::Format::ID::ETC2_R8G8B8_SRGB_BLOCK,
+                                         VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+        {
+            static constexpr Format info(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+                                         angle::Format::ID::ETC2_R8G8B8A1_SRGB_BLOCK,
+                                         VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
+                                         nullptr);
+            return info;
+        }
+        case GL_DEPTH24_STENCIL8:
+        {
+            static constexpr Format info(GL_DEPTH24_STENCIL8,
+                                         angle::Format::ID::D24_UNORM_S8_UINT,
+                                         VK_FORMAT_D24_UNORM_S8_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_DEPTH_COMPONENT16:
+        {
+            static constexpr Format info(GL_DEPTH_COMPONENT16,
+                                         angle::Format::ID::D16_UNORM,
+                                         VK_FORMAT_D16_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_DEPTH_COMPONENT32F:
+        {
+            static constexpr Format info(GL_DEPTH_COMPONENT32F,
+                                         angle::Format::ID::D32_FLOAT,
+                                         VK_FORMAT_D32_SFLOAT,
+                                         nullptr);
+            return info;
+        }
+        case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+        {
+            static constexpr Format info(GL_ETC1_RGB8_LOSSY_DECODE_ANGLE,
+                                         angle::Format::ID::NONE,
+                                         VK_FORMAT_UNDEFINED,
+                                         nullptr);
+            return info;
+        }
+        case GL_ETC1_RGB8_OES:
+        {
+            static constexpr Format info(GL_ETC1_RGB8_OES,
+                                         angle::Format::ID::NONE,
+                                         VK_FORMAT_UNDEFINED,
+                                         nullptr);
+            return info;
+        }
+        case GL_NONE:
+        {
+            static constexpr Format info(GL_NONE,
+                                         angle::Format::ID::NONE,
+                                         VK_FORMAT_UNDEFINED,
+                                         nullptr);
+            return info;
+        }
+        case GL_R16F:
+        {
+            static constexpr Format info(GL_R16F,
+                                         angle::Format::ID::R16_FLOAT,
+                                         VK_FORMAT_R16_SFLOAT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R16I:
+        {
+            static constexpr Format info(GL_R16I,
+                                         angle::Format::ID::R16_SINT,
+                                         VK_FORMAT_R16_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R16UI:
+        {
+            static constexpr Format info(GL_R16UI,
+                                         angle::Format::ID::R16_UINT,
+                                         VK_FORMAT_R16_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R16_EXT:
+        {
+            static constexpr Format info(GL_R16_EXT,
+                                         angle::Format::ID::R16_UNORM,
+                                         VK_FORMAT_R16_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_R16_SNORM_EXT:
+        {
+            static constexpr Format info(GL_R16_SNORM_EXT,
+                                         angle::Format::ID::R16_SNORM,
+                                         VK_FORMAT_R16_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_R32F:
+        {
+            static constexpr Format info(GL_R32F,
+                                         angle::Format::ID::R32_FLOAT,
+                                         VK_FORMAT_R32_SFLOAT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R32I:
+        {
+            static constexpr Format info(GL_R32I,
+                                         angle::Format::ID::R32_SINT,
+                                         VK_FORMAT_R32_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R32UI:
+        {
+            static constexpr Format info(GL_R32UI,
+                                         angle::Format::ID::R32_UINT,
+                                         VK_FORMAT_R32_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R8:
+        {
+            static constexpr Format info(GL_R8,
+                                         angle::Format::ID::R8_UNORM,
+                                         VK_FORMAT_R8_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_R8I:
+        {
+            static constexpr Format info(GL_R8I,
+                                         angle::Format::ID::R8_SINT,
+                                         VK_FORMAT_R8_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R8UI:
+        {
+            static constexpr Format info(GL_R8UI,
+                                         angle::Format::ID::R8_UINT,
+                                         VK_FORMAT_R8_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_R8_SNORM:
+        {
+            static constexpr Format info(GL_R8_SNORM,
+                                         angle::Format::ID::R8_SNORM,
+                                         VK_FORMAT_R8_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG16F:
+        {
+            static constexpr Format info(GL_RG16F,
+                                         angle::Format::ID::R16G16_FLOAT,
+                                         VK_FORMAT_R16G16_SFLOAT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG16I:
+        {
+            static constexpr Format info(GL_RG16I,
+                                         angle::Format::ID::R16G16_SINT,
+                                         VK_FORMAT_R16G16_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG16UI:
+        {
+            static constexpr Format info(GL_RG16UI,
+                                         angle::Format::ID::R16G16_UINT,
+                                         VK_FORMAT_R16G16_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG16_EXT:
+        {
+            static constexpr Format info(GL_RG16_EXT,
+                                         angle::Format::ID::R16G16_UNORM,
+                                         VK_FORMAT_R16G16_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG16_SNORM_EXT:
+        {
+            static constexpr Format info(GL_RG16_SNORM_EXT,
+                                         angle::Format::ID::R16G16_SNORM,
+                                         VK_FORMAT_R16G16_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG32F:
+        {
+            static constexpr Format info(GL_RG32F,
+                                         angle::Format::ID::R32G32_FLOAT,
+                                         VK_FORMAT_R32G32_SFLOAT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG32I:
+        {
+            static constexpr Format info(GL_RG32I,
+                                         angle::Format::ID::R32G32_SINT,
+                                         VK_FORMAT_R32G32_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG32UI:
+        {
+            static constexpr Format info(GL_RG32UI,
+                                         angle::Format::ID::R32G32_UINT,
+                                         VK_FORMAT_R32G32_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG8:
+        {
+            static constexpr Format info(GL_RG8,
+                                         angle::Format::ID::R8G8_UNORM,
+                                         VK_FORMAT_R8G8_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG8I:
+        {
+            static constexpr Format info(GL_RG8I,
+                                         angle::Format::ID::R8G8_SINT,
+                                         VK_FORMAT_R8G8_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG8UI:
+        {
+            static constexpr Format info(GL_RG8UI,
+                                         angle::Format::ID::R8G8_UINT,
+                                         VK_FORMAT_R8G8_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RG8_SNORM:
+        {
+            static constexpr Format info(GL_RG8_SNORM,
+                                         angle::Format::ID::R8G8_SNORM,
+                                         VK_FORMAT_R8G8_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB:
+        {
+            static constexpr Format info(GL_RGB,
+                                         angle::Format::ID::R8G8B8_UNORM,
+                                         VK_FORMAT_R8G8B8_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB16F:
+        {
+            static constexpr Format info(GL_RGB16F,
+                                         angle::Format::ID::R16G16B16_FLOAT,
+                                         VK_FORMAT_R16G16B16_SFLOAT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB16I:
+        {
+            static constexpr Format info(GL_RGB16I,
+                                         angle::Format::ID::R16G16B16_SINT,
+                                         VK_FORMAT_R16G16B16_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB16UI:
+        {
+            static constexpr Format info(GL_RGB16UI,
+                                         angle::Format::ID::R16G16B16_UINT,
+                                         VK_FORMAT_R16G16B16_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB16_EXT:
+        {
+            static constexpr Format info(GL_RGB16_EXT,
+                                         angle::Format::ID::R16G16B16_UNORM,
+                                         VK_FORMAT_R16G16B16_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB16_SNORM_EXT:
+        {
+            static constexpr Format info(GL_RGB16_SNORM_EXT,
+                                         angle::Format::ID::R16G16B16_SNORM,
+                                         VK_FORMAT_R16G16B16_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB32F:
+        {
+            static constexpr Format info(GL_RGB32F,
+                                         angle::Format::ID::R32G32B32_FLOAT,
+                                         VK_FORMAT_R32G32B32_SFLOAT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB32I:
+        {
+            static constexpr Format info(GL_RGB32I,
+                                         angle::Format::ID::R32G32B32_SINT,
+                                         VK_FORMAT_R32G32B32_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB32UI:
+        {
+            static constexpr Format info(GL_RGB32UI,
+                                         angle::Format::ID::R32G32B32_UINT,
+                                         VK_FORMAT_R32G32B32_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB565:
+        {
+            static constexpr Format info(GL_RGB565,
+                                         angle::Format::ID::R5G6B5_UNORM,
+                                         VK_FORMAT_R5G6B5_UNORM_PACK16,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB5_A1:
+        {
+            static constexpr Format info(GL_RGB5_A1,
+                                         angle::Format::ID::R5G5B5A1_UNORM,
+                                         VK_FORMAT_R5G5B5A1_UNORM_PACK16,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB8:
+        {
+            static constexpr Format info(GL_RGB8,
+                                         angle::Format::ID::R8G8B8_UNORM,
+                                         VK_FORMAT_R8G8B8_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB8I:
+        {
+            static constexpr Format info(GL_RGB8I,
+                                         angle::Format::ID::R8G8B8_SINT,
+                                         VK_FORMAT_R8G8B8_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB8UI:
+        {
+            static constexpr Format info(GL_RGB8UI,
+                                         angle::Format::ID::R8G8B8_UINT,
+                                         VK_FORMAT_R8G8B8_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGB8_SNORM:
+        {
+            static constexpr Format info(GL_RGB8_SNORM,
+                                         angle::Format::ID::R8G8B8_SNORM,
+                                         VK_FORMAT_R8G8B8_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA:
+        {
+            static constexpr Format info(GL_RGBA,
+                                         angle::Format::ID::R8G8B8A8_UNORM,
+                                         VK_FORMAT_R8G8B8A8_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA16F:
+        {
+            static constexpr Format info(GL_RGBA16F,
+                                         angle::Format::ID::R16G16B16A16_FLOAT,
+                                         VK_FORMAT_R16G16B16A16_SFLOAT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA16I:
+        {
+            static constexpr Format info(GL_RGBA16I,
+                                         angle::Format::ID::R16G16B16A16_SINT,
+                                         VK_FORMAT_R16G16B16A16_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA16UI:
+        {
+            static constexpr Format info(GL_RGBA16UI,
+                                         angle::Format::ID::R16G16B16A16_UINT,
+                                         VK_FORMAT_R16G16B16A16_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA16_EXT:
+        {
+            static constexpr Format info(GL_RGBA16_EXT,
+                                         angle::Format::ID::R16G16B16A16_UNORM,
+                                         VK_FORMAT_R16G16B16A16_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA16_SNORM_EXT:
+        {
+            static constexpr Format info(GL_RGBA16_SNORM_EXT,
+                                         angle::Format::ID::R16G16B16A16_SNORM,
+                                         VK_FORMAT_R16G16B16A16_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA32F:
+        {
+            static constexpr Format info(GL_RGBA32F,
+                                         angle::Format::ID::R32G32B32A32_FLOAT,
+                                         VK_FORMAT_R32G32B32A32_SFLOAT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA32I:
+        {
+            static constexpr Format info(GL_RGBA32I,
+                                         angle::Format::ID::R32G32B32A32_SINT,
+                                         VK_FORMAT_R32G32B32A32_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA32UI:
+        {
+            static constexpr Format info(GL_RGBA32UI,
+                                         angle::Format::ID::R32G32B32A32_UINT,
+                                         VK_FORMAT_R32G32B32A32_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA4:
+        {
+            static constexpr Format info(GL_RGBA4,
+                                         angle::Format::ID::R4G4B4A4_UNORM,
+                                         VK_FORMAT_R4G4B4A4_UNORM_PACK16,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA8:
+        {
+            static constexpr Format info(GL_RGBA8,
+                                         angle::Format::ID::R8G8B8A8_UNORM,
+                                         VK_FORMAT_R8G8B8A8_UNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA8I:
+        {
+            static constexpr Format info(GL_RGBA8I,
+                                         angle::Format::ID::R8G8B8A8_SINT,
+                                         VK_FORMAT_R8G8B8A8_SINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA8UI:
+        {
+            static constexpr Format info(GL_RGBA8UI,
+                                         angle::Format::ID::R8G8B8A8_UINT,
+                                         VK_FORMAT_R8G8B8A8_UINT,
+                                         nullptr);
+            return info;
+        }
+        case GL_RGBA8_SNORM:
+        {
+            static constexpr Format info(GL_RGBA8_SNORM,
+                                         angle::Format::ID::R8G8B8A8_SNORM,
+                                         VK_FORMAT_R8G8B8A8_SNORM,
+                                         nullptr);
+            return info;
+        }
+        case GL_STENCIL_INDEX8:
+        {
+            static constexpr Format info(GL_STENCIL_INDEX8,
+                                         angle::Format::ID::S8_UINT,
+                                         VK_FORMAT_S8_UINT,
+                                         nullptr);
+            return info;
+        }
+
+        default:
+            break;
+    }
+    // clang-format on
+
+    UNREACHABLE();
+    static const Format noInfo(GL_NONE, angle::Format::ID::NONE, VK_FORMAT_UNDEFINED, nullptr);
+    return noInfo;
+}
+
+}  // namespace vk
+
+}  // namespace rx
diff --git a/src/libGLESv2.gypi b/src/libGLESv2.gypi
index 309a83f..aae80e8 100644
--- a/src/libGLESv2.gypi
+++ b/src/libGLESv2.gypi
@@ -643,8 +643,11 @@
             'libANGLE/renderer/vulkan/TransformFeedbackVk.h',
             'libANGLE/renderer/vulkan/VertexArrayVk.cpp',
             'libANGLE/renderer/vulkan/VertexArrayVk.h',
+            'libANGLE/renderer/vulkan/formatutilsvk.h',
+            'libANGLE/renderer/vulkan/formatutilsvk.cpp',
             'libANGLE/renderer/vulkan/renderervk_utils.cpp',
             'libANGLE/renderer/vulkan/renderervk_utils.h',
+            'libANGLE/renderer/vulkan/vk_format_table_autogen.cpp',
         ],
         'libangle_null_sources':
         [