1 #!/usr/bin/env python3 2 # 3 # Copyright (c) 2015-2016 The Khronos Group Inc. 4 # Copyright (c) 2015-2016 Valve Corporation 5 # Copyright (c) 2015-2016 LunarG, Inc. 6 # Copyright (c) 2015-2016 Google Inc. 7 # 8 # Licensed under the Apache License, Version 2.0 (the "License"); 9 # you may not use this file except in compliance with the License. 10 # You may obtain a copy of the License at 11 # 12 # http://www.apache.org/licenses/LICENSE-2.0 13 # 14 # Unless required by applicable law or agreed to in writing, software 15 # distributed under the License is distributed on an "AS IS" BASIS, 16 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 # See the License for the specific language governing permissions and 18 # limitations under the License. 19 # 20 # Author: Chia-I Wu <olv (at] lunarg.com> 21 # Author: Courtney Goeltzenleuchter <courtney (at] LunarG.com> 22 # Author: Jon Ashburn <jon (at] lunarg.com> 23 # Author: Gwan-gyeong Mun <kk.moon (at] samsung.com> 24 25 import sys 26 27 import vulkan 28 29 def generate_get_proc_addr_check(name): 30 return " if (!%s || %s[0] != 'v' || %s[1] != 'k')\n" \ 31 " return NULL;" % ((name,) * 3) 32 33 class Subcommand(object): 34 def __init__(self, argv): 35 self.argv = argv 36 self.headers = vulkan.headers 37 self.protos = vulkan.protos 38 self.outfile = None 39 40 def run(self): 41 if self.outfile: 42 with open(self.outfile, "w") as outfile: 43 outfile.write(self.generate()) 44 else: 45 print(self.generate()) 46 47 def generate(self): 48 copyright = self.generate_copyright() 49 header = self.generate_header() 50 body = self.generate_body() 51 footer = self.generate_footer() 52 53 contents = [] 54 if copyright: 55 contents.append(copyright) 56 if header: 57 contents.append(header) 58 if body: 59 contents.append(body) 60 if footer: 61 contents.append(footer) 62 63 return "\n\n".join(contents) 64 65 def generate_copyright(self): 66 return """/* THIS FILE IS GENERATED. DO NOT EDIT. */ 67 68 /* 69 * Copyright (c) 2015-2016 The Khronos Group Inc. 70 * Copyright (c) 2015-2016 Valve Corporation 71 * Copyright (c) 2015-2016 LunarG, Inc. 72 * 73 * Licensed under the Apache License, Version 2.0 (the "License"); 74 * you may not use this file except in compliance with the License. 75 * You may obtain a copy of the License at 76 * 77 * http://www.apache.org/licenses/LICENSE-2.0 78 * 79 * Unless required by applicable law or agreed to in writing, software 80 * distributed under the License is distributed on an "AS IS" BASIS, 81 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 82 * See the License for the specific language governing permissions and 83 * limitations under the License. 84 * 85 * Author: Courtney Goeltzenleuchter <courtney (at] LunarG.com> 86 */""" 87 88 def generate_header(self): 89 return "\n".join(["#include <" + h + ">" for h in self.headers]) 90 91 def generate_body(self): 92 pass 93 94 def generate_footer(self): 95 pass 96 97 class DispatchTableOpsSubcommand(Subcommand): 98 def run(self): 99 if len(self.argv) < 1: 100 print("DispatchTableOpsSubcommand: <prefix> unspecified") 101 return 102 103 self.prefix = self.argv[0] 104 105 if len(self.argv) > 2: 106 print("DispatchTableOpsSubcommand: <prefix> [outfile]") 107 return 108 109 if len(self.argv) == 2: 110 self.outfile = self.argv[1] 111 112 super(DispatchTableOpsSubcommand, self).run() 113 114 def generate_header(self): 115 return "\n".join(["#include <vulkan/vulkan.h>", 116 "#include <vulkan/vk_layer.h>", 117 "#include <string.h>"]) 118 119 def _generate_init_dispatch(self, type): 120 stmts = [] 121 func = [] 122 if type == "device": 123 # GPA has to be first one and uses wrapped object 124 stmts.append("memset(table, 0, sizeof(*table));") 125 stmts.append("table->GetDeviceProcAddr =(PFN_vkGetDeviceProcAddr) gpa(device,\"vkGetDeviceProcAddr\");") 126 for proto in self.protos: 127 if proto.name == "CreateInstance" or proto.name == "EnumerateInstanceExtensionProperties" or proto.name == "EnumerateInstanceLayerProperties" or proto.params[0].ty == "VkInstance" or proto.params[0].ty == "VkPhysicalDevice": 128 continue 129 if proto.name != "GetDeviceProcAddr" and 'KHR' not in proto.name: 130 stmts.append("table->%s = (PFN_vk%s) gpa(device, \"vk%s\");" % 131 (proto.name, proto.name, proto.name)) 132 func.append("static inline void %s_init_device_dispatch_table(VkDevice device," 133 % self.prefix) 134 func.append("%s VkLayerDispatchTable *table," 135 % (" " * len(self.prefix))) 136 func.append("%s PFN_vkGetDeviceProcAddr gpa)" 137 % (" " * len(self.prefix))) 138 else: 139 stmts.append("table->GetInstanceProcAddr =(PFN_vkGetInstanceProcAddr) gpa(instance,\"vkGetInstanceProcAddr\");") 140 for proto in self.protos: 141 if proto.params[0].ty != "VkInstance" and proto.params[0].ty != "VkPhysicalDevice": 142 continue 143 if proto.name == "CreateDevice": 144 continue 145 if proto.name != "GetInstanceProcAddr" and 'KHR' not in proto.name: 146 stmts.append("table->%s = (PFN_vk%s) gpa(instance, \"vk%s\");" % 147 (proto.name, proto.name, proto.name)) 148 func.append("static inline void %s_init_instance_dispatch_table(" % self.prefix) 149 func.append("%s VkInstance instance," % (" " * len(self.prefix))) 150 func.append("%s VkLayerInstanceDispatchTable *table," % (" " * len(self.prefix))) 151 func.append("%s PFN_vkGetInstanceProcAddr gpa)" % (" " * len(self.prefix))) 152 func.append("{") 153 func.append(" %s" % "\n ".join(stmts)) 154 func.append("}") 155 156 return "\n".join(func) 157 158 def generate_body(self): 159 body = [self._generate_init_dispatch("device"), 160 self._generate_init_dispatch("instance")] 161 162 return "\n\n".join(body) 163 164 class WinDefFileSubcommand(Subcommand): 165 def run(self): 166 library_exports = { 167 "all": [], 168 "icd": [ 169 "vk_icdGetInstanceProcAddr", 170 ], 171 "layer": [ 172 "vkGetInstanceProcAddr", 173 "vkGetDeviceProcAddr", 174 "vkEnumerateInstanceLayerProperties", 175 "vkEnumerateInstanceExtensionProperties" 176 ], 177 "layer_multi": [ 178 "multi2GetInstanceProcAddr", 179 "multi1GetDeviceProcAddr" 180 ] 181 } 182 183 if len(self.argv) < 2 or len(self.argv) > 3 or self.argv[1] not in library_exports: 184 print("WinDefFileSubcommand: <library-name> {%s} [outfile]" % 185 "|".join(library_exports.keys())) 186 return 187 188 self.library = self.argv[0] 189 if self.library == "VkLayer_multi": 190 self.exports = library_exports["layer_multi"] 191 else: 192 self.exports = library_exports[self.argv[1]] 193 194 if len(self.argv) == 3: 195 self.outfile = self.argv[2] 196 197 super(WinDefFileSubcommand, self).run() 198 199 def generate_copyright(self): 200 return """; THIS FILE IS GENERATED. DO NOT EDIT. 201 202 ;;;; Begin Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 203 ; Vulkan 204 ; 205 ; Copyright (c) 2015-2016 The Khronos Group Inc. 206 ; Copyright (c) 2015-2016 Valve Corporation 207 ; Copyright (c) 2015-2016 LunarG, Inc. 208 ; 209 ; Licensed under the Apache License, Version 2.0 (the "License"); 210 ; you may not use this file except in compliance with the License. 211 ; You may obtain a copy of the License at 212 ; 213 ; http://www.apache.org/licenses/LICENSE-2.0 214 ; 215 ; Unless required by applicable law or agreed to in writing, software 216 ; distributed under the License is distributed on an "AS IS" BASIS, 217 ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 218 ; See the License for the specific language governing permissions and 219 ; limitations under the License. 220 ; 221 ; Author: Courtney Goeltzenleuchter <courtney (at] LunarG.com> 222 ;;;; End Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;""" 223 224 def generate_header(self): 225 return "; The following is required on Windows, for exporting symbols from the DLL" 226 227 def generate_body(self): 228 body = [] 229 230 body.append("LIBRARY " + self.library) 231 body.append("EXPORTS") 232 233 for proto in self.exports: 234 if self.library != "VkLayerSwapchain" or proto != "vkEnumerateInstanceExtensionProperties" and proto != "vkEnumerateInstanceLayerProperties": 235 body.append( proto) 236 237 return "\n".join(body) 238 239 def main(): 240 wsi = { 241 "Win32", 242 "Android", 243 "Xcb", 244 "Xlib", 245 "Wayland", 246 "Mir" 247 } 248 subcommands = { 249 "dispatch-table-ops": DispatchTableOpsSubcommand, 250 "win-def-file": WinDefFileSubcommand, 251 } 252 253 if len(sys.argv) < 3 or sys.argv[1] not in wsi or sys.argv[2] not in subcommands: 254 print("Usage: %s <wsi> <subcommand> [options]" % sys.argv[0]) 255 print 256 print("Available sucommands are: %s" % " ".join(subcommands)) 257 exit(1) 258 259 subcmd = subcommands[sys.argv[2]](sys.argv[3:]) 260 subcmd.run() 261 262 if __name__ == "__main__": 263 main() 264