| Chia-I Wu | fb2559d | 2014-08-01 11:19:52 +0800 | [diff] [blame] | 1 | #!/usr/bin/env python3 | 
| Chia-I Wu | 44e4236 | 2014-09-02 08:32:09 +0800 | [diff] [blame] | 2 | # | 
| Courtney Goeltzenleuchter | 9cc421e | 2015-04-08 15:36:08 -0600 | [diff] [blame] | 3 | # VK | 
| Chia-I Wu | 44e4236 | 2014-09-02 08:32:09 +0800 | [diff] [blame] | 4 | # | 
 | 5 | # Copyright (C) 2014 LunarG, Inc. | 
 | 6 | # | 
 | 7 | # Permission is hereby granted, free of charge, to any person obtaining a | 
 | 8 | # copy of this software and associated documentation files (the "Software"), | 
 | 9 | # to deal in the Software without restriction, including without limitation | 
 | 10 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, | 
 | 11 | # and/or sell copies of the Software, and to permit persons to whom the | 
 | 12 | # Software is furnished to do so, subject to the following conditions: | 
 | 13 | # | 
 | 14 | # The above copyright notice and this permission notice shall be included | 
 | 15 | # in all copies or substantial portions of the Software. | 
 | 16 | # | 
 | 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
 | 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
 | 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL | 
 | 20 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
 | 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | 
 | 22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 
 | 23 | # DEALINGS IN THE SOFTWARE. | 
 | 24 | # | 
 | 25 | # Authors: | 
 | 26 | #   Chia-I Wu <olv@lunarg.com> | 
| Chia-I Wu | fb2559d | 2014-08-01 11:19:52 +0800 | [diff] [blame] | 27 |  | 
 | 28 | import sys | 
 | 29 |  | 
| Courtney Goeltzenleuchter | a8c0628 | 2015-04-14 14:55:44 -0600 | [diff] [blame] | 30 | import vulkan | 
| Chia-I Wu | fb2559d | 2014-08-01 11:19:52 +0800 | [diff] [blame] | 31 |  | 
| Chia-I Wu | f7d6d3c | 2015-01-05 12:55:13 +0800 | [diff] [blame] | 32 | def generate_get_proc_addr_check(name): | 
| Courtney Goeltzenleuchter | 9cc421e | 2015-04-08 15:36:08 -0600 | [diff] [blame] | 33 |     return "    if (!%s || %s[0] != 'v' || %s[1] != 'k')\n" \ | 
 | 34 |            "        return NULL;" % ((name,) * 3) | 
| Chia-I Wu | f7d6d3c | 2015-01-05 12:55:13 +0800 | [diff] [blame] | 35 |  | 
| Chia-I Wu | fb2559d | 2014-08-01 11:19:52 +0800 | [diff] [blame] | 36 | class Subcommand(object): | 
 | 37 |     def __init__(self, argv): | 
 | 38 |         self.argv = argv | 
| Courtney Goeltzenleuchter | a8c0628 | 2015-04-14 14:55:44 -0600 | [diff] [blame] | 39 |         self.headers = vulkan.headers | 
 | 40 |         self.protos = vulkan.protos | 
| Chia-I Wu | fb2559d | 2014-08-01 11:19:52 +0800 | [diff] [blame] | 41 |  | 
 | 42 |     def run(self): | 
| Chia-I Wu | fb2559d | 2014-08-01 11:19:52 +0800 | [diff] [blame] | 43 |         print(self.generate()) | 
 | 44 |  | 
| Jon Ashburn | e18431b | 2015-04-13 18:10:06 -0600 | [diff] [blame] | 45 |     def _does_function_create_object(self, proto): | 
 | 46 |         out_objs = proto.object_out_params() | 
 | 47 |         if proto.name == "ResetFences": | 
 | 48 |             return False | 
 | 49 |         return out_objs and out_objs[-1] == proto.params[-1] | 
 | 50 |  | 
 | 51 |     def _is_loader_special_case(self, proto): | 
| Tony Barbour | 8eddca6 | 2015-04-14 10:22:46 -0600 | [diff] [blame] | 52 |         if proto.name in ["GetProcAddr", "EnumerateGpus", "EnumerateLayers", "DbgRegisterMsgCallback", "DbgUnregisterMsgCallback", "DbgSetGlobalOption", "DestroyInstance"]: | 
| Jon Ashburn | e18431b | 2015-04-13 18:10:06 -0600 | [diff] [blame] | 53 |             return True | 
 | 54 |         return not self.is_dispatchable_object_first_param(proto) | 
 | 55 |  | 
 | 56 |  | 
| Jon Ashburn | eb2728b | 2015-04-10 14:33:07 -0600 | [diff] [blame] | 57 |     def is_dispatchable_object_first_param(self, proto): | 
 | 58 |         in_objs = proto.object_in_params() | 
| Tony Barbour | 8eddca6 | 2015-04-14 10:22:46 -0600 | [diff] [blame] | 59 |         non_dispatch_objs = [] | 
| Jon Ashburn | eb2728b | 2015-04-10 14:33:07 -0600 | [diff] [blame] | 60 |         param0 = proto.params[0] | 
 | 61 |         return (len(in_objs) > 0)  and (in_objs[0].ty == param0.ty) and (param0.ty not in non_dispatch_objs) | 
 | 62 |  | 
| Chia-I Wu | fb2559d | 2014-08-01 11:19:52 +0800 | [diff] [blame] | 63 |     def generate(self): | 
 | 64 |         copyright = self.generate_copyright() | 
 | 65 |         header = self.generate_header() | 
 | 66 |         body = self.generate_body() | 
 | 67 |         footer = self.generate_footer() | 
 | 68 |  | 
 | 69 |         contents = [] | 
 | 70 |         if copyright: | 
 | 71 |             contents.append(copyright) | 
 | 72 |         if header: | 
 | 73 |             contents.append(header) | 
 | 74 |         if body: | 
 | 75 |             contents.append(body) | 
 | 76 |         if footer: | 
 | 77 |             contents.append(footer) | 
 | 78 |  | 
 | 79 |         return "\n\n".join(contents) | 
 | 80 |  | 
 | 81 |     def generate_copyright(self): | 
 | 82 |         return """/* THIS FILE IS GENERATED.  DO NOT EDIT. */ | 
 | 83 |  | 
 | 84 | /* | 
| Courtney Goeltzenleuchter | 9cc421e | 2015-04-08 15:36:08 -0600 | [diff] [blame] | 85 |  * Vulkan | 
| Chia-I Wu | fb2559d | 2014-08-01 11:19:52 +0800 | [diff] [blame] | 86 |  * | 
 | 87 |  * Copyright (C) 2014 LunarG, Inc. | 
 | 88 |  * | 
 | 89 |  * Permission is hereby granted, free of charge, to any person obtaining a | 
 | 90 |  * copy of this software and associated documentation files (the "Software"), | 
 | 91 |  * to deal in the Software without restriction, including without limitation | 
 | 92 |  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | 
 | 93 |  * and/or sell copies of the Software, and to permit persons to whom the | 
 | 94 |  * Software is furnished to do so, subject to the following conditions: | 
 | 95 |  * | 
 | 96 |  * The above copyright notice and this permission notice shall be included | 
 | 97 |  * in all copies or substantial portions of the Software. | 
 | 98 |  * | 
 | 99 |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
 | 100 |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
 | 101 |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL | 
 | 102 |  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
 | 103 |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | 
 | 104 |  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 
 | 105 |  * DEALINGS IN THE SOFTWARE. | 
 | 106 |  */""" | 
 | 107 |  | 
 | 108 |     def generate_header(self): | 
| Chia-I Wu | 6ae460f | 2014-09-13 13:36:06 +0800 | [diff] [blame] | 109 |         return "\n".join(["#include <" + h + ">" for h in self.headers]) | 
| Chia-I Wu | fb2559d | 2014-08-01 11:19:52 +0800 | [diff] [blame] | 110 |  | 
 | 111 |     def generate_body(self): | 
 | 112 |         pass | 
 | 113 |  | 
 | 114 |     def generate_footer(self): | 
 | 115 |         pass | 
 | 116 |  | 
| Chia-I Wu | d4a76ae | 2015-01-04 10:15:48 +0800 | [diff] [blame] | 117 | class LoaderEntrypointsSubcommand(Subcommand): | 
| Chia-I Wu | 2686435 | 2015-01-02 00:21:24 +0800 | [diff] [blame] | 118 |     def generate_header(self): | 
| Chia-I Wu | 1d6731b | 2015-04-11 15:34:07 +0800 | [diff] [blame] | 119 |         return "#include \"loader.h\"" | 
| Chia-I Wu | 2686435 | 2015-01-02 00:21:24 +0800 | [diff] [blame] | 120 |  | 
| Chia-I Wu | 67a81c8 | 2015-04-11 16:07:13 +0800 | [diff] [blame] | 121 |     def _generate_object_setup(self, proto): | 
 | 122 |         method = "loader_init_data" | 
| Courtney Goeltzenleuchter | 9cc421e | 2015-04-08 15:36:08 -0600 | [diff] [blame] | 123 |         cond = "res == VK_SUCCESS" | 
| Chia-I Wu | 67a81c8 | 2015-04-11 16:07:13 +0800 | [diff] [blame] | 124 |  | 
 | 125 |         if "Get" in proto.name: | 
 | 126 |             method = "loader_set_data" | 
 | 127 |  | 
 | 128 |         setup = [] | 
 | 129 |  | 
 | 130 |         if proto.name == "AllocDescriptorSets": | 
 | 131 |             psets = proto.params[-2].name | 
 | 132 |             pcount = proto.params[-1].name | 
 | 133 |             setup.append("uint32_t i;") | 
 | 134 |             setup.append("for (i = 0; i < *%s; i++)" % pcount) | 
 | 135 |             setup.append("    %s(%s[i], disp);" % (method, psets)) | 
 | 136 |         else: | 
 | 137 |             obj_params = proto.object_out_params() | 
 | 138 |             for param in obj_params: | 
 | 139 |                 setup.append("%s(*%s, disp);" % (method, param.name)) | 
 | 140 |  | 
 | 141 |         if setup: | 
 | 142 |             joined = "\n        ".join(setup) | 
 | 143 |             setup = [] | 
 | 144 |             setup.append("    if (%s) {" % cond) | 
 | 145 |             setup.append("        " + joined) | 
 | 146 |             setup.append("    }") | 
 | 147 |  | 
 | 148 |         return "\n".join(setup) | 
 | 149 |  | 
| Chia-I Wu | 2686435 | 2015-01-02 00:21:24 +0800 | [diff] [blame] | 150 |     def _generate_loader_dispatch_entrypoints(self, qual=""): | 
| Chia-I Wu | 468e3c3 | 2014-08-04 08:03:57 +0800 | [diff] [blame] | 151 |         if qual: | 
 | 152 |             qual += " " | 
 | 153 |  | 
| Chia-I Wu | dac3e49 | 2014-08-02 23:49:43 +0800 | [diff] [blame] | 154 |         funcs = [] | 
 | 155 |         for proto in self.protos: | 
| Jon Ashburn | eb2728b | 2015-04-10 14:33:07 -0600 | [diff] [blame] | 156 |             if self._is_loader_special_case(proto): | 
| Tobin Ehlis | 66bbbf5 | 2014-11-12 11:47:07 -0700 | [diff] [blame] | 157 |                 continue | 
| Chia-I Wu | 67a81c8 | 2015-04-11 16:07:13 +0800 | [diff] [blame] | 158 |             func = [] | 
 | 159 |  | 
 | 160 |             obj_setup = self._generate_object_setup(proto) | 
 | 161 |  | 
| Courtney Goeltzenleuchter | 9cc421e | 2015-04-08 15:36:08 -0600 | [diff] [blame] | 162 |             func.append(qual + proto.c_func(prefix="vk", attr="VKAPI")) | 
| Chia-I Wu | 67a81c8 | 2015-04-11 16:07:13 +0800 | [diff] [blame] | 163 |             func.append("{") | 
 | 164 |  | 
 | 165 |             # declare local variables | 
| Jon Ashburn | 301c5f0 | 2015-04-06 10:58:22 -0600 | [diff] [blame] | 166 |             func.append("    const VkLayerDispatchTable *disp;") | 
| Chia-I Wu | 67a81c8 | 2015-04-11 16:07:13 +0800 | [diff] [blame] | 167 |             if proto.ret != 'void' and obj_setup: | 
| Courtney Goeltzenleuchter | 382489d | 2015-04-10 08:34:15 -0600 | [diff] [blame] | 168 |                 func.append("    VkResult res;") | 
| Chia-I Wu | 67a81c8 | 2015-04-11 16:07:13 +0800 | [diff] [blame] | 169 |             func.append("") | 
 | 170 |  | 
| Jon Ashburn | 630e44f | 2015-04-08 21:33:34 -0600 | [diff] [blame] | 171 |             # get dispatch table | 
 | 172 |             func.append("    disp = loader_get_data(%s);" % | 
 | 173 |                     proto.params[0].name) | 
| Chia-I Wu | 67a81c8 | 2015-04-11 16:07:13 +0800 | [diff] [blame] | 174 |             func.append("") | 
 | 175 |  | 
 | 176 |             # dispatch! | 
 | 177 |             dispatch = "disp->%s;" % proto.c_call() | 
 | 178 |             if proto.ret == 'void': | 
 | 179 |                 func.append("    " + dispatch) | 
 | 180 |             elif not obj_setup: | 
 | 181 |                 func.append("    return " + dispatch) | 
 | 182 |             else: | 
 | 183 |                 func.append("    res = " + dispatch) | 
 | 184 |                 func.append(obj_setup) | 
 | 185 |                 func.append("") | 
 | 186 |                 func.append("    return res;") | 
 | 187 |  | 
 | 188 |             func.append("}") | 
 | 189 |  | 
| Ian Elliott | 81ac44c | 2015-01-13 17:52:38 -0700 | [diff] [blame] | 190 |             if 'WsiX11AssociateConnection' == proto.name: | 
| Ian Elliott | e977a6c | 2015-02-26 14:34:52 -0700 | [diff] [blame] | 191 |                 funcs.append("#if defined(__linux__) || defined(XCB_NVIDIA)") | 
| Chia-I Wu | 67a81c8 | 2015-04-11 16:07:13 +0800 | [diff] [blame] | 192 |  | 
 | 193 |             funcs.append("\n".join(func)) | 
| Chia-I Wu | dac3e49 | 2014-08-02 23:49:43 +0800 | [diff] [blame] | 194 |  | 
| Ian Elliott | 81ac44c | 2015-01-13 17:52:38 -0700 | [diff] [blame] | 195 |         funcs.append("#endif") | 
| Chia-I Wu | dac3e49 | 2014-08-02 23:49:43 +0800 | [diff] [blame] | 196 |         return "\n\n".join(funcs) | 
 | 197 |  | 
| Chia-I Wu | fb2559d | 2014-08-01 11:19:52 +0800 | [diff] [blame] | 198 |     def generate_body(self): | 
| Chia-I Wu | 2686435 | 2015-01-02 00:21:24 +0800 | [diff] [blame] | 199 |         body = [self._generate_loader_dispatch_entrypoints("LOADER_EXPORT")] | 
| Jon Ashburn | d43f9b6 | 2014-10-14 19:15:22 -0600 | [diff] [blame] | 200 |  | 
 | 201 |         return "\n\n".join(body) | 
 | 202 |  | 
| Chia-I Wu | 28b8d8c | 2015-01-04 10:19:50 +0800 | [diff] [blame] | 203 | class DispatchTableOpsSubcommand(Subcommand): | 
 | 204 |     def run(self): | 
 | 205 |         if len(self.argv) != 1: | 
 | 206 |             print("DispatchTableOpsSubcommand: <prefix> unspecified") | 
 | 207 |             return | 
 | 208 |  | 
 | 209 |         self.prefix = self.argv[0] | 
 | 210 |         super().run() | 
 | 211 |  | 
 | 212 |     def generate_header(self): | 
| Courtney Goeltzenleuchter | 9cc421e | 2015-04-08 15:36:08 -0600 | [diff] [blame] | 213 |         return "\n".join(["#include <vulkan.h>", | 
 | 214 |                           "#include <vkLayer.h>", | 
| Ian Elliott | 81ac44c | 2015-01-13 17:52:38 -0700 | [diff] [blame] | 215 |                           "#include <string.h>", | 
 | 216 |                           "#include \"loader_platform.h\""]) | 
| Chia-I Wu | 28b8d8c | 2015-01-04 10:19:50 +0800 | [diff] [blame] | 217 |  | 
 | 218 |     def _generate_init(self): | 
 | 219 |         stmts = [] | 
 | 220 |         for proto in self.protos: | 
| Ian Elliott | 81ac44c | 2015-01-13 17:52:38 -0700 | [diff] [blame] | 221 |             if 'WsiX11AssociateConnection' == proto.name: | 
| Ian Elliott | e977a6c | 2015-02-26 14:34:52 -0700 | [diff] [blame] | 222 |                 stmts.append("#if defined(__linux__) || defined(XCB_NVIDIA)") | 
| Mike Stroyan | 9cb208b | 2015-04-08 10:31:48 -0600 | [diff] [blame] | 223 |             if self.is_dispatchable_object_first_param(proto) or proto.name == "CreateInstance": | 
| Courtney Goeltzenleuchter | 382489d | 2015-04-10 08:34:15 -0600 | [diff] [blame] | 224 |                 stmts.append("table->%s = (PFN_vk%s) gpa(gpu, \"vk%s\");" % | 
| Chia-I Wu | 28b8d8c | 2015-01-04 10:19:50 +0800 | [diff] [blame] | 225 |                         (proto.name, proto.name, proto.name)) | 
| Jon Ashburn | 5517886 | 2015-04-13 17:47:29 -0600 | [diff] [blame] | 226 |             else: | 
 | 227 |                 stmts.append("table->%s = vk%s; /* non-dispatchable */" % | 
 | 228 |                              (proto.name, proto.name)) | 
| Ian Elliott | 81ac44c | 2015-01-13 17:52:38 -0700 | [diff] [blame] | 229 |         stmts.append("#endif") | 
| Chia-I Wu | 28b8d8c | 2015-01-04 10:19:50 +0800 | [diff] [blame] | 230 |  | 
 | 231 |         func = [] | 
| Jon Ashburn | 301c5f0 | 2015-04-06 10:58:22 -0600 | [diff] [blame] | 232 |         func.append("static inline void %s_initialize_dispatch_table(VkLayerDispatchTable *table," | 
| Chia-I Wu | 28b8d8c | 2015-01-04 10:19:50 +0800 | [diff] [blame] | 233 |                 % self.prefix) | 
| Courtney Goeltzenleuchter | 382489d | 2015-04-10 08:34:15 -0600 | [diff] [blame] | 234 |         func.append("%s                                              PFN_vkGetProcAddr gpa," | 
| Chia-I Wu | 28b8d8c | 2015-01-04 10:19:50 +0800 | [diff] [blame] | 235 |                 % (" " * len(self.prefix))) | 
| Courtney Goeltzenleuchter | 382489d | 2015-04-10 08:34:15 -0600 | [diff] [blame] | 236 |         func.append("%s                                              VkPhysicalGpu gpu)" | 
| Chia-I Wu | 28b8d8c | 2015-01-04 10:19:50 +0800 | [diff] [blame] | 237 |                 % (" " * len(self.prefix))) | 
 | 238 |         func.append("{") | 
 | 239 |         func.append("    %s" % "\n    ".join(stmts)) | 
 | 240 |         func.append("}") | 
 | 241 |  | 
 | 242 |         return "\n".join(func) | 
 | 243 |  | 
 | 244 |     def _generate_lookup(self): | 
 | 245 |         lookups = [] | 
 | 246 |         for proto in self.protos: | 
| Ian Elliott | 81ac44c | 2015-01-13 17:52:38 -0700 | [diff] [blame] | 247 |             if 'WsiX11AssociateConnection' == proto.name: | 
| Ian Elliott | e977a6c | 2015-02-26 14:34:52 -0700 | [diff] [blame] | 248 |                 lookups.append("#if defined(__linux__) || defined(XCB_NVIDIA)") | 
| Jon Ashburn | eb2728b | 2015-04-10 14:33:07 -0600 | [diff] [blame] | 249 |             if self.is_dispatchable_object_first_param(proto): | 
 | 250 |                 lookups.append("if (!strcmp(name, \"%s\"))" % (proto.name)) | 
 | 251 |                 lookups.append("    return (void *) table->%s;" | 
| Chia-I Wu | 28b8d8c | 2015-01-04 10:19:50 +0800 | [diff] [blame] | 252 |                     % (proto.name)) | 
| Ian Elliott | 81ac44c | 2015-01-13 17:52:38 -0700 | [diff] [blame] | 253 |         lookups.append("#endif") | 
| Chia-I Wu | 28b8d8c | 2015-01-04 10:19:50 +0800 | [diff] [blame] | 254 |  | 
 | 255 |         func = [] | 
| Jon Ashburn | 301c5f0 | 2015-04-06 10:58:22 -0600 | [diff] [blame] | 256 |         func.append("static inline void *%s_lookup_dispatch_table(const VkLayerDispatchTable *table," | 
| Chia-I Wu | 28b8d8c | 2015-01-04 10:19:50 +0800 | [diff] [blame] | 257 |                 % self.prefix) | 
 | 258 |         func.append("%s                                           const char *name)" | 
 | 259 |                 % (" " * len(self.prefix))) | 
 | 260 |         func.append("{") | 
| Chia-I Wu | f7d6d3c | 2015-01-05 12:55:13 +0800 | [diff] [blame] | 261 |         func.append(generate_get_proc_addr_check("name")) | 
| Chia-I Wu | 28b8d8c | 2015-01-04 10:19:50 +0800 | [diff] [blame] | 262 |         func.append("") | 
| Courtney Goeltzenleuchter | 9cc421e | 2015-04-08 15:36:08 -0600 | [diff] [blame] | 263 |         func.append("    name += 2;") | 
| Chia-I Wu | 28b8d8c | 2015-01-04 10:19:50 +0800 | [diff] [blame] | 264 |         func.append("    %s" % "\n    ".join(lookups)) | 
 | 265 |         func.append("") | 
 | 266 |         func.append("    return NULL;") | 
 | 267 |         func.append("}") | 
 | 268 |  | 
 | 269 |         return "\n".join(func) | 
 | 270 |  | 
 | 271 |     def generate_body(self): | 
 | 272 |         body = [self._generate_init(), | 
 | 273 |                 self._generate_lookup()] | 
 | 274 |  | 
 | 275 |         return "\n\n".join(body) | 
 | 276 |  | 
| Chia-I Wu | 731517d | 2015-01-03 23:48:15 +0800 | [diff] [blame] | 277 | class IcdDummyEntrypointsSubcommand(Subcommand): | 
| Chia-I Wu | 30c7829 | 2014-08-04 10:08:08 +0800 | [diff] [blame] | 278 |     def run(self): | 
| Chia-I Wu | 731517d | 2015-01-03 23:48:15 +0800 | [diff] [blame] | 279 |         if len(self.argv) == 1: | 
 | 280 |             self.prefix = self.argv[0] | 
 | 281 |             self.qual = "static" | 
 | 282 |         else: | 
| Courtney Goeltzenleuchter | 9cc421e | 2015-04-08 15:36:08 -0600 | [diff] [blame] | 283 |             self.prefix = "vk" | 
| Chia-I Wu | 731517d | 2015-01-03 23:48:15 +0800 | [diff] [blame] | 284 |             self.qual = "ICD_EXPORT" | 
| Chia-I Wu | 30c7829 | 2014-08-04 10:08:08 +0800 | [diff] [blame] | 285 |  | 
 | 286 |         super().run() | 
 | 287 |  | 
 | 288 |     def generate_header(self): | 
 | 289 |         return "#include \"icd.h\"" | 
 | 290 |  | 
 | 291 |     def _generate_stub_decl(self, proto): | 
| Courtney Goeltzenleuchter | 9cc421e | 2015-04-08 15:36:08 -0600 | [diff] [blame] | 292 |         return proto.c_pretty_decl(self.prefix + proto.name, attr="VKAPI") | 
| Chia-I Wu | 30c7829 | 2014-08-04 10:08:08 +0800 | [diff] [blame] | 293 |  | 
 | 294 |     def _generate_stubs(self): | 
 | 295 |         stubs = [] | 
 | 296 |         for proto in self.protos: | 
| Chia-I Wu | 30c7829 | 2014-08-04 10:08:08 +0800 | [diff] [blame] | 297 |             decl = self._generate_stub_decl(proto) | 
| Mark Lobodzinski | e2d07a5 | 2015-01-29 08:55:56 -0600 | [diff] [blame] | 298 |             if proto.ret != "void": | 
| Courtney Goeltzenleuchter | 9cc421e | 2015-04-08 15:36:08 -0600 | [diff] [blame] | 299 |                 stmt = "    return VK_ERROR_UNKNOWN;\n" | 
| Chia-I Wu | 30c7829 | 2014-08-04 10:08:08 +0800 | [diff] [blame] | 300 |             else: | 
 | 301 |                 stmt = "" | 
 | 302 |  | 
| Chia-I Wu | 731517d | 2015-01-03 23:48:15 +0800 | [diff] [blame] | 303 |             stubs.append("%s %s\n{\n%s}" % (self.qual, decl, stmt)) | 
| Chia-I Wu | 30c7829 | 2014-08-04 10:08:08 +0800 | [diff] [blame] | 304 |  | 
 | 305 |         return "\n\n".join(stubs) | 
 | 306 |  | 
| Chia-I Wu | 30c7829 | 2014-08-04 10:08:08 +0800 | [diff] [blame] | 307 |     def generate_body(self): | 
| Chia-I Wu | 731517d | 2015-01-03 23:48:15 +0800 | [diff] [blame] | 308 |         return self._generate_stubs() | 
| Chia-I Wu | 30c7829 | 2014-08-04 10:08:08 +0800 | [diff] [blame] | 309 |  | 
| Chia-I Wu | 58f2085 | 2015-01-04 00:11:17 +0800 | [diff] [blame] | 310 | class IcdGetProcAddrSubcommand(IcdDummyEntrypointsSubcommand): | 
 | 311 |     def generate_header(self): | 
 | 312 |         return "\n".join(["#include <string.h>", "#include \"icd.h\""]) | 
 | 313 |  | 
 | 314 |     def generate_body(self): | 
 | 315 |         for proto in self.protos: | 
 | 316 |             if proto.name == "GetProcAddr": | 
 | 317 |                 gpa_proto = proto | 
 | 318 |  | 
 | 319 |         gpa_decl = self._generate_stub_decl(gpa_proto) | 
 | 320 |         gpa_pname = gpa_proto.params[-1].name | 
 | 321 |  | 
 | 322 |         lookups = [] | 
 | 323 |         for proto in self.protos: | 
| Ian Elliott | 81ac44c | 2015-01-13 17:52:38 -0700 | [diff] [blame] | 324 |             if 'WsiX11AssociateConnection' == proto.name: | 
| Ian Elliott | e977a6c | 2015-02-26 14:34:52 -0700 | [diff] [blame] | 325 |                 lookups.append("#if defined(__linux__) || defined(XCB_NVIDIA)") | 
| Chia-I Wu | 58f2085 | 2015-01-04 00:11:17 +0800 | [diff] [blame] | 326 |             lookups.append("if (!strcmp(%s, \"%s\"))" % | 
 | 327 |                     (gpa_pname, proto.name)) | 
 | 328 |             lookups.append("    return (%s) %s%s;" % | 
 | 329 |                     (gpa_proto.ret, self.prefix, proto.name)) | 
| Ian Elliott | 81ac44c | 2015-01-13 17:52:38 -0700 | [diff] [blame] | 330 |         lookups.append("#endif") | 
| Chia-I Wu | 58f2085 | 2015-01-04 00:11:17 +0800 | [diff] [blame] | 331 |  | 
 | 332 |         body = [] | 
 | 333 |         body.append("%s %s" % (self.qual, gpa_decl)) | 
 | 334 |         body.append("{") | 
| Chia-I Wu | f7d6d3c | 2015-01-05 12:55:13 +0800 | [diff] [blame] | 335 |         body.append(generate_get_proc_addr_check(gpa_pname)) | 
| Chia-I Wu | 58f2085 | 2015-01-04 00:11:17 +0800 | [diff] [blame] | 336 |         body.append("") | 
| Courtney Goeltzenleuchter | 9cc421e | 2015-04-08 15:36:08 -0600 | [diff] [blame] | 337 |         body.append("    %s += 2;" % gpa_pname) | 
| Chia-I Wu | 58f2085 | 2015-01-04 00:11:17 +0800 | [diff] [blame] | 338 |         body.append("    %s" % "\n    ".join(lookups)) | 
 | 339 |         body.append("") | 
 | 340 |         body.append("    return NULL;") | 
 | 341 |         body.append("}") | 
 | 342 |  | 
 | 343 |         return "\n".join(body) | 
 | 344 |  | 
| Chia-I Wu | f4bd2e4 | 2015-01-05 12:56:13 +0800 | [diff] [blame] | 345 | class LayerInterceptProcSubcommand(Subcommand): | 
 | 346 |     def run(self): | 
| Courtney Goeltzenleuchter | 9cc421e | 2015-04-08 15:36:08 -0600 | [diff] [blame] | 347 |         self.prefix = "vk" | 
| Chia-I Wu | f4bd2e4 | 2015-01-05 12:56:13 +0800 | [diff] [blame] | 348 |  | 
 | 349 |         # we could get the list from argv if wanted | 
 | 350 |         self.intercepted = [proto.name for proto in self.protos | 
| Jon Ashburn | 457c5d1 | 2015-01-29 16:54:38 -0700 | [diff] [blame] | 351 |                 if proto.name not in ["EnumerateGpus"]] | 
| Chia-I Wu | f4bd2e4 | 2015-01-05 12:56:13 +0800 | [diff] [blame] | 352 |  | 
 | 353 |         for proto in self.protos: | 
 | 354 |             if proto.name == "GetProcAddr": | 
 | 355 |                 self.gpa = proto | 
 | 356 |  | 
 | 357 |         super().run() | 
 | 358 |  | 
 | 359 |     def generate_header(self): | 
| Courtney Goeltzenleuchter | 9cc421e | 2015-04-08 15:36:08 -0600 | [diff] [blame] | 360 |         return "\n".join(["#include <string.h>", "#include \"vkLayer.h\""]) | 
| Chia-I Wu | f4bd2e4 | 2015-01-05 12:56:13 +0800 | [diff] [blame] | 361 |  | 
 | 362 |     def generate_body(self): | 
 | 363 |         lookups = [] | 
 | 364 |         for proto in self.protos: | 
 | 365 |             if proto.name not in self.intercepted: | 
 | 366 |                 lookups.append("/* no %s%s */" % (self.prefix, proto.name)) | 
 | 367 |                 continue | 
 | 368 |  | 
| Ian Elliott | 81ac44c | 2015-01-13 17:52:38 -0700 | [diff] [blame] | 369 |             if 'WsiX11AssociateConnection' == proto.name: | 
| Ian Elliott | e977a6c | 2015-02-26 14:34:52 -0700 | [diff] [blame] | 370 |                 lookups.append("#if defined(__linux__) || defined(XCB_NVIDIA)") | 
| Chia-I Wu | f4bd2e4 | 2015-01-05 12:56:13 +0800 | [diff] [blame] | 371 |             lookups.append("if (!strcmp(name, \"%s\"))" % proto.name) | 
 | 372 |             lookups.append("    return (%s) %s%s;" % | 
 | 373 |                     (self.gpa.ret, self.prefix, proto.name)) | 
| Ian Elliott | 81ac44c | 2015-01-13 17:52:38 -0700 | [diff] [blame] | 374 |         lookups.append("#endif") | 
| Chia-I Wu | f4bd2e4 | 2015-01-05 12:56:13 +0800 | [diff] [blame] | 375 |  | 
 | 376 |         body = [] | 
| Ian Elliott | a742a62 | 2015-02-18 12:38:04 -0700 | [diff] [blame] | 377 |         body.append("static inline %s layer_intercept_proc(const char *name)" % | 
| Chia-I Wu | f4bd2e4 | 2015-01-05 12:56:13 +0800 | [diff] [blame] | 378 |                 self.gpa.ret) | 
 | 379 |         body.append("{") | 
 | 380 |         body.append(generate_get_proc_addr_check("name")) | 
 | 381 |         body.append("") | 
| Courtney Goeltzenleuchter | 9cc421e | 2015-04-08 15:36:08 -0600 | [diff] [blame] | 382 |         body.append("    name += 2;") | 
| Chia-I Wu | f4bd2e4 | 2015-01-05 12:56:13 +0800 | [diff] [blame] | 383 |         body.append("    %s" % "\n    ".join(lookups)) | 
 | 384 |         body.append("") | 
 | 385 |         body.append("    return NULL;") | 
 | 386 |         body.append("}") | 
 | 387 |  | 
 | 388 |         return "\n".join(body) | 
 | 389 |  | 
| Chia-I Wu | d98a23c | 2015-04-11 10:56:50 +0800 | [diff] [blame] | 390 | class WinDefFileSubcommand(Subcommand): | 
 | 391 |     def run(self): | 
 | 392 |         library_exports = { | 
 | 393 |                 "all": [], | 
 | 394 |                 "icd": [ | 
 | 395 |                     "EnumerateGpus", | 
 | 396 |                     "CreateInstance", | 
 | 397 |                     "DestroyInstance", | 
 | 398 |                     "GetProcAddr", | 
 | 399 |                 ], | 
 | 400 |                 "layer": [ | 
 | 401 |                     "GetProcAddr", | 
 | 402 |                     "EnumerateLayers", | 
 | 403 |                 ], | 
 | 404 |         } | 
 | 405 |  | 
 | 406 |         if len(self.argv) != 2 or self.argv[1] not in library_exports: | 
 | 407 |             print("WinDefFileSubcommand: <library-name> {%s}" % | 
 | 408 |                     "|".join(library_exports.keys())) | 
 | 409 |             return | 
 | 410 |  | 
 | 411 |         self.library = self.argv[0] | 
 | 412 |         self.exports = library_exports[self.argv[1]] | 
 | 413 |  | 
 | 414 |         super().run() | 
 | 415 |  | 
 | 416 |     def generate_copyright(self): | 
 | 417 |         return """; THIS FILE IS GENERATED.  DO NOT EDIT. | 
 | 418 |  | 
 | 419 | ;;;; Begin Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 
| Courtney Goeltzenleuchter | 9cc421e | 2015-04-08 15:36:08 -0600 | [diff] [blame] | 420 | ; Vulkan | 
| Chia-I Wu | d98a23c | 2015-04-11 10:56:50 +0800 | [diff] [blame] | 421 | ; | 
 | 422 | ; Copyright (C) 2015 LunarG, Inc. | 
 | 423 | ; | 
 | 424 | ; Permission is hereby granted, free of charge, to any person obtaining a | 
 | 425 | ; copy of this software and associated documentation files (the "Software"), | 
 | 426 | ; to deal in the Software without restriction, including without limitation | 
 | 427 | ; the rights to use, copy, modify, merge, publish, distribute, sublicense, | 
 | 428 | ; and/or sell copies of the Software, and to permit persons to whom the | 
 | 429 | ; Software is furnished to do so, subject to the following conditions: | 
 | 430 | ; | 
 | 431 | ; The above copyright notice and this permission notice shall be included | 
 | 432 | ; in all copies or substantial portions of the Software. | 
 | 433 | ; | 
 | 434 | ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
 | 435 | ; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
 | 436 | ; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL | 
 | 437 | ; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
 | 438 | ; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | 
 | 439 | ; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 
 | 440 | ; DEALINGS IN THE SOFTWARE. | 
 | 441 | ;;;;  End Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;""" | 
 | 442 |  | 
 | 443 |     def generate_header(self): | 
 | 444 |         return "; The following is required on Windows, for exporting symbols from the DLL" | 
 | 445 |  | 
 | 446 |     def generate_body(self): | 
 | 447 |         body = [] | 
 | 448 |  | 
 | 449 |         body.append("LIBRARY " + self.library) | 
 | 450 |         body.append("EXPORTS") | 
 | 451 |  | 
 | 452 |         for proto in self.protos: | 
 | 453 |             if self.exports and proto.name not in self.exports: | 
 | 454 |                 continue | 
| Courtney Goeltzenleuchter | 9cc421e | 2015-04-08 15:36:08 -0600 | [diff] [blame] | 455 |             body.append("   vk" + proto.name) | 
| Chia-I Wu | d98a23c | 2015-04-11 10:56:50 +0800 | [diff] [blame] | 456 |  | 
 | 457 |         return "\n".join(body) | 
 | 458 |  | 
| Jon Ashburn | e18431b | 2015-04-13 18:10:06 -0600 | [diff] [blame] | 459 | class LoaderGetProcAddrSubcommand(Subcommand): | 
 | 460 |     def run(self): | 
 | 461 |         self.prefix = "vk" | 
 | 462 |  | 
 | 463 |         # we could get the list from argv if wanted | 
 | 464 |         self.intercepted = [proto.name for proto in self.protos] | 
 | 465 |  | 
 | 466 |         for proto in self.protos: | 
 | 467 |             if proto.name == "GetProcAddr": | 
 | 468 |                 self.gpa = proto | 
 | 469 |  | 
 | 470 |         super().run() | 
 | 471 |  | 
 | 472 |     def generate_header(self): | 
 | 473 |         return "\n".join(["#include <string.h>"]) | 
 | 474 |  | 
 | 475 |     def generate_body(self): | 
 | 476 |         lookups = [] | 
 | 477 |         for proto in self.protos: | 
 | 478 |             if proto.name not in self.intercepted: | 
 | 479 |                 lookups.append("/* no %s%s */" % (self.prefix, proto.name)) | 
 | 480 |                 continue | 
 | 481 |  | 
 | 482 |             if 'WsiX11AssociateConnection' == proto.name: | 
 | 483 |                 lookups.append("#if defined(__linux__) || defined(XCB_NVIDIA)") | 
 | 484 |             lookups.append("if (!strcmp(name, \"%s\"))" % proto.name) | 
 | 485 |             lookups.append("    return (%s) %s%s;" % | 
 | 486 |                     (self.gpa.ret, self.prefix, proto.name)) | 
 | 487 |         lookups.append("#endif") | 
 | 488 |  | 
 | 489 |         special_lookups = [] | 
 | 490 |         # these functions require special trampoline code beyond just the normal create object trampoline code | 
 | 491 |         special_names = ["AllocDescriptorSets", "GetMultiGpuCompatibility"] | 
 | 492 |         for proto in self.protos: | 
 | 493 |             if self._is_loader_special_case(proto) or self._does_function_create_object(proto) or proto.name in special_names: | 
 | 494 |                 special_lookups.append("if (!strcmp(name, \"%s\"))" % proto.name) | 
 | 495 |                 special_lookups.append("    return (%s) %s%s;" % | 
 | 496 |                         (self.gpa.ret, self.prefix, proto.name)) | 
 | 497 |             else: | 
 | 498 |                 continue | 
 | 499 |         body = [] | 
 | 500 |         body.append("static inline %s globalGetProcAddr(const char *name)" % | 
 | 501 |                 self.gpa.ret) | 
 | 502 |         body.append("{") | 
 | 503 |         body.append(generate_get_proc_addr_check("name")) | 
 | 504 |         body.append("") | 
 | 505 |         body.append("    name += 2;") | 
 | 506 |         body.append("    %s" % "\n    ".join(lookups)) | 
 | 507 |         body.append("") | 
 | 508 |         body.append("    return NULL;") | 
 | 509 |         body.append("}") | 
 | 510 |         body.append("") | 
 | 511 |         body.append("static inline void *loader_non_passthrough_gpa(const char *name)") | 
 | 512 |         body.append("{") | 
 | 513 |         body.append(generate_get_proc_addr_check("name")) | 
 | 514 |         body.append("") | 
 | 515 |         body.append("    name += 2;") | 
 | 516 |         body.append("    %s" % "\n    ".join(special_lookups)) | 
 | 517 |         body.append("") | 
 | 518 |         body.append("    return NULL;") | 
 | 519 |         body.append("}") | 
 | 520 |  | 
 | 521 |         return "\n".join(body) | 
 | 522 |  | 
| Chia-I Wu | fb2559d | 2014-08-01 11:19:52 +0800 | [diff] [blame] | 523 | def main(): | 
 | 524 |     subcommands = { | 
| Chia-I Wu | d4a76ae | 2015-01-04 10:15:48 +0800 | [diff] [blame] | 525 |             "loader-entrypoints": LoaderEntrypointsSubcommand, | 
| Chia-I Wu | 28b8d8c | 2015-01-04 10:19:50 +0800 | [diff] [blame] | 526 |             "dispatch-table-ops": DispatchTableOpsSubcommand, | 
| Chia-I Wu | 731517d | 2015-01-03 23:48:15 +0800 | [diff] [blame] | 527 |             "icd-dummy-entrypoints": IcdDummyEntrypointsSubcommand, | 
| Chia-I Wu | 58f2085 | 2015-01-04 00:11:17 +0800 | [diff] [blame] | 528 |             "icd-get-proc-addr": IcdGetProcAddrSubcommand, | 
| Chia-I Wu | f4bd2e4 | 2015-01-05 12:56:13 +0800 | [diff] [blame] | 529 |             "layer-intercept-proc": LayerInterceptProcSubcommand, | 
| Chia-I Wu | d98a23c | 2015-04-11 10:56:50 +0800 | [diff] [blame] | 530 |             "win-def-file": WinDefFileSubcommand, | 
| Jon Ashburn | e18431b | 2015-04-13 18:10:06 -0600 | [diff] [blame] | 531 |             "loader-get-proc-addr": LoaderGetProcAddrSubcommand, | 
| Chia-I Wu | fb2559d | 2014-08-01 11:19:52 +0800 | [diff] [blame] | 532 |     } | 
 | 533 |  | 
 | 534 |     if len(sys.argv) < 2 or sys.argv[1] not in subcommands: | 
 | 535 |         print("Usage: %s <subcommand> [options]" % sys.argv[0]) | 
 | 536 |         print | 
 | 537 |         print("Available sucommands are: %s" % " ".join(subcommands)) | 
 | 538 |         exit(1) | 
 | 539 |  | 
 | 540 |     subcmd = subcommands[sys.argv[1]](sys.argv[2:]) | 
 | 541 |     subcmd.run() | 
 | 542 |  | 
 | 543 | if __name__ == "__main__": | 
 | 544 |     main() |