Home | History | Annotate | Download | only in smoke
      1 #!/usr/bin/env python3
      2 #
      3 # Copyright (C) 2016 Google, Inc.
      4 #
      5 # Permission is hereby granted, free of charge, to any person obtaining a
      6 # copy of this software and associated documentation files (the "Software"),
      7 # to deal in the Software without restriction, including without limitation
      8 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
      9 # and/or sell copies of the Software, and to permit persons to whom the
     10 # Software is furnished to do so, subject to the following conditions:
     11 #
     12 # The above copyright notice and this permission notice shall be included
     13 # in all copies or substantial portions of the Software.
     14 #
     15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21 # DEALINGS IN THE SOFTWARE.
     22 
     23 """Generate Vulkan dispatch table.
     24 """
     25 
     26 import os
     27 import sys
     28 
     29 class Command(object):
     30     PLATFORM = 0
     31     LOADER = 1
     32     INSTANCE = 2
     33     DEVICE = 3
     34 
     35     def __init__(self, name, dispatch):
     36         self.name = name
     37         self.dispatch = dispatch
     38         self.ty = self._get_type()
     39 
     40     @staticmethod
     41     def valid_c_typedef(c):
     42         return (c.startswith("typedef") and
     43                 c.endswith(");") and
     44                 "*PFN_vkVoidFunction" not in c)
     45 
     46     @classmethod
     47     def from_c_typedef(cls, c):
     48         name_begin = c.find("*PFN_vk") + 7
     49         name_end = c.find(")(", name_begin)
     50         name = c[name_begin:name_end]
     51 
     52         dispatch_begin = name_end + 2
     53         dispatch_end = c.find(" ", dispatch_begin)
     54         dispatch = c[dispatch_begin:dispatch_end]
     55         if not dispatch.startswith("Vk"):
     56             dispatch = None
     57 
     58         return cls(name, dispatch)
     59 
     60     def _get_type(self):
     61         if self.dispatch:
     62             if self.dispatch in ["VkDevice", "VkQueue", "VkCommandBuffer"]:
     63                 return self.DEVICE
     64             else:
     65                 return self.INSTANCE
     66         else:
     67             if self.name in ["GetInstanceProcAddr"]:
     68                 return self.PLATFORM
     69             else:
     70                 return self.LOADER
     71 
     72     def __repr__(self):
     73         return "Command(name=%s, dispatch=%s)" % \
     74                 (repr(self.name), repr(self.dispatch))
     75 
     76 class Extension(object):
     77     def __init__(self, name, version, guard=None, commands=[]):
     78         self.name = name
     79         self.version = version
     80         self.guard = guard
     81         self.commands = commands[:]
     82 
     83     def add_command(self, cmd):
     84         self.commands.append(cmd)
     85 
     86     def __repr__(self):
     87         lines = []
     88         lines.append("Extension(name=%s, version=%s, guard=%s, commands=[" %
     89                 (repr(self.name), repr(self.version), repr(self.guard)))
     90 
     91         for cmd in self.commands:
     92             lines.append("    %s," % repr(cmd))
     93 
     94         lines.append("])")
     95 
     96         return "\n".join(lines)
     97 
     98 # generated by "generate-dispatch-table parse vulkan.h"
     99 vk_core = Extension(name='VK_core', version=0, guard=None, commands=[
    100     Command(name='CreateInstance', dispatch=None),
    101     Command(name='DestroyInstance', dispatch='VkInstance'),
    102     Command(name='EnumeratePhysicalDevices', dispatch='VkInstance'),
    103     Command(name='GetPhysicalDeviceFeatures', dispatch='VkPhysicalDevice'),
    104     Command(name='GetPhysicalDeviceFormatProperties', dispatch='VkPhysicalDevice'),
    105     Command(name='GetPhysicalDeviceImageFormatProperties', dispatch='VkPhysicalDevice'),
    106     Command(name='GetPhysicalDeviceProperties', dispatch='VkPhysicalDevice'),
    107     Command(name='GetPhysicalDeviceQueueFamilyProperties', dispatch='VkPhysicalDevice'),
    108     Command(name='GetPhysicalDeviceMemoryProperties', dispatch='VkPhysicalDevice'),
    109     Command(name='GetInstanceProcAddr', dispatch='VkInstance'),
    110     Command(name='GetDeviceProcAddr', dispatch='VkDevice'),
    111     Command(name='CreateDevice', dispatch='VkPhysicalDevice'),
    112     Command(name='DestroyDevice', dispatch='VkDevice'),
    113     Command(name='EnumerateInstanceExtensionProperties', dispatch=None),
    114     Command(name='EnumerateDeviceExtensionProperties', dispatch='VkPhysicalDevice'),
    115     Command(name='EnumerateInstanceLayerProperties', dispatch=None),
    116     Command(name='EnumerateDeviceLayerProperties', dispatch='VkPhysicalDevice'),
    117     Command(name='GetDeviceQueue', dispatch='VkDevice'),
    118     Command(name='QueueSubmit', dispatch='VkQueue'),
    119     Command(name='QueueWaitIdle', dispatch='VkQueue'),
    120     Command(name='DeviceWaitIdle', dispatch='VkDevice'),
    121     Command(name='AllocateMemory', dispatch='VkDevice'),
    122     Command(name='FreeMemory', dispatch='VkDevice'),
    123     Command(name='MapMemory', dispatch='VkDevice'),
    124     Command(name='UnmapMemory', dispatch='VkDevice'),
    125     Command(name='FlushMappedMemoryRanges', dispatch='VkDevice'),
    126     Command(name='InvalidateMappedMemoryRanges', dispatch='VkDevice'),
    127     Command(name='GetDeviceMemoryCommitment', dispatch='VkDevice'),
    128     Command(name='BindBufferMemory', dispatch='VkDevice'),
    129     Command(name='BindImageMemory', dispatch='VkDevice'),
    130     Command(name='GetBufferMemoryRequirements', dispatch='VkDevice'),
    131     Command(name='GetImageMemoryRequirements', dispatch='VkDevice'),
    132     Command(name='GetImageSparseMemoryRequirements', dispatch='VkDevice'),
    133     Command(name='GetPhysicalDeviceSparseImageFormatProperties', dispatch='VkPhysicalDevice'),
    134     Command(name='QueueBindSparse', dispatch='VkQueue'),
    135     Command(name='CreateFence', dispatch='VkDevice'),
    136     Command(name='DestroyFence', dispatch='VkDevice'),
    137     Command(name='ResetFences', dispatch='VkDevice'),
    138     Command(name='GetFenceStatus', dispatch='VkDevice'),
    139     Command(name='WaitForFences', dispatch='VkDevice'),
    140     Command(name='CreateSemaphore', dispatch='VkDevice'),
    141     Command(name='DestroySemaphore', dispatch='VkDevice'),
    142     Command(name='CreateEvent', dispatch='VkDevice'),
    143     Command(name='DestroyEvent', dispatch='VkDevice'),
    144     Command(name='GetEventStatus', dispatch='VkDevice'),
    145     Command(name='SetEvent', dispatch='VkDevice'),
    146     Command(name='ResetEvent', dispatch='VkDevice'),
    147     Command(name='CreateQueryPool', dispatch='VkDevice'),
    148     Command(name='DestroyQueryPool', dispatch='VkDevice'),
    149     Command(name='GetQueryPoolResults', dispatch='VkDevice'),
    150     Command(name='CreateBuffer', dispatch='VkDevice'),
    151     Command(name='DestroyBuffer', dispatch='VkDevice'),
    152     Command(name='CreateBufferView', dispatch='VkDevice'),
    153     Command(name='DestroyBufferView', dispatch='VkDevice'),
    154     Command(name='CreateImage', dispatch='VkDevice'),
    155     Command(name='DestroyImage', dispatch='VkDevice'),
    156     Command(name='GetImageSubresourceLayout', dispatch='VkDevice'),
    157     Command(name='CreateImageView', dispatch='VkDevice'),
    158     Command(name='DestroyImageView', dispatch='VkDevice'),
    159     Command(name='CreateShaderModule', dispatch='VkDevice'),
    160     Command(name='DestroyShaderModule', dispatch='VkDevice'),
    161     Command(name='CreatePipelineCache', dispatch='VkDevice'),
    162     Command(name='DestroyPipelineCache', dispatch='VkDevice'),
    163     Command(name='GetPipelineCacheData', dispatch='VkDevice'),
    164     Command(name='MergePipelineCaches', dispatch='VkDevice'),
    165     Command(name='CreateGraphicsPipelines', dispatch='VkDevice'),
    166     Command(name='CreateComputePipelines', dispatch='VkDevice'),
    167     Command(name='DestroyPipeline', dispatch='VkDevice'),
    168     Command(name='CreatePipelineLayout', dispatch='VkDevice'),
    169     Command(name='DestroyPipelineLayout', dispatch='VkDevice'),
    170     Command(name='CreateSampler', dispatch='VkDevice'),
    171     Command(name='DestroySampler', dispatch='VkDevice'),
    172     Command(name='CreateDescriptorSetLayout', dispatch='VkDevice'),
    173     Command(name='DestroyDescriptorSetLayout', dispatch='VkDevice'),
    174     Command(name='CreateDescriptorPool', dispatch='VkDevice'),
    175     Command(name='DestroyDescriptorPool', dispatch='VkDevice'),
    176     Command(name='ResetDescriptorPool', dispatch='VkDevice'),
    177     Command(name='AllocateDescriptorSets', dispatch='VkDevice'),
    178     Command(name='FreeDescriptorSets', dispatch='VkDevice'),
    179     Command(name='UpdateDescriptorSets', dispatch='VkDevice'),
    180     Command(name='CreateFramebuffer', dispatch='VkDevice'),
    181     Command(name='DestroyFramebuffer', dispatch='VkDevice'),
    182     Command(name='CreateRenderPass', dispatch='VkDevice'),
    183     Command(name='DestroyRenderPass', dispatch='VkDevice'),
    184     Command(name='GetRenderAreaGranularity', dispatch='VkDevice'),
    185     Command(name='CreateCommandPool', dispatch='VkDevice'),
    186     Command(name='DestroyCommandPool', dispatch='VkDevice'),
    187     Command(name='ResetCommandPool', dispatch='VkDevice'),
    188     Command(name='AllocateCommandBuffers', dispatch='VkDevice'),
    189     Command(name='FreeCommandBuffers', dispatch='VkDevice'),
    190     Command(name='BeginCommandBuffer', dispatch='VkCommandBuffer'),
    191     Command(name='EndCommandBuffer', dispatch='VkCommandBuffer'),
    192     Command(name='ResetCommandBuffer', dispatch='VkCommandBuffer'),
    193     Command(name='CmdBindPipeline', dispatch='VkCommandBuffer'),
    194     Command(name='CmdSetViewport', dispatch='VkCommandBuffer'),
    195     Command(name='CmdSetScissor', dispatch='VkCommandBuffer'),
    196     Command(name='CmdSetLineWidth', dispatch='VkCommandBuffer'),
    197     Command(name='CmdSetDepthBias', dispatch='VkCommandBuffer'),
    198     Command(name='CmdSetBlendConstants', dispatch='VkCommandBuffer'),
    199     Command(name='CmdSetDepthBounds', dispatch='VkCommandBuffer'),
    200     Command(name='CmdSetStencilCompareMask', dispatch='VkCommandBuffer'),
    201     Command(name='CmdSetStencilWriteMask', dispatch='VkCommandBuffer'),
    202     Command(name='CmdSetStencilReference', dispatch='VkCommandBuffer'),
    203     Command(name='CmdBindDescriptorSets', dispatch='VkCommandBuffer'),
    204     Command(name='CmdBindIndexBuffer', dispatch='VkCommandBuffer'),
    205     Command(name='CmdBindVertexBuffers', dispatch='VkCommandBuffer'),
    206     Command(name='CmdDraw', dispatch='VkCommandBuffer'),
    207     Command(name='CmdDrawIndexed', dispatch='VkCommandBuffer'),
    208     Command(name='CmdDrawIndirect', dispatch='VkCommandBuffer'),
    209     Command(name='CmdDrawIndexedIndirect', dispatch='VkCommandBuffer'),
    210     Command(name='CmdDispatch', dispatch='VkCommandBuffer'),
    211     Command(name='CmdDispatchIndirect', dispatch='VkCommandBuffer'),
    212     Command(name='CmdCopyBuffer', dispatch='VkCommandBuffer'),
    213     Command(name='CmdCopyImage', dispatch='VkCommandBuffer'),
    214     Command(name='CmdBlitImage', dispatch='VkCommandBuffer'),
    215     Command(name='CmdCopyBufferToImage', dispatch='VkCommandBuffer'),
    216     Command(name='CmdCopyImageToBuffer', dispatch='VkCommandBuffer'),
    217     Command(name='CmdUpdateBuffer', dispatch='VkCommandBuffer'),
    218     Command(name='CmdFillBuffer', dispatch='VkCommandBuffer'),
    219     Command(name='CmdClearColorImage', dispatch='VkCommandBuffer'),
    220     Command(name='CmdClearDepthStencilImage', dispatch='VkCommandBuffer'),
    221     Command(name='CmdClearAttachments', dispatch='VkCommandBuffer'),
    222     Command(name='CmdResolveImage', dispatch='VkCommandBuffer'),
    223     Command(name='CmdSetEvent', dispatch='VkCommandBuffer'),
    224     Command(name='CmdResetEvent', dispatch='VkCommandBuffer'),
    225     Command(name='CmdWaitEvents', dispatch='VkCommandBuffer'),
    226     Command(name='CmdPipelineBarrier', dispatch='VkCommandBuffer'),
    227     Command(name='CmdBeginQuery', dispatch='VkCommandBuffer'),
    228     Command(name='CmdEndQuery', dispatch='VkCommandBuffer'),
    229     Command(name='CmdResetQueryPool', dispatch='VkCommandBuffer'),
    230     Command(name='CmdWriteTimestamp', dispatch='VkCommandBuffer'),
    231     Command(name='CmdCopyQueryPoolResults', dispatch='VkCommandBuffer'),
    232     Command(name='CmdPushConstants', dispatch='VkCommandBuffer'),
    233     Command(name='CmdBeginRenderPass', dispatch='VkCommandBuffer'),
    234     Command(name='CmdNextSubpass', dispatch='VkCommandBuffer'),
    235     Command(name='CmdEndRenderPass', dispatch='VkCommandBuffer'),
    236     Command(name='CmdExecuteCommands', dispatch='VkCommandBuffer'),
    237 ])
    238 
    239 vk_khr_surface = Extension(name='VK_KHR_surface', version=25, guard=None, commands=[
    240     Command(name='DestroySurfaceKHR', dispatch='VkInstance'),
    241     Command(name='GetPhysicalDeviceSurfaceSupportKHR', dispatch='VkPhysicalDevice'),
    242     Command(name='GetPhysicalDeviceSurfaceCapabilitiesKHR', dispatch='VkPhysicalDevice'),
    243     Command(name='GetPhysicalDeviceSurfaceFormatsKHR', dispatch='VkPhysicalDevice'),
    244     Command(name='GetPhysicalDeviceSurfacePresentModesKHR', dispatch='VkPhysicalDevice'),
    245 ])
    246 
    247 vk_khr_swapchain = Extension(name='VK_KHR_swapchain', version=67, guard=None, commands=[
    248     Command(name='CreateSwapchainKHR', dispatch='VkDevice'),
    249     Command(name='DestroySwapchainKHR', dispatch='VkDevice'),
    250     Command(name='GetSwapchainImagesKHR', dispatch='VkDevice'),
    251     Command(name='AcquireNextImageKHR', dispatch='VkDevice'),
    252     Command(name='QueuePresentKHR', dispatch='VkQueue'),
    253 ])
    254 
    255 vk_khr_display = Extension(name='VK_KHR_display', version=21, guard=None, commands=[
    256     Command(name='GetPhysicalDeviceDisplayPropertiesKHR', dispatch='VkPhysicalDevice'),
    257     Command(name='GetPhysicalDeviceDisplayPlanePropertiesKHR', dispatch='VkPhysicalDevice'),
    258     Command(name='GetDisplayPlaneSupportedDisplaysKHR', dispatch='VkPhysicalDevice'),
    259     Command(name='GetDisplayModePropertiesKHR', dispatch='VkPhysicalDevice'),
    260     Command(name='CreateDisplayModeKHR', dispatch='VkPhysicalDevice'),
    261     Command(name='GetDisplayPlaneCapabilitiesKHR', dispatch='VkPhysicalDevice'),
    262     Command(name='CreateDisplayPlaneSurfaceKHR', dispatch='VkInstance'),
    263 ])
    264 
    265 vk_khr_display_swapchain = Extension(name='VK_KHR_display_swapchain', version=9, guard=None, commands=[
    266     Command(name='CreateSharedSwapchainsKHR', dispatch='VkDevice'),
    267 ])
    268 
    269 vk_khr_xlib_surface = Extension(name='VK_KHR_xlib_surface', version=6, guard='VK_USE_PLATFORM_XLIB_KHR', commands=[
    270     Command(name='CreateXlibSurfaceKHR', dispatch='VkInstance'),
    271     Command(name='GetPhysicalDeviceXlibPresentationSupportKHR', dispatch='VkPhysicalDevice'),
    272 ])
    273 
    274 vk_khr_xcb_surface = Extension(name='VK_KHR_xcb_surface', version=6, guard='VK_USE_PLATFORM_XCB_KHR', commands=[
    275     Command(name='CreateXcbSurfaceKHR', dispatch='VkInstance'),
    276     Command(name='GetPhysicalDeviceXcbPresentationSupportKHR', dispatch='VkPhysicalDevice'),
    277 ])
    278 
    279 vk_khr_wayland_surface = Extension(name='VK_KHR_wayland_surface', version=5, guard='VK_USE_PLATFORM_WAYLAND_KHR', commands=[
    280     Command(name='CreateWaylandSurfaceKHR', dispatch='VkInstance'),
    281     Command(name='GetPhysicalDeviceWaylandPresentationSupportKHR', dispatch='VkPhysicalDevice'),
    282 ])
    283 
    284 vk_khr_mir_surface = Extension(name='VK_KHR_mir_surface', version=4, guard='VK_USE_PLATFORM_MIR_KHR', commands=[
    285     Command(name='CreateMirSurfaceKHR', dispatch='VkInstance'),
    286     Command(name='GetPhysicalDeviceMirPresentationSupportKHR', dispatch='VkPhysicalDevice'),
    287 ])
    288 
    289 vk_khr_android_surface = Extension(name='VK_KHR_android_surface', version=6, guard='VK_USE_PLATFORM_ANDROID_KHR', commands=[
    290     Command(name='CreateAndroidSurfaceKHR', dispatch='VkInstance'),
    291 ])
    292 
    293 vk_khr_win32_surface = Extension(name='VK_KHR_win32_surface', version=5, guard='VK_USE_PLATFORM_WIN32_KHR', commands=[
    294     Command(name='CreateWin32SurfaceKHR', dispatch='VkInstance'),
    295     Command(name='GetPhysicalDeviceWin32PresentationSupportKHR', dispatch='VkPhysicalDevice'),
    296 ])
    297 
    298 vk_ext_debug_report = Extension(name='VK_EXT_debug_report', version=1, guard=None, commands=[
    299     Command(name='CreateDebugReportCallbackEXT', dispatch='VkInstance'),
    300     Command(name='DestroyDebugReportCallbackEXT', dispatch='VkInstance'),
    301     Command(name='DebugReportMessageEXT', dispatch='VkInstance'),
    302 ])
    303 
    304 extensions = [
    305     vk_core,
    306     vk_khr_surface,
    307     vk_khr_swapchain,
    308     vk_khr_display,
    309     vk_khr_display_swapchain,
    310     vk_khr_xlib_surface,
    311     vk_khr_xcb_surface,
    312     vk_khr_wayland_surface,
    313     vk_khr_mir_surface,
    314     vk_khr_android_surface,
    315     vk_khr_win32_surface,
    316     vk_ext_debug_report,
    317 ]
    318 
    319 def generate_header(guard):
    320     lines = []
    321     lines.append("// This file is generated.")
    322     lines.append("#ifndef %s" % guard)
    323     lines.append("#define %s" % guard)
    324     lines.append("")
    325     lines.append("#include <vulkan/vulkan.h>")
    326     lines.append("")
    327     lines.append("namespace vk {")
    328     lines.append("")
    329 
    330     for ext in extensions:
    331         if ext.guard:
    332             lines.append("#ifdef %s" % ext.guard)
    333 
    334         lines.append("// %s" % ext.name)
    335         for cmd in ext.commands:
    336             lines.append("extern PFN_vk%s %s;" % (cmd.name, cmd.name))
    337 
    338         if ext.guard:
    339             lines.append("#endif")
    340         lines.append("")
    341 
    342     lines.append("void init_dispatch_table_top(PFN_vkGetInstanceProcAddr get_instance_proc_addr);")
    343     lines.append("void init_dispatch_table_middle(VkInstance instance, bool include_bottom);")
    344     lines.append("void init_dispatch_table_bottom(VkInstance instance, VkDevice dev);")
    345     lines.append("")
    346     lines.append("} // namespace vk")
    347     lines.append("")
    348     lines.append("#endif // %s" % guard)
    349 
    350     return "\n".join(lines)
    351 
    352 def get_proc_addr(dispatchable, cmd, guard=None):
    353     if dispatchable == "dev":
    354         func = "GetDeviceProcAddr"
    355     else:
    356         func = "GetInstanceProcAddr"
    357 
    358     c = "    %s = reinterpret_cast<PFN_vk%s>(%s(%s, \"vk%s\"));" % \
    359             (cmd.name, cmd.name, func, dispatchable, cmd.name)
    360 
    361     if guard:
    362         c = ("#ifdef %s\n" % guard) + c + "\n#endif"
    363 
    364     return c
    365 
    366 def generate_source(header):
    367     lines = []
    368     lines.append("// This file is generated.")
    369     lines.append("#include \"%s\"" % header)
    370     lines.append("")
    371     lines.append("namespace vk {")
    372     lines.append("")
    373 
    374     commands_by_types = {}
    375     get_instance_proc_addr = None
    376     get_device_proc_addr = None
    377     for ext in extensions:
    378         if ext.guard:
    379             lines.append("#ifdef %s" % ext.guard)
    380 
    381         for cmd in ext.commands:
    382             lines.append("PFN_vk%s %s;" % (cmd.name, cmd.name))
    383 
    384             if cmd.ty not in commands_by_types:
    385                 commands_by_types[cmd.ty] = []
    386             commands_by_types[cmd.ty].append([cmd, ext.guard])
    387 
    388             if cmd.name == "GetInstanceProcAddr":
    389                 get_instance_proc_addr = cmd
    390             elif cmd.name == "GetDeviceProcAddr":
    391                 get_device_proc_addr = cmd
    392 
    393         if ext.guard:
    394             lines.append("#endif")
    395     lines.append("")
    396 
    397     lines.append("void init_dispatch_table_top(PFN_vkGetInstanceProcAddr get_instance_proc_addr)")
    398     lines.append("{")
    399     lines.append("    GetInstanceProcAddr = get_instance_proc_addr;")
    400     lines.append("")
    401     for cmd, guard in commands_by_types[Command.LOADER]:
    402         lines.append(get_proc_addr("VK_NULL_HANDLE", cmd, guard))
    403     lines.append("}")
    404     lines.append("")
    405 
    406     lines.append("void init_dispatch_table_middle(VkInstance instance, bool include_bottom)")
    407     lines.append("{")
    408     lines.append(get_proc_addr("instance", get_instance_proc_addr))
    409     lines.append("")
    410     for cmd, guard in commands_by_types[Command.INSTANCE]:
    411         if cmd == get_instance_proc_addr:
    412             continue
    413         lines.append(get_proc_addr("instance", cmd, guard))
    414     lines.append("")
    415     lines.append("    if (!include_bottom)")
    416     lines.append("        return;")
    417     lines.append("")
    418     for cmd, guard in commands_by_types[Command.DEVICE]:
    419         lines.append(get_proc_addr("instance", cmd, guard))
    420     lines.append("}")
    421     lines.append("")
    422 
    423     lines.append("void init_dispatch_table_bottom(VkInstance instance, VkDevice dev)")
    424     lines.append("{")
    425     lines.append(get_proc_addr("instance", get_device_proc_addr))
    426     lines.append(get_proc_addr("dev", get_device_proc_addr))
    427     lines.append("")
    428     for cmd, guard in commands_by_types[Command.DEVICE]:
    429         if cmd == get_device_proc_addr:
    430             continue
    431         lines.append(get_proc_addr("dev", cmd, guard))
    432     lines.append("}")
    433 
    434     lines.append("")
    435     lines.append("} // namespace vk")
    436 
    437     return "\n".join(lines)
    438 
    439 def parse_vulkan_h(filename):
    440     extensions = []
    441 
    442     with open(filename, "r") as f:
    443         current_ext = None
    444         ext_guard = None
    445         spec_version = None
    446 
    447         for line in f:
    448             line = line.strip();
    449 
    450             if line.startswith("#define VK_API_VERSION"):
    451                 minor_end = line.rfind(",")
    452                 minor_begin = line.rfind(",", 0, minor_end) + 1
    453                 spec_version = int(line[minor_begin:minor_end])
    454                 # add core
    455                 current_ext = Extension("VK_core", spec_version)
    456                 extensions.append(current_ext)
    457             elif Command.valid_c_typedef(line):
    458                 current_ext.add_command(Command.from_c_typedef(line))
    459             elif line.startswith("#ifdef VK_USE_PLATFORM"):
    460                 guard_begin = line.find(" ") + 1
    461                 ext_guard = line[guard_begin:]
    462             elif line.startswith("#define") and "SPEC_VERSION " in line:
    463                 version_begin = line.rfind(" ") + 1
    464                 spec_version = int(line[version_begin:])
    465             elif line.startswith("#define") and "EXTENSION_NAME " in line:
    466                 name_end = line.rfind("\"")
    467                 name_begin = line.rfind("\"", 0, name_end) + 1
    468                 name = line[name_begin:name_end]
    469                 # add extension
    470                 current_ext = Extension(name, spec_version, ext_guard)
    471                 extensions.append(current_ext)
    472             elif ext_guard and line.startswith("#endif") and ext_guard in line:
    473                 ext_guard = None
    474 
    475     for ext in extensions:
    476         print("%s = %s" % (ext.name.lower(), repr(ext)))
    477         print("")
    478 
    479     print("extensions = [")
    480     for ext in extensions:
    481         print("    %s," % ext.name.lower())
    482     print("]")
    483 
    484 if __name__ == "__main__":
    485     if sys.argv[1] == "parse":
    486         parse_vulkan_h(sys.argv[2])
    487     else:
    488         filename = sys.argv[1]
    489         base = os.path.basename(filename)
    490         contents = []
    491 
    492         if base.endswith(".h"):
    493             contents = generate_header(base.replace(".", "_").upper())
    494         elif base.endswith(".cpp"):
    495             contents = generate_source(base.replace(".cpp", ".h"))
    496 
    497         with open(filename, "w") as f:
    498             print(contents, file=f)
    499