vk-generate.py revision 11cd02dfb91661c65134cac258cf5924270e9d2b
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 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 164class 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@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 239def 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 262if __name__ == "__main__": 263 main() 264