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@lunarg.com> 21# Author: Courtney Goeltzenleuchter <courtney@LunarG.com> 22# Author: Jon Ashburn <jon@lunarg.com> 23# Author: Gwan-gyeong Mun <kk.moon@samsung.com> 24 25import sys 26 27import vulkan 28 29def generate_get_proc_addr_check(name): 30 return " if (!%s || %s[0] != 'v' || %s[1] != 'k')\n" \ 31 " return NULL;" % ((name,) * 3) 32 33class 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@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 97class DispatchTableOpsSubcommand(Subcommand): 98 def __init__(self, argv): 99 self.argv = argv 100 self.headers = vulkan.headers_all 101 self.protos = vulkan.protos_all 102 self.outfile = None 103 104 def run(self): 105 if len(self.argv) < 1: 106 print("DispatchTableOpsSubcommand: <prefix> unspecified") 107 return 108 109 self.prefix = self.argv[0] 110 111 if len(self.argv) > 2: 112 print("DispatchTableOpsSubcommand: <prefix> [outfile]") 113 return 114 115 if len(self.argv) == 2: 116 self.outfile = self.argv[1] 117 118 super(DispatchTableOpsSubcommand, self).run() 119 120 def generate_header(self): 121 return "\n".join(["#include <vulkan/vulkan.h>", 122 "#include <vulkan/vk_layer.h>", 123 "#include <string.h>"]) 124 125 def _generate_init_dispatch(self, type): 126 stmts = [] 127 func = [] 128 if type == "device": 129 # GPA has to be first one and uses wrapped object 130 stmts.append(" memset(table, 0, sizeof(*table));") 131 stmts.append(" // Core device function pointers") 132 stmts.append(" table->GetDeviceProcAddr = (PFN_vkGetDeviceProcAddr) gpa(device, \"vkGetDeviceProcAddr\");") 133 134 for proto in self.protos: 135 if proto.name == "CreateInstance" or proto.name == "EnumerateInstanceExtensionProperties" or \ 136 proto.name == "EnumerateInstanceLayerProperties" or proto.params[0].ty == "VkInstance" or \ 137 proto.params[0].ty == "VkPhysicalDevice" or proto.name == "GetDeviceProcAddr": 138 continue 139 if proto.name == "GetMemoryWin32HandleNV": 140 stmts.append("#ifdef VK_USE_PLATFORM_WIN32_KHR") 141 stmts.append(" table->%s = (PFN_vk%s) gpa(device, \"vk%s\");" % 142 (proto.name, proto.name, proto.name)) 143 stmts.append("#endif // VK_USE_PLATFORM_WIN32_KHR") 144 else: 145 stmts.append(" table->%s = (PFN_vk%s) gpa(device, \"vk%s\");" % 146 (proto.name, proto.name, proto.name)) 147 func.append("static inline void %s_init_device_dispatch_table(VkDevice device," 148 % self.prefix) 149 func.append("%s VkLayerDispatchTable *table," 150 % (" " * len(self.prefix))) 151 func.append("%s PFN_vkGetDeviceProcAddr gpa)" 152 % (" " * len(self.prefix))) 153 else: 154 stmts.append(" memset(table, 0, sizeof(*table));") 155 stmts.append(" // Core instance function pointers") 156 stmts.append(" table->GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) gpa(instance, \"vkGetInstanceProcAddr\");") 157 158 for proto in self.protos: 159 if proto.params[0].ty != "VkInstance" and proto.params[0].ty != "VkPhysicalDevice" or \ 160 proto.name == "CreateDevice" or proto.name == "GetInstanceProcAddr": 161 continue 162 # Protect platform-dependent APIs with #ifdef 163 if 'KHR' in proto.name and 'Win32' in proto.name: 164 stmts.append("#ifdef VK_USE_PLATFORM_WIN32_KHR") 165 if 'KHR' in proto.name and 'Xlib' in proto.name: 166 stmts.append("#ifdef VK_USE_PLATFORM_XLIB_KHR") 167 if 'KHR' in proto.name and 'Xcb' in proto.name: 168 stmts.append("#ifdef VK_USE_PLATFORM_XCB_KHR") 169 if 'KHR' in proto.name and 'Mir' in proto.name: 170 stmts.append("#ifdef VK_USE_PLATFORM_MIR_KHR") 171 if 'KHR' in proto.name and 'Wayland' in proto.name: 172 stmts.append("#ifdef VK_USE_PLATFORM_WAYLAND_KHR") 173 if 'KHR' in proto.name and 'Android' in proto.name: 174 stmts.append("#ifdef VK_USE_PLATFORM_ANDROID_KHR") 175 # Output dispatch table entry 176 stmts.append(" table->%s = (PFN_vk%s) gpa(instance, \"vk%s\");" % 177 (proto.name, proto.name, proto.name)) 178 # If entry was protected by an #ifdef, close with a #endif 179 if 'KHR' in proto.name and 'Win32' in proto.name: 180 stmts.append("#endif // VK_USE_PLATFORM_WIN32_KHR") 181 if 'KHR' in proto.name and 'Xlib' in proto.name: 182 stmts.append("#endif // VK_USE_PLATFORM_XLIB_KHR") 183 if 'KHR' in proto.name and 'Xcb' in proto.name: 184 stmts.append("#endif // VK_USE_PLATFORM_XCB_KHR") 185 if 'KHR' in proto.name and 'Mir' in proto.name: 186 stmts.append("#endif // VK_USE_PLATFORM_MIR_KHR") 187 if 'KHR' in proto.name and 'Wayland' in proto.name: 188 stmts.append("#endif // VK_USE_PLATFORM_WAYLAND_KHR") 189 if 'KHR' in proto.name and 'Android' in proto.name: 190 stmts.append("#endif // VK_USE_PLATFORM_ANDROID_KHR") 191 func.append("static inline void %s_init_instance_dispatch_table(" % self.prefix) 192 func.append("%s VkInstance instance," % (" " * len(self.prefix))) 193 func.append("%s VkLayerInstanceDispatchTable *table," % (" " * len(self.prefix))) 194 func.append("%s PFN_vkGetInstanceProcAddr gpa)" % (" " * len(self.prefix))) 195 func.append("{") 196 func.append("%s" % "\n".join(stmts)) 197 func.append("}") 198 199 return "\n".join(func) 200 201 def generate_body(self): 202 body = [self._generate_init_dispatch("device"), 203 self._generate_init_dispatch("instance")] 204 205 return "\n\n".join(body) 206 207class WinDefFileSubcommand(Subcommand): 208 def run(self): 209 library_exports = { 210 "all": [], 211 "icd": [ 212 "vk_icdGetInstanceProcAddr", 213 ], 214 "layer": [ 215 "vkGetInstanceProcAddr", 216 "vkGetDeviceProcAddr", 217 "vkEnumerateInstanceLayerProperties", 218 "vkEnumerateInstanceExtensionProperties" 219 ], 220 "layer_multi": [ 221 "multi2GetInstanceProcAddr", 222 "multi1GetDeviceProcAddr" 223 ] 224 } 225 226 if len(self.argv) < 2 or len(self.argv) > 3 or self.argv[1] not in library_exports: 227 print("WinDefFileSubcommand: <library-name> {%s} [outfile]" % 228 "|".join(library_exports.keys())) 229 return 230 231 self.library = self.argv[0] 232 if self.library == "VkLayer_multi": 233 self.exports = library_exports["layer_multi"] 234 else: 235 self.exports = library_exports[self.argv[1]] 236 237 if len(self.argv) == 3: 238 self.outfile = self.argv[2] 239 240 super(WinDefFileSubcommand, self).run() 241 242 def generate_copyright(self): 243 return """; THIS FILE IS GENERATED. DO NOT EDIT. 244 245;;;; Begin Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 246; Vulkan 247; 248; Copyright (c) 2015-2016 The Khronos Group Inc. 249; Copyright (c) 2015-2016 Valve Corporation 250; Copyright (c) 2015-2016 LunarG, Inc. 251; 252; Licensed under the Apache License, Version 2.0 (the "License"); 253; you may not use this file except in compliance with the License. 254; You may obtain a copy of the License at 255; 256; http://www.apache.org/licenses/LICENSE-2.0 257; 258; Unless required by applicable law or agreed to in writing, software 259; distributed under the License is distributed on an "AS IS" BASIS, 260; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 261; See the License for the specific language governing permissions and 262; limitations under the License. 263; 264; Author: Courtney Goeltzenleuchter <courtney@LunarG.com> 265;;;; End Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;""" 266 267 def generate_header(self): 268 return "; The following is required on Windows, for exporting symbols from the DLL" 269 270 def generate_body(self): 271 body = [] 272 273 body.append("LIBRARY " + self.library) 274 body.append("EXPORTS") 275 276 for proto in self.exports: 277 if self.library != "VkLayerSwapchain" or proto != "vkEnumerateInstanceExtensionProperties" and proto != "vkEnumerateInstanceLayerProperties": 278 body.append( proto) 279 280 return "\n".join(body) 281 282def main(): 283 wsi = { 284 "Win32", 285 "Android", 286 "Xcb", 287 "Xlib", 288 "Wayland", 289 "Mir", 290 "Display", 291 "AllPlatforms" 292 } 293 subcommands = { 294 "dispatch-table-ops": DispatchTableOpsSubcommand, 295 "win-def-file": WinDefFileSubcommand, 296 } 297 298 if len(sys.argv) < 3 or sys.argv[1] not in wsi or sys.argv[2] not in subcommands: 299 print("Usage: %s <wsi> <subcommand> [options]" % sys.argv[0]) 300 print 301 print("Available sucommands are: %s" % " ".join(subcommands)) 302 exit(1) 303 304 subcmd = subcommands[sys.argv[2]](sys.argv[3:]) 305 subcmd.run() 306 307if __name__ == "__main__": 308 main() 309