layers: Update build for v1.0.30 XML code-gen

- Updated cmakefiles for new codegen files: renamed genvk.py to
  lvl_genvk.py as the file is modified in this repo.
- Modified dependencies and parameters of cmake build macros.
- Updated reg.py to version 1.0.30
- Updated generator.py to version 1.0.30

Change-Id: Ia87fc7fc68e406a724d5ad9822f1f87b964f9977
diff --git a/generator.py b/generator.py
index c17a644..043121c 100755
--- a/generator.py
+++ b/generator.py
@@ -15,8 +15,6 @@
 # limitations under the License.
 
 import os,re,sys
-from collections import namedtuple
-import xml.etree.ElementTree as etree
 
 def write( *args, **kwargs ):
     file = kwargs.pop('file',sys.stdout)
@@ -41,6 +39,11 @@
     else:
         return None
 
+# apiName - returns True if name is a Vulkan name (vk/Vk/VK prefix, or a
+# function pointer type), False otherwise.
+def apiName(str):
+    return str[0:2].lower() == 'vk' or str[0:3] == 'PFN'
+
 # Primary sort key for regSortFeatures.
 # Sorts by category of the feature name string:
 #   Core API features (those defined with a <feature> tag)
@@ -86,7 +89,8 @@
 # Registry.apiGen() and by base OutputGenerator objects.
 #
 # Members
-#   filename - name of file to generate, or None to write to stdout.
+#   filename - basename of file to generate, or None to write to stdout.
+#   directory - directory in which to generate filename
 #   apiname - string matching <api> 'apiname' attribute, e.g. 'gl'.
 #   profile - string specifying API profile , e.g. 'core', or None.
 #   versions - regex matching API versions to process interfaces for.
@@ -113,6 +117,7 @@
     """Represents options during header production from an API registry"""
     def __init__(self,
                  filename = None,
+                 directory = '.',
                  apiname = None,
                  profile = None,
                  versions = '.*',
@@ -122,6 +127,7 @@
                  removeExtensions = None,
                  sortProcedure = regSortFeatures):
         self.filename          = filename
+        self.directory         = directory
         self.apiname           = apiname
         self.profile           = profile
         self.versions          = self.emptyRegex(versions)
@@ -139,359 +145,6 @@
         else:
             return pat
 
-# CGeneratorOptions - subclass of GeneratorOptions.
-#
-# Adds options used by COutputGenerator objects during C language header
-# generation.
-#
-# Additional members
-#   prefixText - list of strings to prefix generated header with
-#     (usually a copyright statement + calling convention macros).
-#   protectFile - True if multiple inclusion protection should be
-#     generated (based on the filename) around the entire header.
-#   protectFeature - True if #ifndef..#endif protection should be
-#     generated around a feature interface in the header file.
-#   genFuncPointers - True if function pointer typedefs should be
-#     generated
-#   protectProto - If conditional protection should be generated
-#     around prototype declarations, set to either '#ifdef'
-#     to require opt-in (#ifdef protectProtoStr) or '#ifndef'
-#     to require opt-out (#ifndef protectProtoStr). Otherwise
-#     set to None.
-#   protectProtoStr - #ifdef/#ifndef symbol to use around prototype
-#     declarations, if protectProto is set
-#   apicall - string to use for the function declaration prefix,
-#     such as APICALL on Windows.
-#   apientry - string to use for the calling convention macro,
-#     in typedefs, such as APIENTRY.
-#   apientryp - string to use for the calling convention macro
-#     in function pointer typedefs, such as APIENTRYP.
-#   indentFuncProto - True if prototype declarations should put each
-#     parameter on a separate line
-#   indentFuncPointer - True if typedefed function pointers should put each
-#     parameter on a separate line
-#   alignFuncParam - if nonzero and parameters are being put on a
-#     separate line, align parameter names at the specified column
-class CGeneratorOptions(GeneratorOptions):
-    """Represents options during C interface generation for headers"""
-    def __init__(self,
-                 filename = None,
-                 apiname = None,
-                 profile = None,
-                 versions = '.*',
-                 emitversions = '.*',
-                 defaultExtensions = None,
-                 addExtensions = None,
-                 removeExtensions = None,
-                 sortProcedure = regSortFeatures,
-                 prefixText = "",
-                 genFuncPointers = True,
-                 protectFile = True,
-                 protectFeature = True,
-                 protectProto = None,
-                 protectProtoStr = None,
-                 apicall = '',
-                 apientry = '',
-                 apientryp = '',
-                 indentFuncProto = True,
-                 indentFuncPointer = False,
-                 alignFuncParam = 0):
-        GeneratorOptions.__init__(self, filename, apiname, profile,
-                                  versions, emitversions, defaultExtensions,
-                                  addExtensions, removeExtensions, sortProcedure)
-        self.prefixText      = prefixText
-        self.genFuncPointers = genFuncPointers
-        self.protectFile     = protectFile
-        self.protectFeature  = protectFeature
-        self.protectProto    = protectProto
-        self.protectProtoStr = protectProtoStr
-        self.apicall         = apicall
-        self.apientry        = apientry
-        self.apientryp       = apientryp
-        self.indentFuncProto = indentFuncProto
-        self.indentFuncPointer = indentFuncPointer
-        self.alignFuncParam  = alignFuncParam
-
-# DocGeneratorOptions - subclass of GeneratorOptions.
-#
-# Shares many members with CGeneratorOptions, since
-# both are writing C-style declarations:
-#
-#   prefixText - list of strings to prefix generated header with
-#     (usually a copyright statement + calling convention macros).
-#   apicall - string to use for the function declaration prefix,
-#     such as APICALL on Windows.
-#   apientry - string to use for the calling convention macro,
-#     in typedefs, such as APIENTRY.
-#   apientryp - string to use for the calling convention macro
-#     in function pointer typedefs, such as APIENTRYP.
-#   genDirectory - directory into which to generate include files
-#   indentFuncProto - True if prototype declarations should put each
-#     parameter on a separate line
-#   indentFuncPointer - True if typedefed function pointers should put each
-#     parameter on a separate line
-#   alignFuncParam - if nonzero and parameters are being put on a
-#     separate line, align parameter names at the specified column
-#
-# Additional members:
-#
-class DocGeneratorOptions(GeneratorOptions):
-    """Represents options during C interface generation for Asciidoc"""
-    def __init__(self,
-                 filename = None,
-                 apiname = None,
-                 profile = None,
-                 versions = '.*',
-                 emitversions = '.*',
-                 defaultExtensions = None,
-                 addExtensions = None,
-                 removeExtensions = None,
-                 sortProcedure = regSortFeatures,
-                 prefixText = "",
-                 apicall = '',
-                 apientry = '',
-                 apientryp = '',
-                 genDirectory = 'gen',
-                 indentFuncProto = True,
-                 indentFuncPointer = False,
-                 alignFuncParam = 0,
-                 expandEnumerants = True):
-        GeneratorOptions.__init__(self, filename, apiname, profile,
-                                  versions, emitversions, defaultExtensions,
-                                  addExtensions, removeExtensions, sortProcedure)
-        self.prefixText      = prefixText
-        self.apicall         = apicall
-        self.apientry        = apientry
-        self.apientryp       = apientryp
-        self.genDirectory    = genDirectory
-        self.indentFuncProto = indentFuncProto
-        self.indentFuncPointer = indentFuncPointer
-        self.alignFuncParam  = alignFuncParam
-        self.expandEnumerants = expandEnumerants
-
-# ThreadGeneratorOptions - subclass of GeneratorOptions.
-#
-# Adds options used by COutputGenerator objects during C language header
-# generation.
-#
-# Additional members
-#   prefixText - list of strings to prefix generated header with
-#     (usually a copyright statement + calling convention macros).
-#   protectFile - True if multiple inclusion protection should be
-#     generated (based on the filename) around the entire header.
-#   protectFeature - True if #ifndef..#endif protection should be
-#     generated around a feature interface in the header file.
-#   genFuncPointers - True if function pointer typedefs should be
-#     generated
-#   protectProto - True if #ifdef..#endif protection should be
-#     generated around prototype declarations
-#   protectProtoStr - #ifdef symbol to use around prototype
-#     declarations, if protected
-#   apicall - string to use for the function declaration prefix,
-#     such as APICALL on Windows.
-#   apientry - string to use for the calling convention macro,
-#     in typedefs, such as APIENTRY.
-#   apientryp - string to use for the calling convention macro
-#     in function pointer typedefs, such as APIENTRYP.
-#   indentFuncProto - True if prototype declarations should put each
-#     parameter on a separate line
-#   indentFuncPointer - True if typedefed function pointers should put each
-#     parameter on a separate line
-#   alignFuncParam - if nonzero and parameters are being put on a
-#     separate line, align parameter names at the specified column
-class ThreadGeneratorOptions(GeneratorOptions):
-    """Represents options during C interface generation for headers"""
-    def __init__(self,
-                 filename = None,
-                 apiname = None,
-                 profile = None,
-                 versions = '.*',
-                 emitversions = '.*',
-                 defaultExtensions = None,
-                 addExtensions = None,
-                 removeExtensions = None,
-                 sortProcedure = regSortFeatures,
-                 prefixText = "",
-                 genFuncPointers = True,
-                 protectFile = True,
-                 protectFeature = True,
-                 protectProto = True,
-                 protectProtoStr = True,
-                 apicall = '',
-                 apientry = '',
-                 apientryp = '',
-                 indentFuncProto = True,
-                 indentFuncPointer = False,
-                 alignFuncParam = 0,
-                 genDirectory = None):
-        GeneratorOptions.__init__(self, filename, apiname, profile,
-                                  versions, emitversions, defaultExtensions,
-                                  addExtensions, removeExtensions, sortProcedure)
-        self.prefixText      = prefixText
-        self.genFuncPointers = genFuncPointers
-        self.protectFile     = protectFile
-        self.protectFeature  = protectFeature
-        self.protectProto    = protectProto
-        self.protectProtoStr = protectProtoStr
-        self.apicall         = apicall
-        self.apientry        = apientry
-        self.apientryp       = apientryp
-        self.indentFuncProto = indentFuncProto
-        self.indentFuncPointer = indentFuncPointer
-        self.alignFuncParam  = alignFuncParam
-        self.genDirectory    = genDirectory
-
-
-# ParamCheckerGeneratorOptions - subclass of GeneratorOptions.
-#
-# Adds options used by ParamCheckerOutputGenerator objects during parameter validation
-# generation.
-#
-# Additional members
-#   prefixText - list of strings to prefix generated header with
-#     (usually a copyright statement + calling convention macros).
-#   protectFile - True if multiple inclusion protection should be
-#     generated (based on the filename) around the entire header.
-#   protectFeature - True if #ifndef..#endif protection should be
-#     generated around a feature interface in the header file.
-#   genFuncPointers - True if function pointer typedefs should be
-#     generated
-#   protectProto - If conditional protection should be generated
-#     around prototype declarations, set to either '#ifdef'
-#     to require opt-in (#ifdef protectProtoStr) or '#ifndef'
-#     to require opt-out (#ifndef protectProtoStr). Otherwise
-#     set to None.
-#   protectProtoStr - #ifdef/#ifndef symbol to use around prototype
-#     declarations, if protectProto is set
-#   apicall - string to use for the function declaration prefix,
-#     such as APICALL on Windows.
-#   apientry - string to use for the calling convention macro,
-#     in typedefs, such as APIENTRY.
-#   apientryp - string to use for the calling convention macro
-#     in function pointer typedefs, such as APIENTRYP.
-#   indentFuncProto - True if prototype declarations should put each
-#     parameter on a separate line
-#   indentFuncPointer - True if typedefed function pointers should put each
-#     parameter on a separate line
-#   alignFuncParam - if nonzero and parameters are being put on a
-#     separate line, align parameter names at the specified column
-class ParamCheckerGeneratorOptions(GeneratorOptions):
-    """Represents options during C interface generation for headers"""
-    def __init__(self,
-                 filename = None,
-                 apiname = None,
-                 profile = None,
-                 versions = '.*',
-                 emitversions = '.*',
-                 defaultExtensions = None,
-                 addExtensions = None,
-                 removeExtensions = None,
-                 sortProcedure = regSortFeatures,
-                 prefixText = "",
-                 genFuncPointers = True,
-                 protectFile = True,
-                 protectFeature = True,
-                 protectProto = None,
-                 protectProtoStr = None,
-                 apicall = '',
-                 apientry = '',
-                 apientryp = '',
-                 indentFuncProto = True,
-                 indentFuncPointer = False,
-                 alignFuncParam = 0,
-                 genDirectory = None):
-        GeneratorOptions.__init__(self, filename, apiname, profile,
-                                  versions, emitversions, defaultExtensions,
-                                  addExtensions, removeExtensions, sortProcedure)
-        self.prefixText      = prefixText
-        self.genFuncPointers = genFuncPointers
-        self.protectFile     = protectFile
-        self.protectFeature  = protectFeature
-        self.protectProto    = protectProto
-        self.protectProtoStr = protectProtoStr
-        self.apicall         = apicall
-        self.apientry        = apientry
-        self.apientryp       = apientryp
-        self.indentFuncProto = indentFuncProto
-        self.indentFuncPointer = indentFuncPointer
-        self.alignFuncParam  = alignFuncParam
-        self.genDirectory    = genDirectory
-
-# UniqueObjectsGeneratorOptions - subclass of GeneratorOptions.
-#
-# Adds options used by UniqueObjectsOutputGenerator objects during unique
-# Objects layer generation.
-#
-# Additional members
-#   prefixText - list of strings to prefix generated header with
-#     (usually a copyright statement + calling convention macros).
-#   protectFile - True if multiple inclusion protection should be
-#     generated (based on the filename) around the entire header.
-#   protectFeature - True if #ifndef..#endif protection should be
-#     generated around a feature interface in the header file.
-#   genFuncPointers - True if function pointer typedefs should be
-#     generated
-#   protectProto - If conditional protection should be generated
-#     around prototype declarations, set to either '#ifdef'
-#     to require opt-in (#ifdef protectProtoStr) or '#ifndef'
-#     to require opt-out (#ifndef protectProtoStr). Otherwise
-#     set to None.
-#   protectProtoStr - #ifdef/#ifndef symbol to use around prototype
-#     declarations, if protectProto is set
-#   apicall - string to use for the function declaration prefix,
-#     such as APICALL on Windows.
-#   apientry - string to use for the calling convention macro,
-#     in typedefs, such as APIENTRY.
-#   apientryp - string to use for the calling convention macro
-#     in function pointer typedefs, such as APIENTRYP.
-#   indentFuncProto - True if prototype declarations should put each
-#     parameter on a separate line
-#   indentFuncPointer - True if typedefed function pointers should put each
-#     parameter on a separate line
-#   alignFuncParam - if nonzero and parameters are being put on a
-#     separate line, align parameter names at the specified column
-class UniqueObjectsGeneratorOptions(GeneratorOptions):
-    """Represents options during C interface generation for headers"""
-    def __init__(self,
-                 filename = None,
-                 apiname = None,
-                 profile = None,
-                 versions = '.*',
-                 emitversions = '.*',
-                 defaultExtensions = None,
-                 addExtensions = None,
-                 removeExtensions = None,
-                 sortProcedure = regSortFeatures,
-                 prefixText = "",
-                 genFuncPointers = True,
-                 protectFile = False,
-                 protectFeature = True,
-                 protectProto = None,
-                 protectProtoStr = None,
-                 apicall = '',
-                 apientry = '',
-                 apientryp = '',
-                 indentFuncProto = True,
-                 indentFuncPointer = False,
-                 alignFuncParam = 0,
-                 genDirectory = None):
-        GeneratorOptions.__init__(self, filename, apiname, profile,
-                                  versions, emitversions, defaultExtensions,
-                                  addExtensions, removeExtensions, sortProcedure)
-        self.prefixText      = prefixText
-        self.genFuncPointers = genFuncPointers
-        self.protectFile     = protectFile
-        self.protectFeature  = protectFeature
-        self.protectProto    = protectProto
-        self.protectProtoStr = protectProtoStr
-        self.apicall         = apicall
-        self.apientry        = apientry
-        self.apientryp       = apientryp
-        self.indentFuncProto = indentFuncProto
-        self.indentFuncPointer = indentFuncPointer
-        self.alignFuncParam  = alignFuncParam
-        self.genDirectory    = genDirectory
-
 # OutputGenerator - base class for generating API interfaces.
 # Manages basic logic, logging, and output file control
 # Derived classes actually generate formatted output.
@@ -506,6 +159,8 @@
 #   *args - print()-style arguments
 # setExtMap(map) - specify a dictionary map from extension names to
 #   numbers, used in creating values for extension enumerants.
+# makeDir(directory) - create a directory, if not already done.
+#   Generally called from derived generators creating hierarchies.
 # beginFile(genOpts) - start a new interface file
 #   genOpts - GeneratorOptions controlling what's generated and how
 # endFile() - finish an interface file, closing it when done
@@ -525,6 +180,8 @@
 #   name - enum name
 # genCmd(cmdinfo) - generate interface for a command
 #   cmdinfo - CmdInfo for a command
+# isEnumRequired(enumElem) - return True if this <enum> element is required
+#   elem - <enum> element to test
 # makeCDecls(cmd) - return C prototype and function pointer typedef for a
 #     <command> Element, as a list of two strings
 #   cmd - Element for the <command>
@@ -532,6 +189,18 @@
 #
 class OutputGenerator:
     """Generate specified API interfaces in a specific style, such as a C header"""
+    #
+    # categoryToPath - map XML 'category' to include file directory name
+    categoryToPath = {
+        'bitmask'      : 'flags',
+        'enum'         : 'enums',
+        'funcpointer'  : 'funcpointers',
+        'handle'       : 'handles',
+        'define'       : 'defines',
+        'basetype'     : 'basetypes',
+    }
+    #
+    # Constructor
     def __init__(self,
                  errFile = sys.stderr,
                  warnFile = sys.stderr,
@@ -547,6 +216,7 @@
         # Used for extension enum value generation
         self.extBase      = 1000000000
         self.extBlockSize = 1000
+        self.madeDirs = {}
     #
     # logMsg - write a message of different categories to different
     #   destinations.
@@ -633,16 +303,22 @@
             return [numVal, value]
         return [None, None]
     #
+    def makeDir(self, path):
+        self.logMsg('diag', 'OutputGenerator::makeDir(' + path + ')')
+        if not (path in self.madeDirs.keys()):
+            # This can get race conditions with multiple writers, see
+            # https://stackoverflow.com/questions/273192/
+            if not os.path.exists(path):
+                os.makedirs(path)
+            self.madeDirs[path] = None
+    #
     def beginFile(self, genOpts):
         self.genOpts = genOpts
         #
         # Open specified output file. Not done in constructor since a
         # Generator can be used without writing to a file.
         if (self.genOpts.filename != None):
-            if (self.genOpts.genDirectory != None):
-                self.outFile = open(os.path.join(self.genOpts.genDirectory, self.genOpts.filename), 'w')
-            else:
-                self.outFile = open(self.genOpts.filename, 'w')
+            self.outFile = open(self.genOpts.directory + '/' + self.genOpts.filename, 'w')
         else:
             self.outFile = sys.stdout
     def endFile(self):
@@ -715,7 +391,10 @@
                 # Align at specified column, if possible
                 paramdecl = paramdecl.rstrip()
                 oldLen = len(paramdecl)
-                paramdecl = paramdecl.ljust(aligncol)
+                # This works around a problem where very long type names -
+                # longer than the alignment column - would run into the tail
+                # text.
+                paramdecl = paramdecl.ljust(aligncol-1) + ' '
                 newLen = len(paramdecl)
                 self.logMsg('diag', 'Adjust length of parameter decl from', oldLen, 'to', newLen, ':', paramdecl)
             paramdecl += text + tail
@@ -737,6 +416,14 @@
             paramdecl += text + tail
         return newLen
     #
+    # isEnumRequired(elem) - return True if this <enum> element is
+    # required, False otherwise
+    # elem - <enum> element to test
+    def isEnumRequired(self, elem):
+        return (elem.get('extname') is None or
+                re.match(self.genOpts.addExtensions, elem.get('extname')) is not None or
+                self.genOpts.defaultExtensions == elem.get('supported'))
+    #
     # makeCDecls - return C prototype and function pointer typedef for a
     #   command, as a two-element list of strings.
     # cmd - Element containing a <command> tag
@@ -809,3652 +496,3 @@
     def setRegistry(self, registry):
         self.registry = registry
         #
-
-# COutputGenerator - subclass of OutputGenerator.
-# Generates C-language API interfaces.
-#
-# ---- methods ----
-# COutputGenerator(errFile, warnFile, diagFile) - args as for
-#   OutputGenerator. Defines additional internal state.
-# ---- methods overriding base class ----
-# beginFile(genOpts)
-# endFile()
-# beginFeature(interface, emit)
-# endFeature()
-# genType(typeinfo,name)
-# genStruct(typeinfo,name)
-# genGroup(groupinfo,name)
-# genEnum(enuminfo, name)
-# genCmd(cmdinfo)
-class COutputGenerator(OutputGenerator):
-    """Generate specified API interfaces in a specific style, such as a C header"""
-    # This is an ordered list of sections in the header file.
-    TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
-                     'group', 'bitmask', 'funcpointer', 'struct']
-    ALL_SECTIONS = TYPE_SECTIONS + ['commandPointer', 'command']
-    def __init__(self,
-                 errFile = sys.stderr,
-                 warnFile = sys.stderr,
-                 diagFile = sys.stdout):
-        OutputGenerator.__init__(self, errFile, warnFile, diagFile)
-        # Internal state - accumulators for different inner block text
-        self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
-    #
-    def beginFile(self, genOpts):
-        OutputGenerator.beginFile(self, genOpts)
-        # C-specific
-        #
-        # Multiple inclusion protection & C++ wrappers.
-        if (genOpts.protectFile and self.genOpts.filename):
-            headerSym = re.sub('\.h', '_h_',
-                               os.path.basename(self.genOpts.filename)).upper()
-            write('#ifndef', headerSym, file=self.outFile)
-            write('#define', headerSym, '1', file=self.outFile)
-            self.newline()
-        write('#ifdef __cplusplus', file=self.outFile)
-        write('extern "C" {', file=self.outFile)
-        write('#endif', file=self.outFile)
-        self.newline()
-        #
-        # User-supplied prefix text, if any (list of strings)
-        if (genOpts.prefixText):
-            for s in genOpts.prefixText:
-                write(s, file=self.outFile)
-        #
-        # Some boilerplate describing what was generated - this
-        # will probably be removed later since the extensions
-        # pattern may be very long.
-        # write('/* Generated C header for:', file=self.outFile)
-        # write(' * API:', genOpts.apiname, file=self.outFile)
-        # if (genOpts.profile):
-        #     write(' * Profile:', genOpts.profile, file=self.outFile)
-        # write(' * Versions considered:', genOpts.versions, file=self.outFile)
-        # write(' * Versions emitted:', genOpts.emitversions, file=self.outFile)
-        # write(' * Default extensions included:', genOpts.defaultExtensions, file=self.outFile)
-        # write(' * Additional extensions included:', genOpts.addExtensions, file=self.outFile)
-        # write(' * Extensions removed:', genOpts.removeExtensions, file=self.outFile)
-        # write(' */', file=self.outFile)
-    def endFile(self):
-        # C-specific
-        # Finish C++ wrapper and multiple inclusion protection
-        self.newline()
-        write('#ifdef __cplusplus', file=self.outFile)
-        write('}', file=self.outFile)
-        write('#endif', file=self.outFile)
-        if (self.genOpts.protectFile and self.genOpts.filename):
-            self.newline()
-            write('#endif', file=self.outFile)
-        # Finish processing in superclass
-        OutputGenerator.endFile(self)
-    def beginFeature(self, interface, emit):
-        # Start processing in superclass
-        OutputGenerator.beginFeature(self, interface, emit)
-        # C-specific
-        # Accumulate includes, defines, types, enums, function pointer typedefs,
-        # end function prototypes separately for this feature. They're only
-        # printed in endFeature().
-        self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
-    def endFeature(self):
-        # C-specific
-        # Actually write the interface to the output file.
-        if (self.emit):
-            self.newline()
-            if (self.genOpts.protectFeature):
-                write('#ifndef', self.featureName, file=self.outFile)
-            # If type declarations are needed by other features based on
-            # this one, it may be necessary to suppress the ExtraProtect,
-            # or move it below the 'for section...' loop.
-            if (self.featureExtraProtect != None):
-                write('#ifdef', self.featureExtraProtect, file=self.outFile)
-            write('#define', self.featureName, '1', file=self.outFile)
-            for section in self.TYPE_SECTIONS:
-                contents = self.sections[section]
-                if contents:
-                    write('\n'.join(contents), file=self.outFile)
-                    self.newline()
-            if (self.genOpts.genFuncPointers and self.sections['commandPointer']):
-                write('\n'.join(self.sections['commandPointer']), file=self.outFile)
-                self.newline()
-            if (self.sections['command']):
-                if (self.genOpts.protectProto):
-                    write(self.genOpts.protectProto,
-                          self.genOpts.protectProtoStr, file=self.outFile)
-                write('\n'.join(self.sections['command']), end='', file=self.outFile)
-                if (self.genOpts.protectProto):
-                    write('#endif', file=self.outFile)
-                else:
-                    self.newline()
-            if (self.featureExtraProtect != None):
-                write('#endif /*', self.featureExtraProtect, '*/', file=self.outFile)
-            if (self.genOpts.protectFeature):
-                write('#endif /*', self.featureName, '*/', file=self.outFile)
-        # Finish processing in superclass
-        OutputGenerator.endFeature(self)
-    #
-    # Append a definition to the specified section
-    def appendSection(self, section, text):
-        # self.sections[section].append('SECTION: ' + section + '\n')
-        self.sections[section].append(text)
-    #
-    # Type generation
-    def genType(self, typeinfo, name):
-        OutputGenerator.genType(self, typeinfo, name)
-        typeElem = typeinfo.elem
-        # If the type is a struct type, traverse the imbedded <member> tags
-        # generating a structure. Otherwise, emit the tag text.
-        category = typeElem.get('category')
-        if (category == 'struct' or category == 'union'):
-            self.genStruct(typeinfo, name)
-        else:
-            # Replace <apientry /> tags with an APIENTRY-style string
-            # (from self.genOpts). Copy other text through unchanged.
-            # If the resulting text is an empty string, don't emit it.
-            s = noneStr(typeElem.text)
-            for elem in typeElem:
-                if (elem.tag == 'apientry'):
-                    s += self.genOpts.apientry + noneStr(elem.tail)
-                else:
-                    s += noneStr(elem.text) + noneStr(elem.tail)
-            if s:
-                # Add extra newline after multi-line entries.
-                if '\n' in s:
-                    s += '\n'
-                self.appendSection(category, s)
-    #
-    # Struct (e.g. C "struct" type) generation.
-    # This is a special case of the <type> tag where the contents are
-    # interpreted as a set of <member> tags instead of freeform C
-    # C type declarations. The <member> tags are just like <param>
-    # tags - they are a declaration of a struct or union member.
-    # Only simple member declarations are supported (no nested
-    # structs etc.)
-    def genStruct(self, typeinfo, typeName):
-        OutputGenerator.genStruct(self, typeinfo, typeName)
-        body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
-        # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
-        targetLen = 0;
-        for member in typeinfo.elem.findall('.//member'):
-            targetLen = max(targetLen, self.getCParamTypeLength(member))
-        for member in typeinfo.elem.findall('.//member'):
-            body += self.makeCParamDecl(member, targetLen + 4)
-            body += ';\n'
-        body += '} ' + typeName + ';\n'
-        self.appendSection('struct', body)
-    #
-    # Group (e.g. C "enum" type) generation.
-    # These are concatenated together with other types.
-    def genGroup(self, groupinfo, groupName):
-        OutputGenerator.genGroup(self, groupinfo, groupName)
-        groupElem = groupinfo.elem
-
-        expandName = re.sub(r'([0-9a-z_])([A-Z0-9][^A-Z0-9]?)',r'\1_\2',groupName).upper()
-
-        expandPrefix = expandName
-        expandSuffix = ''
-        expandSuffixMatch = re.search(r'[A-Z][A-Z]+$',groupName)
-        if expandSuffixMatch:
-            expandSuffix = '_' + expandSuffixMatch.group()
-            # Strip off the suffix from the prefix
-            expandPrefix = expandName.rsplit(expandSuffix, 1)[0]
-
-        # Prefix
-        body = "\ntypedef enum " + groupName + " {\n"
-
-        isEnum = ('FLAG_BITS' not in expandPrefix)
-
-        # Loop over the nested 'enum' tags. Keep track of the minimum and
-        # maximum numeric values, if they can be determined; but only for
-        # core API enumerants, not extension enumerants. This is inferred
-        # by looking for 'extends' attributes.
-        minName = None
-        for elem in groupElem.findall('enum'):
-            # Convert the value to an integer and use that to track min/max.
-            # Values of form -(number) are accepted but nothing more complex.
-            # Should catch exceptions here for more complex constructs. Not yet.
-            (numVal,strVal) = self.enumToValue(elem, True)
-            name = elem.get('name')
-
-            # Extension enumerants are only included if they are requested
-            # in addExtensions or match defaultExtensions.
-            if (elem.get('extname') is None or
-              re.match(self.genOpts.addExtensions,elem.get('extname')) is not None or
-              self.genOpts.defaultExtensions == elem.get('supported')):
-                body += "    " + name + " = " + strVal + ",\n"
-
-            if (isEnum  and elem.get('extends') is None):
-                if (minName == None):
-                    minName = maxName = name
-                    minValue = maxValue = numVal
-                elif (numVal < minValue):
-                    minName = name
-                    minValue = numVal
-                elif (numVal > maxValue):
-                    maxName = name
-                    maxValue = numVal
-        # Generate min/max value tokens and a range-padding enum. Need some
-        # additional padding to generate correct names...
-        if isEnum:
-            body += "    " + expandPrefix + "_BEGIN_RANGE" + expandSuffix + " = " + minName + ",\n"
-            body += "    " + expandPrefix + "_END_RANGE" + expandSuffix + " = " + maxName + ",\n"
-            body += "    " + expandPrefix + "_RANGE_SIZE" + expandSuffix + " = (" + maxName + " - " + minName + " + 1),\n"
-
-        body += "    " + expandPrefix + "_MAX_ENUM" + expandSuffix + " = 0x7FFFFFFF\n"
-
-        # Postfix
-        body += "} " + groupName + ";"
-        if groupElem.get('type') == 'bitmask':
-            section = 'bitmask'
-        else:
-            section = 'group'
-        self.appendSection(section, body)
-    # Enumerant generation
-    # <enum> tags may specify their values in several ways, but are usually
-    # just integers.
-    def genEnum(self, enuminfo, name):
-        OutputGenerator.genEnum(self, enuminfo, name)
-        (numVal,strVal) = self.enumToValue(enuminfo.elem, False)
-        body = '#define ' + name.ljust(33) + ' ' + strVal
-        self.appendSection('enum', body)
-    #
-    # Command generation
-    def genCmd(self, cmdinfo, name):
-        OutputGenerator.genCmd(self, cmdinfo, name)
-        #
-        decls = self.makeCDecls(cmdinfo.elem)
-        self.appendSection('command', decls[0] + '\n')
-        if (self.genOpts.genFuncPointers):
-            self.appendSection('commandPointer', decls[1])
-
-# DocOutputGenerator - subclass of OutputGenerator.
-# Generates AsciiDoc includes with C-language API interfaces, for reference
-# pages and the Vulkan specification. Similar to COutputGenerator, but
-# each interface is written into a different file as determined by the
-# options, only actual C types are emitted, and none of the boilerplate
-# preprocessor code is emitted.
-#
-# ---- methods ----
-# DocOutputGenerator(errFile, warnFile, diagFile) - args as for
-#   OutputGenerator. Defines additional internal state.
-# ---- methods overriding base class ----
-# beginFile(genOpts)
-# endFile()
-# beginFeature(interface, emit)
-# endFeature()
-# genType(typeinfo,name)
-# genStruct(typeinfo,name)
-# genGroup(groupinfo,name)
-# genEnum(enuminfo, name)
-# genCmd(cmdinfo)
-class DocOutputGenerator(OutputGenerator):
-    """Generate specified API interfaces in a specific style, such as a C header"""
-    def __init__(self,
-                 errFile = sys.stderr,
-                 warnFile = sys.stderr,
-                 diagFile = sys.stdout):
-        OutputGenerator.__init__(self, errFile, warnFile, diagFile)
-    #
-    def beginFile(self, genOpts):
-        OutputGenerator.beginFile(self, genOpts)
-    def endFile(self):
-        OutputGenerator.endFile(self)
-    def beginFeature(self, interface, emit):
-        # Start processing in superclass
-        OutputGenerator.beginFeature(self, interface, emit)
-    def endFeature(self):
-        # Finish processing in superclass
-        OutputGenerator.endFeature(self)
-    #
-    # Generate an include file
-    #
-    # directory - subdirectory to put file in
-    # basename - base name of the file
-    # contents - contents of the file (Asciidoc boilerplate aside)
-    def writeInclude(self, directory, basename, contents):
-        # Create file
-        filename = self.genOpts.genDirectory + '/' + directory + '/' + basename + '.txt'
-        self.logMsg('diag', '# Generating include file:', filename)
-        fp = open(filename, 'w')
-        # Asciidoc anchor
-        write('// WARNING: DO NOT MODIFY! This file is automatically generated from the vk.xml registry', file=fp)
-        write('ifndef::doctype-manpage[]', file=fp)
-        write('[[{0},{0}]]'.format(basename), file=fp)
-        write('["source","{basebackend@docbook:c++:cpp}",title=""]', file=fp)
-        write('endif::doctype-manpage[]', file=fp)
-        write('ifdef::doctype-manpage[]', file=fp)
-        write('["source","{basebackend@docbook:c++:cpp}"]', file=fp)
-        write('endif::doctype-manpage[]', file=fp)
-        write('------------------------------------------------------------------------------', file=fp)
-        write(contents, file=fp)
-        write('------------------------------------------------------------------------------', file=fp)
-        fp.close()
-    #
-    # Type generation
-    def genType(self, typeinfo, name):
-        OutputGenerator.genType(self, typeinfo, name)
-        typeElem = typeinfo.elem
-        # If the type is a struct type, traverse the imbedded <member> tags
-        # generating a structure. Otherwise, emit the tag text.
-        category = typeElem.get('category')
-        if (category == 'struct' or category == 'union'):
-            self.genStruct(typeinfo, name)
-        else:
-            # Replace <apientry /> tags with an APIENTRY-style string
-            # (from self.genOpts). Copy other text through unchanged.
-            # If the resulting text is an empty string, don't emit it.
-            s = noneStr(typeElem.text)
-            for elem in typeElem:
-                if (elem.tag == 'apientry'):
-                    s += self.genOpts.apientry + noneStr(elem.tail)
-                else:
-                    s += noneStr(elem.text) + noneStr(elem.tail)
-            if (len(s) > 0):
-                if (category == 'bitmask'):
-                    self.writeInclude('flags', name, s + '\n')
-                elif (category == 'enum'):
-                    self.writeInclude('enums', name, s + '\n')
-                elif (category == 'funcpointer'):
-                    self.writeInclude('funcpointers', name, s+ '\n')
-                else:
-                    self.logMsg('diag', '# NOT writing include file for type:',
-                        name, 'category: ', category)
-            else:
-                self.logMsg('diag', '# NOT writing empty include file for type', name)
-    #
-    # Struct (e.g. C "struct" type) generation.
-    # This is a special case of the <type> tag where the contents are
-    # interpreted as a set of <member> tags instead of freeform C
-    # C type declarations. The <member> tags are just like <param>
-    # tags - they are a declaration of a struct or union member.
-    # Only simple member declarations are supported (no nested
-    # structs etc.)
-    def genStruct(self, typeinfo, typeName):
-        OutputGenerator.genStruct(self, typeinfo, typeName)
-        s = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
-        # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
-        targetLen = 0;
-        for member in typeinfo.elem.findall('.//member'):
-            targetLen = max(targetLen, self.getCParamTypeLength(member))
-        for member in typeinfo.elem.findall('.//member'):
-            s += self.makeCParamDecl(member, targetLen + 4)
-            s += ';\n'
-        s += '} ' + typeName + ';'
-        self.writeInclude('structs', typeName, s)
-    #
-    # Group (e.g. C "enum" type) generation.
-    # These are concatenated together with other types.
-    def genGroup(self, groupinfo, groupName):
-        OutputGenerator.genGroup(self, groupinfo, groupName)
-        groupElem = groupinfo.elem
-
-        # See if we need min/max/num/padding at end
-        expand = self.genOpts.expandEnumerants
-
-        if expand:
-            expandName = re.sub(r'([0-9a-z_])([A-Z0-9][^A-Z0-9]?)',r'\1_\2',groupName).upper()
-            isEnum = ('FLAG_BITS' not in expandName)
-
-            expandPrefix = expandName
-            expandSuffix = ''
-
-            # Look for a suffix
-            expandSuffixMatch = re.search(r'[A-Z][A-Z]+$',groupName)
-            if expandSuffixMatch:
-                expandSuffix = '_' + expandSuffixMatch.group()
-                # Strip off the suffix from the prefix
-                expandPrefix = expandName.rsplit(expandSuffix, 1)[0]
-
-        # Prefix
-        s = "typedef enum " + groupName + " {\n"
-
-        # Loop over the nested 'enum' tags. Keep track of the minimum and
-        # maximum numeric values, if they can be determined.
-        minName = None
-        for elem in groupElem.findall('enum'):
-            # Convert the value to an integer and use that to track min/max.
-            # Values of form -(number) are accepted but nothing more complex.
-            # Should catch exceptions here for more complex constructs. Not yet.
-            (numVal,strVal) = self.enumToValue(elem, True)
-            name = elem.get('name')
-
-            # Extension enumerants are only included if they are requested
-            # in addExtensions or match defaultExtensions.
-            if (elem.get('extname') is None or
-              re.match(self.genOpts.addExtensions,elem.get('extname')) is not None or
-              self.genOpts.defaultExtensions == elem.get('supported')):
-                s += "    " + name + " = " + strVal + ",\n"
-
-            if (expand and isEnum and elem.get('extends') is None):
-                if (minName == None):
-                    minName = maxName = name
-                    minValue = maxValue = numVal
-                elif (numVal < minValue):
-                    minName = name
-                    minValue = numVal
-                elif (numVal > maxValue):
-                    maxName = name
-                    maxValue = numVal
-        # Generate min/max value tokens and a range-padding enum. Need some
-        # additional padding to generate correct names...
-        if (expand):
-            s += "\n"
-            if isEnum:
-                s += "    " + expandPrefix + "_BEGIN_RANGE" + expandSuffix + " = " + minName + ",\n"
-                s += "    " + expandPrefix + "_END_RANGE" + expandSuffix + " = " + maxName + ",\n"
-                s += "    " + expandPrefix + "_RANGE_SIZE" + expandSuffix + " = (" + maxName + " - " + minName + " + 1),\n"
-
-            s += "    " + expandPrefix + "_MAX_ENUM" + expandSuffix + " = 0x7FFFFFFF\n"
-        # Postfix
-        s += "} " + groupName + ";"
-        self.writeInclude('enums', groupName, s)
-    # Enumerant generation
-    # <enum> tags may specify their values in several ways, but are usually
-    # just integers.
-    def genEnum(self, enuminfo, name):
-        OutputGenerator.genEnum(self, enuminfo, name)
-        (numVal,strVal) = self.enumToValue(enuminfo.elem, False)
-        s = '#define ' + name.ljust(33) + ' ' + strVal
-        self.logMsg('diag', '# NOT writing compile-time constant', name)
-        # self.writeInclude('consts', name, s)
-    #
-    # Command generation
-    def genCmd(self, cmdinfo, name):
-        OutputGenerator.genCmd(self, cmdinfo, name)
-        #
-        decls = self.makeCDecls(cmdinfo.elem)
-        self.writeInclude('protos', name, decls[0])
-
-# PyOutputGenerator - subclass of OutputGenerator.
-# Generates Python data structures describing API names.
-# Similar to DocOutputGenerator, but writes a single
-# file.
-#
-# ---- methods ----
-# PyOutputGenerator(errFile, warnFile, diagFile) - args as for
-#   OutputGenerator. Defines additional internal state.
-# ---- methods overriding base class ----
-# beginFile(genOpts)
-# endFile()
-# genType(typeinfo,name)
-# genStruct(typeinfo,name)
-# genGroup(groupinfo,name)
-# genEnum(enuminfo, name)
-# genCmd(cmdinfo)
-class PyOutputGenerator(OutputGenerator):
-    """Generate specified API interfaces in a specific style, such as a C header"""
-    def __init__(self,
-                 errFile = sys.stderr,
-                 warnFile = sys.stderr,
-                 diagFile = sys.stdout):
-        OutputGenerator.__init__(self, errFile, warnFile, diagFile)
-    #
-    def beginFile(self, genOpts):
-        OutputGenerator.beginFile(self, genOpts)
-        for dict in [ 'flags', 'enums', 'structs', 'consts', 'enums',
-          'consts', 'protos', 'funcpointers' ]:
-            write(dict, '= {}', file=self.outFile)
-    def endFile(self):
-        OutputGenerator.endFile(self)
-    #
-    # Add a name from the interface
-    #
-    # dict - type of name (see beginFile above)
-    # name - name to add
-    # value - A serializable Python value for the name
-    def addName(self, dict, name, value=None):
-        write(dict + "['" + name + "'] = ", value, file=self.outFile)
-    #
-    # Type generation
-    # For 'struct' or 'union' types, defer to genStruct() to
-    #   add to the dictionary.
-    # For 'bitmask' types, add the type name to the 'flags' dictionary,
-    #   with the value being the corresponding 'enums' name defining
-    #   the acceptable flag bits.
-    # For 'enum' types, add the type name to the 'enums' dictionary,
-    #   with the value being '@STOPHERE@' (because this case seems
-    #   never to happen).
-    # For 'funcpointer' types, add the type name to the 'funcpointers'
-    #   dictionary.
-    # For 'handle' and 'define' types, add the handle or #define name
-    #   to the 'struct' dictionary, because that's how the spec sources
-    #   tag these types even though they aren't structs.
-    def genType(self, typeinfo, name):
-        OutputGenerator.genType(self, typeinfo, name)
-        typeElem = typeinfo.elem
-        # If the type is a struct type, traverse the imbedded <member> tags
-        # generating a structure. Otherwise, emit the tag text.
-        category = typeElem.get('category')
-        if (category == 'struct' or category == 'union'):
-            self.genStruct(typeinfo, name)
-        else:
-            # Extract the type name
-            # (from self.genOpts). Copy other text through unchanged.
-            # If the resulting text is an empty string, don't emit it.
-            count = len(noneStr(typeElem.text))
-            for elem in typeElem:
-                count += len(noneStr(elem.text)) + len(noneStr(elem.tail))
-            if (count > 0):
-                if (category == 'bitmask'):
-                    requiredEnum = typeElem.get('requires')
-                    self.addName('flags', name, enquote(requiredEnum))
-                elif (category == 'enum'):
-                    # This case never seems to come up!
-                    # @enums   C 'enum' name           Dictionary of enumerant names
-                    self.addName('enums', name, enquote('@STOPHERE@'))
-                elif (category == 'funcpointer'):
-                    self.addName('funcpointers', name, None)
-                elif (category == 'handle' or category == 'define'):
-                    self.addName('structs', name, None)
-                else:
-                    write('# Unprocessed type:', name, 'category:', category, file=self.outFile)
-            else:
-                write('# Unprocessed type:', name, file=self.outFile)
-    #
-    # Struct (e.g. C "struct" type) generation.
-    #
-    # Add the struct name to the 'structs' dictionary, with the
-    # value being an ordered list of the struct member names.
-    def genStruct(self, typeinfo, typeName):
-        OutputGenerator.genStruct(self, typeinfo, typeName)
-
-        members = [member.text for member in typeinfo.elem.findall('.//member/name')]
-        self.addName('structs', typeName, members)
-    #
-    # Group (e.g. C "enum" type) generation.
-    # These are concatenated together with other types.
-    #
-    # Add the enum type name to the 'enums' dictionary, with
-    #   the value being an ordered list of the enumerant names.
-    # Add each enumerant name to the 'consts' dictionary, with
-    #   the value being the enum type the enumerant is part of.
-    def genGroup(self, groupinfo, groupName):
-        OutputGenerator.genGroup(self, groupinfo, groupName)
-        groupElem = groupinfo.elem
-
-        # @enums   C 'enum' name           Dictionary of enumerant names
-        # @consts  C enumerant/const name  Name of corresponding 'enums' key
-
-        # Loop over the nested 'enum' tags. Keep track of the minimum and
-        # maximum numeric values, if they can be determined.
-        enumerants = [elem.get('name') for elem in groupElem.findall('enum')]
-        for name in enumerants:
-            self.addName('consts', name, enquote(groupName))
-        self.addName('enums', groupName, enumerants)
-    # Enumerant generation (compile-time constants)
-    #
-    # Add the constant name to the 'consts' dictionary, with the
-    #   value being None to indicate that the constant isn't
-    #   an enumeration value.
-    def genEnum(self, enuminfo, name):
-        OutputGenerator.genEnum(self, enuminfo, name)
-
-        # @consts  C enumerant/const name  Name of corresponding 'enums' key
-
-        self.addName('consts', name, None)
-    #
-    # Command generation
-    #
-    # Add the command name to the 'protos' dictionary, with the
-    #   value being an ordered list of the parameter names.
-    def genCmd(self, cmdinfo, name):
-        OutputGenerator.genCmd(self, cmdinfo, name)
-
-        params = [param.text for param in cmdinfo.elem.findall('param/name')]
-        self.addName('protos', name, params)
-
-# ValidityOutputGenerator - subclass of OutputGenerator.
-# Generates AsciiDoc includes of valid usage information, for reference
-# pages and the Vulkan specification. Similar to DocOutputGenerator.
-#
-# ---- methods ----
-# ValidityOutputGenerator(errFile, warnFile, diagFile) - args as for
-#   OutputGenerator. Defines additional internal state.
-# ---- methods overriding base class ----
-# beginFile(genOpts)
-# endFile()
-# beginFeature(interface, emit)
-# endFeature()
-# genCmd(cmdinfo)
-class ValidityOutputGenerator(OutputGenerator):
-    """Generate specified API interfaces in a specific style, such as a C header"""
-    def __init__(self,
-                 errFile = sys.stderr,
-                 warnFile = sys.stderr,
-                 diagFile = sys.stdout):
-        OutputGenerator.__init__(self, errFile, warnFile, diagFile)
-
-    def beginFile(self, genOpts):
-        OutputGenerator.beginFile(self, genOpts)
-    def endFile(self):
-        OutputGenerator.endFile(self)
-    def beginFeature(self, interface, emit):
-        # Start processing in superclass
-        OutputGenerator.beginFeature(self, interface, emit)
-    def endFeature(self):
-        # Finish processing in superclass
-        OutputGenerator.endFeature(self)
-
-    def makeParameterName(self, name):
-        return 'pname:' + name
-
-    def makeStructName(self, name):
-        return 'sname:' + name
-
-    def makeBaseTypeName(self, name):
-        return 'basetype:' + name
-
-    def makeEnumerationName(self, name):
-        return 'elink:' + name
-
-    def makeEnumerantName(self, name):
-        return 'ename:' + name
-
-    def makeFLink(self, name):
-        return 'flink:' + name
-
-    #
-    # Generate an include file
-    #
-    # directory - subdirectory to put file in
-    # basename - base name of the file
-    # contents - contents of the file (Asciidoc boilerplate aside)
-    def writeInclude(self, directory, basename, validity, threadsafety, commandpropertiesentry, successcodes, errorcodes):
-        # Create file
-        filename = self.genOpts.genDirectory + '/' + directory + '/' + basename + '.txt'
-        self.logMsg('diag', '# Generating include file:', filename)
-        fp = open(filename, 'w')
-        # Asciidoc anchor
-        write('// WARNING: DO NOT MODIFY! This file is automatically generated from the vk.xml registry', file=fp)
-
-        # Valid Usage
-        if validity is not None:
-            write('ifndef::doctype-manpage[]', file=fp)
-            write('.Valid Usage', file=fp)
-            write('*' * 80, file=fp)
-            write('endif::doctype-manpage[]', file=fp)
-            write('ifdef::doctype-manpage[]', file=fp)
-            write('Valid Usage', file=fp)
-            write('-----------', file=fp)
-            write('endif::doctype-manpage[]', file=fp)
-            write(validity, file=fp, end='')
-            write('ifndef::doctype-manpage[]', file=fp)
-            write('*' * 80, file=fp)
-            write('endif::doctype-manpage[]', file=fp)
-            write('', file=fp)
-
-        # Host Synchronization
-        if threadsafety is not None:
-            write('ifndef::doctype-manpage[]', file=fp)
-            write('.Host Synchronization', file=fp)
-            write('*' * 80, file=fp)
-            write('endif::doctype-manpage[]', file=fp)
-            write('ifdef::doctype-manpage[]', file=fp)
-            write('Host Synchronization', file=fp)
-            write('--------------------', file=fp)
-            write('endif::doctype-manpage[]', file=fp)
-            write(threadsafety, file=fp, end='')
-            write('ifndef::doctype-manpage[]', file=fp)
-            write('*' * 80, file=fp)
-            write('endif::doctype-manpage[]', file=fp)
-            write('', file=fp)
-
-        # Command Properties - contained within a block, to avoid table numbering
-        if commandpropertiesentry is not None:
-            write('ifndef::doctype-manpage[]', file=fp)
-            write('.Command Properties', file=fp)
-            write('*' * 80, file=fp)
-            write('endif::doctype-manpage[]', file=fp)
-            write('ifdef::doctype-manpage[]', file=fp)
-            write('Command Properties', file=fp)
-            write('------------------', file=fp)
-            write('endif::doctype-manpage[]', file=fp)
-            write('[options="header", width="100%"]', file=fp)
-            write('|=====================', file=fp)
-            write('|Command Buffer Levels|Render Pass Scope|Supported Queue Types', file=fp)
-            write(commandpropertiesentry, file=fp)
-            write('|=====================', file=fp)
-            write('ifndef::doctype-manpage[]', file=fp)
-            write('*' * 80, file=fp)
-            write('endif::doctype-manpage[]', file=fp)
-            write('', file=fp)
-
-        # Success Codes - contained within a block, to avoid table numbering
-        if successcodes is not None or errorcodes is not None:
-            write('ifndef::doctype-manpage[]', file=fp)
-            write('.Return Codes', file=fp)
-            write('*' * 80, file=fp)
-            write('endif::doctype-manpage[]', file=fp)
-            write('ifdef::doctype-manpage[]', file=fp)
-            write('Return Codes', file=fp)
-            write('------------', file=fp)
-            write('endif::doctype-manpage[]', file=fp)
-            if successcodes is not None:
-                write('ifndef::doctype-manpage[]', file=fp)
-                write('<<fundamentals-successcodes,Success>>::', file=fp)
-                write('endif::doctype-manpage[]', file=fp)
-                write('ifdef::doctype-manpage[]', file=fp)
-                write('On success, this command returns::', file=fp)
-                write('endif::doctype-manpage[]', file=fp)
-                write(successcodes, file=fp)
-            if errorcodes is not None:
-                write('ifndef::doctype-manpage[]', file=fp)
-                write('<<fundamentals-errorcodes,Failure>>::', file=fp)
-                write('endif::doctype-manpage[]', file=fp)
-                write('ifdef::doctype-manpage[]', file=fp)
-                write('On failure, this command returns::', file=fp)
-                write('endif::doctype-manpage[]', file=fp)
-                write(errorcodes, file=fp)
-            write('ifndef::doctype-manpage[]', file=fp)
-            write('*' * 80, file=fp)
-            write('endif::doctype-manpage[]', file=fp)
-            write('', file=fp)
-
-        fp.close()
-
-    #
-    # Check if the parameter passed in is a pointer
-    def paramIsPointer(self, param):
-        ispointer = False
-        paramtype = param.find('type')
-        if paramtype.tail is not None and '*' in paramtype.tail:
-            ispointer = True
-
-        return ispointer
-
-    #
-    # Check if the parameter passed in is a static array
-    def paramIsStaticArray(self, param):
-        if param.find('name').tail is not None:
-            if param.find('name').tail[0] == '[':
-                return True
-
-    #
-    # Get the length of a parameter that's been identified as a static array
-    def staticArrayLength(self, param):
-        paramname = param.find('name')
-        paramenumsize = param.find('enum')
-
-        if paramenumsize is not None:
-            return paramenumsize.text
-        else:
-            return paramname.tail[1:-1]
-
-    #
-    # Check if the parameter passed in is a pointer to an array
-    def paramIsArray(self, param):
-        return param.attrib.get('len') is not None
-
-    #
-    # Get the parent of a handle object
-    def getHandleParent(self, typename):
-        types = self.registry.findall("types/type")
-        for elem in types:
-            if (elem.find("name") is not None and elem.find('name').text == typename) or elem.attrib.get('name') == typename:
-                return elem.attrib.get('parent')
-
-    #
-    # Check if a parent object is dispatchable or not
-    def isHandleTypeDispatchable(self, handlename):
-        handle = self.registry.find("types/type/[name='" + handlename + "'][@category='handle']")
-        if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
-            return True
-        else:
-            return False
-
-    def isHandleOptional(self, param, params):
-
-        # See if the handle is optional
-        isOptional = False
-
-        # Simple, if it's optional, return true
-        if param.attrib.get('optional') is not None:
-            return True
-
-        # If no validity is being generated, it usually means that validity is complex and not absolute, so let's say yes.
-        if param.attrib.get('noautovalidity') is not None:
-            return True
-
-        # If the parameter is an array and we haven't already returned, find out if any of the len parameters are optional
-        if self.paramIsArray(param):
-            lengths = param.attrib.get('len').split(',')
-            for length in lengths:
-                if (length) != 'null-terminated' and (length) != '1':
-                    for otherparam in params:
-                        if otherparam.find('name').text == length:
-                            if otherparam.attrib.get('optional') is not None:
-                                return True
-
-        return False
-    #
-    # Get the category of a type
-    def getTypeCategory(self, typename):
-        types = self.registry.findall("types/type")
-        for elem in types:
-            if (elem.find("name") is not None and elem.find('name').text == typename) or elem.attrib.get('name') == typename:
-                return elem.attrib.get('category')
-
-    #
-    # Make a chunk of text for the end of a parameter if it is an array
-    def makeAsciiDocPreChunk(self, param, params):
-        paramname = param.find('name')
-        paramtype = param.find('type')
-
-        # General pre-amble. Check optionality and add stuff.
-        asciidoc = '* '
-
-        if self.paramIsStaticArray(param):
-            asciidoc += 'Any given element of '
-
-        elif self.paramIsArray(param):
-            lengths = param.attrib.get('len').split(',')
-
-            # Find all the parameters that are called out as optional, so we can document that they might be zero, and the array may be ignored
-            optionallengths = []
-            for length in lengths:
-                if (length) != 'null-terminated' and (length) != '1':
-                    for otherparam in params:
-                        if otherparam.find('name').text == length:
-                            if otherparam.attrib.get('optional') is not None:
-                                if self.paramIsPointer(otherparam):
-                                    optionallengths.append('the value referenced by ' + self.makeParameterName(length))
-                                else:
-                                    optionallengths.append(self.makeParameterName(length))
-
-            # Document that these arrays may be ignored if any of the length values are 0
-            if len(optionallengths) != 0 or param.attrib.get('optional') is not None:
-                asciidoc += 'If '
-
-
-                if len(optionallengths) != 0:
-                    if len(optionallengths) == 1:
-
-                        asciidoc += optionallengths[0]
-                        asciidoc += ' is '
-
-                    else:
-                        asciidoc += ' or '.join(optionallengths)
-                        asciidoc += ' are '
-
-                    asciidoc += 'not `0`, '
-
-                if len(optionallengths) != 0 and param.attrib.get('optional') is not None:
-                    asciidoc += 'and '
-
-                if param.attrib.get('optional') is not None:
-                    asciidoc += self.makeParameterName(paramname.text)
-                    asciidoc += ' is not `NULL`, '
-
-        elif param.attrib.get('optional') is not None:
-            # Don't generate this stub for bitflags
-            if self.getTypeCategory(paramtype.text) != 'bitmask':
-                if param.attrib.get('optional').split(',')[0] == 'true':
-                    asciidoc += 'If '
-                    asciidoc += self.makeParameterName(paramname.text)
-                    asciidoc += ' is not '
-                    if self.paramIsArray(param) or self.paramIsPointer(param) or self.isHandleTypeDispatchable(paramtype.text):
-                        asciidoc += '`NULL`'
-                    elif self.getTypeCategory(paramtype.text) == 'handle':
-                        asciidoc += 'sname:VK_NULL_HANDLE'
-                    else:
-                        asciidoc += '`0`'
-
-                    asciidoc += ', '
-
-        return asciidoc
-
-    #
-    # Make the generic asciidoc line chunk portion used for all parameters.
-    # May return an empty string if nothing to validate.
-    def createValidationLineForParameterIntroChunk(self, param, params, typetext):
-        asciidoc = ''
-        paramname = param.find('name')
-        paramtype = param.find('type')
-
-        asciidoc += self.makeAsciiDocPreChunk(param, params)
-
-        asciidoc += self.makeParameterName(paramname.text)
-        asciidoc += ' must: be '
-
-        if self.paramIsArray(param):
-            # Arrays. These are hard to get right, apparently
-
-            lengths = param.attrib.get('len').split(',')
-
-            if (lengths[0]) == 'null-terminated':
-                asciidoc += 'a null-terminated '
-            elif (lengths[0]) == '1':
-                asciidoc += 'a pointer to '
-            else:
-                asciidoc += 'a pointer to an array of '
-
-                # Handle equations, which are currently denoted with latex
-                if 'latexmath:' in lengths[0]:
-                    asciidoc += lengths[0]
-                else:
-                    asciidoc += self.makeParameterName(lengths[0])
-                asciidoc += ' '
-
-            for length in lengths[1:]:
-                if (length) == 'null-terminated': # This should always be the last thing. If it ever isn't for some bizarre reason, then this will need some massaging.
-                    asciidoc += 'null-terminated '
-                elif (length) == '1':
-                    asciidoc += 'pointers to '
-                else:
-                    asciidoc += 'pointers to arrays of '
-                    # Handle equations, which are currently denoted with latex
-                    if 'latex:' in length:
-                        asciidoc += length
-                    else:
-                        asciidoc += self.makeParameterName(length)
-                    asciidoc += ' '
-
-            # Void pointers don't actually point at anything - remove the word "to"
-            if paramtype.text == 'void':
-                if lengths[-1] == '1':
-                    if len(lengths) > 1:
-                        asciidoc = asciidoc[:-5]    # Take care of the extra s added by the post array chunk function. #HACK#
-                    else:
-                        asciidoc = asciidoc[:-4]
-                else:
-                    # An array of void values is a byte array.
-                    asciidoc += 'byte'
-
-            elif paramtype.text == 'char':
-                # A null terminated array of chars is a string
-                if lengths[-1] == 'null-terminated':
-                    asciidoc += 'string'
-                else:
-                    # Else it's just a bunch of chars
-                    asciidoc += 'char value'
-            elif param.text is not None:
-                # If a value is "const" that means it won't get modified, so it must be valid going into the function.
-                if 'const' in param.text:
-                    typecategory = self.getTypeCategory(paramtype.text)
-                    if (typecategory != 'struct' and typecategory != 'union' and typecategory != 'basetype' and typecategory is not None) or not self.isStructAlwaysValid(paramtype.text):
-                        asciidoc += 'valid '
-
-            asciidoc += typetext
-
-            # pluralize
-            if len(lengths) > 1 or (lengths[0] != '1' and lengths[0] != 'null-terminated'):
-                asciidoc += 's'
-
-        elif self.paramIsPointer(param):
-            # Handle pointers - which are really special case arrays (i.e. they don't have a length)
-            pointercount = paramtype.tail.count('*')
-
-            # Could be multi-level pointers (e.g. ppData - pointer to a pointer). Handle that.
-            for i in range(0, pointercount):
-                asciidoc += 'a pointer to '
-
-            if paramtype.text == 'void':
-                # If there's only one pointer, it's optional, and it doesn't point at anything in particular - we don't need any language.
-                if pointercount == 1 and param.attrib.get('optional') is not None:
-                    return '' # early return
-                else:
-                    # Pointer to nothing in particular - delete the " to " portion
-                    asciidoc = asciidoc[:-4]
-            else:
-                # Add an article for English semantic win
-                asciidoc += 'a '
-
-            # If a value is "const" that means it won't get modified, so it must be valid going into the function.
-            if param.text is not None and paramtype.text != 'void':
-                if 'const' in param.text:
-                    asciidoc += 'valid '
-
-            asciidoc += typetext
-
-        else:
-            # Non-pointer, non-optional things must be valid
-            asciidoc += 'a valid '
-            asciidoc += typetext
-
-        if asciidoc != '':
-            asciidoc += '\n'
-
-            # Add additional line for non-optional bitmasks
-            if self.getTypeCategory(paramtype.text) == 'bitmask':
-                if param.attrib.get('optional') is None:
-                    asciidoc += '* '
-                    if self.paramIsArray(param):
-                        asciidoc += 'Each element of '
-                    asciidoc += 'pname:'
-                    asciidoc += paramname.text
-                    asciidoc += ' mustnot: be `0`'
-                    asciidoc += '\n'
-
-        return asciidoc
-
-    def makeAsciiDocLineForParameter(self, param, params, typetext):
-        if param.attrib.get('noautovalidity') is not None:
-            return ''
-        asciidoc  = self.createValidationLineForParameterIntroChunk(param, params, typetext)
-
-        return asciidoc
-
-    # Try to do check if a structure is always considered valid (i.e. there's no rules to its acceptance)
-    def isStructAlwaysValid(self, structname):
-
-        struct = self.registry.find("types/type[@name='" + structname + "']")
-
-        params = struct.findall('member')
-        validity = struct.find('validity')
-
-        if validity is not None:
-            return False
-
-        for param in params:
-            paramname = param.find('name')
-            paramtype = param.find('type')
-            typecategory = self.getTypeCategory(paramtype.text)
-
-            if paramname.text == 'pNext':
-                return False
-
-            if paramname.text == 'sType':
-                return False
-
-            if paramtype.text == 'void' or paramtype.text == 'char' or self.paramIsArray(param) or self.paramIsPointer(param):
-                if self.makeAsciiDocLineForParameter(param, params, '') != '':
-                    return False
-            elif typecategory == 'handle' or typecategory == 'enum' or typecategory == 'bitmask' or param.attrib.get('returnedonly') == 'true':
-                return False
-            elif typecategory == 'struct' or typecategory == 'union':
-                if self.isStructAlwaysValid(paramtype.text) is False:
-                    return False
-
-        return True
-
-    #
-    # Make an entire asciidoc line for a given parameter
-    def createValidationLineForParameter(self, param, params, typecategory):
-        asciidoc = ''
-        paramname = param.find('name')
-        paramtype = param.find('type')
-
-        if paramtype.text == 'void' or paramtype.text == 'char':
-            # Chars and void are special cases - needs care inside the generator functions
-            # A null-terminated char array is a string, else it's chars.
-            # An array of void values is a byte array, a void pointer is just a pointer to nothing in particular
-            asciidoc += self.makeAsciiDocLineForParameter(param, params, '')
-        elif typecategory == 'bitmask':
-            bitsname = paramtype.text.replace('Flags', 'FlagBits')
-            if self.registry.find("enums[@name='" + bitsname + "']") is None:
-                asciidoc += '* '
-                asciidoc += self.makeParameterName(paramname.text)
-                asciidoc += ' must: be `0`'
-                asciidoc += '\n'
-            else:
-                if self.paramIsArray(param):
-                    asciidoc += self.makeAsciiDocLineForParameter(param, params, 'combinations of ' + self.makeEnumerationName(bitsname) + ' value')
-                else:
-                    asciidoc += self.makeAsciiDocLineForParameter(param, params, 'combination of ' + self.makeEnumerationName(bitsname) + ' values')
-        elif typecategory == 'handle':
-            asciidoc += self.makeAsciiDocLineForParameter(param, params, self.makeStructName(paramtype.text) + ' handle')
-        elif typecategory == 'enum':
-            asciidoc += self.makeAsciiDocLineForParameter(param, params, self.makeEnumerationName(paramtype.text) + ' value')
-        elif typecategory == 'struct':
-            if (self.paramIsArray(param) or self.paramIsPointer(param)) or not self.isStructAlwaysValid(paramtype.text):
-                asciidoc += self.makeAsciiDocLineForParameter(param, params, self.makeStructName(paramtype.text) + ' structure')
-        elif typecategory == 'union':
-            if (self.paramIsArray(param) or self.paramIsPointer(param)) or not self.isStructAlwaysValid(paramtype.text):
-                asciidoc += self.makeAsciiDocLineForParameter(param, params, self.makeStructName(paramtype.text) + ' union')
-        elif self.paramIsArray(param) or self.paramIsPointer(param):
-            asciidoc += self.makeAsciiDocLineForParameter(param, params, self.makeBaseTypeName(paramtype.text) + ' value')
-
-        return asciidoc
-
-    #
-    # Make an asciidoc validity entry for a handle's parent object
-    def makeAsciiDocHandleParent(self, param, params):
-        asciidoc = ''
-        paramname = param.find('name')
-        paramtype = param.find('type')
-
-        # Deal with handle parents
-        handleparent = self.getHandleParent(paramtype.text)
-        if handleparent is not None:
-            parentreference = None
-            for otherparam in params:
-                if otherparam.find('type').text == handleparent:
-                    parentreference = otherparam.find('name').text
-            if parentreference is not None:
-                asciidoc += '* '
-
-                if self.isHandleOptional(param, params):
-                    if self.paramIsArray(param):
-                        asciidoc += 'Each element of '
-                        asciidoc += self.makeParameterName(paramname.text)
-                        asciidoc += ' that is a valid handle'
-                    else:
-                        asciidoc += 'If '
-                        asciidoc += self.makeParameterName(paramname.text)
-                        asciidoc += ' is a valid handle, it'
-                else:
-                    if self.paramIsArray(param):
-                        asciidoc += 'Each element of '
-                    asciidoc += self.makeParameterName(paramname.text)
-                asciidoc += ' must: have been created, allocated or retrieved from '
-                asciidoc += self.makeParameterName(parentreference)
-
-                asciidoc += '\n'
-        return asciidoc
-
-    #
-    # Generate an asciidoc validity line for the sType value of a struct
-    def makeStructureType(self, blockname, param):
-        asciidoc = '* '
-        paramname = param.find('name')
-        paramtype = param.find('type')
-
-        asciidoc += self.makeParameterName(paramname.text)
-        asciidoc += ' must: be '
-
-        structuretype = ''
-        for elem in re.findall(r'(([A-Z][a-z]+)|([A-Z][A-Z]+))', blockname):
-            if elem[0] == 'Vk':
-                structuretype += 'VK_STRUCTURE_TYPE_'
-            else:
-                structuretype += elem[0].upper()
-                structuretype += '_'
-
-        asciidoc += self.makeEnumerantName(structuretype[:-1])
-        asciidoc += '\n'
-
-        return asciidoc
-
-    #
-    # Generate an asciidoc validity line for the pNext value of a struct
-    def makeStructureExtensionPointer(self, param):
-        asciidoc = '* '
-        paramname = param.find('name')
-        paramtype = param.find('type')
-
-        asciidoc += self.makeParameterName(paramname.text)
-
-        validextensionstructs = param.attrib.get('validextensionstructs')
-        asciidoc += ' must: be `NULL`'
-        if validextensionstructs is not None:
-            extensionstructs = ['slink:' + x for x in validextensionstructs.split(',')]
-            asciidoc += ', or a pointer to a valid instance of '
-            if len(extensionstructs) == 1:
-                asciidoc += validextensionstructs
-            else:
-                asciidoc += (', ').join(extensionstructs[:-1]) + ' or ' + extensionstructs[-1]
-
-        asciidoc += '\n'
-
-        return asciidoc
-
-    #
-    # Generate all the valid usage information for a given struct or command
-    def makeValidUsageStatements(self, cmd, blockname, params, usages):
-        # Start the asciidoc block for this
-        asciidoc = ''
-
-        handles = []
-        anyparentedhandlesoptional = False
-        parentdictionary = {}
-        arraylengths = set()
-        for param in params:
-            paramname = param.find('name')
-            paramtype = param.find('type')
-
-            # Get the type's category
-            typecategory = self.getTypeCategory(paramtype.text)
-
-            # Generate language to independently validate a parameter
-            if paramtype.text == 'VkStructureType' and paramname.text == 'sType':
-                asciidoc += self.makeStructureType(blockname, param)
-            elif paramtype.text == 'void' and paramname.text == 'pNext':
-                asciidoc += self.makeStructureExtensionPointer(param)
-            else:
-                asciidoc += self.createValidationLineForParameter(param, params, typecategory)
-
-            # Ensure that any parenting is properly validated, and list that a handle was found
-            if typecategory == 'handle':
-                # Don't detect a parent for return values!
-                if not self.paramIsPointer(param) or (param.text is not None and 'const' in param.text):
-                    parent = self.getHandleParent(paramtype.text)
-                    if parent is not None:
-                        handles.append(param)
-
-                        # If any param is optional, it affects the output
-                        if self.isHandleOptional(param, params):
-                            anyparentedhandlesoptional = True
-
-                        # Find the first dispatchable parent
-                        ancestor = parent
-                        while ancestor is not None and not self.isHandleTypeDispatchable(ancestor):
-                            ancestor = self.getHandleParent(ancestor)
-
-                        # If one was found, add this parameter to the parent dictionary
-                        if ancestor is not None:
-                            if ancestor not in parentdictionary:
-                                parentdictionary[ancestor] = []
-
-                            if self.paramIsArray(param):
-                                parentdictionary[ancestor].append('the elements of ' + self.makeParameterName(paramname.text))
-                            else:
-                                parentdictionary[ancestor].append(self.makeParameterName(paramname.text))
-
-            # Get the array length for this parameter
-            arraylength = param.attrib.get('len')
-            if arraylength is not None:
-                for onelength in arraylength.split(','):
-                    arraylengths.add(onelength)
-
-        # For any vkQueue* functions, there might be queue type data
-        if 'vkQueue' in blockname:
-            # The queue type must be valid
-            queuetypes = cmd.attrib.get('queues')
-            if queuetypes is not None:
-                queuebits = []
-                for queuetype in re.findall(r'([^,]+)', queuetypes):
-                    queuebits.append(queuetype.replace('_',' '))
-
-                asciidoc += '* '
-                asciidoc += 'The pname:queue must: support '
-                if len(queuebits) == 1:
-                    asciidoc += queuebits[0]
-                else:
-                    asciidoc += (', ').join(queuebits[:-1])
-                    asciidoc += ' or '
-                    asciidoc += queuebits[-1]
-                asciidoc += ' operations'
-                asciidoc += '\n'
-
-        if 'vkCmd' in blockname:
-            # The commandBuffer parameter must be being recorded
-            asciidoc += '* '
-            asciidoc += 'pname:commandBuffer must: be in the recording state'
-            asciidoc += '\n'
-
-            # The queue type must be valid
-            queuetypes = cmd.attrib.get('queues')
-            queuebits = []
-            for queuetype in re.findall(r'([^,]+)', queuetypes):
-                queuebits.append(queuetype.replace('_',' '))
-
-            asciidoc += '* '
-            asciidoc += 'The sname:VkCommandPool that pname:commandBuffer was allocated from must: support '
-            if len(queuebits) == 1:
-                asciidoc += queuebits[0]
-            else:
-                asciidoc += (', ').join(queuebits[:-1])
-                asciidoc += ' or '
-                asciidoc += queuebits[-1]
-            asciidoc += ' operations'
-            asciidoc += '\n'
-
-            # Must be called inside/outside a renderpass appropriately
-            renderpass = cmd.attrib.get('renderpass')
-
-            if renderpass != 'both':
-                asciidoc += '* This command must: only be called '
-                asciidoc += renderpass
-                asciidoc += ' of a render pass instance'
-                asciidoc += '\n'
-
-            # Must be in the right level command buffer
-            cmdbufferlevel = cmd.attrib.get('cmdbufferlevel')
-
-            if cmdbufferlevel != 'primary,secondary':
-                asciidoc += '* pname:commandBuffer must: be a '
-                asciidoc += cmdbufferlevel
-                asciidoc += ' sname:VkCommandBuffer'
-                asciidoc += '\n'
-
-        # Any non-optional arraylengths should specify they must be greater than 0
-        for param in params:
-            paramname = param.find('name')
-
-            for arraylength in arraylengths:
-                if paramname.text == arraylength and param.attrib.get('optional') is None:
-                    # Get all the array dependencies
-                    arrays = cmd.findall("param/[@len='" + arraylength + "'][@optional='true']")
-
-                    # Get all the optional array dependencies, including those not generating validity for some reason
-                    optionalarrays = cmd.findall("param/[@len='" + arraylength + "'][@optional='true']")
-                    optionalarrays.extend(cmd.findall("param/[@len='" + arraylength + "'][@noautovalidity='true']"))
-
-                    asciidoc += '* '
-
-                    # Allow lengths to be arbitrary if all their dependents are optional
-                    if len(optionalarrays) == len(arrays) and len(optionalarrays) != 0:
-                        asciidoc += 'If '
-                        if len(optionalarrays) > 1:
-                            asciidoc += 'any of '
-
-                        for array in optionalarrays[:-1]:
-                            asciidoc += self.makeParameterName(optionalarrays.find('name').text)
-                            asciidoc += ', '
-
-                        if len(optionalarrays) > 1:
-                            asciidoc += 'and '
-                            asciidoc += self.makeParameterName(optionalarrays[-1].find('name').text)
-                            asciidoc += ' are '
-                        else:
-                            asciidoc += self.makeParameterName(optionalarrays[-1].find('name').text)
-                            asciidoc += ' is '
-
-                        asciidoc += 'not `NULL`, '
-
-                        if self.paramIsPointer(param):
-                            asciidoc += 'the value referenced by '
-
-                    elif self.paramIsPointer(param):
-                        asciidoc += 'The value referenced by '
-
-                    asciidoc += self.makeParameterName(arraylength)
-                    asciidoc += ' must: be greater than `0`'
-                    asciidoc += '\n'
-
-        # Find the parents of all objects referenced in this command
-        for param in handles:
-            asciidoc += self.makeAsciiDocHandleParent(param, params)
-
-        # Find the common ancestors of objects
-        noancestorscount = 0
-        while noancestorscount < len(parentdictionary):
-            noancestorscount = 0
-            oldparentdictionary = parentdictionary.copy()
-            for parent in oldparentdictionary.items():
-                ancestor = self.getHandleParent(parent[0])
-
-                while ancestor is not None and ancestor not in parentdictionary:
-                    ancestor = self.getHandleParent(ancestor)
-
-                if ancestor is not None:
-                    parentdictionary[ancestor] += parentdictionary.pop(parent[0])
-                else:
-                    # No ancestors possible - so count it up
-                    noancestorscount += 1
-
-        # Add validation language about common ancestors
-        for parent in parentdictionary.items():
-            if len(parent[1]) > 1:
-                parentlanguage = '* '
-
-                parentlanguage += 'Each of '
-                parentlanguage += ", ".join(parent[1][:-1])
-                parentlanguage += ' and '
-                parentlanguage += parent[1][-1]
-                if anyparentedhandlesoptional is True:
-                    parentlanguage += ' that are valid handles'
-                parentlanguage += ' must: have been created, allocated or retrieved from the same '
-                parentlanguage += self.makeStructName(parent[0])
-                parentlanguage += '\n'
-
-                # Capitalize and add to the main language
-                asciidoc += parentlanguage
-
-        # Add in any plain-text validation language that should be added
-        for usage in usages:
-            asciidoc += '* '
-            asciidoc += usage
-            asciidoc += '\n'
-
-        # In case there's nothing to report, return None
-        if asciidoc == '':
-            return None
-        # Delimit the asciidoc block
-        return asciidoc
-
-    def makeThreadSafetyBlock(self, cmd, paramtext):
-        """Generate C function pointer typedef for <command> Element"""
-        paramdecl = ''
-
-        # For any vkCmd* functions, the commandBuffer parameter must be being recorded
-        if cmd.find('proto/name') is not None and 'vkCmd' in cmd.find('proto/name'):
-            paramdecl += '* '
-            paramdecl += 'The sname:VkCommandPool that pname:commandBuffer was created from'
-            paramdecl += '\n'
-
-        # Find and add any parameters that are thread unsafe
-        explicitexternsyncparams = cmd.findall(paramtext + "[@externsync]")
-        if (explicitexternsyncparams is not None):
-            for param in explicitexternsyncparams:
-                externsyncattribs = param.attrib.get('externsync')
-                paramname = param.find('name')
-                for externsyncattrib in externsyncattribs.split(','):
-                    paramdecl += '* '
-                    paramdecl += 'Host access to '
-                    if externsyncattrib == 'true':
-                        if self.paramIsArray(param):
-                            paramdecl += 'each member of ' + self.makeParameterName(paramname.text)
-                        elif self.paramIsPointer(param):
-                            paramdecl += 'the object referenced by ' + self.makeParameterName(paramname.text)
-                        else:
-                            paramdecl += self.makeParameterName(paramname.text)
-                    else:
-                        paramdecl += 'pname:'
-                        paramdecl += externsyncattrib
-                    paramdecl += ' must: be externally synchronized\n'
-
-        # Find and add any "implicit" parameters that are thread unsafe
-        implicitexternsyncparams = cmd.find('implicitexternsyncparams')
-        if (implicitexternsyncparams is not None):
-            for elem in implicitexternsyncparams:
-                paramdecl += '* '
-                paramdecl += 'Host access to '
-                paramdecl += elem.text
-                paramdecl += ' must: be externally synchronized\n'
-
-        if (paramdecl == ''):
-            return None
-        else:
-            return paramdecl
-
-    def makeCommandPropertiesTableEntry(self, cmd, name):
-
-        if 'vkCmd' in name:
-            # Must be called inside/outside a renderpass appropriately
-            cmdbufferlevel = cmd.attrib.get('cmdbufferlevel')
-            cmdbufferlevel = (' + \n').join(cmdbufferlevel.title().split(','))
-
-            renderpass = cmd.attrib.get('renderpass')
-            renderpass = renderpass.capitalize()
-
-            queues = cmd.attrib.get('queues')
-            queues = (' + \n').join(queues.upper().split(','))
-
-            return '|' + cmdbufferlevel + '|' + renderpass + '|' + queues
-        elif 'vkQueue' in name:
-            # Must be called inside/outside a renderpass appropriately
-
-            queues = cmd.attrib.get('queues')
-            if queues is None:
-                queues = 'Any'
-            else:
-                queues = (' + \n').join(queues.upper().split(','))
-
-            return '|-|-|' + queues
-
-        return None
-
-    def makeSuccessCodes(self, cmd, name):
-
-        successcodes = cmd.attrib.get('successcodes')
-        if successcodes is not None:
-
-            successcodeentry = ''
-            successcodes = successcodes.split(',')
-            return '* ename:' + '\n* ename:'.join(successcodes)
-
-        return None
-
-    def makeErrorCodes(self, cmd, name):
-
-        errorcodes = cmd.attrib.get('errorcodes')
-        if errorcodes is not None:
-
-            errorcodeentry = ''
-            errorcodes = errorcodes.split(',')
-            return '* ename:' + '\n* ename:'.join(errorcodes)
-
-        return None
-
-    #
-    # Command generation
-    def genCmd(self, cmdinfo, name):
-        OutputGenerator.genCmd(self, cmdinfo, name)
-        #
-        # Get all the parameters
-        params = cmdinfo.elem.findall('param')
-        usageelements = cmdinfo.elem.findall('validity/usage')
-        usages = []
-
-        for usage in usageelements:
-            usages.append(usage.text)
-        for usage in cmdinfo.additionalValidity:
-            usages.append(usage.text)
-        for usage in cmdinfo.removedValidity:
-            usages.remove(usage.text)
-
-        validity = self.makeValidUsageStatements(cmdinfo.elem, name, params, usages)
-        threadsafety = self.makeThreadSafetyBlock(cmdinfo.elem, 'param')
-        commandpropertiesentry = self.makeCommandPropertiesTableEntry(cmdinfo.elem, name)
-        successcodes = self.makeSuccessCodes(cmdinfo.elem, name)
-        errorcodes = self.makeErrorCodes(cmdinfo.elem, name)
-
-        self.writeInclude('validity/protos', name, validity, threadsafety, commandpropertiesentry, successcodes, errorcodes)
-
-    #
-    # Struct Generation
-    def genStruct(self, typeinfo, typename):
-        OutputGenerator.genStruct(self, typeinfo, typename)
-
-        # Anything that's only ever returned can't be set by the user, so shouldn't have any validity information.
-        if typeinfo.elem.attrib.get('returnedonly') is None:
-            params = typeinfo.elem.findall('member')
-
-            usageelements = typeinfo.elem.findall('validity/usage')
-            usages = []
-
-            for usage in usageelements:
-                usages.append(usage.text)
-            for usage in typeinfo.additionalValidity:
-                usages.append(usage.text)
-            for usage in typeinfo.removedValidity:
-                usages.remove(usage.text)
-
-            validity = self.makeValidUsageStatements(typeinfo.elem, typename, params, usages)
-            threadsafety = self.makeThreadSafetyBlock(typeinfo.elem, 'member')
-
-            self.writeInclude('validity/structs', typename, validity, threadsafety, None, None, None)
-        else:
-            # Still generate files for return only structs, in case this state changes later
-            self.writeInclude('validity/structs', typename, None, None, None, None, None)
-
-    #
-    # Type Generation
-    def genType(self, typeinfo, typename):
-        OutputGenerator.genType(self, typeinfo, typename)
-
-        category = typeinfo.elem.get('category')
-        if (category == 'struct' or category == 'union'):
-            self.genStruct(typeinfo, typename)
-
-# HostSynchronizationOutputGenerator - subclass of OutputGenerator.
-# Generates AsciiDoc includes of the externsync parameter table for the
-# fundamentals chapter of the Vulkan specification. Similar to
-# DocOutputGenerator.
-#
-# ---- methods ----
-# HostSynchronizationOutputGenerator(errFile, warnFile, diagFile) - args as for
-#   OutputGenerator. Defines additional internal state.
-# ---- methods overriding base class ----
-# genCmd(cmdinfo)
-class HostSynchronizationOutputGenerator(OutputGenerator):
-    # Generate Host Synchronized Parameters in a table at the top of the spec
-    def __init__(self,
-                 errFile = sys.stderr,
-                 warnFile = sys.stderr,
-                 diagFile = sys.stdout):
-        OutputGenerator.__init__(self, errFile, warnFile, diagFile)
-
-    threadsafety = {'parameters': '', 'parameterlists': '', 'implicit': ''}
-
-    def makeParameterName(self, name):
-        return 'pname:' + name
-
-    def makeFLink(self, name):
-        return 'flink:' + name
-
-    #
-    # Generate an include file
-    #
-    # directory - subdirectory to put file in
-    # basename - base name of the file
-    # contents - contents of the file (Asciidoc boilerplate aside)
-    def writeInclude(self):
-
-        if self.threadsafety['parameters'] is not None:
-            # Create file
-            filename = self.genOpts.genDirectory + '/' + self.genOpts.filename + '/parameters.txt'
-            self.logMsg('diag', '# Generating include file:', filename)
-            fp = open(filename, 'w')
-
-            # Host Synchronization
-            write('// WARNING: DO NOT MODIFY! This file is automatically generated from the vk.xml registry', file=fp)
-            write('.Externally Synchronized Parameters', file=fp)
-            write('*' * 80, file=fp)
-            write(self.threadsafety['parameters'], file=fp, end='')
-            write('*' * 80, file=fp)
-            write('', file=fp)
-
-        if self.threadsafety['parameterlists'] is not None:
-            # Create file
-            filename = self.genOpts.genDirectory + '/' + self.genOpts.filename + '/parameterlists.txt'
-            self.logMsg('diag', '# Generating include file:', filename)
-            fp = open(filename, 'w')
-
-            # Host Synchronization
-            write('// WARNING: DO NOT MODIFY! This file is automatically generated from the vk.xml registry', file=fp)
-            write('.Externally Synchronized Parameter Lists', file=fp)
-            write('*' * 80, file=fp)
-            write(self.threadsafety['parameterlists'], file=fp, end='')
-            write('*' * 80, file=fp)
-            write('', file=fp)
-
-        if self.threadsafety['implicit'] is not None:
-            # Create file
-            filename = self.genOpts.genDirectory + '/' + self.genOpts.filename + '/implicit.txt'
-            self.logMsg('diag', '# Generating include file:', filename)
-            fp = open(filename, 'w')
-
-            # Host Synchronization
-            write('// WARNING: DO NOT MODIFY! This file is automatically generated from the vk.xml registry', file=fp)
-            write('.Implicit Externally Synchronized Parameters', file=fp)
-            write('*' * 80, file=fp)
-            write(self.threadsafety['implicit'], file=fp, end='')
-            write('*' * 80, file=fp)
-            write('', file=fp)
-
-        fp.close()
-
-    #
-    # Check if the parameter passed in is a pointer to an array
-    def paramIsArray(self, param):
-        return param.attrib.get('len') is not None
-
-    # Check if the parameter passed in is a pointer
-    def paramIsPointer(self, param):
-        ispointer = False
-        paramtype = param.find('type')
-        if paramtype.tail is not None and '*' in paramtype.tail:
-            ispointer = True
-
-        return ispointer
-
-    # Turn the "name[].member[]" notation into plain English.
-    def makeThreadDereferenceHumanReadable(self, dereference):
-        matches = re.findall(r"[\w]+[^\w]*",dereference)
-        stringval = ''
-        for match in reversed(matches):
-            if '->' in match or '.' in match:
-                stringval += 'member of '
-            if '[]' in match:
-                stringval += 'each element of '
-
-            stringval += 'the '
-            stringval += self.makeParameterName(re.findall(r"[\w]+",match)[0])
-            stringval += ' '
-
-        stringval += 'parameter'
-
-        return stringval[0].upper() + stringval[1:]
-
-    def makeThreadSafetyBlocks(self, cmd, paramtext):
-        protoname = cmd.find('proto/name').text
-
-        # Find and add any parameters that are thread unsafe
-        explicitexternsyncparams = cmd.findall(paramtext + "[@externsync]")
-        if (explicitexternsyncparams is not None):
-            for param in explicitexternsyncparams:
-                externsyncattribs = param.attrib.get('externsync')
-                paramname = param.find('name')
-                for externsyncattrib in externsyncattribs.split(','):
-
-                    tempstring = '* '
-                    if externsyncattrib == 'true':
-                        if self.paramIsArray(param):
-                            tempstring += 'Each element of the '
-                        elif self.paramIsPointer(param):
-                            tempstring += 'The object referenced by the '
-                        else:
-                            tempstring += 'The '
-
-                        tempstring += self.makeParameterName(paramname.text)
-                        tempstring += ' parameter'
-
-                    else:
-                        tempstring += self.makeThreadDereferenceHumanReadable(externsyncattrib)
-
-                    tempstring += ' in '
-                    tempstring += self.makeFLink(protoname)
-                    tempstring += '\n'
-
-
-                    if ' element of ' in tempstring:
-                        self.threadsafety['parameterlists'] += tempstring
-                    else:
-                        self.threadsafety['parameters'] += tempstring
-
-
-        # Find and add any "implicit" parameters that are thread unsafe
-        implicitexternsyncparams = cmd.find('implicitexternsyncparams')
-        if (implicitexternsyncparams is not None):
-            for elem in implicitexternsyncparams:
-                self.threadsafety['implicit'] += '* '
-                self.threadsafety['implicit'] += elem.text[0].upper()
-                self.threadsafety['implicit'] += elem.text[1:]
-                self.threadsafety['implicit'] += ' in '
-                self.threadsafety['implicit'] += self.makeFLink(protoname)
-                self.threadsafety['implicit'] += '\n'
-
-
-        # For any vkCmd* functions, the commandBuffer parameter must be being recorded
-        if protoname is not None and 'vkCmd' in protoname:
-            self.threadsafety['implicit'] += '* '
-            self.threadsafety['implicit'] += 'The sname:VkCommandPool that pname:commandBuffer was allocated from, in '
-            self.threadsafety['implicit'] += self.makeFLink(protoname)
-
-            self.threadsafety['implicit'] += '\n'
-
-    #
-    # Command generation
-    def genCmd(self, cmdinfo, name):
-        OutputGenerator.genCmd(self, cmdinfo, name)
-        #
-        # Get all thh parameters
-        params = cmdinfo.elem.findall('param')
-        usages = cmdinfo.elem.findall('validity/usage')
-
-        self.makeThreadSafetyBlocks(cmdinfo.elem, 'param')
-
-        self.writeInclude()
-
-# ThreadOutputGenerator - subclass of OutputGenerator.
-# Generates Thread checking framework
-#
-# ---- methods ----
-# ThreadOutputGenerator(errFile, warnFile, diagFile) - args as for
-#   OutputGenerator. Defines additional internal state.
-# ---- methods overriding base class ----
-# beginFile(genOpts)
-# endFile()
-# beginFeature(interface, emit)
-# endFeature()
-# genType(typeinfo,name)
-# genStruct(typeinfo,name)
-# genGroup(groupinfo,name)
-# genEnum(enuminfo, name)
-# genCmd(cmdinfo)
-class ThreadOutputGenerator(OutputGenerator):
-    """Generate specified API interfaces in a specific style, such as a C header"""
-    # This is an ordered list of sections in the header file.
-    TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
-                     'group', 'bitmask', 'funcpointer', 'struct']
-    ALL_SECTIONS = TYPE_SECTIONS + ['command']
-    def __init__(self,
-                 errFile = sys.stderr,
-                 warnFile = sys.stderr,
-                 diagFile = sys.stdout):
-        OutputGenerator.__init__(self, errFile, warnFile, diagFile)
-        # Internal state - accumulators for different inner block text
-        self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
-        self.intercepts = []
-
-    # Check if the parameter passed in is a pointer to an array
-    def paramIsArray(self, param):
-        return param.attrib.get('len') is not None
-
-    # Check if the parameter passed in is a pointer
-    def paramIsPointer(self, param):
-        ispointer = False
-        for elem in param:
-            #write('paramIsPointer '+elem.text, file=sys.stderr)
-            #write('elem.tag '+elem.tag, file=sys.stderr)
-            #if (elem.tail is None):
-            #    write('elem.tail is None', file=sys.stderr)
-            #else:
-            #    write('elem.tail '+elem.tail, file=sys.stderr)
-            if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
-                ispointer = True
-            #    write('is pointer', file=sys.stderr)
-        return ispointer
-    def makeThreadUseBlock(self, cmd, functionprefix):
-        """Generate C function pointer typedef for <command> Element"""
-        paramdecl = ''
-        thread_check_dispatchable_objects = [
-            "VkCommandBuffer",
-            "VkDevice",
-            "VkInstance",
-            "VkQueue",
-        ]
-        thread_check_nondispatchable_objects = [
-            "VkBuffer",
-            "VkBufferView",
-            "VkCommandPool",
-            "VkDescriptorPool",
-            "VkDescriptorSetLayout",
-            "VkDeviceMemory",
-            "VkEvent",
-            "VkFence",
-            "VkFramebuffer",
-            "VkImage",
-            "VkImageView",
-            "VkPipeline",
-            "VkPipelineCache",
-            "VkPipelineLayout",
-            "VkQueryPool",
-            "VkRenderPass",
-            "VkSampler",
-            "VkSemaphore",
-            "VkShaderModule",
-        ]
-
-        # Find and add any parameters that are thread unsafe
-        params = cmd.findall('param')
-        for param in params:
-            paramname = param.find('name')
-            if False: # self.paramIsPointer(param):
-                paramdecl += '    // not watching use of pointer ' + paramname.text + '\n'
-            else:
-                externsync = param.attrib.get('externsync')
-                if externsync == 'true':
-                    if self.paramIsArray(param):
-                        paramdecl += '    for (uint32_t index=0;index<' + param.attrib.get('len') + ';index++) {\n'
-                        paramdecl += '        ' + functionprefix + 'WriteObject(my_data, ' + paramname.text + '[index]);\n'
-                        paramdecl += '    }\n'
-                    else:
-                        paramdecl += '    ' + functionprefix + 'WriteObject(my_data, ' + paramname.text + ');\n'
-                elif (param.attrib.get('externsync')):
-                    if self.paramIsArray(param):
-                        # Externsync can list pointers to arrays of members to synchronize
-                        paramdecl += '    for (uint32_t index=0;index<' + param.attrib.get('len') + ';index++) {\n'
-                        for member in externsync.split(","):
-                            # Replace first empty [] in member name with index
-                            element = member.replace('[]','[index]',1)
-                            if '[]' in element:
-                                # Replace any second empty [] in element name with
-                                # inner array index based on mapping array names like
-                                # "pSomeThings[]" to "someThingCount" array size.
-                                # This could be more robust by mapping a param member
-                                # name to a struct type and "len" attribute.
-                                limit = element[0:element.find('s[]')] + 'Count'
-                                dotp = limit.rfind('.p')
-                                limit = limit[0:dotp+1] + limit[dotp+2:dotp+3].lower() + limit[dotp+3:]
-                                paramdecl += '        for(uint32_t index2=0;index2<'+limit+';index2++)\n'
-                                element = element.replace('[]','[index2]')
-                            paramdecl += '            ' + functionprefix + 'WriteObject(my_data, ' + element + ');\n'
-                        paramdecl += '    }\n'
-                    else:
-                        # externsync can list members to synchronize
-                        for member in externsync.split(","):
-                            member = str(member).replace("::", "->")
-                            paramdecl += '    ' + functionprefix + 'WriteObject(my_data, ' + member + ');\n'
-                else:
-                    paramtype = param.find('type')
-                    if paramtype is not None:
-                        paramtype = paramtype.text
-                    else:
-                        paramtype = 'None'
-                    if paramtype in thread_check_dispatchable_objects or paramtype in thread_check_nondispatchable_objects:
-                        if self.paramIsArray(param) and ('pPipelines' != paramname.text):
-                            paramdecl += '    for (uint32_t index=0;index<' + param.attrib.get('len') + ';index++) {\n'
-                            paramdecl += '        ' + functionprefix + 'ReadObject(my_data, ' + paramname.text + '[index]);\n'
-                            paramdecl += '    }\n'
-                        elif not self.paramIsPointer(param):
-                            # Pointer params are often being created.
-                            # They are not being read from.
-                            paramdecl += '    ' + functionprefix + 'ReadObject(my_data, ' + paramname.text + ');\n'
-        explicitexternsyncparams = cmd.findall("param[@externsync]")
-        if (explicitexternsyncparams is not None):
-            for param in explicitexternsyncparams:
-                externsyncattrib = param.attrib.get('externsync')
-                paramname = param.find('name')
-                paramdecl += '    // Host access to '
-                if externsyncattrib == 'true':
-                    if self.paramIsArray(param):
-                        paramdecl += 'each member of ' + paramname.text
-                    elif self.paramIsPointer(param):
-                        paramdecl += 'the object referenced by ' + paramname.text
-                    else:
-                        paramdecl += paramname.text
-                else:
-                    paramdecl += externsyncattrib
-                paramdecl += ' must be externally synchronized\n'
-
-        # Find and add any "implicit" parameters that are thread unsafe
-        implicitexternsyncparams = cmd.find('implicitexternsyncparams')
-        if (implicitexternsyncparams is not None):
-            for elem in implicitexternsyncparams:
-                paramdecl += '    // '
-                paramdecl += elem.text
-                paramdecl += ' must be externally synchronized between host accesses\n'
-
-        if (paramdecl == ''):
-            return None
-        else:
-            return paramdecl
-    def beginFile(self, genOpts):
-        OutputGenerator.beginFile(self, genOpts)
-        # C-specific
-        #
-        # Multiple inclusion protection & C++ namespace.
-        if (genOpts.protectFile and self.genOpts.filename):
-            headerSym = '__' + re.sub('\.h', '_h_', os.path.basename(self.genOpts.filename))
-            write('#ifndef', headerSym, file=self.outFile)
-            write('#define', headerSym, '1', file=self.outFile)
-            self.newline()
-        write('namespace threading {', file=self.outFile)
-        self.newline()
-        #
-        # User-supplied prefix text, if any (list of strings)
-        if (genOpts.prefixText):
-            for s in genOpts.prefixText:
-                write(s, file=self.outFile)
-    def endFile(self):
-        # C-specific
-        # Finish C++ namespace and multiple inclusion protection
-        self.newline()
-        # record intercepted procedures
-        write('// intercepts', file=self.outFile)
-        write('struct { const char* name; PFN_vkVoidFunction pFunc;} procmap[] = {', file=self.outFile)
-        write('\n'.join(self.intercepts), file=self.outFile)
-        write('};\n', file=self.outFile)
-        self.newline()
-        write('} // namespace threading', file=self.outFile)
-        if (self.genOpts.protectFile and self.genOpts.filename):
-            self.newline()
-            write('#endif', file=self.outFile)
-        # Finish processing in superclass
-        OutputGenerator.endFile(self)
-    def beginFeature(self, interface, emit):
-        #write('// starting beginFeature', file=self.outFile)
-        # Start processing in superclass
-        OutputGenerator.beginFeature(self, interface, emit)
-        # C-specific
-        # Accumulate includes, defines, types, enums, function pointer typedefs,
-        # end function prototypes separately for this feature. They're only
-        # printed in endFeature().
-        self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
-        #write('// ending beginFeature', file=self.outFile)
-    def endFeature(self):
-        # C-specific
-        # Actually write the interface to the output file.
-        #write('// starting endFeature', file=self.outFile)
-        if (self.emit):
-            self.newline()
-            if (self.genOpts.protectFeature):
-                write('#ifndef', self.featureName, file=self.outFile)
-            # If type declarations are needed by other features based on
-            # this one, it may be necessary to suppress the ExtraProtect,
-            # or move it below the 'for section...' loop.
-            #write('// endFeature looking at self.featureExtraProtect', file=self.outFile)
-            if (self.featureExtraProtect != None):
-                write('#ifdef', self.featureExtraProtect, file=self.outFile)
-            #write('#define', self.featureName, '1', file=self.outFile)
-            for section in self.TYPE_SECTIONS:
-                #write('// endFeature writing section'+section, file=self.outFile)
-                contents = self.sections[section]
-                if contents:
-                    write('\n'.join(contents), file=self.outFile)
-                    self.newline()
-            #write('// endFeature looking at self.sections[command]', file=self.outFile)
-            if (self.sections['command']):
-                write('\n'.join(self.sections['command']), end='', file=self.outFile)
-                self.newline()
-            if (self.featureExtraProtect != None):
-                write('#endif /*', self.featureExtraProtect, '*/', file=self.outFile)
-            if (self.genOpts.protectFeature):
-                write('#endif /*', self.featureName, '*/', file=self.outFile)
-        # Finish processing in superclass
-        OutputGenerator.endFeature(self)
-        #write('// ending endFeature', file=self.outFile)
-    #
-    # Append a definition to the specified section
-    def appendSection(self, section, text):
-        # self.sections[section].append('SECTION: ' + section + '\n')
-        self.sections[section].append(text)
-    #
-    # Type generation
-    def genType(self, typeinfo, name):
-        pass
-    #
-    # Struct (e.g. C "struct" type) generation.
-    # This is a special case of the <type> tag where the contents are
-    # interpreted as a set of <member> tags instead of freeform C
-    # C type declarations. The <member> tags are just like <param>
-    # tags - they are a declaration of a struct or union member.
-    # Only simple member declarations are supported (no nested
-    # structs etc.)
-    def genStruct(self, typeinfo, typeName):
-        OutputGenerator.genStruct(self, typeinfo, typeName)
-        body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
-        # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
-        for member in typeinfo.elem.findall('.//member'):
-            body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
-            body += ';\n'
-        body += '} ' + typeName + ';\n'
-        self.appendSection('struct', body)
-    #
-    # Group (e.g. C "enum" type) generation.
-    # These are concatenated together with other types.
-    def genGroup(self, groupinfo, groupName):
-        pass
-    # Enumerant generation
-    # <enum> tags may specify their values in several ways, but are usually
-    # just integers.
-    def genEnum(self, enuminfo, name):
-        pass
-    #
-    # Command generation
-    def genCmd(self, cmdinfo, name):
-        # Commands shadowed by interface functions and are not implemented
-        interface_functions = [
-            'vkEnumerateInstanceLayerProperties',
-            'vkEnumerateInstanceExtensionProperties',
-            'vkEnumerateDeviceLayerProperties',
-        ]
-        if name in interface_functions:
-            return
-        special_functions = [
-            'vkGetDeviceProcAddr',
-            'vkGetInstanceProcAddr',
-            'vkCreateDevice',
-            'vkDestroyDevice',
-            'vkCreateInstance',
-            'vkDestroyInstance',
-            'vkAllocateCommandBuffers',
-            'vkFreeCommandBuffers',
-            'vkCreateDebugReportCallbackEXT',
-            'vkDestroyDebugReportCallbackEXT',
-        ]
-        if name in special_functions:
-            decls = self.makeCDecls(cmdinfo.elem)
-            self.appendSection('command', '')
-            self.appendSection('command', '// declare only')
-            self.appendSection('command', decls[0])
-            self.intercepts += [ '    {"%s", reinterpret_cast<PFN_vkVoidFunction>(%s)},' % (name,name[2:]) ]
-            return
-        if "KHR" in name:
-            self.appendSection('command', '// TODO - not wrapping KHR function ' + name)
-            return
-        if ("DebugMarker" in name) and ("EXT" in name):
-            self.appendSection('command', '// TODO - not wrapping EXT function ' + name)
-            return
-        # Determine first if this function needs to be intercepted
-        startthreadsafety = self.makeThreadUseBlock(cmdinfo.elem, 'start')
-        if startthreadsafety is None:
-            return
-        finishthreadsafety = self.makeThreadUseBlock(cmdinfo.elem, 'finish')
-        # record that the function will be intercepted
-        if (self.featureExtraProtect != None):
-            self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
-        self.intercepts += [ '    {"%s", reinterpret_cast<PFN_vkVoidFunction>(%s)},' % (name,name[2:]) ]
-        if (self.featureExtraProtect != None):
-            self.intercepts += [ '#endif' ]
-
-        OutputGenerator.genCmd(self, cmdinfo, name)
-        #
-        decls = self.makeCDecls(cmdinfo.elem)
-        self.appendSection('command', '')
-        self.appendSection('command', decls[0][:-1])
-        self.appendSection('command', '{')
-        # setup common to call wrappers
-        # first parameter is always dispatchable
-        dispatchable_type = cmdinfo.elem.find('param/type').text
-        dispatchable_name = cmdinfo.elem.find('param/name').text
-        self.appendSection('command', '    dispatch_key key = get_dispatch_key('+dispatchable_name+');')
-        self.appendSection('command', '    layer_data *my_data = get_my_data_ptr(key, layer_data_map);')
-        if dispatchable_type in ["VkPhysicalDevice", "VkInstance"]:
-            self.appendSection('command', '    VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;')
-        else:
-            self.appendSection('command', '    VkLayerDispatchTable *pTable = my_data->device_dispatch_table;')
-        # Declare result variable, if any.
-        resulttype = cmdinfo.elem.find('proto/type')
-        if (resulttype != None and resulttype.text == 'void'):
-          resulttype = None
-        if (resulttype != None):
-            self.appendSection('command', '    ' + resulttype.text + ' result;')
-            assignresult = 'result = '
-        else:
-            assignresult = ''
-
-        self.appendSection('command', '    bool threadChecks = startMultiThread();')
-        self.appendSection('command', '    if (threadChecks) {')
-        self.appendSection('command', "    "+"\n    ".join(str(startthreadsafety).rstrip().split("\n")))
-        self.appendSection('command', '    }')
-        params = cmdinfo.elem.findall('param/name')
-        paramstext = ','.join([str(param.text) for param in params])
-        API = cmdinfo.elem.attrib.get('name').replace('vk','pTable->',1)
-        self.appendSection('command', '    ' + assignresult + API + '(' + paramstext + ');')
-        self.appendSection('command', '    if (threadChecks) {')
-        self.appendSection('command', "    "+"\n    ".join(str(finishthreadsafety).rstrip().split("\n")))
-        self.appendSection('command', '    } else {')
-        self.appendSection('command', '        finishMultiThread();')
-        self.appendSection('command', '    }')
-        # Return result variable, if any.
-        if (resulttype != None):
-            self.appendSection('command', '    return result;')
-        self.appendSection('command', '}')
-    #
-    # override makeProtoName to drop the "vk" prefix
-    def makeProtoName(self, name, tail):
-        return self.genOpts.apientry + name[2:] + tail
-
-# ParamCheckerOutputGenerator - subclass of OutputGenerator.
-# Generates param checker layer code.
-#
-# ---- methods ----
-# ParamCheckerOutputGenerator(errFile, warnFile, diagFile) - args as for
-#   OutputGenerator. Defines additional internal state.
-# ---- methods overriding base class ----
-# beginFile(genOpts)
-# endFile()
-# beginFeature(interface, emit)
-# endFeature()
-# genType(typeinfo,name)
-# genStruct(typeinfo,name)
-# genGroup(groupinfo,name)
-# genEnum(enuminfo, name)
-# genCmd(cmdinfo)
-class ParamCheckerOutputGenerator(OutputGenerator):
-    """Generate ParamChecker code based on XML element attributes"""
-    # This is an ordered list of sections in the header file.
-    ALL_SECTIONS = ['command']
-    def __init__(self,
-                 errFile = sys.stderr,
-                 warnFile = sys.stderr,
-                 diagFile = sys.stdout):
-        OutputGenerator.__init__(self, errFile, warnFile, diagFile)
-        self.INDENT_SPACES = 4
-        # Commands to ignore
-        self.blacklist = [
-            'vkGetInstanceProcAddr',
-            'vkGetDeviceProcAddr',
-            'vkEnumerateInstanceLayerProperties',
-            'vkEnumerateInstanceExtensionsProperties',
-            'vkEnumerateDeviceLayerProperties',
-            'vkEnumerateDeviceExtensionsProperties',
-            'vkCreateDebugReportCallbackEXT',
-            'vkDebugReportMessageEXT']
-        # Validation conditions for some special case struct members that are conditionally validated
-        self.structMemberValidationConditions = { 'VkPipelineColorBlendStateCreateInfo' : { 'logicOp' : '{}logicOpEnable == VK_TRUE' } }
-        # Header version
-        self.headerVersion = None
-        # Internal state - accumulators for different inner block text
-        self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
-        self.structNames = []                             # List of Vulkan struct typenames
-        self.stypes = []                                  # Values from the VkStructureType enumeration
-        self.structTypes = dict()                         # Map of Vulkan struct typename to required VkStructureType
-        self.handleTypes = set()                          # Set of handle type names
-        self.commands = []                                # List of CommandData records for all Vulkan commands
-        self.structMembers = []                           # List of StructMemberData records for all Vulkan structs
-        self.validatedStructs = dict()                    # Map of structs type names to generated validation code for that struct type
-        self.enumRanges = dict()                          # Map of enum name to BEGIN/END range values
-        self.flags = set()                                # Map of flags typenames
-        self.flagBits = dict()                            # Map of flag bits typename to list of values
-        # Named tuples to store struct and command data
-        self.StructType = namedtuple('StructType', ['name', 'value'])
-        self.CommandParam = namedtuple('CommandParam', ['type', 'name', 'ispointer', 'isstaticarray', 'isbool', 'israngedenum',
-                                                        'isconst', 'isoptional', 'iscount', 'noautovalidity', 'len', 'extstructs',
-                                                        'condition', 'cdecl'])
-        self.CommandData = namedtuple('CommandData', ['name', 'params', 'cdecl'])
-        self.StructMemberData = namedtuple('StructMemberData', ['name', 'members'])
-    #
-    def incIndent(self, indent):
-        inc = ' ' * self.INDENT_SPACES
-        if indent:
-            return indent + inc
-        return inc
-    #
-    def decIndent(self, indent):
-        if indent and (len(indent) > self.INDENT_SPACES):
-            return indent[:-self.INDENT_SPACES]
-        return ''
-    #
-    def beginFile(self, genOpts):
-        OutputGenerator.beginFile(self, genOpts)
-        # C-specific
-        #
-        # User-supplied prefix text, if any (list of strings)
-        if (genOpts.prefixText):
-            for s in genOpts.prefixText:
-                write(s, file=self.outFile)
-        #
-        # Multiple inclusion protection & C++ wrappers.
-        if (genOpts.protectFile and self.genOpts.filename):
-            headerSym = re.sub('\.h', '_H', os.path.basename(self.genOpts.filename)).upper()
-            write('#ifndef', headerSym, file=self.outFile)
-            write('#define', headerSym, '1', file=self.outFile)
-            self.newline()
-        #
-        # Headers
-        write('#include <string>', file=self.outFile)
-        self.newline()
-        write('#include "vulkan/vulkan.h"', file=self.outFile)
-        write('#include "vk_layer_extension_utils.h"', file=self.outFile)
-        write('#include "parameter_validation_utils.h"', file=self.outFile)
-        #
-        # Macros
-        self.newline()
-        write('#ifndef UNUSED_PARAMETER', file=self.outFile)
-        write('#define UNUSED_PARAMETER(x) (void)(x)', file=self.outFile)
-        write('#endif // UNUSED_PARAMETER', file=self.outFile)
-        #
-        # Namespace
-        self.newline()
-        write('namespace parameter_validation {', file = self.outFile)
-    def endFile(self):
-        # C-specific
-        self.newline()
-        # Namespace
-        write('} // namespace parameter_validation', file = self.outFile)
-        # Finish C++ wrapper and multiple inclusion protection
-        if (self.genOpts.protectFile and self.genOpts.filename):
-            self.newline()
-            write('#endif', file=self.outFile)
-        # Finish processing in superclass
-        OutputGenerator.endFile(self)
-    def beginFeature(self, interface, emit):
-        # Start processing in superclass
-        OutputGenerator.beginFeature(self, interface, emit)
-        # C-specific
-        # Accumulate includes, defines, types, enums, function pointer typedefs,
-        # end function prototypes separately for this feature. They're only
-        # printed in endFeature().
-        self.headerVersion = None
-        self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
-        self.structNames = []
-        self.stypes = []
-        self.structTypes = dict()
-        self.handleTypes = set()
-        self.commands = []
-        self.structMembers = []
-        self.validatedStructs = dict()
-        self.enumRanges = dict()
-        self.flags = set()
-        self.flagBits = dict()
-    def endFeature(self):
-        # C-specific
-        # Actually write the interface to the output file.
-        if (self.emit):
-            self.newline()
-            # If type declarations are needed by other features based on
-            # this one, it may be necessary to suppress the ExtraProtect,
-            # or move it below the 'for section...' loop.
-            if (self.featureExtraProtect != None):
-                write('#ifdef', self.featureExtraProtect, file=self.outFile)
-            # Generate the struct member checking code from the captured data
-            self.processStructMemberData()
-            # Generate the command parameter checking code from the captured data
-            self.processCmdData()
-            # Write the declaration for the HeaderVersion
-            if self.headerVersion:
-                write('const uint32_t GeneratedHeaderVersion = {};'.format(self.headerVersion), file=self.outFile)
-                self.newline()
-            # Write the declarations for the VkFlags values combining all flag bits
-            for flag in sorted(self.flags):
-                flagBits = flag.replace('Flags', 'FlagBits')
-                if flagBits in self.flagBits:
-                    bits = self.flagBits[flagBits]
-                    decl = 'const {} All{} = {}'.format(flag, flagBits, bits[0])
-                    for bit in bits[1:]:
-                        decl += '|' + bit
-                    decl += ';'
-                    write(decl, file=self.outFile)
-            self.newline()
-            # Write the parameter validation code to the file
-            if (self.sections['command']):
-                if (self.genOpts.protectProto):
-                    write(self.genOpts.protectProto,
-                          self.genOpts.protectProtoStr, file=self.outFile)
-                write('\n'.join(self.sections['command']), end='', file=self.outFile)
-            if (self.featureExtraProtect != None):
-                write('#endif /*', self.featureExtraProtect, '*/', file=self.outFile)
-            else:
-                self.newline()
-        # Finish processing in superclass
-        OutputGenerator.endFeature(self)
-    #
-    # Append a definition to the specified section
-    def appendSection(self, section, text):
-        # self.sections[section].append('SECTION: ' + section + '\n')
-        self.sections[section].append(text)
-    #
-    # Type generation
-    def genType(self, typeinfo, name):
-        OutputGenerator.genType(self, typeinfo, name)
-        typeElem = typeinfo.elem
-        # If the type is a struct type, traverse the imbedded <member> tags
-        # generating a structure. Otherwise, emit the tag text.
-        category = typeElem.get('category')
-        if (category == 'struct' or category == 'union'):
-            self.structNames.append(name)
-            self.genStruct(typeinfo, name)
-        elif (category == 'handle'):
-            self.handleTypes.add(name)
-        elif (category == 'bitmask'):
-            self.flags.add(name)
-        elif (category == 'define'):
-            if name == 'VK_HEADER_VERSION':
-                nameElem = typeElem.find('name')
-                self.headerVersion = noneStr(nameElem.tail).strip()
-    #
-    # Struct parameter check generation.
-    # This is a special case of the <type> tag where the contents are
-    # interpreted as a set of <member> tags instead of freeform C
-    # C type declarations. The <member> tags are just like <param>
-    # tags - they are a declaration of a struct or union member.
-    # Only simple member declarations are supported (no nested
-    # structs etc.)
-    def genStruct(self, typeinfo, typeName):
-        OutputGenerator.genStruct(self, typeinfo, typeName)
-        conditions = self.structMemberValidationConditions[typeName] if typeName in self.structMemberValidationConditions else None
-        members = typeinfo.elem.findall('.//member')
-        #
-        # Iterate over members once to get length parameters for arrays
-        lens = set()
-        for member in members:
-            len = self.getLen(member)
-            if len:
-                lens.add(len)
-        #
-        # Generate member info
-        membersInfo = []
-        for member in members:
-            # Get the member's type and name
-            info = self.getTypeNameTuple(member)
-            type = info[0]
-            name = info[1]
-            stypeValue = ''
-            cdecl = self.makeCParamDecl(member, 0)
-            # Process VkStructureType
-            if type == 'VkStructureType':
-                # Extract the required struct type value from the comments
-                # embedded in the original text defining the 'typeinfo' element
-                rawXml = etree.tostring(typeinfo.elem).decode('ascii')
-                result = re.search(r'VK_STRUCTURE_TYPE_\w+', rawXml)
-                if result:
-                    value = result.group(0)
-                else:
-                    value = self.genVkStructureType(typeName)
-                # Store the required type value
-                self.structTypes[typeName] = self.StructType(name=name, value=value)
-            #
-            # Store pointer/array/string info
-            # Check for parameter name in lens set
-            iscount = False
-            if name in lens:
-                iscount = True
-            # The pNext members are not tagged as optional, but are treated as
-            # optional for parameter NULL checks.  Static array members
-            # are also treated as optional to skip NULL pointer validation, as
-            # they won't be NULL.
-            isstaticarray = self.paramIsStaticArray(member)
-            isoptional = False
-            if self.paramIsOptional(member) or (name == 'pNext') or (isstaticarray):
-                isoptional = True
-            membersInfo.append(self.CommandParam(type=type, name=name,
-                                                ispointer=self.paramIsPointer(member),
-                                                isstaticarray=isstaticarray,
-                                                isbool=True if type == 'VkBool32' else False,
-                                                israngedenum=True if type in self.enumRanges else False,
-                                                isconst=True if 'const' in cdecl else False,
-                                                isoptional=isoptional,
-                                                iscount=iscount,
-                                                noautovalidity=True if member.attrib.get('noautovalidity') is not None else False,
-                                                len=self.getLen(member),
-                                                extstructs=member.attrib.get('validextensionstructs') if name == 'pNext' else None,
-                                                condition=conditions[name] if conditions and name in conditions else None,
-                                                cdecl=cdecl))
-        self.structMembers.append(self.StructMemberData(name=typeName, members=membersInfo))
-    #
-    # Capture group (e.g. C "enum" type) info to be used for
-    # param check code generation.
-    # These are concatenated together with other types.
-    def genGroup(self, groupinfo, groupName):
-        OutputGenerator.genGroup(self, groupinfo, groupName)
-        groupElem = groupinfo.elem
-        #
-        # Store the sType values
-        if groupName == 'VkStructureType':
-            for elem in groupElem.findall('enum'):
-                self.stypes.append(elem.get('name'))
-        elif 'FlagBits' in groupName:
-            bits = []
-            for elem in groupElem.findall('enum'):
-                bits.append(elem.get('name'))
-            if bits:
-                self.flagBits[groupName] = bits
-        else:
-            # Determine if begin/end ranges are needed (we don't do this for VkStructureType, which has a more finely grained check)
-            expandName = re.sub(r'([0-9a-z_])([A-Z0-9][^A-Z0-9]?)',r'\1_\2',groupName).upper()
-            expandPrefix = expandName
-            expandSuffix = ''
-            expandSuffixMatch = re.search(r'[A-Z][A-Z]+$',groupName)
-            if expandSuffixMatch:
-                expandSuffix = '_' + expandSuffixMatch.group()
-                # Strip off the suffix from the prefix
-                expandPrefix = expandName.rsplit(expandSuffix, 1)[0]
-            isEnum = ('FLAG_BITS' not in expandPrefix)
-            if isEnum:
-                self.enumRanges[groupName] = (expandPrefix + '_BEGIN_RANGE' + expandSuffix, expandPrefix + '_END_RANGE' + expandSuffix)
-    #
-    # Capture command parameter info to be used for param
-    # check code generation.
-    def genCmd(self, cmdinfo, name):
-        OutputGenerator.genCmd(self, cmdinfo, name)
-        if name not in self.blacklist:
-            params = cmdinfo.elem.findall('param')
-            # Get list of array lengths
-            lens = set()
-            for param in params:
-                len = self.getLen(param)
-                if len:
-                    lens.add(len)
-            # Get param info
-            paramsInfo = []
-            for param in params:
-                paramInfo = self.getTypeNameTuple(param)
-                cdecl = self.makeCParamDecl(param, 0)
-                # Check for parameter name in lens set
-                iscount = False
-                if paramInfo[1] in lens:
-                    iscount = True
-                paramsInfo.append(self.CommandParam(type=paramInfo[0], name=paramInfo[1],
-                                                    ispointer=self.paramIsPointer(param),
-                                                    isstaticarray=self.paramIsStaticArray(param),
-                                                    isbool=True if paramInfo[0] == 'VkBool32' else False,
-                                                    israngedenum=True if paramInfo[0] in self.enumRanges else False,
-                                                    isconst=True if 'const' in cdecl else False,
-                                                    isoptional=self.paramIsOptional(param),
-                                                    iscount=iscount,
-                                                    noautovalidity=True if param.attrib.get('noautovalidity') is not None else False,
-                                                    len=self.getLen(param),
-                                                    extstructs=None,
-                                                    condition=None,
-                                                    cdecl=cdecl))
-            self.commands.append(self.CommandData(name=name, params=paramsInfo, cdecl=self.makeCDecls(cmdinfo.elem)[0]))
-    #
-    # Check if the parameter passed in is a pointer
-    def paramIsPointer(self, param):
-        ispointer = 0
-        paramtype = param.find('type')
-        if (paramtype.tail is not None) and ('*' in paramtype.tail):
-            ispointer = paramtype.tail.count('*')
-        elif paramtype.text[:4] == 'PFN_':
-            # Treat function pointer typedefs as a pointer to a single value
-            ispointer = 1
-        return ispointer
-    #
-    # Check if the parameter passed in is a static array
-    def paramIsStaticArray(self, param):
-        isstaticarray = 0
-        paramname = param.find('name')
-        if (paramname.tail is not None) and ('[' in paramname.tail):
-            isstaticarray = paramname.tail.count('[')
-        return isstaticarray
-    #
-    # Check if the parameter passed in is optional
-    # Returns a list of Boolean values for comma separated len attributes (len='false,true')
-    def paramIsOptional(self, param):
-        # See if the handle is optional
-        isoptional = False
-        # Simple, if it's optional, return true
-        optString = param.attrib.get('optional')
-        if optString:
-            if optString == 'true':
-                isoptional = True
-            elif ',' in optString:
-                opts = []
-                for opt in optString.split(','):
-                    val = opt.strip()
-                    if val == 'true':
-                        opts.append(True)
-                    elif val == 'false':
-                        opts.append(False)
-                    else:
-                        print('Unrecognized len attribute value',val)
-                isoptional = opts
-        return isoptional
-    #
-    # Check if the handle passed in is optional
-    # Uses the same logic as ValidityOutputGenerator.isHandleOptional
-    def isHandleOptional(self, param, lenParam):
-        # Simple, if it's optional, return true
-        if param.isoptional:
-            return True
-        # If no validity is being generated, it usually means that validity is complex and not absolute, so let's say yes.
-        if param.noautovalidity:
-            return True
-        # If the parameter is an array and we haven't already returned, find out if any of the len parameters are optional
-        if lenParam and lenParam.isoptional:
-            return True
-        return False
-    #
-    # Generate a VkStructureType based on a structure typename
-    def genVkStructureType(self, typename):
-        # Add underscore between lowercase then uppercase
-        value = re.sub('([a-z0-9])([A-Z])', r'\1_\2', typename)
-        # Change to uppercase
-        value = value.upper()
-        # Add STRUCTURE_TYPE_
-        return re.sub('VK_', 'VK_STRUCTURE_TYPE_', value)
-    #
-    # Get the cached VkStructureType value for the specified struct typename, or generate a VkStructureType
-    # value assuming the struct is defined by a different feature
-    def getStructType(self, typename):
-        value = None
-        if typename in self.structTypes:
-            value = self.structTypes[typename].value
-        else:
-            value = self.genVkStructureType(typename)
-            self.logMsg('diag', 'ParameterValidation: Generating {} for {} structure type that was not defined by the current feature'.format(value, typename))
-        return value
-    #
-    # Retrieve the value of the len tag
-    def getLen(self, param):
-        result = None
-        len = param.attrib.get('len')
-        if len and len != 'null-terminated':
-            # For string arrays, 'len' can look like 'count,null-terminated',
-            # indicating that we have a null terminated array of strings.  We
-            # strip the null-terminated from the 'len' field and only return
-            # the parameter specifying the string count
-            if 'null-terminated' in len:
-                result = len.split(',')[0]
-            else:
-                result = len
-            result = str(result).replace('::', '->')
-        return result
-    #
-    # Retrieve the type and name for a parameter
-    def getTypeNameTuple(self, param):
-        type = ''
-        name = ''
-        for elem in param:
-            if elem.tag == 'type':
-                type = noneStr(elem.text)
-            elif elem.tag == 'name':
-                name = noneStr(elem.text)
-        return (type, name)
-    #
-    # Find a named parameter in a parameter list
-    def getParamByName(self, params, name):
-        for param in params:
-            if param.name == name:
-                return param
-        return None
-    #
-    # Extract length values from latexmath.  Currently an inflexible solution that looks for specific
-    # patterns that are found in vk.xml.  Will need to be updated when new patterns are introduced.
-    def parseLateXMath(self, source):
-        name = 'ERROR'
-        decoratedName = 'ERROR'
-        if 'mathit' in source:
-            # Matches expressions similar to 'latexmath:[$\lceil{\mathit{rasterizationSamples} \over 32}\rceil$]'
-            match = re.match(r'latexmath\s*\:\s*\[\s*\$\\l(\w+)\s*\{\s*\\mathit\s*\{\s*(\w+)\s*\}\s*\\over\s*(\d+)\s*\}\s*\\r(\w+)\$\s*\]', source)
-            if not match or match.group(1) != match.group(4):
-                raise 'Unrecognized latexmath expression'
-            name = match.group(2)
-            decoratedName = '{}({}/{})'.format(*match.group(1, 2, 3))
-        else:
-            # Matches expressions similar to 'latexmath : [$dataSize \over 4$]'
-            match = re.match(r'latexmath\s*\:\s*\[\s*\$\s*(\w+)\s*\\over\s*(\d+)\s*\$\s*\]', source)
-            name = match.group(1)
-            decoratedName = '{}/{}'.format(*match.group(1, 2))
-        return name, decoratedName
-    #
-    # Get the length paramater record for the specified parameter name
-    def getLenParam(self, params, name):
-        lenParam = None
-        if name:
-            if '->' in name:
-                # The count is obtained by dereferencing a member of a struct parameter
-                lenParam = self.CommandParam(name=name, iscount=True, ispointer=False, isbool=False, israngedenum=False, isconst=False,
-                                             isstaticarray=None, isoptional=False, type=None, noautovalidity=False, len=None, extstructs=None,
-                                             condition=None, cdecl=None)
-            elif 'latexmath' in name:
-                lenName, decoratedName = self.parseLateXMath(name)
-                lenParam = self.getParamByName(params, lenName)
-                # TODO: Zero-check the result produced by the equation?
-                # Copy the stored len parameter entry and overwrite the name with the processed latexmath equation
-                #param = self.getParamByName(params, lenName)
-                #lenParam = self.CommandParam(name=decoratedName, iscount=param.iscount, ispointer=param.ispointer,
-                #                             isoptional=param.isoptional, type=param.type, len=param.len,
-                #                             isstaticarray=param.isstaticarray, extstructs=param.extstructs,
-                #                             noautovalidity=True, condition=None, cdecl=param.cdecl)
-            else:
-                lenParam = self.getParamByName(params, name)
-        return lenParam
-    #
-    # Convert a vulkan.h command declaration into a parameter_validation.h definition
-    def getCmdDef(self, cmd):
-        #
-        # Strip the trailing ';' and split into individual lines
-        lines = cmd.cdecl[:-1].split('\n')
-        # Replace Vulkan prototype
-        lines[0] = 'static bool parameter_validation_' + cmd.name + '('
-        # Replace the first argument with debug_report_data, when the first
-        # argument is a handle (not vkCreateInstance)
-        reportData = '    debug_report_data*'.ljust(self.genOpts.alignFuncParam) + 'report_data,'
-        if cmd.name != 'vkCreateInstance':
-            lines[1] = reportData
-        else:
-            lines.insert(1, reportData)
-        return '\n'.join(lines)
-    #
-    # Generate the code to check for a NULL dereference before calling the
-    # validation function
-    def genCheckedLengthCall(self, name, exprs):
-        count = name.count('->')
-        if count:
-            checkedExpr = []
-            localIndent = ''
-            elements = name.split('->')
-            # Open the if expression blocks
-            for i in range(0, count):
-                checkedExpr.append(localIndent + 'if ({} != NULL) {{\n'.format('->'.join(elements[0:i+1])))
-                localIndent = self.incIndent(localIndent)
-            # Add the validation expression
-            for expr in exprs:
-                checkedExpr.append(localIndent + expr)
-            # Close the if blocks
-            for i in range(0, count):
-                localIndent = self.decIndent(localIndent)
-                checkedExpr.append(localIndent + '}\n')
-            return [checkedExpr]
-        # No if statements were required
-        return exprs
-    #
-    # Generate code to check for a specific condition before executing validation code
-    def genConditionalCall(self, prefix, condition, exprs):
-        checkedExpr = []
-        localIndent = ''
-        formattedCondition = condition.format(prefix)
-        checkedExpr.append(localIndent + 'if ({})\n'.format(formattedCondition))
-        checkedExpr.append(localIndent + '{\n')
-        localIndent = self.incIndent(localIndent)
-        for expr in exprs:
-            checkedExpr.append(localIndent + expr)
-        localIndent = self.decIndent(localIndent)
-        checkedExpr.append(localIndent + '}\n')
-        return [checkedExpr]
-    #
-    # Generate the sType check string
-    def makeStructTypeCheck(self, prefix, value, lenValue, valueRequired, lenValueRequired, lenPtrRequired, funcPrintName, lenPrintName, valuePrintName, postProcSpec):
-        checkExpr = []
-        stype = self.structTypes[value.type]
-        if lenValue:
-            # This is an array with a pointer to a count value
-            if lenValue.ispointer:
-                # When the length parameter is a pointer, there is an extra Boolean parameter in the function call to indicate if it is required
-                checkExpr.append('skipCall |= validate_struct_type_array(report_data, "{}", {ppp}"{ldn}"{pps}, {ppp}"{dn}"{pps}, "{sv}", {pf}{ln}, {pf}{vn}, {sv}, {}, {}, {});\n'.format(
-                    funcPrintName, lenPtrRequired, lenValueRequired, valueRequired, ln=lenValue.name, ldn=lenPrintName, dn=valuePrintName, vn=value.name, sv=stype.value, pf=prefix, **postProcSpec))
-            # This is an array with an integer count value
-            else:
-                checkExpr.append('skipCall |= validate_struct_type_array(report_data, "{}", {ppp}"{ldn}"{pps}, {ppp}"{dn}"{pps}, "{sv}", {pf}{ln}, {pf}{vn}, {sv}, {}, {});\n'.format(
-                    funcPrintName, lenValueRequired, valueRequired, ln=lenValue.name, ldn=lenPrintName, dn=valuePrintName, vn=value.name, sv=stype.value, pf=prefix, **postProcSpec))
-        # This is an individual struct
-        else:
-            checkExpr.append('skipCall |= validate_struct_type(report_data, "{}", {ppp}"{}"{pps}, "{sv}", {}{vn}, {sv}, {});\n'.format(
-                funcPrintName, valuePrintName, prefix, valueRequired, vn=value.name, sv=stype.value, **postProcSpec))
-        return checkExpr
-    #
-    # Generate the handle check string
-    def makeHandleCheck(self, prefix, value, lenValue, valueRequired, lenValueRequired, funcPrintName, lenPrintName, valuePrintName, postProcSpec):
-        checkExpr = []
-        if lenValue:
-            if lenValue.ispointer:
-                # This is assumed to be an output array with a pointer to a count value
-                raise('Unsupported parameter validation case: Output handle array elements are not NULL checked')
-            else:
-                # This is an array with an integer count value
-                checkExpr.append('skipCall |= validate_handle_array(report_data, "{}", {ppp}"{ldn}"{pps}, {ppp}"{dn}"{pps}, {pf}{ln}, {pf}{vn}, {}, {});\n'.format(
-                    funcPrintName, lenValueRequired, valueRequired, ln=lenValue.name, ldn=lenPrintName, dn=valuePrintName, vn=value.name, pf=prefix, **postProcSpec))
-        else:
-            # This is assumed to be an output handle pointer
-            raise('Unsupported parameter validation case: Output handles are not NULL checked')
-        return checkExpr
-    #
-    # Generate check string for an array of VkFlags values
-    def makeFlagsArrayCheck(self, prefix, value, lenValue, valueRequired, lenValueRequired, funcPrintName, lenPrintName, valuePrintName, postProcSpec):
-        checkExpr = []
-        flagBitsName = value.type.replace('Flags', 'FlagBits')
-        if not flagBitsName in self.flagBits:
-            raise('Unsupported parameter validation case: array of reserved VkFlags')
-        else:
-            allFlags = 'All' + flagBitsName
-            checkExpr.append('skipCall |= validate_flags_array(report_data, "{}", {ppp}"{}"{pps}, {ppp}"{}"{pps}, "{}", {}, {pf}{}, {pf}{}, {}, {});\n'.format(funcPrintName, lenPrintName, valuePrintName, flagBitsName, allFlags, lenValue.name, value.name, lenValueRequired, valueRequired, pf=prefix, **postProcSpec))
-        return checkExpr
-    #
-    # Generate pNext check string
-    def makeStructNextCheck(self, prefix, value, funcPrintName, valuePrintName, postProcSpec):
-        checkExpr = []
-        # Generate an array of acceptable VkStructureType values for pNext
-        extStructCount = 0
-        extStructVar = 'NULL'
-        extStructNames = 'NULL'
-        if value.extstructs:
-            structs = value.extstructs.split(',')
-            checkExpr.append('const VkStructureType allowedStructs[] = {' + ', '.join([self.getStructType(s) for s in structs]) + '};\n')
-            extStructCount = 'ARRAY_SIZE(allowedStructs)'
-            extStructVar = 'allowedStructs'
-            extStructNames = '"' + ', '.join(structs) + '"'
-        checkExpr.append('skipCall |= validate_struct_pnext(report_data, "{}", {ppp}"{}"{pps}, {}, {}{}, {}, {}, GeneratedHeaderVersion);\n'.format(
-            funcPrintName, valuePrintName, extStructNames, prefix, value.name, extStructCount, extStructVar, **postProcSpec))
-        return checkExpr
-    #
-    # Generate the pointer check string
-    def makePointerCheck(self, prefix, value, lenValue, valueRequired, lenValueRequired, lenPtrRequired, funcPrintName, lenPrintName, valuePrintName, postProcSpec):
-        checkExpr = []
-        if lenValue:
-            # This is an array with a pointer to a count value
-            if lenValue.ispointer:
-                # If count and array parameters are optional, there will be no validation
-                if valueRequired == 'true' or lenPtrRequired == 'true' or lenValueRequired == 'true':
-                    # When the length parameter is a pointer, there is an extra Boolean parameter in the function call to indicate if it is required
-                    checkExpr.append('skipCall |= validate_array(report_data, "{}", {ppp}"{ldn}"{pps}, {ppp}"{dn}"{pps}, {pf}{ln}, {pf}{vn}, {}, {}, {});\n'.format(
-                        funcPrintName, lenPtrRequired, lenValueRequired, valueRequired, ln=lenValue.name, ldn=lenPrintName, dn=valuePrintName, vn=value.name, pf=prefix, **postProcSpec))
-            # This is an array with an integer count value
-            else:
-                # If count and array parameters are optional, there will be no validation
-                if valueRequired == 'true' or lenValueRequired == 'true':
-                    # Arrays of strings receive special processing
-                    validationFuncName = 'validate_array' if value.type != 'char' else 'validate_string_array'
-                    checkExpr.append('skipCall |= {}(report_data, "{}", {ppp}"{ldn}"{pps}, {ppp}"{dn}"{pps}, {pf}{ln}, {pf}{vn}, {}, {});\n'.format(
-                        validationFuncName, funcPrintName, lenValueRequired, valueRequired, ln=lenValue.name, ldn=lenPrintName, dn=valuePrintName, vn=value.name, pf=prefix, **postProcSpec))
-            if checkExpr:
-                if lenValue and ('->' in lenValue.name):
-                    # Add checks to ensure the validation call does not dereference a NULL pointer to obtain the count
-                    checkExpr = self.genCheckedLengthCall(lenValue.name, checkExpr)
-        # This is an individual struct that is not allowed to be NULL
-        elif not value.isoptional:
-            # Function pointers need a reinterpret_cast to void*
-            if value.type[:4] == 'PFN_':
-                checkExpr.append('skipCall |= validate_required_pointer(report_data, "{}", {ppp}"{}"{pps}, reinterpret_cast<const void*>({}{}));\n'.format(funcPrintName, valuePrintName, prefix, value.name, **postProcSpec))
-            else:
-                checkExpr.append('skipCall |= validate_required_pointer(report_data, "{}", {ppp}"{}"{pps}, {}{});\n'.format(funcPrintName, valuePrintName, prefix, value.name, **postProcSpec))
-        return checkExpr
-    #
-    # Process struct member validation code, performing name suibstitution if required
-    def processStructMemberCode(self, line, funcName, memberNamePrefix, memberDisplayNamePrefix, postProcSpec):
-        # Build format specifier list
-        kwargs = {}
-        if '{postProcPrefix}' in line:
-            # If we have a tuple that includes a format string and format parameters, need to use ParameterName class
-            if type(memberDisplayNamePrefix) is tuple:
-                kwargs['postProcPrefix'] = 'ParameterName('
-            else:
-                kwargs['postProcPrefix'] = postProcSpec['ppp']
-        if '{postProcSuffix}' in line:
-            # If we have a tuple that includes a format string and format parameters, need to use ParameterName class
-            if type(memberDisplayNamePrefix) is tuple:
-                kwargs['postProcSuffix'] = ', ParameterName::IndexVector{{ {}{} }})'.format(postProcSpec['ppi'], memberDisplayNamePrefix[1])
-            else:
-                kwargs['postProcSuffix'] = postProcSpec['pps']
-        if '{postProcInsert}' in line:
-            # If we have a tuple that includes a format string and format parameters, need to use ParameterName class
-            if type(memberDisplayNamePrefix) is tuple:
-                kwargs['postProcInsert'] = '{}{}, '.format(postProcSpec['ppi'], memberDisplayNamePrefix[1])
-            else:
-                kwargs['postProcInsert'] = postProcSpec['ppi']
-        if '{funcName}' in line:
-            kwargs['funcName'] = funcName
-        if '{valuePrefix}' in line:
-            kwargs['valuePrefix'] = memberNamePrefix
-        if '{displayNamePrefix}' in line:
-            # Check for a tuple that includes a format string and format parameters to be used with the ParameterName class
-            if type(memberDisplayNamePrefix) is tuple:
-                kwargs['displayNamePrefix'] = memberDisplayNamePrefix[0]
-            else:
-                kwargs['displayNamePrefix'] = memberDisplayNamePrefix
-
-        if kwargs:
-            # Need to escape the C++ curly braces
-            if 'IndexVector' in line:
-                line = line.replace('IndexVector{ ', 'IndexVector{{ ')
-                line = line.replace(' }),', ' }}),')
-            return line.format(**kwargs)
-        return line
-    #
-    # Process struct validation code for inclusion in function or parent struct validation code
-    def expandStructCode(self, lines, funcName, memberNamePrefix, memberDisplayNamePrefix, indent, output, postProcSpec):
-        for line in lines:
-            if output:
-                output[-1] += '\n'
-            if type(line) is list:
-                for sub in line:
-                    output.append(self.processStructMemberCode(indent + sub, funcName, memberNamePrefix, memberDisplayNamePrefix, postProcSpec))
-            else:
-                output.append(self.processStructMemberCode(indent + line, funcName, memberNamePrefix, memberDisplayNamePrefix, postProcSpec))
-        return output
-    #
-    # Process struct pointer/array validation code, perfoeming name substitution if required
-    def expandStructPointerCode(self, prefix, value, lenValue, funcName, valueDisplayName, postProcSpec):
-        expr = []
-        expr.append('if ({}{} != NULL)\n'.format(prefix, value.name))
-        expr.append('{')
-        indent = self.incIndent(None)
-        if lenValue:
-            # Need to process all elements in the array
-            indexName = lenValue.name.replace('Count', 'Index')
-            expr[-1] += '\n'
-            expr.append(indent + 'for (uint32_t {iname} = 0; {iname} < {}{}; ++{iname})\n'.format(prefix, lenValue.name, iname=indexName))
-            expr.append(indent + '{')
-            indent = self.incIndent(indent)
-            # Prefix for value name to display in error message
-            memberNamePrefix = '{}{}[{}].'.format(prefix, value.name, indexName)
-            memberDisplayNamePrefix = ('{}[%i].'.format(valueDisplayName), indexName)
-        else:
-            memberNamePrefix = '{}{}->'.format(prefix, value.name)
-            memberDisplayNamePrefix = '{}->'.format(valueDisplayName)
-        #
-        # Expand the struct validation lines
-        expr = self.expandStructCode(self.validatedStructs[value.type], funcName, memberNamePrefix, memberDisplayNamePrefix, indent, expr, postProcSpec)
-        #
-        if lenValue:
-            # Close if and for scopes
-            indent = self.decIndent(indent)
-            expr.append(indent + '}\n')
-        expr.append('}\n')
-        return expr
-    #
-    # Generate the parameter checking code
-    def genFuncBody(self, funcName, values, valuePrefix, displayNamePrefix, structTypeName):
-        lines = []    # Generated lines of code
-        unused = []   # Unused variable names
-        for value in values:
-            usedLines = []
-            lenParam = None
-            #
-            # Prefix and suffix for post processing of parameter names for struct members.  Arrays of structures need special processing to include the array index in the full parameter name.
-            postProcSpec = {}
-            postProcSpec['ppp'] = '' if not structTypeName else '{postProcPrefix}'
-            postProcSpec['pps'] = '' if not structTypeName else '{postProcSuffix}'
-            postProcSpec['ppi'] = '' if not structTypeName else '{postProcInsert}'
-            #
-            # Generate the full name of the value, which will be printed in the error message, by adding the variable prefix to the value name
-            valueDisplayName = '{}{}'.format(displayNamePrefix, value.name)
-            #
-            # Check for NULL pointers, ignore the inout count parameters that
-            # will be validated with their associated array
-            if (value.ispointer or value.isstaticarray) and not value.iscount:
-                #
-                # Parameters for function argument generation
-                req = 'true'    # Paramerter cannot be NULL
-                cpReq = 'true'  # Count pointer cannot be NULL
-                cvReq = 'true'  # Count value cannot be 0
-                lenDisplayName = None # Name of length parameter to print with validation messages; parameter name with prefix applied
-                #
-                # Generate required/optional parameter strings for the pointer and count values
-                if value.isoptional:
-                    req = 'false'
-                if value.len:
-                    # The parameter is an array with an explicit count parameter
-                    lenParam = self.getLenParam(values, value.len)
-                    lenDisplayName = '{}{}'.format(displayNamePrefix, lenParam.name)
-                    if lenParam.ispointer:
-                        # Count parameters that are pointers are inout
-                        if type(lenParam.isoptional) is list:
-                            if lenParam.isoptional[0]:
-                                cpReq = 'false'
-                            if lenParam.isoptional[1]:
-                                cvReq = 'false'
-                        else:
-                            if lenParam.isoptional:
-                                cpReq = 'false'
-                    else:
-                        if lenParam.isoptional:
-                            cvReq = 'false'
-                #
-                # The parameter will not be processes when tagged as 'noautovalidity'
-                # For the pointer to struct case, the struct pointer will not be validated, but any
-                # members not tagged as 'noatuvalidity' will be validated
-                if value.noautovalidity:
-                    # Log a diagnostic message when validation cannot be automatically generated and must be implemented manually
-                    self.logMsg('diag', 'ParameterValidation: No validation for {} {}'.format(structTypeName if structTypeName else funcName, value.name))
-                else:
-                    #
-                    # If this is a pointer to a struct with an sType field, verify the type
-                    if value.type in self.structTypes:
-                        usedLines += self.makeStructTypeCheck(valuePrefix, value, lenParam, req, cvReq, cpReq, funcName, lenDisplayName, valueDisplayName, postProcSpec)
-                    # If this is an input handle array that is not allowed to contain NULL handles, verify that none of the handles are VK_NULL_HANDLE
-                    elif value.type in self.handleTypes and value.isconst and not self.isHandleOptional(value, lenParam):
-                        usedLines += self.makeHandleCheck(valuePrefix, value, lenParam, req, cvReq, funcName, lenDisplayName, valueDisplayName, postProcSpec)
-                    elif value.type in self.flags and value.isconst:
-                        usedLines += self.makeFlagsArrayCheck(valuePrefix, value, lenParam, req, cvReq, funcName, lenDisplayName, valueDisplayName, postProcSpec)
-                    elif value.isbool and value.isconst:
-                        usedLines.append('skipCall |= validate_bool32_array(report_data, "{}", {ppp}"{}"{pps}, {ppp}"{}"{pps}, {pf}{}, {pf}{}, {}, {});\n'.format(funcName, lenDisplayName, valueDisplayName, lenParam.name, value.name, cvReq, req, pf=valuePrefix, **postProcSpec))
-                    elif value.israngedenum and value.isconst:
-                        enumRange = self.enumRanges[value.type]
-                        usedLines.append('skipCall |= validate_ranged_enum_array(report_data, "{}", {ppp}"{}"{pps}, {ppp}"{}"{pps}, "{}", {}, {}, {pf}{}, {pf}{}, {}, {});\n'.format(funcName, lenDisplayName, valueDisplayName, value.type, enumRange[0], enumRange[1], lenParam.name, value.name, cvReq, req, pf=valuePrefix, **postProcSpec))
-                    elif value.name == 'pNext':
-                        # We need to ignore VkDeviceCreateInfo and VkInstanceCreateInfo, as the loader manipulates them in a way that is not documented in vk.xml
-                        if not structTypeName in ['VkDeviceCreateInfo', 'VkInstanceCreateInfo']:
-                            usedLines += self.makeStructNextCheck(valuePrefix, value, funcName, valueDisplayName, postProcSpec)
-                    else:
-                        usedLines += self.makePointerCheck(valuePrefix, value, lenParam, req, cvReq, cpReq, funcName, lenDisplayName, valueDisplayName, postProcSpec)
-                    #
-                    # If this is a pointer to a struct (input), see if it contains members that need to be checked
-                    if value.type in self.validatedStructs and value.isconst:
-                        usedLines.append(self.expandStructPointerCode(valuePrefix, value, lenParam, funcName, valueDisplayName, postProcSpec))
-            # Non-pointer types
-            else:
-                #
-                # The parameter will not be processes when tagged as 'noautovalidity'
-                # For the struct case, the struct type will not be validated, but any
-                # members not tagged as 'noatuvalidity' will be validated
-                if value.noautovalidity:
-                    # Log a diagnostic message when validation cannot be automatically generated and must be implemented manually
-                    self.logMsg('diag', 'ParameterValidation: No validation for {} {}'.format(structTypeName if structTypeName else funcName, value.name))
-                else:
-                    if value.type in self.structTypes:
-                        stype = self.structTypes[value.type]
-                        usedLines.append('skipCall |= validate_struct_type(report_data, "{}", {ppp}"{}"{pps}, "{sv}", &({}{vn}), {sv}, false);\n'.format(
-                            funcName, valueDisplayName, valuePrefix, vn=value.name, sv=stype.value, **postProcSpec))
-                    elif value.type in self.handleTypes:
-                        if not self.isHandleOptional(value, None):
-                            usedLines.append('skipCall |= validate_required_handle(report_data, "{}", {ppp}"{}"{pps}, {}{});\n'.format(funcName, valueDisplayName, valuePrefix, value.name, **postProcSpec))
-                    elif value.type in self.flags:
-                        flagBitsName = value.type.replace('Flags', 'FlagBits')
-                        if not flagBitsName in self.flagBits:
-                            usedLines.append('skipCall |= validate_reserved_flags(report_data, "{}", {ppp}"{}"{pps}, {pf}{});\n'.format(funcName, valueDisplayName, value.name, pf=valuePrefix, **postProcSpec))
-                        else:
-                            flagsRequired = 'false' if value.isoptional else 'true'
-                            allFlagsName = 'All' + flagBitsName
-                            usedLines.append('skipCall |= validate_flags(report_data, "{}", {ppp}"{}"{pps}, "{}", {}, {pf}{}, {});\n'.format(funcName, valueDisplayName, flagBitsName, allFlagsName, value.name, flagsRequired, pf=valuePrefix, **postProcSpec))
-                    elif value.isbool:
-                        usedLines.append('skipCall |= validate_bool32(report_data, "{}", {ppp}"{}"{pps}, {}{});\n'.format(funcName, valueDisplayName, valuePrefix, value.name, **postProcSpec))
-                    elif value.israngedenum:
-                        enumRange = self.enumRanges[value.type]
-                        usedLines.append('skipCall |= validate_ranged_enum(report_data, "{}", {ppp}"{}"{pps}, "{}", {}, {}, {}{});\n'.format(funcName, valueDisplayName, value.type, enumRange[0], enumRange[1], valuePrefix, value.name, **postProcSpec))
-                    #
-                    # If this is a struct, see if it contains members that need to be checked
-                    if value.type in self.validatedStructs:
-                        memberNamePrefix = '{}{}.'.format(valuePrefix, value.name)
-                        memberDisplayNamePrefix = '{}.'.format(valueDisplayName)
-                        usedLines.append(self.expandStructCode(self.validatedStructs[value.type], funcName, memberNamePrefix, memberDisplayNamePrefix, '', [], postProcSpec))
-            #
-            # Append the parameter check to the function body for the current command
-            if usedLines:
-                # Apply special conditional checks
-                if value.condition:
-                    usedLines = self.genConditionalCall(valuePrefix, value.condition, usedLines)
-                lines += usedLines
-            elif not value.iscount:
-                # If no expression was generated for this value, it is unreferenced by the validation function, unless
-                # it is an array count, which is indirectly referenced for array valiadation.
-                unused.append(value.name)
-        return lines, unused
-    #
-    # Generate the struct member check code from the captured data
-    def processStructMemberData(self):
-        indent = self.incIndent(None)
-        for struct in self.structMembers:
-            #
-            # The string returned by genFuncBody will be nested in an if check for a NULL pointer, so needs its indent incremented
-            lines, unused = self.genFuncBody('{funcName}', struct.members, '{valuePrefix}', '{displayNamePrefix}', struct.name)
-            if lines:
-                self.validatedStructs[struct.name] = lines
-    #
-    # Generate the command param check code from the captured data
-    def processCmdData(self):
-        indent = self.incIndent(None)
-        for command in self.commands:
-            # Skip first parameter if it is a dispatch handle (everything except vkCreateInstance)
-            startIndex = 0 if command.name == 'vkCreateInstance' else 1
-            lines, unused = self.genFuncBody(command.name, command.params[startIndex:], '', '', None)
-            if lines:
-                cmdDef = self.getCmdDef(command) + '\n'
-                cmdDef += '{\n'
-                # Process unused parameters, Ignoring the first dispatch handle parameter, which is not
-                # processed by parameter_validation (except for vkCreateInstance, which does not have a
-                # handle as its first parameter)
-                if unused:
-                    for name in unused:
-                        cmdDef += indent + 'UNUSED_PARAMETER({});\n'.format(name)
-                    if len(unused) > 0:
-                        cmdDef += '\n'
-                cmdDef += indent + 'bool skipCall = false;\n'
-                for line in lines:
-                    cmdDef += '\n'
-                    if type(line) is list:
-                        for sub in line:
-                            cmdDef += indent + sub
-                    else:
-                        cmdDef += indent + line
-                cmdDef += '\n'
-                cmdDef += indent + 'return skipCall;\n'
-                cmdDef += '}\n'
-                self.appendSection('command', cmdDef)
-
-# UniqueObjectsOutputGenerator - subclass of OutputGenerator.
-# Generates unique objects layer non-dispatchable handle-wrapping code.
-#
-# ---- methods ----
-# UniqueObjectsOutputGenerator(errFile, warnFile, diagFile) - args as for OutputGenerator. Defines additional internal state.
-# ---- methods overriding base class ----
-# beginFile(genOpts)
-# endFile()
-# beginFeature(interface, emit)
-# endFeature()
-# genCmd(cmdinfo)
-# genStruct()
-# genType()
-class UniqueObjectsOutputGenerator(OutputGenerator):
-    """Generate UniqueObjects code based on XML element attributes"""
-    # This is an ordered list of sections in the header file.
-    ALL_SECTIONS = ['command']
-    def __init__(self,
-                 errFile = sys.stderr,
-                 warnFile = sys.stderr,
-                 diagFile = sys.stdout):
-        OutputGenerator.__init__(self, errFile, warnFile, diagFile)
-        self.INDENT_SPACES = 4
-        # Commands to ignore
-        self.intercepts = []
-        # Commands which are not autogenerated but still intercepted
-        self.no_autogen_list = [
-            'vkGetDeviceProcAddr', 
-            'vkGetInstanceProcAddr',
-            'vkCreateInstance',
-            'vkDestroyInstance',
-            'vkCreateDevice',
-            'vkDestroyDevice',
-            'vkAllocateMemory',
-            'vkCreateComputePipelines',
-            'vkCreateGraphicsPipelines',
-            'vkCreateSwapchainKHR',
-            'vkGetSwapchainImagesKHR',
-            'vkEnumerateInstanceLayerProperties',
-            'vkEnumerateDeviceLayerProperties',
-            'vkEnumerateInstanceExtensionProperties',
-            ]
-        # Commands shadowed by interface functions and are not implemented
-        self.interface_functions = [
-            'vkGetPhysicalDeviceDisplayPropertiesKHR',
-            'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
-            'vkGetDisplayPlaneSupportedDisplaysKHR',
-            'vkGetDisplayModePropertiesKHR',
-            # DebugReport APIs are hooked, but handled separately in the source file
-            'vkCreateDebugReportCallbackEXT',
-            'vkDestroyDebugReportCallbackEXT',
-            'vkDebugReportMessageEXT',
-            ]
-        self.headerVersion = None
-        # Internal state - accumulators for different inner block text
-        self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
-        self.structNames = []                             # List of Vulkan struct typenames
-        self.structTypes = dict()                         # Map of Vulkan struct typename to required VkStructureType
-        self.handleTypes = set()                          # Set of handle type names
-        self.commands = []                                # List of CommandData records for all Vulkan commands
-        self.structMembers = []                           # List of StructMemberData records for all Vulkan structs
-        self.flags = set()                                # Map of flags typenames
-        # Named tuples to store struct and command data
-        self.StructType = namedtuple('StructType', ['name', 'value'])
-        self.CommandParam = namedtuple('CommandParam', ['type', 'name', 'ispointer', 'isconst', 'iscount', 'len', 'extstructs', 'cdecl', 'islocal', 'iscreate', 'isdestroy'])
-        self.CommandData = namedtuple('CommandData', ['name', 'return_type', 'params', 'cdecl'])
-        self.StructMemberData = namedtuple('StructMemberData', ['name', 'members'])
-    #
-    def incIndent(self, indent):
-        inc = ' ' * self.INDENT_SPACES
-        if indent:
-            return indent + inc
-        return inc
-    #
-    def decIndent(self, indent):
-        if indent and (len(indent) > self.INDENT_SPACES):
-            return indent[:-self.INDENT_SPACES]
-        return ''
-    #
-    # Override makeProtoName to drop the "vk" prefix
-    def makeProtoName(self, name, tail):
-        return self.genOpts.apientry + name[2:] + tail
-    #
-    # Check if the parameter passed in is a pointer to an array
-    def paramIsArray(self, param):
-        return param.attrib.get('len') is not None
-    #
-    def beginFile(self, genOpts):
-        OutputGenerator.beginFile(self, genOpts)
-        # User-supplied prefix text, if any (list of strings)
-        if (genOpts.prefixText):
-            for s in genOpts.prefixText:
-                write(s, file=self.outFile)
-        # Namespace
-        self.newline()
-        write('namespace unique_objects {', file = self.outFile)
-    #
-    def endFile(self):
-        self.newline()
-        # Record intercepted procedures
-        write('// intercepts', file=self.outFile)
-        write('struct { const char* name; PFN_vkVoidFunction pFunc;} procmap[] = {', file=self.outFile)
-        write('\n'.join(self.intercepts), file=self.outFile)
-        write('};\n', file=self.outFile)
-        self.newline()
-        write('} // namespace unique_objects', file=self.outFile)
-        if (self.genOpts.protectFile and self.genOpts.filename):
-            self.newline()
-            write('#endif', file=self.outFile)
-        # Finish processing in superclass
-        OutputGenerator.endFile(self)
-    #
-    def beginFeature(self, interface, emit):
-        # Start processing in superclass
-        OutputGenerator.beginFeature(self, interface, emit)
-        self.headerVersion = None
-        self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
-        self.structNames = []
-        self.structTypes = dict()
-        self.handleTypes = set()
-        self.commands = []
-        self.structMembers = []
-        self.cmdMembers = []
-        self.flags = set()
-        self.StructMemberData = namedtuple('StructMemberData', ['name', 'members'])
-        self.CmdMemberData = namedtuple('CmdMemberData', ['name', 'members'])
-    #
-    def endFeature(self):
-        # Actually write the interface to the output file.
-        if (self.emit):
-            self.newline()
-            if (self.featureExtraProtect != None):
-                write('#ifdef', self.featureExtraProtect, file=self.outFile)
-            # Write the unique_objects code to the file
-            if (self.sections['command']):
-                if (self.genOpts.protectProto):
-                    write(self.genOpts.protectProto,
-                          self.genOpts.protectProtoStr, file=self.outFile)
-                write('\n'.join(self.sections['command']), end='', file=self.outFile)
-            if (self.featureExtraProtect != None):
-                write('\n#endif //', self.featureExtraProtect, file=self.outFile)
-            else:
-                self.newline()
-        # Finish processing in superclass
-        OutputGenerator.endFeature(self)
-    #
-    def genType(self, typeinfo, name):
-        OutputGenerator.genType(self, typeinfo, name)
-        typeElem = typeinfo.elem
-        # If the type is a struct type, traverse the imbedded <member> tags generating a structure.
-        # Otherwise, emit the tag text.
-        category = typeElem.get('category')
-        if (category == 'struct' or category == 'union'):
-            self.structNames.append(name)
-            self.genStruct(typeinfo, name)
-    #
-    # Append a definition to the specified section
-    def appendSection(self, section, text):
-        # self.sections[section].append('SECTION: ' + section + '\n')
-        self.sections[section].append(text)
-    #
-    # Check if the parameter passed in is a pointer
-    def paramIsPointer(self, param):
-        ispointer = False
-        for elem in param:
-            if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
-                ispointer = True
-        return ispointer
-    #
-    # Get the category of a type
-    def getTypeCategory(self, typename):
-        types = self.registry.findall("types/type")
-        for elem in types:
-            if (elem.find("name") is not None and elem.find('name').text == typename) or elem.attrib.get('name') == typename:
-                return elem.attrib.get('category')
-    #
-    # Check if a parent object is dispatchable or not
-    def isHandleTypeNonDispatchable(self, handletype):
-        handle = self.registry.find("types/type/[name='" + handletype + "'][@category='handle']")
-        if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
-            return True
-        else:
-            return False
-    #
-    # Retrieve the type and name for a parameter
-    def getTypeNameTuple(self, param):
-        type = ''
-        name = ''
-        for elem in param:
-            if elem.tag == 'type':
-                type = noneStr(elem.text)
-            elif elem.tag == 'name':
-                name = noneStr(elem.text)
-        return (type, name)
-    #
-    # Retrieve the value of the len tag
-    def getLen(self, param):
-        result = None
-        len = param.attrib.get('len')
-        if len and len != 'null-terminated':
-            # For string arrays, 'len' can look like 'count,null-terminated', indicating that we
-            # have a null terminated array of strings.  We strip the null-terminated from the
-            # 'len' field and only return the parameter specifying the string count
-            if 'null-terminated' in len:
-                result = len.split(',')[0]
-            else:
-                result = len
-            # Spec has now notation for len attributes, using :: instead of platform specific pointer symbol
-            result = str(result).replace('::', '->')
-        return result
-    #
-    # Generate a VkStructureType based on a structure typename
-    def genVkStructureType(self, typename):
-        # Add underscore between lowercase then uppercase
-        value = re.sub('([a-z0-9])([A-Z])', r'\1_\2', typename)
-        # Change to uppercase
-        value = value.upper()
-        # Add STRUCTURE_TYPE_
-        return re.sub('VK_', 'VK_STRUCTURE_TYPE_', value)
-    #
-    # Struct parameter check generation.
-    # This is a special case of the <type> tag where the contents are interpreted as a set of
-    # <member> tags instead of freeform C type declarations. The <member> tags are just like
-    # <param> tags - they are a declaration of a struct or union member. Only simple member
-    # declarations are supported (no nested structs etc.)
-    def genStruct(self, typeinfo, typeName):
-        OutputGenerator.genStruct(self, typeinfo, typeName)
-        members = typeinfo.elem.findall('.//member')
-        # Iterate over members once to get length parameters for arrays
-        lens = set()
-        for member in members:
-            len = self.getLen(member)
-            if len:
-                lens.add(len)
-        # Generate member info
-        membersInfo = []
-        for member in members:
-            # Get the member's type and name
-            info = self.getTypeNameTuple(member)
-            type = info[0]
-            name = info[1]
-            cdecl = self.makeCParamDecl(member, 0)
-            # Process VkStructureType
-            if type == 'VkStructureType':
-                # Extract the required struct type value from the comments
-                # embedded in the original text defining the 'typeinfo' element
-                rawXml = etree.tostring(typeinfo.elem).decode('ascii')
-                result = re.search(r'VK_STRUCTURE_TYPE_\w+', rawXml)
-                if result:
-                    value = result.group(0)
-                else:
-                    value = self.genVkStructureType(typeName)
-                # Store the required type value
-                self.structTypes[typeName] = self.StructType(name=name, value=value)
-            # Store pointer/array/string info
-            membersInfo.append(self.CommandParam(type=type,
-                                                 name=name,
-                                                 ispointer=self.paramIsPointer(member),
-                                                 isconst=True if 'const' in cdecl else False,
-                                                 iscount=True if name in lens else False,
-                                                 len=self.getLen(member),
-                                                 extstructs=member.attrib.get('validextensionstructs') if name == 'pNext' else None,
-                                                 cdecl=cdecl,
-                                                 islocal=False,
-                                                 iscreate=False,
-                                                 isdestroy=False))
-        self.structMembers.append(self.StructMemberData(name=typeName, members=membersInfo))
-    #
-    # Insert a lock_guard line
-    def lock_guard(self, indent):
-        return '%sstd::lock_guard<std::mutex> lock(global_lock);\n' % indent
-    #
-    # Determine if a struct has an NDO as a member or an embedded member
-    def struct_contains_ndo(self, struct_item):
-        struct_member_dict = dict(self.structMembers)
-        struct_members = struct_member_dict[struct_item]
-
-        for member in struct_members:
-            if self.isHandleTypeNonDispatchable(member.type):
-                return True
-            elif member.type in struct_member_dict:
-                if self.struct_contains_ndo(member.type) == True:
-                    return True
-        return False
-    #
-    # Return list of struct members which contain, or which sub-structures contain
-    # an NDO in a given list of parameters or members
-    def getParmeterStructsWithNdos(self, item_list):
-        struct_list = set()
-        for item in item_list:
-            paramtype = item.find('type')
-            typecategory = self.getTypeCategory(paramtype.text)
-            if typecategory == 'struct':
-                if self.struct_contains_ndo(paramtype.text) == True:
-                    struct_list.add(item)
-        return struct_list
-    #
-    # Return list of non-dispatchable objects from a given list of parameters or members
-    def getNdosInParameterList(self, item_list, create_func):
-        ndo_list = set()
-        if create_func == True:
-            member_list = item_list[0:-1]
-        else:
-            member_list = item_list
-        for item in member_list:
-            if self.isHandleTypeNonDispatchable(paramtype.text):
-                ndo_list.add(item)
-        return ndo_list
-    #
-    # Generate source for creating a non-dispatchable object
-    def generate_create_ndo_code(self, indent, proto, params, cmd_info):
-        create_ndo_code = ''
-        if True in [create_txt in proto.text for create_txt in ['Create', 'Allocate']]:
-            handle_type = params[-1].find('type')
-            if self.isHandleTypeNonDispatchable(handle_type.text):
-                # Check for special case where multiple handles are returned
-                ndo_array = False
-                if cmd_info[-1].len is not None:
-                    ndo_array = True;
-                handle_name = params[-1].find('name')
-                create_ndo_code += '%sif (VK_SUCCESS == result) {\n' % (indent)
-                indent = self.incIndent(indent)
-                create_ndo_code += '%sstd::lock_guard<std::mutex> lock(global_lock);\n' % (indent)
-                ndo_dest = '*%s' % handle_name.text
-                if ndo_array == True:
-                    create_ndo_code += '%sfor (uint32_t index0 = 0; index0 < %s; index0++) {\n' % (indent, cmd_info[-1].len)
-                    indent = self.incIndent(indent)
-                    ndo_dest = '%s[index0]' % cmd_info[-1].name
-                create_ndo_code += '%suint64_t unique_id = global_unique_id++;\n' % (indent)
-                create_ndo_code += '%sdev_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t &>(%s);\n' % (indent, ndo_dest)
-                create_ndo_code += '%s%s = reinterpret_cast<%s&>(unique_id);\n' % (indent, ndo_dest, handle_type.text)
-                if ndo_array == True:
-                    indent = self.decIndent(indent)
-                    create_ndo_code += '%s}\n' % indent
-                indent = self.decIndent(indent)
-                create_ndo_code += '%s}\n' % (indent)
-        return create_ndo_code
-    #
-    # Generate source for destroying a non-dispatchable object
-    def generate_destroy_ndo_code(self, indent, proto, cmd_info):
-        destroy_ndo_code = ''
-        ndo_array = False
-        if True in [destroy_txt in proto.text for destroy_txt in ['Destroy', 'Free']]:
-            # Check for special case where multiple handles are returned
-            if cmd_info[-1].len is not None:
-                ndo_array = True;
-                param = -1
-            else:
-                param = -2
-            if self.isHandleTypeNonDispatchable(cmd_info[param].type) == True:
-                if ndo_array == True:
-                    # This API is freeing an array of handles.  Remove them from the unique_id map.
-                    destroy_ndo_code += '%sif ((VK_SUCCESS == result) && (%s)) {\n' % (indent, cmd_info[param].name)
-                    indent = self.incIndent(indent)
-                    destroy_ndo_code += '%sstd::unique_lock<std::mutex> lock(global_lock);\n' % (indent)
-                    destroy_ndo_code += '%sfor (uint32_t index0 = 0; index0 < %s; index0++) {\n' % (indent, cmd_info[param].len)
-                    indent = self.incIndent(indent)
-                    destroy_ndo_code += '%s%s handle = %s[index0];\n' % (indent, cmd_info[param].type, cmd_info[param].name)
-                    destroy_ndo_code += '%suint64_t unique_id = reinterpret_cast<uint64_t &>(handle);\n' % (indent)
-                    destroy_ndo_code += '%sdev_data->unique_id_mapping.erase(unique_id);\n' % (indent)
-                    indent = self.decIndent(indent);
-                    destroy_ndo_code += '%s}\n' % indent
-                    indent = self.decIndent(indent);
-                    destroy_ndo_code += '%s}\n' % indent
-                else:
-                    # Remove a single handle from the map
-                    destroy_ndo_code += '%sstd::unique_lock<std::mutex> lock(global_lock);\n' % (indent)
-                    destroy_ndo_code += '%suint64_t %s_id = reinterpret_cast<uint64_t &>(%s);\n' % (indent, cmd_info[param].name, cmd_info[param].name)
-                    destroy_ndo_code += '%s%s = (%s)dev_data->unique_id_mapping[%s_id];\n' % (indent, cmd_info[param].name, cmd_info[param].type, cmd_info[param].name)
-                    destroy_ndo_code += '%sdev_data->unique_id_mapping.erase(%s_id);\n' % (indent, cmd_info[param].name)
-                    destroy_ndo_code += '%slock.unlock();\n' % (indent)
-        return ndo_array, destroy_ndo_code
-
-    #
-    # Clean up local declarations
-    def cleanUpLocalDeclarations(self, indent, prefix, name, len):
-        cleanup = '%sif (local_%s%s)\n' % (indent, prefix, name)
-        if len is not None:
-            cleanup += '%s    delete[] local_%s%s;\n' % (indent, prefix, name)
-        else:
-            cleanup += '%s    delete local_%s%s;\n' % (indent, prefix, name)
-        return cleanup
-    #
-    # Output UO code for a single NDO (ndo_count is NULL) or a counted list of NDOs
-    def outputNDOs(self, ndo_type, ndo_name, ndo_count, prefix, index, indent, destroy_func, destroy_array, top_level):
-        decl_code = ''
-        pre_call_code = ''
-        post_call_code = ''
-        if ndo_count is not None:
-            if top_level == True:
-                decl_code += '%s%s *local_%s%s = NULL;\n' % (indent, ndo_type, prefix, ndo_name)
-            pre_call_code += '%s    if (%s%s) {\n' % (indent, prefix, ndo_name)
-            indent = self.incIndent(indent)
-            if top_level == True:
-                pre_call_code += '%s    local_%s%s = new %s[%s];\n' % (indent, prefix, ndo_name, ndo_type, ndo_count)
-                pre_call_code += '%s    for (uint32_t %s = 0; %s < %s; ++%s) {\n' % (indent, index, index, ndo_count, index)
-                indent = self.incIndent(indent)
-                pre_call_code += '%s    local_%s%s[%s] = (%s)dev_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(%s[%s])];\n' % (indent, prefix, ndo_name, index, ndo_type, ndo_name, index)
-            else:
-                pre_call_code += '%s    for (uint32_t %s = 0; %s < %s; ++%s) {\n' % (indent, index, index, ndo_count, index)
-                indent = self.incIndent(indent)
-                pre_call_code += '%s    %s%s[%s] = (%s)dev_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(%s%s[%s])];\n' % (indent, prefix, ndo_name, index, ndo_type, prefix, ndo_name, index)
-            indent = self.decIndent(indent)
-            pre_call_code += '%s    }\n' % indent
-            indent = self.decIndent(indent)
-            pre_call_code += '%s    }\n' % indent
-            if top_level == True:
-                post_call_code += '%sif (local_%s%s)\n' % (indent, prefix, ndo_name)
-                indent = self.incIndent(indent)
-                post_call_code += '%sdelete[] local_%s;\n' % (indent, ndo_name)
-        else:
-            if top_level == True:
-                if (destroy_func == False) or (destroy_array == True):       #### LUGMAL This line needs to be skipped for destroy_ndo and not destroy_array
-                    pre_call_code += '%s    %s = (%s)dev_data->unique_id_mapping[reinterpret_cast<uint64_t &>(%s)];\n' % (indent, ndo_name, ndo_type, ndo_name)
-            else:
-                # Make temp copy of this var with the 'local' removed. It may be better to not pass in 'local_'
-                # as part of the string and explicitly print it
-                fix = str(prefix).strip('local_');
-                pre_call_code += '%s    if (%s%s) {\n' % (indent, fix, ndo_name)
-                indent = self.incIndent(indent)
-                pre_call_code += '%s    %s%s = (%s)dev_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(%s%s)];\n' % (indent, prefix, ndo_name, ndo_type, fix, ndo_name)
-                indent = self.decIndent(indent)
-                pre_call_code += '%s    }\n' % indent
-        return decl_code, pre_call_code, post_call_code
-    #
-    # first_level_param indicates if elements are passed directly into the function else they're below a ptr/struct
-    # create_func means that this is API creates or allocates NDOs
-    # destroy_func indicates that this API destroys or frees NDOs
-    # destroy_array means that the destroy_func operated on an array of NDOs
-    def uniquify_members(self, members, indent, prefix, array_index, create_func, destroy_func, destroy_array, first_level_param):
-        decls = ''
-        pre_code = ''
-        post_code = ''
-        struct_member_dict = dict(self.structMembers)
-        index = 'index%s' % str(array_index)
-        array_index += 1
-        # Process any NDOs in this structure and recurse for any sub-structs in this struct
-        for member in members:
-            # Handle NDOs
-            if self.isHandleTypeNonDispatchable(member.type) == True:
-                count_name = member.len  
-                if (count_name is not None):
-                    if first_level_param == False:
-                        count_name = '%s%s' % (prefix, member.len)
-
-                if (first_level_param == False) or (create_func == False):
-                    (tmp_decl, tmp_pre, tmp_post) = self.outputNDOs(member.type, member.name, count_name, prefix, index, indent, destroy_func, destroy_array, first_level_param)
-                    decls += tmp_decl
-                    pre_code += tmp_pre
-                    post_code += tmp_post
-            # Handle Structs that contain NDOs at some level
-            elif member.type in struct_member_dict:
-                # All structs at first level will have an NDO
-                if self.struct_contains_ndo(member.type) == True:
-                    struct_info = struct_member_dict[member.type]
-                    # Struct Array
-                    if member.len is not None:
-                        # Update struct prefix
-                        if first_level_param == True:
-                            new_prefix = 'local_%s' % member.name
-                            # Declare safe_VarType for struct
-                            decls += '%ssafe_%s *%s = NULL;\n' % (indent, member.type, new_prefix)
-                        else:
-                            new_prefix = '%s%s' % (prefix, member.name)
-                        pre_code += '%s    if (%s%s) {\n' % (indent, prefix, member.name)
-                        indent = self.incIndent(indent)
-                        if first_level_param == True:
-                            pre_code += '%s    %s = new safe_%s[%s];\n' % (indent, new_prefix, member.type, member.len)
-                        pre_code += '%s    for (uint32_t %s = 0; %s < %s%s; ++%s) {\n' % (indent, index, index, prefix, member.len, index)
-                        indent = self.incIndent(indent)
-                        if first_level_param == True:
-                            pre_code += '%s    %s[%s].initialize(&%s[%s]);\n' % (indent, new_prefix, index, member.name, index)
-                        local_prefix = '%s[%s].' % (new_prefix, index)
-                        # Process sub-structs in this struct
-                        (tmp_decl, tmp_pre, tmp_post) = self.uniquify_members(struct_info, indent, local_prefix, array_index, create_func, destroy_func, destroy_array, False)
-                        decls += tmp_decl
-                        pre_code += tmp_pre
-                        post_code += tmp_post
-                        indent = self.decIndent(indent)
-                        pre_code += '%s    }\n' % indent
-                        indent = self.decIndent(indent)
-                        pre_code += '%s    }\n' % indent
-                        if first_level_param == True:
-                            post_code += self.cleanUpLocalDeclarations(indent, prefix, member.name, member.len)
-                    # Single Struct
-                    else:
-                        # Update struct prefix
-                        if first_level_param == True:
-                            new_prefix = 'local_%s->' % member.name
-                            decls += '%ssafe_%s *local_%s%s = NULL;\n' % (indent, member.type, prefix, member.name)
-                        else:
-                            new_prefix = '%s%s->' % (prefix, member.name)
-                        # Declare safe_VarType for struct
-                        pre_code += '%s    if (%s%s) {\n' % (indent, prefix, member.name)
-                        indent = self.incIndent(indent)
-                        if first_level_param == True:
-                            pre_code += '%s    local_%s%s = new safe_%s(%s);\n' % (indent, prefix, member.name, member.type, member.name)
-                        # Process sub-structs in this struct
-                        (tmp_decl, tmp_pre, tmp_post) = self.uniquify_members(struct_info, indent, new_prefix, array_index, create_func, destroy_func, destroy_array, False)
-                        decls += tmp_decl
-                        pre_code += tmp_pre
-                        post_code += tmp_post
-                        indent = self.decIndent(indent)
-                        pre_code += '%s    }\n' % indent
-                        if first_level_param == True:
-                            post_code += self.cleanUpLocalDeclarations(indent, prefix, member.name, member.len)
-        return decls, pre_code, post_code
-    #
-    # For a particular API, generate the non-dispatchable-object wrapping/unwrapping code
-    def generate_wrapping_code(self, cmd):
-        indent = '    '
-        proto = cmd.find('proto/name')
-        params = cmd.findall('param')
-        if proto.text is not None:
-            cmd_member_dict = dict(self.cmdMembers)
-            cmd_info = cmd_member_dict[proto.text]
-            # Handle ndo create/allocate operations
-            if cmd_info[0].iscreate:
-                create_ndo_code = self.generate_create_ndo_code(indent, proto, params, cmd_info)
-            else:
-                create_ndo_code = ''
-            # Handle ndo destroy/free operations
-            if cmd_info[0].isdestroy:
-                (destroy_array, destroy_ndo_code) = self.generate_destroy_ndo_code(indent, proto, cmd_info)
-            else:
-                destroy_array = False
-                destroy_ndo_code = ''
-            paramdecl = ''
-            param_pre_code = ''
-            param_post_code = ''
-            create_func = True if create_ndo_code else False
-            destroy_func = True if destroy_ndo_code else False
-            (paramdecl, param_pre_code, param_post_code) = self.uniquify_members(cmd_info, indent, '', 0, create_func, destroy_func, destroy_array, True)
-            param_post_code += create_ndo_code
-            if destroy_ndo_code:
-                if destroy_array == True:
-                    param_post_code += destroy_ndo_code
-                else:
-                    param_pre_code += destroy_ndo_code
-            if param_pre_code:
-                if (not destroy_func) or (destroy_array):
-                    param_pre_code = '%s{\n%s%s%s%s}\n' % ('    ', indent, self.lock_guard(indent), param_pre_code, indent)
-        return paramdecl, param_pre_code, param_post_code
-    #
-    # Capture command parameter info needed to wrap NDOs as well as handling some boilerplate code
-    def genCmd(self, cmdinfo, cmdname):
-        if cmdname in self.interface_functions:
-            return
-        if cmdname in self.no_autogen_list:
-            decls = self.makeCDecls(cmdinfo.elem)
-            self.appendSection('command', '')
-            self.appendSection('command', '// Declare only')
-            self.appendSection('command', decls[0])
-            self.intercepts += [ '    {"%s", reinterpret_cast<PFN_vkVoidFunction>(%s)},' % (cmdname,cmdname[2:]) ]
-            return
-        # Add struct-member type information to command parameter information
-        OutputGenerator.genCmd(self, cmdinfo, cmdname)
-        members = cmdinfo.elem.findall('.//param')
-        # Iterate over members once to get length parameters for arrays
-        lens = set()
-        for member in members:
-            len = self.getLen(member)
-            if len:
-                lens.add(len)
-        struct_member_dict = dict(self.structMembers)
-        # Generate member info
-        membersInfo = []
-        for member in members:
-            # Get type and name of member
-            info = self.getTypeNameTuple(member)
-            type = info[0]
-            name = info[1]
-            cdecl = self.makeCParamDecl(member, 0)
-            # Check for parameter name in lens set
-            iscount = True if name in lens else False
-            len = self.getLen(member)
-            isconst = True if 'const' in cdecl else False
-            ispointer = self.paramIsPointer(member)
-            # Mark param as local if it is an array of NDOs
-            islocal = False;
-            if self.isHandleTypeNonDispatchable(type) == True:
-                if (len is not None) and (isconst == True):
-                    islocal = True
-            # Or if it's a struct that contains an NDO
-            elif type in struct_member_dict:
-                if self.struct_contains_ndo(type) == True:
-                    islocal = True
-
-            isdestroy = True if True in [destroy_txt in cmdname for destroy_txt in ['Destroy', 'Free']] else False
-            iscreate = True if True in [create_txt in cmdname for create_txt in ['Create', 'Allocate']] else False
-
-            membersInfo.append(self.CommandParam(type=type,
-                                                 name=name,
-                                                 ispointer=ispointer,
-                                                 isconst=isconst,
-                                                 iscount=iscount,
-                                                 len=len,
-                                                 extstructs=member.attrib.get('validextensionstructs') if name == 'pNext' else None,
-                                                 cdecl=cdecl,
-                                                 islocal=islocal,
-                                                 iscreate=iscreate,
-                                                 isdestroy=isdestroy))
-        self.cmdMembers.append(self.CmdMemberData(name=cmdname, members=membersInfo))
-        # Generate NDO wrapping/unwrapping code for all parameters
-        (api_decls, api_pre, api_post) = self.generate_wrapping_code(cmdinfo.elem)
-        # If API doesn't contain an NDO's, don't fool with it
-        if not api_decls and not api_pre and not api_post:
-            return
-        # Record that the function will be intercepted
-        if (self.featureExtraProtect != None):
-            self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
-        self.intercepts += [ '    {"%s", reinterpret_cast<PFN_vkVoidFunction>(%s)},' % (cmdname,cmdname[2:]) ]
-        if (self.featureExtraProtect != None):
-            self.intercepts += [ '#endif' ]
-        decls = self.makeCDecls(cmdinfo.elem)
-        self.appendSection('command', '')
-        self.appendSection('command', decls[0][:-1])
-        self.appendSection('command', '{')
-        # Setup common to call wrappers, first parameter is always dispatchable
-        dispatchable_type = cmdinfo.elem.find('param/type').text
-        dispatchable_name = cmdinfo.elem.find('param/name').text
-        # Generate local instance/pdev/device data lookup
-        self.appendSection('command', '    layer_data *dev_data = get_my_data_ptr(get_dispatch_key('+dispatchable_name+'), layer_data_map);')
-        # Handle return values, if any
-        resulttype = cmdinfo.elem.find('proto/type')
-        if (resulttype != None and resulttype.text == 'void'):
-          resulttype = None
-        if (resulttype != None):
-            assignresult = resulttype.text + ' result = '
-        else:
-            assignresult = ''
-        # Pre-pend declarations and pre-api-call codegen
-        if api_decls:
-            self.appendSection('command', "\n".join(str(api_decls).rstrip().split("\n")))
-        if api_pre:
-            self.appendSection('command', "\n".join(str(api_pre).rstrip().split("\n")))
-        # Generate the API call itself
-        # Gather the parameter items
-        params = cmdinfo.elem.findall('param/name')
-        # Pull out the text for each of the parameters, separate them by commas in a list
-        paramstext = ', '.join([str(param.text) for param in params])
-        # If any of these paramters has been replaced by a local var, fix up the list
-        cmd_member_dict = dict(self.cmdMembers)
-        params = cmd_member_dict[cmdname]
-        for param in params:
-            if param.islocal == True:
-                if param.ispointer == True:
-                    paramstext = paramstext.replace(param.name, '(%s %s*)local_%s' % ('const', param.type, param.name))
-                else:
-                    paramstext = paramstext.replace(param.name, '(%s %s)local_%s' % ('const', param.type, param.name))
-        # Use correct dispatch table
-        if dispatchable_type in ["VkPhysicalDevice", "VkInstance"]:
-            API = cmdinfo.elem.attrib.get('name').replace('vk','dev_data->instance_dispatch_table->',1)
-        else:
-            API = cmdinfo.elem.attrib.get('name').replace('vk','dev_data->device_dispatch_table->',1)
-        # Put all this together for the final down-chain call
-        self.appendSection('command', '    ' + assignresult + API + '(' + paramstext + ');')
-        # And add the post-API-call codegen
-        self.appendSection('command', "\n".join(str(api_post).rstrip().split("\n")))
-        # Handle the return result variable, if any
-        if (resulttype != None):
-            self.appendSection('command', '    return result;')
-        self.appendSection('command', '}')