loader: Add dynamic dispatch for unknown device extension entrypoints

GetInstancePorcAddr() is specified to return trampoline entrypoints for all
Vulkan core and extension entrypoints that are dispatched on an instance object
or a child of that instance object. However, typically, device extensions would
be unknown to the loader (don't want to rev the loader everytime an IHV creates
a new device extension).

This patch allows loader to dynamically discover device extension entrypoints
and configure generic trampoline code for these discovered device extensions.
diff --git a/loader/vk-loader-generate.py b/loader/vk-loader-generate.py
index 143af61..e2c794d 100755
--- a/loader/vk-loader-generate.py
+++ b/loader/vk-loader-generate.py
@@ -91,6 +91,7 @@
 /*
  *
  * Copyright (C) 2015 Valve Corporation
+ * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -111,6 +112,8 @@
  * DEALINGS IN THE SOFTWARE.
  *
  * Author: Jon Ashburn <jon@lunarg.com>
+ * Author: Chia-I Wu <olv@lunarg.com>
+ * Author: Courtney Goeltzenleuchter <courtney@lunarg.com>
  */"""
 
     def generate_header(self):
@@ -122,6 +125,37 @@
     def generate_footer(self):
         pass
 
+class DevExtTrampolineSubcommand(Subcommand):
+    def generate_header(self):
+        lines = []
+        lines.append("#include \"vk_loader_platform.h\"")
+        lines.append("#include \"loader.h\"")
+        lines.append("#if defined(__linux__)")
+        lines.append("#pragma GCC optimize(3)  // force gcc to use tail-calls")
+        lines.append("#endif")
+        return "\n".join(lines)
+
+    def generate_body(self):
+        lines = []
+        for i in range(250):
+            lines.append('\nVKAPI_ATTR void VKAPI_CALL vkDevExt%s(VkDevice device)' % i)
+            lines.append('{')
+            lines.append('    const struct loader_dev_dispatch_table *disp;')
+            lines.append('    disp = loader_get_dev_dispatch(device);')
+            lines.append('    disp->ext_dispatch.DevExt[%s](device);' % i)
+            lines.append('}')
+        lines.append('')
+        lines.append('void *loader_get_dev_ext_trampoline(uint32_t index)')
+        lines.append('{')
+        lines.append('    switch (index) {')
+        for i in range(250):
+            lines.append('        case %s:' % i)
+            lines.append('            return vkDevExt%s;' % i)
+        lines.append('    }')
+        lines.append('    return NULL;')
+        lines.append('}')
+        return "\n".join(lines)
+
 class LoaderEntrypointsSubcommand(Subcommand):
     def generate_header(self):
         return "#include \"loader.h\""
@@ -412,6 +446,7 @@
 
 def main():
     subcommands = {
+            "dev-ext-trampoline": DevExtTrampolineSubcommand,
             "loader-entrypoints": LoaderEntrypointsSubcommand,
             "dispatch-table-ops": DispatchTableOpsSubcommand,
             "win-def-file": WinDefFileSubcommand,