scripts: Move layer scripts into scripts directory

Simplifies sharing code among python modules, keeps everything together.

- Moved python scripts out of layers dir into scripts dir
- Updated relative paths for input/output files in layers dir
- Updated doc validation tests to use correct paths

Change-Id: I57e6ad6f551d4fb652583315fe3dccb23b187db1
diff --git a/scripts/spec.py b/scripts/spec.py
new file mode 100644
index 0000000..de34632
--- /dev/null
+++ b/scripts/spec.py
@@ -0,0 +1,357 @@
+#!/usr/bin/python -i
+
+import sys
+try:
+    import urllib.request as urllib2
+except ImportError:
+    import urllib2
+from bs4 import BeautifulSoup
+import json
+import vuid_mapping
+
+#############################
+# spec.py script
+#
+# Overview - this script is intended to generate validation error codes and message strings from the json spec file
+#  that contains all of the valid usage statements. In addition to generating the header file, it provides a number of
+#  corrollary services to aid in generating/updating the header.
+#
+# Ideal flow - Pull the valid usage text and IDs from the spec json, pull the IDs from the validation error database,
+#  then update the database with any new IDs from the json file and generate new database and header file.
+#
+# TODO:
+#  1. When VUs go away (in error DB, but not in json) need to report them and remove from DB as deleted
+#
+#############################
+
+
+out_filename = "../layers/vk_validation_error_messages.h" # can override w/ '-out <filename>' option
+db_filename = "../layers/vk_validation_error_database.txt" # can override w/ '-gendb <filename>' option
+json_filename = None # con pass in w/ '-json <filename> option
+gen_db = False # set to True when '-gendb <filename>' option provided
+json_compare = False # compare existing DB to json file input
+json_url = "https://www.khronos.org/registry/vulkan/specs/1.0-extensions/validation/validusage.json"
+read_json = False
+# This is the root spec link that is used in error messages to point users to spec sections
+#old_spec_url = "https://www.khronos.org/registry/vulkan/specs/1.0/xhtml/vkspec.html"
+spec_url = "https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html"
+core_url = "https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html"
+ext_url = "https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html"
+# After the custom validation error message, this is the prefix for the standard message that includes the
+#  spec valid usage language as well as the link to nearest section of spec to that language
+error_msg_prefix = "The spec valid usage text states "
+validation_error_enum_name = "VALIDATION_ERROR_"
+
+def printHelp():
+    print ("Usage: python spec.py [-out <headerfile.h>] [-gendb <databasefile.txt>] [-update] [-json <json_file>] [-help]")
+    print ("\n Default script behavior is to parse the specfile and generate a header of unique error enums and corresponding error messages based on the specfile.\n")
+    print ("  Default specfile is from online at %s" % (spec_url))
+    print ("  Default headerfile is %s" % (out_filename))
+    print ("  Default databasefile is %s" % (db_filename))
+    print ("\nIf '-gendb' option is specified then a database file is generated to default file or <databasefile.txt> if supplied. The database file stores")
+    print ("  the list of enums and their error messages.")
+    print ("\nIf '-update' option is specified this triggers the master flow to automate updating header and database files using default db file as baseline")
+    print ("  and online spec file as the latest. The default header and database files will be updated in-place for review and commit to the git repo.")
+    print ("\nIf '-json' option is used trigger the script to load in data from a json file.")
+    print ("\nIf '-json-file' option is it will point to a local json file, else '%s' is used from the web." % (json_url))
+
+def get8digithex(dec_num):
+    """Convert a decimal # into an 8-digit hex"""
+    if dec_num > 4294967295:
+        print ("ERROR: Decimal # %d can't be represented in 8 hex digits" % (dec_num))
+        sys.exit()
+    hex_num = hex(dec_num)
+    return hex_num[2:].zfill(8)
+
+class Specification:
+    def __init__(self):
+        self.tree   = None
+        self.error_db_dict = {} # dict of previous error values read in from database file
+        self.delimiter = '~^~' # delimiter for db file
+        # Global dicts used for tracking spec updates from old to new VUs
+        self.orig_no_link_msg_dict = {} # Pair of API,Original msg w/o spec link to ID list mapping
+        self.orig_core_msg_dict = {} # Pair of API,Original core msg (no link or section) to ID list mapping
+        self.last_mapped_id = -10 # start as negative so we don't hit an accidental sequence
+        self.orig_test_imp_enums = set() # Track old enums w/ tests and/or implementation to flag any that aren't carried fwd
+        # Dict of data from json DB
+        # Key is API,<short_msg> which leads to dict w/ following values
+        #   'ext' -> <core|<ext_name>>
+        #   'string_vuid' -> <string_vuid>
+        #   'number_vuid' -> <numerical_vuid>
+        self.json_db = {}
+        self.json_missing = 0
+        self.struct_to_func_map = {} # Map structs to the API func that they fall under in the spec
+        self.duplicate_json_key_count = 0
+        self.copyright = """/* THIS FILE IS GENERATED.  DO NOT EDIT. */
+
+/*
+ * Vulkan
+ *
+ * Copyright (c) 2016 Google Inc.
+ * Copyright (c) 2016 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Tobin Ehlis <tobine@google.com>
+ */"""
+
+    def readJSON(self):
+        """Read in JSON file"""
+        if json_filename is not None:
+            with open(json_filename) as jsf:
+                self.json_data = json.load(jsf, encoding='utf-8')
+        else:
+            response = urllib2.urlopen(json_url).read().decode('utf-8')
+            self.json_data = json.loads(response)
+
+    def parseJSON(self):
+        """Parse JSON VUIDs into data struct"""
+        # Format of JSON file is:
+        # "API": { "core|EXT": [ {"vuid": "<id>", "text": "<VU txt>"}]},
+        # "VK_KHX_external_memory" & "VK_KHX_device_group" - extension case (vs. "core")
+        for top_level in sorted(self.json_data):
+            if "validation" == top_level:
+                for api in sorted(self.json_data[top_level]):
+                    for ext in sorted(self.json_data[top_level][api]):
+                        for vu_txt_dict in self.json_data[top_level][api][ext]:
+                            print ("Looking at dict for api:ext entry %s:%s" % (api, ext))
+                            vuid = vu_txt_dict['vuid']
+                            vutxt = vu_txt_dict['text']
+                            #print ("%s:%s:%s:%s" % (api, ext, vuid, vutxt))
+                            #print ("VUTXT orig:%s" % (vutxt))
+                            just_txt = BeautifulSoup(vutxt, 'html.parser')
+                            #print ("VUTXT only:%s" % (just_txt.get_text()))
+                            num_vuid = vuid_mapping.convertVUID(vuid)
+                            self.json_db[vuid] = {}
+                            self.json_db[vuid]['ext'] = ext
+                            self.json_db[vuid]['number_vuid'] = num_vuid
+                            self.json_db[vuid]['struct_func'] = api
+                            just_txt = just_txt.get_text().strip()
+                            unicode_map = {
+                            u"\u2019" : "'",
+                            u"\u2192" : "->",
+                            }
+                            for um in unicode_map:
+                                just_txt = just_txt.replace(um, unicode_map[um])
+                            self.json_db[vuid]['vu_txt'] = just_txt.replace("\\", "")
+                            print ("Spec vu txt:%s" % (self.json_db[vuid]['vu_txt']))
+        #sys.exit()
+
+    def compareJSON(self):
+        """Compare parsed json file with existing data read in from DB file"""
+        json_db_set = set()
+        for vuid in self.json_db: # pull entries out and see which fields we're missing from error_db
+            json_db_set.add(vuid)
+        for enum in self.error_db_dict:
+            vuid_string = self.error_db_dict[enum]['vuid_string']
+            if vuid_string not in self.json_db:
+                #print ("Full string for %s is:%s" % (enum, full_error_string))
+                print ("WARN: Couldn't find vuid_string in json db:%s" % (vuid_string))
+                self.json_missing = self.json_missing + 1
+                self.error_db_dict[enum]['ext'] = 'core'
+                # TODO: Currently GL843 tracks 2 VUs that are missing from json incorrectly
+                #  Fix will land in 1.0.51 spec. After that we should take some alternative
+                #  action here to indicate that VUs have gone away.
+                #  Can have a removed_enums set that we add to and report to user
+                #sys.exit()
+            else:
+                json_db_set.remove(vuid_string)
+                self.error_db_dict[enum]['ext'] = self.json_db[vuid_string]['ext']
+                if 'core' == self.json_db[vuid_string]['ext'] or '!' in self.json_db[vuid_string]['ext']:
+                    spec_link = "%s#%s" % (core_url, vuid_string)
+                else:
+                    spec_link = "%s#%s" % (ext_url, vuid_string)
+                self.error_db_dict[enum]['error_msg'] = "%s'%s' (%s)" % (error_msg_prefix, self.json_db[vuid_string]['vu_txt'], spec_link)
+                print ("Updated error_db error_msg:%s" % (self.error_db_dict[enum]['error_msg']))
+        #sys.exit()
+        print ("These json DB entries are not in error DB:")
+        for extra_vuid in json_db_set:
+            print ("\t%s" % (extra_vuid))
+            # Add these missing entries into the error_db
+            # Create link into core or ext spec as needed
+            if 'core' == self.json_db[extra_vuid]['ext'] or '!' in self.json_db[extra_vuid]['ext']:
+                spec_link = "%s#%s" % (core_url, extra_vuid)
+            else:
+                spec_link = "%s#%s" % (ext_url, extra_vuid)
+            error_enum = "%s%s" % (validation_error_enum_name, get8digithex(self.json_db[extra_vuid]['number_vuid']))
+            self.error_db_dict[error_enum] = {}
+            self.error_db_dict[error_enum]['check_implemented'] = 'N'
+            self.error_db_dict[error_enum]['testname'] = 'None'
+            self.error_db_dict[error_enum]['api'] = self.json_db[extra_vuid]['struct_func']
+            self.error_db_dict[error_enum]['vuid_string'] = extra_vuid
+            self.error_db_dict[error_enum]['error_msg'] = "%s'%s' (%s)" % (error_msg_prefix, self.json_db[extra_vuid]['vu_txt'], spec_link)
+            self.error_db_dict[error_enum]['note'] = ''
+            self.error_db_dict[error_enum]['ext'] = self.json_db[extra_vuid]['ext']
+            implicit = False
+            last_segment = extra_vuid.split("-")[-1]
+            if last_segment in vuid_mapping.implicit_type_map:
+                implicit = True
+            elif not last_segment.isdigit(): # Explicit ids should only have digits in last segment
+                print ("ERROR: Found last segment of val error ID that isn't in implicit map and doesn't have numbers in last segment: %s" % (last_segment))
+                sys.exit()
+            self.error_db_dict[error_enum]['implicit'] = implicit
+
+    def genHeader(self, header_file):
+        """Generate a header file based on the contents of a parsed spec"""
+        print ("Generating header %s..." % (header_file))
+        file_contents = []
+        file_contents.append(self.copyright)
+        file_contents.append('\n#pragma once')
+        file_contents.append('\n// Disable auto-formatting for generated file')
+        file_contents.append('// clang-format off')
+        file_contents.append('\n#include <unordered_map>')
+        file_contents.append('\n// enum values for unique validation error codes')
+        file_contents.append('//  Corresponding validation error message for each enum is given in the mapping table below')
+        file_contents.append('//  When a given error occurs, these enum values should be passed to the as the messageCode')
+        file_contents.append('//  parameter to the PFN_vkDebugReportCallbackEXT function')
+        enum_decl = ['enum UNIQUE_VALIDATION_ERROR_CODE {\n    VALIDATION_ERROR_UNDEFINED = -1,']
+        error_string_map = ['static std::unordered_map<int, char const *const> validation_error_map{']
+        enum_value = 0
+        max_enum_val = 0
+        for enum in sorted(self.error_db_dict):
+            #print ("Header enum is %s" % (enum))
+            # TMP: Use updated value
+            vuid_str = self.error_db_dict[enum]['vuid_string']
+            if vuid_str in self.json_db:
+                enum_value = self.json_db[vuid_str]['number_vuid']
+            else:
+                enum_value = vuid_mapping.convertVUID(vuid_str)
+            new_enum = "%s%s" % (validation_error_enum_name, get8digithex(enum_value))
+            enum_decl.append('    %s = 0x%s,' % (new_enum, get8digithex(enum_value)))
+            error_string_map.append('    {%s, "%s"},' % (new_enum, self.error_db_dict[enum]['error_msg']))
+            max_enum_val = max(max_enum_val, enum_value)
+        enum_decl.append('    %sMAX_ENUM = %d,' % (validation_error_enum_name, max_enum_val + 1))
+        enum_decl.append('};')
+        error_string_map.append('};\n')
+        file_contents.extend(enum_decl)
+        file_contents.append('\n// Mapping from unique validation error enum to the corresponding error message')
+        file_contents.append('// The error message should be appended to the end of a custom error message that is passed')
+        file_contents.append('// as the pMessage parameter to the PFN_vkDebugReportCallbackEXT function')
+        file_contents.extend(error_string_map)
+        #print ("File contents: %s" % (file_contents))
+        with open(header_file, "w") as outfile:
+            outfile.write("\n".join(file_contents))
+    def genDB(self, db_file):
+        """Generate a database of check_enum, check_coded?, testname, API, VUID_string, core|ext, error_string, notes"""
+        db_lines = []
+        # Write header for database file
+        db_lines.append("# This is a database file with validation error check information")
+        db_lines.append("# Comments are denoted with '#' char")
+        db_lines.append("# The format of the lines is:")
+        db_lines.append("# <error_enum>%s<check_implemented>%s<testname>%s<api>%s<vuid_string>%s<core|ext>%s<errormsg>%s<note>" % (self.delimiter, self.delimiter, self.delimiter, self.delimiter, self.delimiter, self.delimiter, self.delimiter))
+        db_lines.append("# error_enum: Unique error enum for this check of format %s<uniqueid>" % validation_error_enum_name)
+        db_lines.append("# check_implemented: 'Y' if check has been implemented in layers, or 'N' for not implemented")
+        db_lines.append("# testname: Name of validation test for this check, 'Unknown' for unknown, 'None' if not implemented, or 'NotTestable' if cannot be implemented")
+        db_lines.append("# api: Vulkan API function that this check is related to")
+        db_lines.append("# vuid_string: Unique string to identify this check")
+        db_lines.append("# core|ext: Either 'core' for core spec or some extension string that indicates the extension required for this VU to be relevant")
+        db_lines.append("# errormsg: The unique error message for this check that includes spec language and link")
+        db_lines.append("# note: Free txt field with any custom notes related to the check in question")
+        for enum in sorted(self.error_db_dict):
+            print ("Gen DB for enum %s" % (enum))
+            implicit = self.error_db_dict[enum]['implicit']
+            implemented = self.error_db_dict[enum]['check_implemented']
+            testname = self.error_db_dict[enum]['testname']
+            note = self.error_db_dict[enum]['note']
+            core_ext = self.error_db_dict[enum]['ext']
+            self.error_db_dict[enum]['vuid_string'] = self.error_db_dict[enum]['vuid_string']
+            if implicit and 'implicit' not in note: # add implicit note
+                if '' != note:
+                    note = "implicit, %s" % (note)
+                else:
+                    note = "implicit"
+            db_lines.append("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" % (enum, self.delimiter, implemented, self.delimiter, testname, self.delimiter, self.error_db_dict[enum]['api'], self.delimiter, self.error_db_dict[enum]['vuid_string'], self.delimiter, core_ext, self.delimiter, self.error_db_dict[enum]['error_msg'], self.delimiter, note))
+        db_lines.append("\n") # newline at end of file
+        print ("Generating database file %s" % (db_file))
+        with open(db_file, "w") as outfile:
+            outfile.write("\n".join(db_lines))
+    def readDB(self, db_file):
+        """Read a db file into a dict, refer to genDB function above for format of each line"""
+        with open(db_file, "r") as infile:
+            for line in infile:
+                line = line.strip()
+                if line.startswith('#') or '' == line:
+                    continue
+                db_line = line.split(self.delimiter)
+                if len(db_line) != 8:
+                    print ("ERROR: Bad database line doesn't have 8 elements: %s" % (line))
+                error_enum = db_line[0]
+                implemented = db_line[1]
+                testname = db_line[2]
+                api = db_line[3]
+                vuid_str = db_line[4]
+                core_ext = db_line[5]
+                error_str = db_line[6]
+                note = db_line[7]
+                # Also read complete database contents into our class var for later use
+                self.error_db_dict[error_enum] = {}
+                self.error_db_dict[error_enum]['check_implemented'] = implemented
+                self.error_db_dict[error_enum]['testname'] = testname
+                self.error_db_dict[error_enum]['api'] = api
+                self.error_db_dict[error_enum]['vuid_string'] = vuid_str
+                self.error_db_dict[error_enum]['ext'] = core_ext
+                self.error_db_dict[error_enum]['error_msg'] = error_str
+                self.error_db_dict[error_enum]['note'] = note
+                implicit = False
+                last_segment = vuid_str.split("-")[-1]
+                if last_segment in vuid_mapping.implicit_type_map:
+                    implicit = True
+                elif not last_segment.isdigit(): # Explicit ids should only have digits in last segment
+                    print ("ERROR: Found last segment of val error ID that isn't in implicit map and doesn't have numbers in last segment: %s" % (last_segment))
+                    sys.exit()
+                self.error_db_dict[error_enum]['implicit'] = implicit
+if __name__ == "__main__":
+    i = 1
+    use_online = True # Attempt to grab spec from online by default
+    while (i < len(sys.argv)):
+        arg = sys.argv[i]
+        i = i + 1
+        if (arg == '-json-file'):
+            json_filename = sys.argv[i]
+            i = i + 1
+        elif (arg == '-json'):
+            read_json = True
+        elif (arg == '-json-compare'):
+            json_compare = True
+        elif (arg == '-out'):
+            out_filename = sys.argv[i]
+            i = i + 1
+        elif (arg == '-gendb'):
+            gen_db = True
+            # Set filename if supplied, else use default
+            if i < len(sys.argv) and not sys.argv[i].startswith('-'):
+                db_filename = sys.argv[i]
+                i = i + 1
+        elif (arg == '-update'):
+            read_json = True
+            json_compare = True
+            gen_db = True
+        elif (arg in ['-help', '-h']):
+            printHelp()
+            sys.exit()
+    spec = Specification()
+    if read_json:
+        spec.readJSON()
+        spec.parseJSON()
+        #sys.exit()
+    if (json_compare):
+        # Read in current spec info from db file
+        (orig_err_msg_dict) = spec.readDB(db_filename)
+        spec.compareJSON()
+        print ("Found %d missing db entries in json db" % (spec.json_missing))
+        print ("Found %d duplicate json entries" % (spec.duplicate_json_key_count))
+        spec.genDB(db_filename)
+    if (gen_db):
+        spec.genDB(db_filename)
+    print ("Writing out file (-out) to '%s'" % (out_filename))
+    spec.genHeader(out_filename)
diff --git a/scripts/vk_validation_stats.py b/scripts/vk_validation_stats.py
new file mode 100755
index 0000000..a4abd6d
--- /dev/null
+++ b/scripts/vk_validation_stats.py
@@ -0,0 +1,423 @@
+#!/usr/bin/env python3
+# Copyright (c) 2015-2017 The Khronos Group Inc.
+# Copyright (c) 2015-2017 Valve Corporation
+# Copyright (c) 2015-2017 LunarG, Inc.
+# Copyright (c) 2015-2017 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Author: Tobin Ehlis <tobine@google.com>
+
+import argparse
+import os
+import sys
+import platform
+
+# vk_validation_stats.py overview
+# This script is intended to generate statistics on the state of validation code
+#  based on information parsed from the source files and the database file
+# Here's what it currently does:
+#  1. Parse vk_validation_error_database.txt to store claimed state of validation checks
+#  2. Parse vk_validation_error_messages.h to verify the actual checks in header vs. the
+#     claimed state of the checks
+#  3. Parse source files to identify which checks are implemented and verify that this
+#     exactly matches the list of checks claimed to be implemented in the database
+#  4. Parse test file(s) and verify that reported tests exist
+#  5. Report out stats on number of checks, implemented checks, and duplicated checks
+#
+# If a mis-match is found during steps 2, 3, or 4, then the script exits w/ a non-zero error code
+#  otherwise, the script will exit(0)
+#
+# TODO:
+#  1. Would also like to report out number of existing checks that don't yet use new, unique enum
+#  2. Could use notes to store custom fields (like TODO) and print those out here
+#  3. Update test code to check if tests use new, unique enums to check for errors instead of strings
+
+db_file = '../layers/vk_validation_error_database.txt'
+layer_source_files = [
+'../layers/core_validation.cpp',
+'../layers/descriptor_sets.cpp',
+'../layers/parameter_validation.cpp',
+'../layers/object_tracker.cpp',
+'../layers/shader_validation.cpp',
+'../layers/buffer_validation.cpp',
+]
+header_file = '../layers/vk_validation_error_messages.h'
+# TODO : Don't hardcode linux path format if we want this to run on windows
+test_file = '../tests/layer_validation_tests.cpp'
+# List of enums that are allowed to be used more than once so don't warn on their duplicates
+duplicate_exceptions = [
+'VALIDATION_ERROR_258004ea', # This covers the broad case that all child objects must be destroyed at DestroyInstance time
+'VALIDATION_ERROR_24a002f4', # This covers the broad case that all child objects must be destroyed at DestroyDevice time
+'VALIDATION_ERROR_0280006e', # Obj tracker check makes sure non-null framebuffer is valid & CV check makes sure it's compatible w/ renderpass framebuffer
+'VALIDATION_ERROR_12200682', # This is an aliasing error that we report twice, for each of the two allocations that are aliasing
+'VALIDATION_ERROR_1060d201', # Covers valid shader module handle for both Compute & Graphics pipelines
+'VALIDATION_ERROR_0c20c601', # This is a case for VkMappedMemoryRange struct that is used by both Flush & Invalidate MappedMemoryRange
+'VALIDATION_ERROR_0a400c01', # This is a blanket case for all invalid image aspect bit errors. The spec link has appropriate details for all separate cases.
+'VALIDATION_ERROR_0a8007fc', # This case covers two separate checks which are done independently
+'VALIDATION_ERROR_0a800800', # This case covers two separate checks which are done independently
+'VALIDATION_ERROR_15c0028a', # This is a descriptor set write update error that we use for a couple copy cases as well
+'VALIDATION_ERROR_1bc002de', # Single error for mis-matched stageFlags of vkCmdPushConstants() that is flagged for no stage flags & mis-matched flags
+'VALIDATION_ERROR_1880000e', # Handles both depth/stencil & compressed image errors for vkCmdClearColorImage()
+'VALIDATION_ERROR_0a600152', # Used for the mipLevel check of both dst & src images on vkCmdCopyImage call
+'VALIDATION_ERROR_0a600154', # Used for the arraySize check of both dst & src images on vkCmdCopyImage call
+'VALIDATION_ERROR_1500099e', # Used for both x & y bounds of viewport
+'VALIDATION_ERROR_1d8004a6', # Used for both x & y value of scissors to make sure they're not negative
+'VALIDATION_ERROR_1462ec01', # Surface of VkSwapchainCreateInfoKHR must be valid when creating both single or shared swapchains
+'VALIDATION_ERROR_1460de01', # oldSwapchain of VkSwapchainCreateInfoKHR must be valid when creating both single or shared swapchains
+'VALIDATION_ERROR_146009f2', # Single error for both imageFormat & imageColorSpace requirements when creating swapchain
+'VALIDATION_ERROR_15c00294', # Used twice for the same error codepath as both a param & to set a variable, so not really a duplicate
+]
+
+class ValidationDatabase:
+    def __init__(self, filename=db_file):
+        self.db_file = filename
+        self.delimiter = '~^~'
+        self.db_dict = {} # complete dict of all db values per error enum
+        # specialized data structs with slices of complete dict
+        self.db_implemented_enums = [] # list of all error enums claiming to be implemented in database file
+        self.db_unimplemented_implicit = [] # list of all implicit checks that aren't marked implemented
+        self.db_enum_to_tests = {} # dict where enum is key to lookup list of tests implementing the enum
+        self.db_invalid_implemented = [] # list of checks with invalid check_implemented flags
+        #self.src_implemented_enums
+    def read(self):
+        """Read a database file into internal data structures, format of each line is <enum><implemented Y|N?><testname><api><errormsg><notes>"""
+        #db_dict = {} # This is a simple db of just enum->errormsg, the same as is created from spec
+        #max_id = 0
+        with open(self.db_file, "r") as infile:
+            for line in infile:
+                line = line.strip()
+                if line.startswith('#') or '' == line:
+                    continue
+                db_line = line.split(self.delimiter)
+                if len(db_line) != 8:
+                    print("ERROR: Bad database line doesn't have 8 elements: %s" % (line))
+                error_enum = db_line[0]
+                implemented = db_line[1]
+                testname = db_line[2]
+                api = db_line[3]
+                vuid_string = db_line[4]
+                core_ext = db_line[5]
+                error_str = db_line[6]
+                note = db_line[7]
+                # Read complete database contents into our class var for later use
+                self.db_dict[error_enum] = {}
+                self.db_dict[error_enum]['check_implemented'] = implemented
+                self.db_dict[error_enum]['testname'] = testname
+                self.db_dict[error_enum]['api'] = api
+                self.db_dict[error_enum]['vuid_string'] = vuid_string
+                self.db_dict[error_enum]['core_ext'] = core_ext
+                self.db_dict[error_enum]['error_string'] = error_str
+                self.db_dict[error_enum]['note'] = note
+                # Now build custom data structs
+                if 'Y' == implemented:
+                    self.db_implemented_enums.append(error_enum)
+                elif 'implicit' in note: # only make note of non-implemented implicit checks
+                    self.db_unimplemented_implicit.append(error_enum)
+                if implemented not in ['Y', 'N']:
+                    self.db_invalid_implemented.append(error_enum)
+                if testname.lower() not in ['unknown', 'none', 'nottestable']:
+                    self.db_enum_to_tests[error_enum] = testname.split(',')
+                    #if len(self.db_enum_to_tests[error_enum]) > 1:
+                    #    print "Found check %s that has multiple tests: %s" % (error_enum, self.db_enum_to_tests[error_enum])
+                    #else:
+                    #    print "Check %s has single test: %s" % (error_enum, self.db_enum_to_tests[error_enum])
+                #unique_id = int(db_line[0].split('_')[-1])
+                #if unique_id > max_id:
+                #    max_id = unique_id
+        #print "Found %d total enums in database" % (len(self.db_dict.keys()))
+        #print "Found %d enums claiming to be implemented in source" % (len(self.db_implemented_enums))
+        #print "Found %d enums claiming to have tests implemented" % (len(self.db_enum_to_tests.keys()))
+
+class ValidationHeader:
+    def __init__(self, filename=header_file):
+        self.filename = header_file
+        self.enums = []
+    def read(self):
+        """Read unique error enum header file into internal data structures"""
+        grab_enums = False
+        with open(self.filename, "r") as infile:
+            for line in infile:
+                line = line.strip()
+                if 'enum UNIQUE_VALIDATION_ERROR_CODE {' in line:
+                    grab_enums = True
+                    continue
+                if grab_enums:
+                    if 'VALIDATION_ERROR_MAX_ENUM' in line:
+                        grab_enums = False
+                        break # done
+                    elif 'VALIDATION_ERROR_UNDEFINED' in line:
+                        continue
+                    elif 'VALIDATION_ERROR_' in line:
+                        enum = line.split(' = ')[0]
+                        self.enums.append(enum)
+        #print "Found %d error enums. First is %s and last is %s." % (len(self.enums), self.enums[0], self.enums[-1])
+
+class ValidationSource:
+    def __init__(self, source_file_list):
+        self.source_files = source_file_list
+        self.enum_count_dict = {} # dict of enum values to the count of how much they're used, and location of where they're used
+        # 1500099c is a special case that provides an exception when an extension is enabled. No specific error is flagged, but the exception is handled so add it here
+        self.enum_count_dict['VALIDATION_ERROR_1500099c'] = {}
+        self.enum_count_dict['VALIDATION_ERROR_1500099c']['count'] = 1
+        self.enum_count_dict['VALIDATION_ERROR_1500099c']['file_line'] = []
+    def parse(self):
+        duplicate_checks = 0
+        for sf in self.source_files:
+            line_num = 0
+            with open(sf) as f:
+                for line in f:
+                    line_num = line_num + 1
+                    if True in [line.strip().startswith(comment) for comment in ['//', '/*']]:
+                        continue
+                    # Find enums
+                    #if 'VALIDATION_ERROR_' in line and True not in [ignore in line for ignore in ['[VALIDATION_ERROR_', 'UNIQUE_VALIDATION_ERROR_CODE']]:
+                    if ' VALIDATION_ERROR_' in line:
+                        # Need to isolate the validation error enum
+                        #print("Line has check:%s" % (line))
+                        line_list = line.split()
+                        enum_list = []
+                        for str in line_list:
+                            if 'VALIDATION_ERROR_' in str and True not in [ignore_str in str for ignore_str in ['[VALIDATION_ERROR_', 'VALIDATION_ERROR_UNDEFINED', 'UNIQUE_VALIDATION_ERROR_CODE']]:
+                                enum_list.append(str.strip(',);'))
+                                #break
+                        for enum in enum_list:
+                            if enum != '':
+                                if enum not in self.enum_count_dict:
+                                    self.enum_count_dict[enum] = {}
+                                    self.enum_count_dict[enum]['count'] = 1
+                                    self.enum_count_dict[enum]['file_line'] = []
+                                    self.enum_count_dict[enum]['file_line'].append('%s,%d' % (sf, line_num))
+                                    #print "Found enum %s implemented for first time in file %s" % (enum, sf)
+                                else:
+                                    self.enum_count_dict[enum]['count'] = self.enum_count_dict[enum]['count'] + 1
+                                    self.enum_count_dict[enum]['file_line'].append('%s,%d' % (sf, line_num))
+                                    #print "Found enum %s implemented for %d time in file %s" % (enum, self.enum_count_dict[enum], sf)
+                                    duplicate_checks = duplicate_checks + 1
+                            #else:
+                                #print("Didn't find actual check in line:%s" % (line))
+        #print "Found %d unique implemented checks and %d are duplicated at least once" % (len(self.enum_count_dict.keys()), duplicate_checks)
+
+# Class to parse the validation layer test source and store testnames
+# TODO: Enhance class to detect use of unique error enums in the test
+class TestParser:
+    def __init__(self, test_file_list, test_group_name=['VkLayerTest', 'VkPositiveLayerTest', 'VkWsiEnabledLayerTest']):
+        self.test_files = test_file_list
+        self.test_to_errors = {} # Dict where testname maps to list of error enums found in that test
+        self.test_trigger_txt_list = []
+        for tg in test_group_name:
+            self.test_trigger_txt_list.append('TEST_F(%s' % tg)
+            #print('Test trigger test list: %s' % (self.test_trigger_txt_list))
+
+    # Parse test files into internal data struct
+    def parse(self):
+        # For each test file, parse test names into set
+        grab_next_line = False # handle testname on separate line than wildcard
+        testname = ''
+        for test_file in self.test_files:
+            with open(test_file) as tf:
+                for line in tf:
+                    if True in [line.strip().startswith(comment) for comment in ['//', '/*']]:
+                        continue
+
+                    if True in [ttt in line for ttt in self.test_trigger_txt_list]:
+                        #print('Test wildcard in line: %s' % (line))
+                        testname = line.split(',')[-1]
+                        testname = testname.strip().strip(' {)')
+                        #print('Inserting test: "%s"' % (testname))
+                        if ('' == testname):
+                            grab_next_line = True
+                            continue
+                        self.test_to_errors[testname] = []
+                    if grab_next_line: # test name on its own line
+                        grab_next_line = False
+                        testname = testname.strip().strip(' {)')
+                        self.test_to_errors[testname] = []
+                    if ' VALIDATION_ERROR_' in line:
+                        line_list = line.split()
+                        for sub_str in line_list:
+                            if 'VALIDATION_ERROR_' in sub_str and True not in [ignore_str in sub_str for ignore_str in ['VALIDATION_ERROR_UNDEFINED', 'UNIQUE_VALIDATION_ERROR_CODE', 'VALIDATION_ERROR_MAX_ENUM']]:
+                                #print("Trying to add enums for line: %s" % ())
+                                #print("Adding enum %s to test %s" % (sub_str.strip(',);'), testname))
+                                self.test_to_errors[testname].append(sub_str.strip(',);'))
+
+# Little helper class for coloring cmd line output
+class bcolors:
+
+    def __init__(self):
+        self.GREEN = '\033[0;32m'
+        self.RED = '\033[0;31m'
+        self.YELLOW = '\033[1;33m'
+        self.ENDC = '\033[0m'
+        if 'Linux' != platform.system():
+            self.GREEN = ''
+            self.RED = ''
+            self.YELLOW = ''
+            self.ENDC = ''
+
+    def green(self):
+        return self.GREEN
+
+    def red(self):
+        return self.RED
+
+    def yellow(self):
+        return self.YELLOW
+
+    def endc(self):
+        return self.ENDC
+
+def main(argv):
+    result = 0 # Non-zero result indicates an error case
+    terse_mode = 'terse_mode' in sys.argv
+    # parse db
+    val_db = ValidationDatabase()
+    val_db.read()
+    # parse header
+    val_header = ValidationHeader()
+    val_header.read()
+    # Create parser for layer files
+    val_source = ValidationSource(layer_source_files)
+    val_source.parse()
+    # Parse test files
+    test_parser = TestParser([test_file, ])
+    test_parser.parse()
+
+    # Process stats - Just doing this inline in main, could make a fancy class to handle
+    #   all the processing of data and then get results from that
+    txt_color = bcolors()
+    if terse_mode == False:
+        print("Validation Statistics")
+    else:
+        print("Validation/Documentation Consistency Test)")
+    # First give number of checks in db & header and report any discrepancies
+    db_enums = len(val_db.db_dict.keys())
+    hdr_enums = len(val_header.enums)
+    if not terse_mode:
+        print(" Database file includes %d unique checks" % (db_enums))
+        print(" Header file declares %d unique checks" % (hdr_enums))
+
+    # Report any checks that have an invalid check_implemented flag
+    if len(val_db.db_invalid_implemented) > 0:
+        result = 1
+        print(txt_color.red() + "The following checks have an invalid check_implemented flag (must be 'Y' or 'N'):" + txt_color.endc())
+        for invalid_imp_enum in val_db.db_invalid_implemented:
+            check_implemented = val_db.db_dict[invalid_imp_enum]['check_implemented']
+            print(txt_color.red() + "    %s has check_implemented flag '%s'" % (invalid_imp_enum, check_implemented) + txt_color.endc())
+
+    # Report details about how well the Database and Header are synchronized.
+    tmp_db_dict = val_db.db_dict
+    db_missing = []
+    for enum in val_header.enums:
+        if not tmp_db_dict.pop(enum, False):
+            db_missing.append(enum)
+    if db_enums == hdr_enums and len(db_missing) == 0 and len(tmp_db_dict.keys()) == 0:
+        if not terse_mode:
+            print(txt_color.green() + "  Database and Header match, GREAT!" + txt_color.endc())
+    else:
+        print(txt_color.red() + "  Uh oh, Database doesn't match Header :(" + txt_color.endc())
+        result = 1
+        if len(db_missing) != 0:
+            print(txt_color.red() + "   The following checks are in header but missing from database:" + txt_color.endc())
+            for missing_enum in db_missing:
+                print(txt_color.red() + "    %s" % (missing_enum) + txt_color.endc())
+        if len(tmp_db_dict.keys()) != 0:
+            print(txt_color.red() + "   The following checks are in database but haven't been declared in the header:" + txt_color.endc())
+            for extra_enum in tmp_db_dict:
+                print(txt_color.red() + "    %s" % (extra_enum) + txt_color.endc())
+
+    # Report out claimed implemented checks vs. found actual implemented checks
+    imp_not_found = [] # Checks claimed to implemented in DB file but no source found
+    imp_not_claimed = [] # Checks found implemented but not claimed to be in DB
+    multiple_uses = False # Flag if any enums are used multiple times
+    for db_imp in val_db.db_implemented_enums:
+        if db_imp not in val_source.enum_count_dict:
+            imp_not_found.append(db_imp)
+    for src_enum in val_source.enum_count_dict:
+        if val_source.enum_count_dict[src_enum]['count'] > 1 and src_enum not in duplicate_exceptions:
+            multiple_uses = True
+        if src_enum not in val_db.db_implemented_enums:
+            imp_not_claimed.append(src_enum)
+    if not terse_mode:
+        print(" Database file claims that %d checks (%s) are implemented in source." % (len(val_db.db_implemented_enums), "{0:.0f}%".format(float(len(val_db.db_implemented_enums))/db_enums * 100)))
+
+    if len(val_db.db_unimplemented_implicit) > 0 and not terse_mode:
+        print(" Database file claims %d implicit checks (%s) that are not implemented." % (len(val_db.db_unimplemented_implicit), "{0:.0f}%".format(float(len(val_db.db_unimplemented_implicit))/db_enums * 100)))
+        total_checks = len(val_db.db_implemented_enums) + len(val_db.db_unimplemented_implicit)
+        print(" If all implicit checks are handled by parameter validation this is a total of %d (%s) checks covered." % (total_checks, "{0:.0f}%".format(float(total_checks)/db_enums * 100)))
+    if len(imp_not_found) == 0 and len(imp_not_claimed) == 0:
+        if not terse_mode:
+            print(txt_color.green() + "  All claimed Database implemented checks have been found in source, and no source checks aren't claimed in Database, GREAT!" + txt_color.endc())
+    else:
+        result = 1
+        print(txt_color.red() + "  Uh oh, Database claimed implemented don't match Source :(" + txt_color.endc())
+        if len(imp_not_found) != 0:
+            print(txt_color.red() + "   The following %d checks are claimed to be implemented in Database, but weren't found in source:" % (len(imp_not_found)) + txt_color.endc())
+            for not_imp_enum in imp_not_found:
+                print(txt_color.red() + "    %s" % (not_imp_enum) + txt_color.endc())
+        if len(imp_not_claimed) != 0:
+            print(txt_color.red() + "   The following checks are implemented in source, but not claimed to be in Database:" + txt_color.endc())
+            for imp_enum in imp_not_claimed:
+                print(txt_color.red() + "    %s" % (imp_enum) + txt_color.endc())
+
+    if multiple_uses and not terse_mode:
+        print(txt_color.yellow() + "  Note that some checks are used multiple times. These may be good candidates for new valid usage spec language." + txt_color.endc())
+        print(txt_color.yellow() + "  Here is a list of each check used multiple times with its number of uses:" + txt_color.endc())
+        for enum in val_source.enum_count_dict:
+            if val_source.enum_count_dict[enum]['count'] > 1 and enum not in duplicate_exceptions:
+                print(txt_color.yellow() + "   %s: %d uses in file,line:" % (enum, val_source.enum_count_dict[enum]['count']) + txt_color.endc())
+                for file_line in val_source.enum_count_dict[enum]['file_line']:
+                    print(txt_color.yellow() + "   \t%s" % (file_line) + txt_color.endc())
+
+    # Now check that tests claimed to be implemented are actual test names
+    bad_testnames = []
+    tests_missing_enum = {} # Report tests that don't use validation error enum to check for error case
+    for enum in val_db.db_enum_to_tests:
+        for testname in val_db.db_enum_to_tests[enum]:
+            if testname not in test_parser.test_to_errors:
+                bad_testnames.append(testname)
+            else:
+                enum_found = False
+                for test_enum in test_parser.test_to_errors[testname]:
+                    if test_enum == enum:
+                        #print("Found test that correctly checks for enum: %s" % (enum))
+                        enum_found = True
+                if not enum_found:
+                    #print("Test %s is not using enum %s to check for error" % (testname, enum))
+                    if testname not in tests_missing_enum:
+                        tests_missing_enum[testname] = []
+                    tests_missing_enum[testname].append(enum)
+    if tests_missing_enum and not terse_mode:
+        print(txt_color.yellow() + "  \nThe following tests do not use their reported enums to check for the validation error. You may want to update these to pass the expected enum to SetDesiredFailureMsg:" + txt_color.endc())
+        for testname in tests_missing_enum:
+            print(txt_color.yellow() + "   Testname %s does not explicitly check for these ids:" % (testname) + txt_color.endc())
+            for enum in tests_missing_enum[testname]:
+                print(txt_color.yellow() + "    %s" % (enum) + txt_color.endc())
+
+    # TODO : Go through all enums found in the test file and make sure they're correctly documented in the database file
+    if not terse_mode:
+        print(" Database file claims that %d checks have tests written." % len(val_db.db_enum_to_tests))
+    if len(bad_testnames) == 0:
+        if not terse_mode:
+            print(txt_color.green() + "  All claimed tests have valid names. That's good!" + txt_color.endc())
+    else:
+        print(txt_color.red() + "  The following testnames in Database appear to be invalid:")
+        result = 1
+        for bt in bad_testnames:
+            print(txt_color.red() + "   %s" % (bt) + txt_color.endc())
+
+    return result
+
+if __name__ == "__main__":
+    sys.exit(main(sys.argv[1:]))
+
diff --git a/scripts/vuid_mapping.py b/scripts/vuid_mapping.py
new file mode 100644
index 0000000..6317178
--- /dev/null
+++ b/scripts/vuid_mapping.py
@@ -0,0 +1,941 @@
+#!/usr/bin/python -i
+
+import sys
+import xml.etree.ElementTree as etree
+try:
+    import urllib.request as urllib2
+except ImportError:
+    import urllib2
+from bs4 import BeautifulSoup
+import json
+
+#############################
+# vuid_mapping.py script
+#
+# VUID Mapping Details
+#  The Vulkan spec creation process automatically generates string-based unique IDs for each Valid Usage statement
+#  For implicit VUs, the format is VUID-<func|struct>-[<param_name>]-<type>
+#   func|struct is the name of the API function or structure that the VU is under
+#   param_name is an optional entry with the name of the function or struct parameter
+#   type is the type of implicit check, see table below for possible values
+#
+#  For explicit VUs, the format is VUID-<func|struct>-[<param_name>]-<uniqueid>
+#   All fields are the same as implicit VUs except the last parameter is a globally unique integer ID instead of a string type
+#
+# The values below are used to map the strings into unique integers that are used for the unique enum values returned by debug callbacks
+# Here's how the bits of the numerical unique ID map to the ID type and values
+# 31:21 - 11 bits that map to unique value for the function/struct
+# 20:1  - 20 bits that map to param-type combo for implicit VU and uniqueid for explicit VU
+# 0     - 1 bit on for implicit VU or off for explicit VU
+#
+# For implicit VUs 20:1 is split into 20:9 for parameter and 8:1 for type
+FUNC_STRUCT_SHIFT = 21
+EXPLICIT_ID_SHIFT = 1
+IMPLICIT_TYPE_SHIFT = 1
+IMPLICIT_PARAM_SHIFT = 9
+explicit_bit0 = 0x0 # All explicit IDs are even
+implicit_bit0 = 0x1 # All implicit IDs are odd
+# Implicit type values, shifted up by ID_SHIFT bits in final ID
+implicit_type_map = {
+'parameter'       : 0,
+'requiredbitmask' : 1,
+'zerobitmask'     : 2,
+'parent'          : 3,
+'commonparent'    : 4,
+'sType'           : 5,
+'pNext'           : 6,
+'unique'          : 7,
+'queuetype'       : 8,
+'recording'       : 9,
+'cmdpool'         : 10,
+'renderpass'      : 11,
+'bufferlevel'     : 12,
+'arraylength'     : 13,
+}
+# Function/struct value mappings, shifted up FUNC_STRUCT_SHIFT bits in final ID
+func_struct_id_map = {
+'VkAcquireNextImageInfoKHX' : 0,
+'VkAllocationCallbacks' : 1,
+'VkAndroidSurfaceCreateInfoKHR' : 2,
+'VkApplicationInfo' : 3,
+'VkAttachmentDescription' : 4,
+'VkAttachmentReference' : 5,
+'VkBindBufferMemoryInfoKHX' : 6,
+'VkBindImageMemoryInfoKHX' : 7,
+'VkBindImageMemorySwapchainInfoKHX' : 8,
+'VkBindSparseInfo' : 9,
+'VkBufferCreateInfo' : 10,
+'VkBufferImageCopy' : 11,
+'VkBufferMemoryBarrier' : 12,
+'VkBufferViewCreateInfo' : 13,
+'VkClearAttachment' : 14,
+'VkClearDepthStencilValue' : 15,
+'VkClearValue' : 16,
+'VkCmdProcessCommandsInfoNVX' : 17,
+'VkCmdReserveSpaceForCommandsInfoNVX' : 18,
+'VkCommandBufferAllocateInfo' : 19,
+'VkCommandBufferBeginInfo' : 20,
+'VkCommandBufferInheritanceInfo' : 21,
+'VkCommandPoolCreateInfo' : 22,
+'VkComponentMapping' : 23,
+'VkComputePipelineCreateInfo' : 24,
+'VkCopyDescriptorSet' : 25,
+'VkD3D12FenceSubmitInfoKHX' : 26,
+'VkDebugMarkerMarkerInfoEXT' : 27,
+'VkDebugMarkerObjectNameInfoEXT' : 28,
+'VkDebugMarkerObjectTagInfoEXT' : 29,
+'VkDebugReportCallbackCreateInfoEXT' : 30,
+'VkDedicatedAllocationBufferCreateInfoNV' : 31,
+'VkDedicatedAllocationImageCreateInfoNV' : 32,
+'VkDedicatedAllocationMemoryAllocateInfoNV' : 33,
+'VkDescriptorBufferInfo' : 34,
+'VkDescriptorImageInfo' : 35,
+'VkDescriptorPoolCreateInfo' : 36,
+'VkDescriptorPoolSize' : 37,
+'VkDescriptorSetAllocateInfo' : 38,
+'VkDescriptorSetLayoutBinding' : 39,
+'VkDescriptorSetLayoutCreateInfo' : 40,
+'VkDescriptorUpdateTemplateCreateInfoKHR' : 41,
+'VkDescriptorUpdateTemplateEntryKHR' : 42,
+'VkDeviceCreateInfo' : 43,
+'VkDeviceEventInfoEXT' : 44,
+'VkDeviceGeneratedCommandsFeaturesNVX' : 45,
+'VkDeviceGeneratedCommandsLimitsNVX' : 46,
+'VkDeviceGroupBindSparseInfoKHX' : 47,
+'VkDeviceGroupCommandBufferBeginInfoKHX' : 48,
+'VkDeviceGroupDeviceCreateInfoKHX' : 49,
+'VkDeviceGroupPresentInfoKHX' : 50,
+'VkDeviceGroupRenderPassBeginInfoKHX' : 51,
+'VkDeviceGroupSubmitInfoKHX' : 52,
+'VkDeviceGroupSwapchainCreateInfoKHX' : 53,
+'VkDeviceQueueCreateInfo' : 54,
+'VkDispatchIndirectCommand' : 55,
+'VkDisplayEventInfoEXT' : 56,
+'VkDisplayModeCreateInfoKHR' : 57,
+'VkDisplayPowerInfoEXT' : 58,
+'VkDisplayPresentInfoKHR' : 59,
+'VkDisplaySurfaceCreateInfoKHR' : 60,
+'VkDrawIndexedIndirectCommand' : 61,
+'VkDrawIndirectCommand' : 62,
+'VkEventCreateInfo' : 63,
+'VkExportMemoryAllocateInfoKHX' : 64,
+'VkExportMemoryAllocateInfoNV' : 65,
+'VkExportMemoryWin32HandleInfoKHX' : 66,
+'VkExportMemoryWin32HandleInfoNV' : 67,
+'VkExportSemaphoreCreateInfoKHX' : 68,
+'VkExportSemaphoreWin32HandleInfoKHX' : 69,
+'VkExternalMemoryBufferCreateInfoKHX' : 70,
+'VkExternalMemoryImageCreateInfoKHX' : 71,
+'VkExternalMemoryImageCreateInfoNV' : 72,
+'VkFenceCreateInfo' : 73,
+'VkFramebufferCreateInfo' : 74,
+'VkGraphicsPipelineCreateInfo' : 75,
+'VkIOSSurfaceCreateInfoMVK' : 76,
+'VkImageBlit' : 77,
+'VkImageCopy' : 78,
+'VkImageCreateInfo' : 79,
+'VkImageMemoryBarrier' : 80,
+'VkImageResolve' : 81,
+'VkImageSubresource' : 82,
+'VkImageSubresourceLayers' : 83,
+'VkImageSubresourceRange' : 84,
+'VkImageSwapchainCreateInfoKHX' : 85,
+'VkImageViewCreateInfo' : 86,
+'VkImportMemoryFdInfoKHX' : 87,
+'VkImportMemoryWin32HandleInfoKHX' : 88,
+'VkImportMemoryWin32HandleInfoNV' : 89,
+'VkImportSemaphoreFdInfoKHX' : 90,
+'VkImportSemaphoreWin32HandleInfoKHX' : 91,
+'VkIndirectCommandsLayoutCreateInfoNVX' : 92,
+'VkIndirectCommandsLayoutTokenNVX' : 93,
+'VkIndirectCommandsTokenNVX' : 94,
+'VkInstanceCreateInfo' : 95,
+'VkMacOSSurfaceCreateInfoMVK' : 96,
+'VkMappedMemoryRange' : 97,
+'VkMemoryAllocateFlagsInfoKHX' : 98,
+'VkMemoryAllocateInfo' : 99,
+'VkMemoryBarrier' : 100,
+'VkMirSurfaceCreateInfoKHR' : 101,
+'VkObjectTableCreateInfoNVX' : 102,
+'VkObjectTableDescriptorSetEntryNVX' : 103,
+'VkObjectTableEntryNVX' : 104,
+'VkObjectTableIndexBufferEntryNVX' : 105,
+'VkObjectTablePipelineEntryNVX' : 106,
+'VkObjectTablePushConstantEntryNVX' : 107,
+'VkObjectTableVertexBufferEntryNVX' : 108,
+'VkPhysicalDeviceDiscardRectanglePropertiesEXT' : 109,
+'VkPhysicalDeviceExternalBufferInfoKHX' : 110,
+'VkPhysicalDeviceExternalImageFormatInfoKHX' : 111,
+'VkPhysicalDeviceExternalSemaphoreInfoKHX' : 112,
+'VkPhysicalDeviceFeatures' : 113,
+'VkPhysicalDeviceFeatures2KHR' : 114,
+'VkPhysicalDeviceImageFormatInfo2KHR' : 115,
+'VkPhysicalDeviceMultiviewFeaturesKHX' : 116,
+'VkPhysicalDevicePushDescriptorPropertiesKHR' : 117,
+'VkPhysicalDeviceSparseImageFormatInfo2KHR' : 118,
+'VkPhysicalDeviceSurfaceInfo2KHR' : 119,
+'VkPipelineCacheCreateInfo' : 120,
+'VkPipelineColorBlendAttachmentState' : 121,
+'VkPipelineColorBlendStateCreateInfo' : 122,
+'VkPipelineDepthStencilStateCreateInfo' : 123,
+'VkPipelineDiscardRectangleStateCreateInfoEXT' : 124,
+'VkPipelineDynamicStateCreateInfo' : 125,
+'VkPipelineInputAssemblyStateCreateInfo' : 126,
+'VkPipelineLayoutCreateInfo' : 127,
+'VkPipelineMultisampleStateCreateInfo' : 128,
+'VkPipelineRasterizationStateCreateInfo' : 129,
+'VkPipelineRasterizationStateRasterizationOrderAMD' : 130,
+'VkPipelineShaderStageCreateInfo' : 131,
+'VkPipelineTessellationStateCreateInfo' : 132,
+'VkPipelineVertexInputStateCreateInfo' : 133,
+'VkPipelineViewportStateCreateInfo' : 134,
+'VkPipelineViewportSwizzleStateCreateInfoNV' : 135,
+'VkPipelineViewportWScalingStateCreateInfoNV' : 136,
+'VkPresentInfoKHR' : 137,
+'VkPresentRegionKHR' : 138,
+'VkPresentRegionsKHR' : 139,
+'VkPresentTimesInfoGOOGLE' : 140,
+'VkPushConstantRange' : 141,
+'VkQueryPoolCreateInfo' : 142,
+'VkRectLayerKHR' : 143,
+'VkRenderPassBeginInfo' : 144,
+'VkRenderPassCreateInfo' : 145,
+'VkRenderPassMultiviewCreateInfoKHX' : 146,
+'VkSamplerCreateInfo' : 147,
+'VkSemaphoreCreateInfo' : 148,
+'VkShaderModuleCreateInfo' : 149,
+'VkSparseBufferMemoryBindInfo' : 150,
+'VkSparseImageMemoryBind' : 151,
+'VkSparseImageMemoryBindInfo' : 152,
+'VkSparseImageOpaqueMemoryBindInfo' : 153,
+'VkSparseMemoryBind' : 154,
+'VkSpecializationInfo' : 155,
+'VkSpecializationMapEntry' : 156,
+'VkStencilOpState' : 157,
+'VkSubmitInfo' : 158,
+'VkSubpassDependency' : 159,
+'VkSubpassDescription' : 160,
+'VkSurfaceCapabilities2EXT' : 161,
+'VkSwapchainCounterCreateInfoEXT' : 162,
+'VkSwapchainCreateInfoKHR' : 163,
+'VkValidationFlagsEXT' : 164,
+'VkVertexInputAttributeDescription' : 165,
+'VkVertexInputBindingDescription' : 166,
+'VkViSurfaceCreateInfoNN' : 167,
+'VkViewport' : 168,
+'VkViewportSwizzleNV' : 169,
+'VkWaylandSurfaceCreateInfoKHR' : 170,
+'VkWin32KeyedMutexAcquireReleaseInfoKHX' : 171,
+'VkWin32KeyedMutexAcquireReleaseInfoNV' : 172,
+'VkWin32SurfaceCreateInfoKHR' : 173,
+'VkWriteDescriptorSet' : 174,
+'VkXcbSurfaceCreateInfoKHR' : 175,
+'VkXlibSurfaceCreateInfoKHR' : 176,
+'vkAcquireNextImage2KHX' : 177,
+'vkAcquireNextImageKHR' : 178,
+'vkAcquireXlibDisplayEXT' : 179,
+'vkAllocateCommandBuffers' : 180,
+'vkAllocateDescriptorSets' : 181,
+'vkAllocateMemory' : 182,
+'vkBeginCommandBuffer' : 183,
+'vkBindBufferMemory' : 184,
+'vkBindBufferMemory2KHX' : 185,
+'vkBindImageMemory' : 186,
+'vkBindImageMemory2KHX' : 187,
+'vkCmdBeginQuery' : 188,
+'vkCmdBeginRenderPass' : 189,
+'vkCmdBindDescriptorSets' : 190,
+'vkCmdBindIndexBuffer' : 191,
+'vkCmdBindPipeline' : 192,
+'vkCmdBindVertexBuffers' : 193,
+'vkCmdBlitImage' : 194,
+'vkCmdClearAttachments' : 195,
+'vkCmdClearColorImage' : 196,
+'vkCmdClearDepthStencilImage' : 197,
+'vkCmdCopyBuffer' : 198,
+'vkCmdCopyBufferToImage' : 199,
+'vkCmdCopyImage' : 200,
+'vkCmdCopyImageToBuffer' : 201,
+'vkCmdCopyQueryPoolResults' : 202,
+'vkCmdDebugMarkerBeginEXT' : 203,
+'vkCmdDebugMarkerEndEXT' : 204,
+'vkCmdDebugMarkerInsertEXT' : 205,
+'vkCmdDispatch' : 206,
+'vkCmdDispatchBaseKHX' : 207,
+'vkCmdDispatchIndirect' : 208,
+'vkCmdDraw' : 209,
+'vkCmdDrawIndexed' : 210,
+'vkCmdDrawIndexedIndirect' : 211,
+'vkCmdDrawIndexedIndirectCountAMD' : 212,
+'vkCmdDrawIndirect' : 213,
+'vkCmdDrawIndirectCountAMD' : 214,
+'vkCmdEndQuery' : 215,
+'vkCmdEndRenderPass' : 216,
+'vkCmdExecuteCommands' : 217,
+'vkCmdFillBuffer' : 218,
+'vkCmdNextSubpass' : 219,
+'vkCmdPipelineBarrier' : 220,
+'vkCmdProcessCommandsNVX' : 221,
+'vkCmdPushConstants' : 222,
+'vkCmdPushDescriptorSetKHR' : 223,
+'vkCmdPushDescriptorSetWithTemplateKHR' : 224,
+'vkCmdReserveSpaceForCommandsNVX' : 225,
+'vkCmdResetEvent' : 226,
+'vkCmdResetQueryPool' : 227,
+'vkCmdResolveImage' : 228,
+'vkCmdSetBlendConstants' : 229,
+'vkCmdSetDepthBias' : 230,
+'vkCmdSetDepthBounds' : 231,
+'vkCmdSetDeviceMaskKHX' : 232,
+'vkCmdSetDiscardRectangleEXT' : 233,
+'vkCmdSetEvent' : 234,
+'vkCmdSetLineWidth' : 235,
+'vkCmdSetScissor' : 236,
+'vkCmdSetStencilCompareMask' : 237,
+'vkCmdSetStencilReference' : 238,
+'vkCmdSetStencilWriteMask' : 239,
+'vkCmdSetViewport' : 240,
+'vkCmdSetViewportWScalingNV' : 241,
+'vkCmdUpdateBuffer' : 242,
+'vkCmdWaitEvents' : 243,
+'vkCmdWriteTimestamp' : 244,
+'vkCreateAndroidSurfaceKHR' : 245,
+'vkCreateBuffer' : 246,
+'vkCreateBufferView' : 247,
+'vkCreateCommandPool' : 248,
+'vkCreateComputePipelines' : 249,
+'vkCreateDebugReportCallbackEXT' : 250,
+'vkCreateDescriptorPool' : 251,
+'vkCreateDescriptorSetLayout' : 252,
+'vkCreateDescriptorUpdateTemplateKHR' : 253,
+'vkCreateDevice' : 254,
+'vkCreateDisplayModeKHR' : 255,
+'vkCreateDisplayPlaneSurfaceKHR' : 256,
+'vkCreateEvent' : 257,
+'vkCreateFence' : 258,
+'vkCreateFramebuffer' : 259,
+'vkCreateGraphicsPipelines' : 260,
+'vkCreateIOSSurfaceMVK' : 261,
+'vkCreateImage' : 262,
+'vkCreateImageView' : 263,
+'vkCreateIndirectCommandsLayoutNVX' : 264,
+'vkCreateInstance' : 265,
+'vkCreateMacOSSurfaceMVK' : 266,
+'vkCreateMirSurfaceKHR' : 267,
+'vkCreateObjectTableNVX' : 268,
+'vkCreatePipelineCache' : 269,
+'vkCreatePipelineLayout' : 270,
+'vkCreateQueryPool' : 271,
+'vkCreateRenderPass' : 272,
+'vkCreateSampler' : 273,
+'vkCreateSemaphore' : 274,
+'vkCreateShaderModule' : 275,
+'vkCreateSharedSwapchainsKHR' : 276,
+'vkCreateSwapchainKHR' : 277,
+'vkCreateViSurfaceNN' : 278,
+'vkCreateWaylandSurfaceKHR' : 279,
+'vkCreateWin32SurfaceKHR' : 280,
+'vkCreateXcbSurfaceKHR' : 281,
+'vkCreateXlibSurfaceKHR' : 282,
+'vkDebugMarkerSetObjectNameEXT' : 283,
+'vkDebugMarkerSetObjectTagEXT' : 284,
+'vkDebugReportMessageEXT' : 285,
+'vkDestroyBuffer' : 286,
+'vkDestroyBufferView' : 287,
+'vkDestroyCommandPool' : 288,
+'vkDestroyDebugReportCallbackEXT' : 289,
+'vkDestroyDescriptorPool' : 290,
+'vkDestroyDescriptorSetLayout' : 291,
+'vkDestroyDescriptorUpdateTemplateKHR' : 292,
+'vkDestroyDevice' : 293,
+'vkDestroyEvent' : 294,
+'vkDestroyFence' : 295,
+'vkDestroyFramebuffer' : 296,
+'vkDestroyImage' : 297,
+'vkDestroyImageView' : 298,
+'vkDestroyIndirectCommandsLayoutNVX' : 299,
+'vkDestroyInstance' : 300,
+'vkDestroyObjectTableNVX' : 301,
+'vkDestroyPipeline' : 302,
+'vkDestroyPipelineCache' : 303,
+'vkDestroyPipelineLayout' : 304,
+'vkDestroyQueryPool' : 305,
+'vkDestroyRenderPass' : 306,
+'vkDestroySampler' : 307,
+'vkDestroySemaphore' : 308,
+'vkDestroyShaderModule' : 309,
+'vkDestroySurfaceKHR' : 310,
+'vkDestroySwapchainKHR' : 311,
+'vkDeviceWaitIdle' : 312,
+'vkDisplayPowerControlEXT' : 313,
+'vkEndCommandBuffer' : 314,
+'vkEnumerateDeviceExtensionProperties' : 315,
+'vkEnumerateDeviceLayerProperties' : 316,
+'vkEnumerateInstanceExtensionProperties' : 317,
+'vkEnumerateInstanceLayerProperties' : 318,
+'vkEnumeratePhysicalDeviceGroupsKHX' : 319,
+'vkEnumeratePhysicalDevices' : 320,
+'vkFlushMappedMemoryRanges' : 321,
+'vkFreeCommandBuffers' : 322,
+'vkFreeDescriptorSets' : 323,
+'vkFreeMemory' : 324,
+'vkGetBufferMemoryRequirements' : 325,
+'vkGetDeviceGroupPeerMemoryFeaturesKHX' : 326,
+'vkGetDeviceGroupPresentCapabilitiesKHX' : 327,
+'vkGetDeviceGroupSurfacePresentModesKHX' : 328,
+'vkGetDeviceMemoryCommitment' : 329,
+'vkGetDeviceProcAddr' : 330,
+'vkGetDeviceQueue' : 331,
+'vkGetDisplayModePropertiesKHR' : 332,
+'vkGetDisplayPlaneCapabilitiesKHR' : 333,
+'vkGetDisplayPlaneSupportedDisplaysKHR' : 334,
+'vkGetEventStatus' : 335,
+'vkGetFenceStatus' : 336,
+'vkGetImageMemoryRequirements' : 337,
+'vkGetImageSparseMemoryRequirements' : 338,
+'vkGetImageSubresourceLayout' : 339,
+'vkGetInstanceProcAddr' : 340,
+'vkGetMemoryFdKHX' : 341,
+'vkGetMemoryFdPropertiesKHX' : 342,
+'vkGetMemoryWin32HandleKHX' : 343,
+'vkGetMemoryWin32HandleNV' : 344,
+'vkGetMemoryWin32HandlePropertiesKHX' : 345,
+'vkGetPastPresentationTimingGOOGLE' : 346,
+'vkGetPhysicalDeviceDisplayPlanePropertiesKHR' : 347,
+'vkGetPhysicalDeviceDisplayPropertiesKHR' : 348,
+'vkGetPhysicalDeviceExternalBufferPropertiesKHX' : 349,
+'vkGetPhysicalDeviceExternalImageFormatPropertiesNV' : 350,
+'vkGetPhysicalDeviceExternalSemaphorePropertiesKHX' : 351,
+'vkGetPhysicalDeviceFeatures' : 352,
+'vkGetPhysicalDeviceFeatures2KHR' : 353,
+'vkGetPhysicalDeviceFormatProperties' : 354,
+'vkGetPhysicalDeviceFormatProperties2KHR' : 355,
+'vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX' : 356,
+'vkGetPhysicalDeviceImageFormatProperties' : 357,
+'vkGetPhysicalDeviceImageFormatProperties2KHR' : 358,
+'vkGetPhysicalDeviceMemoryProperties' : 359,
+'vkGetPhysicalDeviceMemoryProperties2KHR' : 360,
+'vkGetPhysicalDeviceMirPresentationSupportKHR' : 361,
+'vkGetPhysicalDevicePresentRectanglesKHX' : 362,
+'vkGetPhysicalDeviceProperties' : 363,
+'vkGetPhysicalDeviceProperties2KHR' : 364,
+'vkGetPhysicalDeviceQueueFamilyProperties' : 365,
+'vkGetPhysicalDeviceQueueFamilyProperties2KHR' : 366,
+'vkGetPhysicalDeviceSparseImageFormatProperties' : 367,
+'vkGetPhysicalDeviceSparseImageFormatProperties2KHR' : 368,
+'vkGetPhysicalDeviceSurfaceCapabilities2EXT' : 369,
+'vkGetPhysicalDeviceSurfaceCapabilities2KHR' : 370,
+'vkGetPhysicalDeviceSurfaceCapabilitiesKHR' : 371,
+'vkGetPhysicalDeviceSurfaceFormats2KHR' : 372,
+'vkGetPhysicalDeviceSurfaceFormatsKHR' : 373,
+'vkGetPhysicalDeviceSurfacePresentModesKHR' : 374,
+'vkGetPhysicalDeviceSurfaceSupportKHR' : 375,
+'vkGetPhysicalDeviceWaylandPresentationSupportKHR' : 376,
+'vkGetPhysicalDeviceWin32PresentationSupportKHR' : 377,
+'vkGetPhysicalDeviceXcbPresentationSupportKHR' : 378,
+'vkGetPhysicalDeviceXlibPresentationSupportKHR' : 379,
+'vkGetPipelineCacheData' : 380,
+'vkGetQueryPoolResults' : 381,
+'vkGetRandROutputDisplayEXT' : 382,
+'vkGetRefreshCycleDurationGOOGLE' : 383,
+'vkGetRenderAreaGranularity' : 384,
+'vkGetSemaphoreFdKHX' : 385,
+'vkGetSemaphoreWin32HandleKHX' : 386,
+'vkGetSwapchainCounterEXT' : 387,
+'vkGetSwapchainImagesKHR' : 388,
+'vkGetSwapchainStatusKHR' : 389,
+'vkImportSemaphoreFdKHX' : 390,
+'vkImportSemaphoreWin32HandleKHX' : 391,
+'vkInvalidateMappedMemoryRanges' : 392,
+'vkMapMemory' : 393,
+'vkMergePipelineCaches' : 394,
+'vkQueueBindSparse' : 395,
+'vkQueuePresentKHR' : 396,
+'vkQueueSubmit' : 397,
+'vkQueueWaitIdle' : 398,
+'vkRegisterDeviceEventEXT' : 399,
+'vkRegisterDisplayEventEXT' : 400,
+'vkRegisterObjectsNVX' : 401,
+'vkReleaseDisplayEXT' : 402,
+'vkResetCommandBuffer' : 403,
+'vkResetCommandPool' : 404,
+'vkResetDescriptorPool' : 405,
+'vkResetEvent' : 406,
+'vkResetFences' : 407,
+'vkSetEvent' : 408,
+'vkSetHdrMetadataEXT' : 409,
+'vkTrimCommandPoolKHR' : 410,
+'vkUnmapMemory' : 411,
+'vkUnregisterObjectsNVX' : 412,
+'vkUpdateDescriptorSetWithTemplateKHR' : 413,
+'vkUpdateDescriptorSets' : 414,
+'vkWaitForFences' : 415,
+### ADD New func/struct mappings above this line
+}
+# Mapping of params to unique IDs
+implicit_param_map = {
+'a' : 0,
+'addressModeU' : 1,
+'addressModeV' : 2,
+'addressModeW' : 3,
+'alphaBlendOp' : 4,
+'alphaMode' : 5,
+'aspectMask' : 6,
+'attachmentCount' : 7,
+'b' : 8,
+'back' : 9,
+'bindCount' : 10,
+'bindInfoCount' : 11,
+'bindingCount' : 12,
+'buffer' : 13,
+'bufferView' : 14,
+'callback' : 15,
+'colorBlendOp' : 16,
+'colorWriteMask' : 17,
+'commandBuffer' : 18,
+'commandBufferCount' : 19,
+'commandPool' : 20,
+'compareOp' : 21,
+'components' : 22,
+'compositeAlpha' : 23,
+'connection' : 24,
+'contents' : 25,
+'countBuffer' : 26,
+'counter' : 27,
+'createInfoCount' : 28,
+'cullMode' : 29,
+'dataSize' : 30,
+'dependencyFlags' : 31,
+'depthCompareOp' : 32,
+'depthFailOp' : 33,
+'descriptorCount' : 34,
+'descriptorPool' : 35,
+'descriptorSet' : 36,
+'descriptorSetCount' : 37,
+'descriptorSetLayout' : 38,
+'descriptorType' : 39,
+'descriptorUpdateEntryCount' : 40,
+'descriptorUpdateTemplate' : 41,
+'descriptorWriteCount' : 42,
+'device' : 43,
+'deviceEvent' : 44,
+'disabledValidationCheckCount' : 45,
+'discardRectangleCount' : 46,
+'discardRectangleMode' : 47,
+'display' : 48,
+'displayEvent' : 49,
+'displayMode' : 50,
+'dpy' : 51,
+'dstAccessMask' : 52,
+'dstAlphaBlendFactor' : 53,
+'dstBuffer' : 54,
+'dstCache' : 55,
+'dstColorBlendFactor' : 56,
+'dstImage' : 57,
+'dstImageLayout' : 58,
+'dstSet' : 59,
+'dstStageMask' : 60,
+'dstSubresource' : 61,
+'dynamicStateCount' : 62,
+'event' : 63,
+'eventCount' : 64,
+'externalHandleType' : 65,
+'faceMask' : 66,
+'failOp' : 67,
+'fence' : 68,
+'fenceCount' : 69,
+'filter' : 70,
+'finalLayout' : 71,
+'flags' : 72,
+'format' : 73,
+'framebuffer' : 74,
+'front' : 75,
+'frontFace' : 76,
+'g' : 77,
+'handleType' : 78,
+'handleTypes' : 79,
+'image' : 80,
+'imageColorSpace' : 81,
+'imageFormat' : 82,
+'imageLayout' : 83,
+'imageSharingMode' : 84,
+'imageSubresource' : 85,
+'imageType' : 86,
+'imageUsage' : 87,
+'imageView' : 88,
+'indexType' : 89,
+'indirectCommandsLayout' : 90,
+'indirectCommandsTokenCount' : 91,
+'initialLayout' : 92,
+'inputRate' : 93,
+'instance' : 94,
+'layout' : 95,
+'level' : 96,
+'loadOp' : 97,
+'magFilter' : 98,
+'memory' : 99,
+'memoryRangeCount' : 100,
+'minFilter' : 101,
+'mipmapMode' : 102,
+'mode' : 103,
+'modes' : 104,
+'module' : 105,
+'newLayout' : 106,
+'objectCount' : 107,
+'objectTable' : 108,
+'objectType' : 109,
+'oldLayout' : 110,
+'oldSwapchain' : 111,
+'pAcquireInfo' : 112,
+'pAcquireKeys' : 113,
+'pAcquireSyncs' : 114,
+'pAcquireTimeoutMilliseconds' : 115,
+'pAcquireTimeouts' : 116,
+'pAllocateInfo' : 117,
+'pAllocator' : 118,
+'pApplicationInfo' : 119,
+'pApplicationName' : 120,
+'pAttachments' : 121,
+'pAttributes' : 122,
+'pBeginInfo' : 123,
+'pBindInfo' : 124,
+'pBindInfos' : 125,
+'pBindings' : 126,
+'pBinds' : 127,
+'pBuffer' : 128,
+'pBufferBinds' : 129,
+'pBufferMemoryBarriers' : 130,
+'pBuffers' : 131,
+'pCallback' : 132,
+'pCapabilities' : 133,
+'pCode' : 134,
+'pColor' : 135,
+'pColorAttachments' : 136,
+'pCommandBufferDeviceMasks' : 137,
+'pCommandBuffers' : 138,
+'pCommandPool' : 139,
+'pCommittedMemoryInBytes' : 140,
+'pCorrelationMasks' : 141,
+'pCounterValue' : 142,
+'pCreateInfo' : 143,
+'pCreateInfos' : 144,
+'pData' : 145,
+'pDataSize' : 146,
+'pDependencies' : 147,
+'pDepthStencil' : 148,
+'pDepthStencilAttachment' : 149,
+'pDescriptorCopies' : 150,
+'pDescriptorPool' : 151,
+'pDescriptorSets' : 152,
+'pDescriptorUpdateEntries' : 153,
+'pDescriptorUpdateTemplate' : 154,
+'pDescriptorWrites' : 155,
+'pDevice' : 156,
+'pDeviceEventInfo' : 157,
+'pDeviceGroupPresentCapabilities' : 158,
+'pDeviceIndices' : 159,
+'pDeviceMasks' : 160,
+'pDeviceRenderAreas' : 161,
+'pDisabledValidationChecks' : 162,
+'pDiscardRectangles' : 163,
+'pDisplay' : 164,
+'pDisplayCount' : 165,
+'pDisplayEventInfo' : 166,
+'pDisplayPowerInfo' : 167,
+'pDisplayTimingProperties' : 168,
+'pDisplays' : 169,
+'pDynamicOffsets' : 170,
+'pDynamicState' : 171,
+'pDynamicStates' : 172,
+'pEnabledFeatures' : 173,
+'pEngineName' : 174,
+'pEvent' : 175,
+'pEvents' : 176,
+'pExternalBufferInfo' : 177,
+'pExternalBufferProperties' : 178,
+'pExternalImageFormatProperties' : 179,
+'pExternalSemaphoreInfo' : 180,
+'pExternalSemaphoreProperties' : 181,
+'pFd' : 182,
+'pFeatures' : 183,
+'pFence' : 184,
+'pFences' : 185,
+'pFormatInfo' : 186,
+'pFormatProperties' : 187,
+'pFramebuffer' : 188,
+'pGranularity' : 189,
+'pHandle' : 190,
+'pImage' : 191,
+'pImageBinds' : 192,
+'pImageFormatInfo' : 193,
+'pImageFormatProperties' : 194,
+'pImageIndex' : 195,
+'pImageIndices' : 196,
+'pImageMemoryBarriers' : 197,
+'pImageOpaqueBinds' : 198,
+'pImportSemaphoreFdInfo' : 199,
+'pImportSemaphoreWin32HandleInfo' : 200,
+'pIndirectCommandsLayout' : 201,
+'pIndirectCommandsTokens' : 202,
+'pInitialData' : 203,
+'pInputAssemblyState' : 204,
+'pInputAttachments' : 205,
+'pInstance' : 206,
+'pLayerName' : 207,
+'pLayerPrefix' : 208,
+'pLayout' : 209,
+'pLimits' : 210,
+'pMarkerInfo' : 211,
+'pMarkerName' : 212,
+'pMemory' : 213,
+'pMemoryBarriers' : 214,
+'pMemoryFdProperties' : 215,
+'pMemoryProperties' : 216,
+'pMemoryRanges' : 217,
+'pMemoryRequirements' : 218,
+'pMemoryWin32HandleProperties' : 219,
+'pMessage' : 220,
+'pMetadata' : 221,
+'pMode' : 222,
+'pModes' : 223,
+'pName' : 224,
+'pNameInfo' : 225,
+'pNext' : 226,
+'pObjectEntryCounts' : 227,
+'pObjectEntryTypes' : 228,
+'pObjectEntryUsageFlags' : 229,
+'pObjectIndices' : 230,
+'pObjectName' : 231,
+'pObjectTable' : 232,
+'pOffsets' : 233,
+'pPeerMemoryFeatures' : 234,
+'pPhysicalDeviceCount' : 235,
+'pPhysicalDeviceGroupCount' : 236,
+'pPhysicalDeviceGroupProperties' : 237,
+'pPhysicalDevices' : 238,
+'pPipelineCache' : 239,
+'pPipelineLayout' : 240,
+'pPipelines' : 241,
+'pPoolSizes' : 242,
+'pPresentInfo' : 243,
+'pPresentModeCount' : 244,
+'pPresentModes' : 245,
+'pPresentationTimingCount' : 246,
+'pPresentationTimings' : 247,
+'pPreserveAttachments' : 248,
+'pProcessCommandsInfo' : 249,
+'pProperties' : 250,
+'pPropertyCount' : 251,
+'pPushConstantRanges' : 252,
+'pQueryPool' : 253,
+'pQueue' : 254,
+'pQueueCreateInfos' : 255,
+'pQueueFamilyProperties' : 256,
+'pQueueFamilyPropertyCount' : 257,
+'pQueuePriorities' : 258,
+'pRanges' : 259,
+'pRasterizationState' : 260,
+'pRectCount' : 261,
+'pRectangles' : 262,
+'pRects' : 263,
+'pRegions' : 264,
+'pReleaseKeys' : 265,
+'pReleaseSyncs' : 266,
+'pRenderPass' : 267,
+'pRenderPassBegin' : 268,
+'pReserveSpaceInfo' : 269,
+'pResolveAttachments' : 270,
+'pResults' : 271,
+'pSFRRects' : 272,
+'pSampleMask' : 273,
+'pSampler' : 274,
+'pScissors' : 275,
+'pSemaphore' : 276,
+'pSetLayout' : 277,
+'pSetLayouts' : 278,
+'pShaderModule' : 279,
+'pSignalSemaphoreDeviceIndices' : 280,
+'pSignalSemaphoreValues' : 281,
+'pSignalSemaphores' : 282,
+'pSparseMemoryRequirementCount' : 283,
+'pSparseMemoryRequirements' : 284,
+'pSpecializationInfo' : 285,
+'pSrcCaches' : 286,
+'pStages' : 287,
+'pSubmits' : 288,
+'pSubpasses' : 289,
+'pSubresource' : 290,
+'pSupported' : 291,
+'pSurface' : 292,
+'pSurfaceCapabilities' : 293,
+'pSurfaceFormatCount' : 294,
+'pSurfaceFormats' : 295,
+'pSurfaceInfo' : 296,
+'pSwapchain' : 297,
+'pSwapchainImageCount' : 298,
+'pSwapchainImages' : 299,
+'pSwapchains' : 300,
+'pTag' : 301,
+'pTagInfo' : 302,
+'pTimes' : 303,
+'pTokens' : 304,
+'pValues' : 305,
+'pVertexAttributeDescriptions' : 306,
+'pVertexBindingDescriptions' : 307,
+'pVertexInputState' : 308,
+'pView' : 309,
+'pViewMasks' : 310,
+'pViewOffsets' : 311,
+'pWaitDstStageMask' : 312,
+'pWaitSemaphoreDeviceIndices' : 313,
+'pWaitSemaphoreValues' : 314,
+'pWaitSemaphores' : 315,
+'passOp' : 316,
+'physicalDevice' : 317,
+'pipeline' : 318,
+'pipelineBindPoint' : 319,
+'pipelineCache' : 320,
+'pipelineLayout' : 321,
+'pipelineStage' : 322,
+'polygonMode' : 323,
+'poolSizeCount' : 324,
+'powerState' : 325,
+'ppData' : 326,
+'ppEnabledExtensionNames' : 327,
+'ppEnabledLayerNames' : 328,
+'ppObjectTableEntries' : 329,
+'preTransform' : 330,
+'presentMode' : 331,
+'queryPool' : 332,
+'queryType' : 333,
+'queue' : 334,
+'queueCount' : 335,
+'queueCreateInfoCount' : 336,
+'r' : 337,
+'rangeCount' : 338,
+'rasterizationOrder' : 339,
+'rasterizationSamples' : 340,
+'rectCount' : 341,
+'regionCount' : 342,
+'renderPass' : 343,
+'sType' : 344,
+'sampler' : 345,
+'samples' : 346,
+'scissorCount' : 347,
+'semaphore' : 348,
+'sequencesCountBuffer' : 349,
+'sequencesIndexBuffer' : 350,
+'shaderModule' : 351,
+'sharingMode' : 352,
+'size' : 353,
+'srcAccessMask' : 354,
+'srcAlphaBlendFactor' : 355,
+'srcBuffer' : 356,
+'srcCacheCount' : 357,
+'srcColorBlendFactor' : 358,
+'srcImage' : 359,
+'srcImageLayout' : 360,
+'srcSet' : 361,
+'srcStageMask' : 362,
+'srcSubresource' : 363,
+'stage' : 364,
+'stageCount' : 365,
+'stageFlags' : 366,
+'stageMask' : 367,
+'stencilLoadOp' : 368,
+'stencilStoreOp' : 369,
+'storeOp' : 370,
+'subpassCount' : 371,
+'subresource' : 372,
+'subresourceRange' : 373,
+'surface' : 374,
+'surfaceCounters' : 375,
+'swapchain' : 376,
+'swapchainCount' : 377,
+'tagSize' : 378,
+'targetCommandBuffer' : 379,
+'templateType' : 380,
+'tiling' : 381,
+'tokenCount' : 382,
+'tokenType' : 383,
+'topology' : 384,
+'transform' : 385,
+'type' : 386,
+'usage' : 387,
+'viewType' : 388,
+'viewportCount' : 389,
+'w' : 390,
+'window' : 391,
+'x' : 392,
+'y' : 393,
+'z' : 394,
+### ADD New implicit param mappings above this line
+}
+
+uniqueid_set = set() # store uniqueid to make sure we don't have duplicates
+
+# Convert a string VUID into numerical value
+#  See "VUID Mapping Details" comment above for more info
+def convertVUID(vuid_string):
+    """Convert a string-based VUID into a numberical value"""
+    #func_struct_update = False
+    #imp_param_update = False
+    if vuid_string in ['', None]:
+        return -1
+    vuid_parts = vuid_string.split('-')
+    if vuid_parts[1] not in func_struct_id_map:
+        print ("ERROR: Missing func/struct map value for '%s'!" % (vuid_parts[1]))
+        print (" TODO: Need to add mapping for this to end of func_struct_id_map")
+        print ("   replace '### ADD New func/struct mappings above this line' line with \"'%s' : %d,\"" % (vuid_parts[1], len(func_struct_id_map)))
+        func_struct_id_map[vuid_parts[1]] = len(func_struct_id_map)
+        #func_struct_update = True
+        sys.exit()
+    uniqueid = func_struct_id_map[vuid_parts[1]] << FUNC_STRUCT_SHIFT
+    if vuid_parts[-1].isdigit(): # explit VUID has int on the end
+        explicit_id = int(vuid_parts[-1])
+        # For explicit case, id is explicit_base + func/struct mapping + unique id
+        uniqueid = uniqueid + (explicit_id << EXPLICIT_ID_SHIFT) + explicit_bit0
+    else: # implicit case
+        if vuid_parts[-1] not in implicit_type_map:
+            print("ERROR: Missing mapping for implicit type '%s'!\nTODO: Please add new mapping." % (vuid_parts[-1]))
+            sys.exit()
+        else:
+            param_id = 0 # Default when no param is available
+            if vuid_parts[-2] != vuid_parts[1]: # we have a parameter
+                if vuid_parts[-2] in implicit_param_map:
+                    param_id = implicit_param_map[vuid_parts[-2]]
+                else:
+                    print ("ERROR: Missing param '%s' from implicit_param_map\n TODO: Please add new mapping." % (vuid_parts[-2]))
+                    print ("   replace '### ADD New implicit param mappings above this line' line with \"'%s' : %d,\"" % (vuid_parts[-2], len(implicit_param_map)))
+                    implicit_param_map[vuid_parts[-2]] = len(implicit_param_map)
+                    #imp_param_update = True
+                    sys.exit()
+                uniqueid = uniqueid + (param_id << IMPLICIT_PARAM_SHIFT) + (implicit_type_map[vuid_parts[-1]] << IMPLICIT_TYPE_SHIFT) + implicit_bit0
+            else: # No parameter so that field is 0
+                uniqueid = uniqueid + (implicit_type_map[vuid_parts[-1]] << IMPLICIT_TYPE_SHIFT) + implicit_bit0
+#    if uniqueid in uniqueid_set:
+#        print ("ERROR: Uniqueid %d for string id %s is a duplicate!" % (uniqueid, vuid_string))
+#        print (" TODO: Figure out what caused the dupe and fix it")
+        #sys.exit()
+    print ("Storing uniqueid %d for unique string %s" % (uniqueid, vuid_string))
+    uniqueid_set.add(uniqueid)
+#    if func_struct_update:
+#        print ("func_struct_id_map updated, here's new structure")
+#        print ("func_struct_id_map = {")
+#        fs_id = 0
+#        for fs in sorted(func_struct_id_map):
+#            print ("'%s' : %d," % (fs, fs_id))
+#            fs_id = fs_id + 1
+#        print ("### ADD New func/struct mappings above this line")
+#        print ("}")
+#    if imp_param_update:
+#        print ("implicit_param_map updated, here's new structure")
+#        print ("implicit_param_map = {")
+#        ip_id = 0
+#        for ip in sorted(implicit_param_map):
+#            print ("'%s' : %d," % (ip, ip_id))
+#            ip_id = ip_id + 1
+#        print ("### ADD New implicit param mappings above this line")
+#        print ("}")
+
+    return uniqueid