1#!/usr/bin/python3 -i 2# 3# Copyright (c) 2015-2017 The Khronos Group Inc. 4# Copyright (c) 2015-2017 Valve Corporation 5# Copyright (c) 2015-2017 LunarG, Inc. 6# Copyright (c) 2015-2017 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: Mark Young <marky@lunarg.com> 21 22import os,re,sys 23import xml.etree.ElementTree as etree 24from generator import * 25from collections import namedtuple 26 27WSI_EXT_NAMES = ['VK_KHR_surface', 28 'VK_KHR_display', 29 'VK_KHR_xlib_surface', 30 'VK_KHR_xcb_surface', 31 'VK_KHR_wayland_surface', 32 'VK_KHR_mir_surface', 33 'VK_KHR_win32_surface', 34 'VK_KHR_android_surface', 35 'VK_KHR_swapchain', 36 'VK_KHR_display_swapchain'] 37 38AVOID_EXT_NAMES = ['VK_EXT_debug_report'] 39 40DEVICE_CMDS_NEED_TERM = ['vkGetDeviceProcAddr', 41 'vkCreateSwapchainKHR', 42 'vkCreateSharedSwapchainsKHR', 43 'vkGetDeviceGroupSurfacePresentModesKHX', 44 'vkDebugMarkerSetObjectTagEXT', 45 'vkDebugMarkerSetObjectNameEXT'] 46 47PRE_INSTANCE_FUNCTIONS = ['vkEnumerateInstanceExtensionProperties', 48 'vkEnumerateInstanceLayerProperties'] 49 50# 51# LoaderExtensionGeneratorOptions - subclass of GeneratorOptions. 52class LoaderExtensionGeneratorOptions(GeneratorOptions): 53 def __init__(self, 54 filename = None, 55 directory = '.', 56 apiname = None, 57 profile = None, 58 versions = '.*', 59 emitversions = '.*', 60 defaultExtensions = None, 61 addExtensions = None, 62 removeExtensions = None, 63 sortProcedure = regSortFeatures, 64 prefixText = "", 65 genFuncPointers = True, 66 protectFile = True, 67 protectFeature = True, 68 protectProto = None, 69 protectProtoStr = None, 70 apicall = '', 71 apientry = '', 72 apientryp = '', 73 alignFuncParam = 0, 74 currentExtension = '', 75 extensionOfInterest = 0): 76 GeneratorOptions.__init__(self, filename, directory, apiname, profile, 77 versions, emitversions, defaultExtensions, 78 addExtensions, removeExtensions, sortProcedure) 79 self.prefixText = prefixText 80 self.genFuncPointers = genFuncPointers 81 self.prefixText = None 82 self.protectFile = protectFile 83 self.protectFeature = protectFeature 84 self.protectProto = protectProto 85 self.protectProtoStr = protectProtoStr 86 self.apicall = apicall 87 self.apientry = apientry 88 self.apientryp = apientryp 89 self.alignFuncParam = alignFuncParam 90# 91# LoaderExtensionOutputGenerator - subclass of OutputGenerator. 92# Generates dispatch table helper header files for LVL 93class LoaderExtensionOutputGenerator(OutputGenerator): 94 """Generate dispatch table helper header based on XML element attributes""" 95 def __init__(self, 96 errFile = sys.stderr, 97 warnFile = sys.stderr, 98 diagFile = sys.stdout): 99 OutputGenerator.__init__(self, errFile, warnFile, diagFile) 100 101 # Internal state - accumulators for different inner block text 102 self.ext_instance_dispatch_list = [] # List of extension entries for instance dispatch list 103 self.ext_device_dispatch_list = [] # List of extension entries for device dispatch list 104 self.core_commands = [] # List of CommandData records for core Vulkan commands 105 self.ext_commands = [] # List of CommandData records for extension Vulkan commands 106 self.CommandParam = namedtuple('CommandParam', ['type', 'name', 'cdecl']) 107 self.CommandData = namedtuple('CommandData', ['name', 'ext_name', 'ext_type', 'protect', 'return_type', 'handle_type', 'params', 'cdecl']) 108 self.instanceExtensions = [] 109 self.ExtensionData = namedtuple('ExtensionData', ['name', 'type', 'protect', 'define', 'num_commands']) 110 111 # 112 # Called once at the beginning of each run 113 def beginFile(self, genOpts): 114 OutputGenerator.beginFile(self, genOpts) 115 116 # User-supplied prefix text, if any (list of strings) 117 if (genOpts.prefixText): 118 for s in genOpts.prefixText: 119 write(s, file=self.outFile) 120 121 # File Comment 122 file_comment = '// *** THIS FILE IS GENERATED - DO NOT EDIT ***\n' 123 file_comment += '// See loader_extension_generator.py for modifications\n' 124 write(file_comment, file=self.outFile) 125 126 # Copyright Notice 127 copyright = '/*\n' 128 copyright += ' * Copyright (c) 2015-2017 The Khronos Group Inc.\n' 129 copyright += ' * Copyright (c) 2015-2017 Valve Corporation\n' 130 copyright += ' * Copyright (c) 2015-2017 LunarG, Inc.\n' 131 copyright += ' *\n' 132 copyright += ' * Licensed under the Apache License, Version 2.0 (the "License");\n' 133 copyright += ' * you may not use this file except in compliance with the License.\n' 134 copyright += ' * You may obtain a copy of the License at\n' 135 copyright += ' *\n' 136 copyright += ' * http://www.apache.org/licenses/LICENSE-2.0\n' 137 copyright += ' *\n' 138 copyright += ' * Unless required by applicable law or agreed to in writing, software\n' 139 copyright += ' * distributed under the License is distributed on an "AS IS" BASIS,\n' 140 copyright += ' * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n' 141 copyright += ' * See the License for the specific language governing permissions and\n' 142 copyright += ' * limitations under the License.\n' 143 copyright += ' *\n' 144 copyright += ' * Author: Mark Lobodzinski <mark@lunarg.com>\n' 145 copyright += ' * Author: Mark Young <marky@lunarg.com>\n' 146 copyright += ' */\n' 147 148 preamble = '' 149 150 if self.genOpts.filename == 'vk_loader_extensions.h': 151 preamble += '#pragma once\n' 152 153 elif self.genOpts.filename == 'vk_loader_extensions.c': 154 preamble += '#define _GNU_SOURCE\n' 155 preamble += '#include <stdio.h>\n' 156 preamble += '#include <stdlib.h>\n' 157 preamble += '#include <string.h>\n' 158 preamble += '#include "vk_loader_platform.h"\n' 159 preamble += '#include "loader.h"\n' 160 preamble += '#include "vk_loader_extensions.h"\n' 161 preamble += '#include <vulkan/vk_icd.h>\n' 162 preamble += '#include "wsi.h"\n' 163 preamble += '#include "debug_report.h"\n' 164 preamble += '#include "extension_manual.h"\n' 165 166 elif self.genOpts.filename == 'vk_layer_dispatch_table.h': 167 preamble += '#pragma once\n' 168 preamble += '\n' 169 preamble += 'typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_GetPhysicalDeviceProcAddr)(VkInstance instance, const char* pName);\n' 170 171 write(copyright, file=self.outFile) 172 write(preamble, file=self.outFile) 173 174 # 175 # Write generate and write dispatch tables to output file 176 def endFile(self): 177 file_data = '' 178 179 if self.genOpts.filename == 'vk_loader_extensions.h': 180 file_data += self.OutputPrototypesInHeader() 181 file_data += self.OutputLoaderTerminators() 182 file_data += self.OutputIcdDispatchTable() 183 file_data += self.OutputIcdExtensionEnableUnion() 184 185 elif self.genOpts.filename == 'vk_loader_extensions.c': 186 file_data += self.OutputUtilitiesInSource() 187 file_data += self.OutputIcdDispatchTableInit() 188 file_data += self.OutputLoaderDispatchTables() 189 file_data += self.OutputLoaderLookupFunc() 190 file_data += self.CreateTrampTermFuncs() 191 file_data += self.InstExtensionGPA() 192 file_data += self.InstantExtensionCreate() 193 file_data += self.DeviceExtensionGetTerminator() 194 file_data += self.InitInstLoaderExtensionDispatchTable() 195 file_data += self.OutputInstantExtensionWhitelistArray() 196 197 elif self.genOpts.filename == 'vk_layer_dispatch_table.h': 198 file_data += self.OutputLayerInstanceDispatchTable() 199 file_data += self.OutputLayerDeviceDispatchTable() 200 201 write(file_data, file=self.outFile); 202 203 # Finish processing in superclass 204 OutputGenerator.endFile(self) 205 206 def beginFeature(self, interface, emit): 207 # Start processing in superclass 208 OutputGenerator.beginFeature(self, interface, emit) 209 210 enums = interface[0].findall('enum') 211 self.currentExtension = '' 212 self.name_definition = '' 213 214 for item in enums: 215 name_definition = item.get('name') 216 if 'EXTENSION_NAME' in name_definition: 217 self.name_definition = name_definition 218 219 self.type = interface.get('type') 220 self.num_commands = 0 221 name = interface.get('name') 222 self.currentExtension = name 223 224 # 225 # Process commands, adding to appropriate dispatch tables 226 def genCmd(self, cmdinfo, name): 227 OutputGenerator.genCmd(self, cmdinfo, name) 228 229 # Get first param type 230 params = cmdinfo.elem.findall('param') 231 info = self.getTypeNameTuple(params[0]) 232 233 self.num_commands += 1 234 235 if 'android' not in name: 236 self.AddCommandToDispatchList(self.currentExtension, self.type, name, cmdinfo, info[0]) 237 238 def endFeature(self): 239 240 if 'android' not in self.currentExtension: 241 self.instanceExtensions.append(self.ExtensionData(name=self.currentExtension, 242 type=self.type, 243 protect=self.featureExtraProtect, 244 define=self.name_definition, 245 num_commands=self.num_commands)) 246 247 # Finish processing in superclass 248 OutputGenerator.endFeature(self) 249 250 # 251 # Retrieve the value of the len tag 252 def getLen(self, param): 253 result = None 254 len = param.attrib.get('len') 255 if len and len != 'null-terminated': 256 # For string arrays, 'len' can look like 'count,null-terminated', 257 # indicating that we have a null terminated array of strings. We 258 # strip the null-terminated from the 'len' field and only return 259 # the parameter specifying the string count 260 if 'null-terminated' in len: 261 result = len.split(',')[0] 262 else: 263 result = len 264 result = str(result).replace('::', '->') 265 return result 266 267 # 268 # Determine if this API should be ignored or added to the instance or device dispatch table 269 def AddCommandToDispatchList(self, extension_name, extension_type, name, cmdinfo, handle_type): 270 handle = self.registry.tree.find("types/type/[name='" + handle_type + "'][@category='handle']") 271 272 return_type = cmdinfo.elem.find('proto/type') 273 if (return_type != None and return_type.text == 'void'): 274 return_type = None 275 276 cmd_params = [] 277 278 # Generate a list of commands for use in printing the necessary 279 # core instance terminator prototypes 280 params = cmdinfo.elem.findall('param') 281 lens = set() 282 for param in params: 283 len = self.getLen(param) 284 if len: 285 lens.add(len) 286 paramsInfo = [] 287 for param in params: 288 paramInfo = self.getTypeNameTuple(param) 289 param_type = paramInfo[0] 290 param_name = paramInfo[1] 291 param_cdecl = self.makeCParamDecl(param, 0) 292 cmd_params.append(self.CommandParam(type=param_type, name=param_name, 293 cdecl=param_cdecl)) 294 295 if handle != None and handle_type != 'VkInstance' and handle_type != 'VkPhysicalDevice': 296 # The Core Vulkan code will be wrapped in a feature called VK_VERSION_#_# 297 # For example: VK_VERSION_1_0 wraps the core 1.0 Vulkan functionality 298 if 'VK_VERSION_' in extension_name: 299 self.core_commands.append( 300 self.CommandData(name=name, ext_name=extension_name, 301 ext_type='device', 302 protect=self.featureExtraProtect, 303 return_type = return_type, 304 handle_type = handle_type, 305 params = cmd_params, 306 cdecl=self.makeCDecls(cmdinfo.elem)[0])) 307 else: 308 self.ext_device_dispatch_list.append((name, self.featureExtraProtect)) 309 self.ext_commands.append( 310 self.CommandData(name=name, ext_name=extension_name, 311 ext_type=extension_type, 312 protect=self.featureExtraProtect, 313 return_type = return_type, 314 handle_type = handle_type, 315 params = cmd_params, 316 cdecl=self.makeCDecls(cmdinfo.elem)[0])) 317 else: 318 # The Core Vulkan code will be wrapped in a feature called VK_VERSION_#_# 319 # For example: VK_VERSION_1_0 wraps the core 1.0 Vulkan functionality 320 if 'VK_VERSION_' in extension_name: 321 self.core_commands.append( 322 self.CommandData(name=name, ext_name=extension_name, 323 ext_type='instance', 324 protect=self.featureExtraProtect, 325 return_type = return_type, 326 handle_type = handle_type, 327 params = cmd_params, 328 cdecl=self.makeCDecls(cmdinfo.elem)[0])) 329 330 else: 331 self.ext_instance_dispatch_list.append((name, self.featureExtraProtect)) 332 self.ext_commands.append( 333 self.CommandData(name=name, ext_name=extension_name, 334 ext_type=extension_type, 335 protect=self.featureExtraProtect, 336 return_type = return_type, 337 handle_type = handle_type, 338 params = cmd_params, 339 cdecl=self.makeCDecls(cmdinfo.elem)[0])) 340 341 # 342 # Retrieve the type and name for a parameter 343 def getTypeNameTuple(self, param): 344 type = '' 345 name = '' 346 for elem in param: 347 if elem.tag == 'type': 348 type = noneStr(elem.text) 349 elif elem.tag == 'name': 350 name = noneStr(elem.text) 351 return (type, name) 352 353 def OutputPrototypesInHeader(self): 354 protos = '' 355 protos += '// Structures defined externally, but used here\n' 356 protos += 'struct loader_instance;\n' 357 protos += 'struct loader_icd_term;\n' 358 protos += 'struct loader_dev_dispatch_table;\n' 359 protos += '\n' 360 protos += '// Device extension error function\n' 361 protos += 'VKAPI_ATTR VkResult VKAPI_CALL vkDevExtError(VkDevice dev);\n' 362 protos += '\n' 363 protos += '// Extension interception for vkGetInstanceProcAddr function, so we can return\n' 364 protos += '// the appropriate information for any instance extensions we know about.\n' 365 protos += 'bool extension_instance_gpa(struct loader_instance *ptr_instance, const char *name, void **addr);\n' 366 protos += '\n' 367 protos += '// Extension interception for vkCreateInstance function, so we can properly\n' 368 protos += '// detect and enable any instance extension information for extensions we know\n' 369 protos += '// about.\n' 370 protos += 'void extensions_create_instance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo);\n' 371 protos += '\n' 372 protos += '// Extension interception for vkGetDeviceProcAddr function, so we can return\n' 373 protos += '// an appropriate terminator if this is one of those few device commands requiring\n' 374 protos += '// a terminator.\n' 375 protos += 'PFN_vkVoidFunction get_extension_device_proc_terminator(const char *pName);\n' 376 protos += '\n' 377 protos += '// Dispatch table properly filled in with appropriate terminators for the\n' 378 protos += '// supported extensions.\n' 379 protos += 'extern const VkLayerInstanceDispatchTable instance_disp;\n' 380 protos += '\n' 381 protos += '// Array of extension strings for instance extensions we support.\n' 382 protos += 'extern const char *const LOADER_INSTANCE_EXTENSIONS[];\n' 383 protos += '\n' 384 protos += 'VKAPI_ATTR bool VKAPI_CALL loader_icd_init_entries(struct loader_icd_term *icd_term, VkInstance inst,\n' 385 protos += ' const PFN_vkGetInstanceProcAddr fp_gipa);\n' 386 protos += '\n' 387 protos += '// Init Device function pointer dispatch table with core commands\n' 388 protos += 'VKAPI_ATTR void VKAPI_CALL loader_init_device_dispatch_table(struct loader_dev_dispatch_table *dev_table, PFN_vkGetDeviceProcAddr gpa,\n' 389 protos += ' VkDevice dev);\n' 390 protos += '\n' 391 protos += '// Init Device function pointer dispatch table with extension commands\n' 392 protos += 'VKAPI_ATTR void VKAPI_CALL loader_init_device_extension_dispatch_table(struct loader_dev_dispatch_table *dev_table,\n' 393 protos += ' PFN_vkGetDeviceProcAddr gpa, VkDevice dev);\n' 394 protos += '\n' 395 protos += '// Init Instance function pointer dispatch table with core commands\n' 396 protos += 'VKAPI_ATTR void VKAPI_CALL loader_init_instance_core_dispatch_table(VkLayerInstanceDispatchTable *table, PFN_vkGetInstanceProcAddr gpa,\n' 397 protos += ' VkInstance inst);\n' 398 protos += '\n' 399 protos += '// Init Instance function pointer dispatch table with core commands\n' 400 protos += 'VKAPI_ATTR void VKAPI_CALL loader_init_instance_extension_dispatch_table(VkLayerInstanceDispatchTable *table, PFN_vkGetInstanceProcAddr gpa,\n' 401 protos += ' VkInstance inst);\n' 402 protos += '\n' 403 protos += '// Device command lookup function\n' 404 protos += 'VKAPI_ATTR void* VKAPI_CALL loader_lookup_device_dispatch_table(const VkLayerDispatchTable *table, const char *name);\n' 405 protos += '\n' 406 protos += '// Instance command lookup function\n' 407 protos += 'VKAPI_ATTR void* VKAPI_CALL loader_lookup_instance_dispatch_table(const VkLayerInstanceDispatchTable *table, const char *name,\n' 408 protos += ' bool *found_name);\n' 409 protos += '\n' 410 protos += 'VKAPI_ATTR bool VKAPI_CALL loader_icd_init_entries(struct loader_icd_term *icd_term, VkInstance inst,\n' 411 protos += ' const PFN_vkGetInstanceProcAddr fp_gipa);\n' 412 protos += '\n' 413 return protos 414 415 def OutputUtilitiesInSource(self): 416 protos = '' 417 protos += '// Device extension error function\n' 418 protos += 'VKAPI_ATTR VkResult VKAPI_CALL vkDevExtError(VkDevice dev) {\n' 419 protos += ' struct loader_device *found_dev;\n' 420 protos += ' // The device going in is a trampoline device\n' 421 protos += ' struct loader_icd_term *icd_term = loader_get_icd_and_device(dev, &found_dev, NULL);\n' 422 protos += '\n' 423 protos += ' if (icd_term)\n' 424 protos += ' loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,\n' 425 protos += ' "Bad destination in loader trampoline dispatch,"\n' 426 protos += ' "Are layers and extensions that you are calling enabled?");\n' 427 protos += ' return VK_ERROR_EXTENSION_NOT_PRESENT;\n' 428 protos += '}\n\n' 429 return protos 430 431 # 432 # Create a layer instance dispatch table from the appropriate list and return it as a string 433 def OutputLayerInstanceDispatchTable(self): 434 commands = [] 435 table = '' 436 cur_extension_name = '' 437 438 table += '// Instance function pointer dispatch table\n' 439 table += 'typedef struct VkLayerInstanceDispatchTable_ {\n' 440 441 # First add in an entry for GetPhysicalDeviceProcAddr. This will not 442 # ever show up in the XML or header, so we have to manually add it. 443 table += ' // Manually add in GetPhysicalDeviceProcAddr entry\n' 444 table += ' PFN_GetPhysicalDeviceProcAddr GetPhysicalDeviceProcAddr;\n' 445 446 for x in range(0, 2): 447 if x == 0: 448 commands = self.core_commands 449 else: 450 commands = self.ext_commands 451 452 for cur_cmd in commands: 453 is_inst_handle_type = cur_cmd.ext_type == 'instance' or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice' 454 if is_inst_handle_type: 455 456 if cur_cmd.ext_name != cur_extension_name: 457 if 'VK_VERSION_' in cur_cmd.ext_name: 458 table += '\n // ---- Core %s commands\n' % cur_cmd.ext_name[11:] 459 else: 460 table += '\n // ---- %s extension commands\n' % cur_cmd.ext_name 461 cur_extension_name = cur_cmd.ext_name 462 463 # Remove 'vk' from proto name 464 base_name = cur_cmd.name[2:] 465 466 if cur_cmd.protect is not None: 467 table += '#ifdef %s\n' % cur_cmd.protect 468 469 table += ' PFN_%s %s;\n' % (cur_cmd.name, base_name) 470 471 if cur_cmd.protect is not None: 472 table += '#endif // %s\n' % cur_cmd.protect 473 474 table += '} VkLayerInstanceDispatchTable;\n\n' 475 return table 476 477 # 478 # Create a layer device dispatch table from the appropriate list and return it as a string 479 def OutputLayerDeviceDispatchTable(self): 480 commands = [] 481 table = '' 482 cur_extension_name = '' 483 484 table += '// Device function pointer dispatch table\n' 485 table += 'typedef struct VkLayerDispatchTable_ {\n' 486 487 for x in range(0, 2): 488 if x == 0: 489 commands = self.core_commands 490 else: 491 commands = self.ext_commands 492 493 for cur_cmd in commands: 494 is_inst_handle_type = cur_cmd.ext_type == 'instance' or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice' 495 if not is_inst_handle_type: 496 497 if cur_cmd.ext_name != cur_extension_name: 498 if 'VK_VERSION_' in cur_cmd.ext_name: 499 table += '\n // ---- Core %s commands\n' % cur_cmd.ext_name[11:] 500 else: 501 table += '\n // ---- %s extension commands\n' % cur_cmd.ext_name 502 cur_extension_name = cur_cmd.ext_name 503 504 # Remove 'vk' from proto name 505 base_name = cur_cmd.name[2:] 506 507 if cur_cmd.protect is not None: 508 table += '#ifdef %s\n' % cur_cmd.protect 509 510 table += ' PFN_%s %s;\n' % (cur_cmd.name, base_name) 511 512 if cur_cmd.protect is not None: 513 table += '#endif // %s\n' % cur_cmd.protect 514 515 table += '} VkLayerDispatchTable;\n\n' 516 return table 517 518 # 519 # Create a dispatch table from the appropriate list and return it as a string 520 def OutputIcdDispatchTable(self): 521 commands = [] 522 table = '' 523 cur_extension_name = '' 524 525 table += '// ICD function pointer dispatch table\n' 526 table += 'struct loader_icd_term_dispatch {\n' 527 528 for x in range(0, 2): 529 if x == 0: 530 commands = self.core_commands 531 else: 532 commands = self.ext_commands 533 534 for cur_cmd in commands: 535 is_inst_handle_type = cur_cmd.ext_type == 'instance' or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice' 536 if ((is_inst_handle_type or cur_cmd.name in DEVICE_CMDS_NEED_TERM) and 537 (cur_cmd.name != 'vkGetInstanceProcAddr' and cur_cmd.name != 'vkEnumerateDeviceLayerProperties')): 538 539 if cur_cmd.ext_name != cur_extension_name: 540 if 'VK_VERSION_' in cur_cmd.ext_name: 541 table += '\n // ---- Core %s commands\n' % cur_cmd.ext_name[11:] 542 else: 543 table += '\n // ---- %s extension commands\n' % cur_cmd.ext_name 544 cur_extension_name = cur_cmd.ext_name 545 546 # Remove 'vk' from proto name 547 base_name = cur_cmd.name[2:] 548 549 if cur_cmd.protect is not None: 550 table += '#ifdef %s\n' % cur_cmd.protect 551 552 table += ' PFN_%s %s;\n' % (cur_cmd.name, base_name) 553 554 if cur_cmd.protect is not None: 555 table += '#endif // %s\n' % cur_cmd.protect 556 557 table += '};\n\n' 558 return table 559 560 # 561 # Init a dispatch table from the appropriate list and return it as a string 562 def OutputIcdDispatchTableInit(self): 563 commands = [] 564 cur_extension_name = '' 565 566 table = '' 567 table += 'VKAPI_ATTR bool VKAPI_CALL loader_icd_init_entries(struct loader_icd_term *icd_term, VkInstance inst,\n' 568 table += ' const PFN_vkGetInstanceProcAddr fp_gipa) {\n' 569 table += '\n' 570 table += '#define LOOKUP_GIPA(func, required) \\\n' 571 table += ' do { \\\n' 572 table += ' icd_term->dispatch.func = (PFN_vk##func)fp_gipa(inst, "vk" #func); \\\n' 573 table += ' if (!icd_term->dispatch.func && required) { \\\n' 574 table += ' loader_log((struct loader_instance *)inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, \\\n' 575 table += ' loader_platform_get_proc_address_error("vk" #func)); \\\n' 576 table += ' return false; \\\n' 577 table += ' } \\\n' 578 table += ' } while (0)\n' 579 table += '\n' 580 581 skip_gipa_commands = ['vkGetInstanceProcAddr', 582 'vkEnumerateDeviceLayerProperties', 583 'vkCreateInstance', 584 'vkEnumerateInstanceExtensionProperties', 585 'vkEnumerateInstanceLayerProperties', 586 ] 587 588 for x in range(0, 2): 589 if x == 0: 590 commands = self.core_commands 591 else: 592 commands = self.ext_commands 593 594 for cur_cmd in commands: 595 is_inst_handle_type = cur_cmd.ext_type == 'instance' or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice' 596 if ((is_inst_handle_type or cur_cmd.name in DEVICE_CMDS_NEED_TERM) and (cur_cmd.name not in skip_gipa_commands)): 597 598 if cur_cmd.ext_name != cur_extension_name: 599 if 'VK_VERSION_' in cur_cmd.ext_name: 600 table += '\n // ---- Core %s\n' % cur_cmd.ext_name[11:] 601 else: 602 table += '\n // ---- %s extension commands\n' % cur_cmd.ext_name 603 cur_extension_name = cur_cmd.ext_name 604 605 # Remove 'vk' from proto name 606 base_name = cur_cmd.name[2:] 607 608 if cur_cmd.protect is not None: 609 table += '#ifdef %s\n' % cur_cmd.protect 610 611 # The Core Vulkan code will be wrapped in a feature called VK_VERSION_#_# 612 # For example: VK_VERSION_1_0 wraps the core 1.0 Vulkan functionality 613 if x == 0: 614 table += ' LOOKUP_GIPA(%s, true);\n' % (base_name) 615 else: 616 table += ' LOOKUP_GIPA(%s, false);\n' % (base_name) 617 618 if cur_cmd.protect is not None: 619 table += '#endif // %s\n' % cur_cmd.protect 620 621 table += '\n' 622 table += '#undef LOOKUP_GIPA\n' 623 table += '\n' 624 table += ' return true;\n' 625 table += '};\n\n' 626 return table 627 628 # 629 # Create the extension enable union 630 def OutputIcdExtensionEnableUnion(self): 631 extensions = self.instanceExtensions 632 633 union = '' 634 union += 'union loader_instance_extension_enables {\n' 635 union += ' struct {\n' 636 for ext in extensions: 637 if ('VK_VERSION_' in ext.name or ext.name in WSI_EXT_NAMES or 638 ext.type == 'device' or ext.num_commands == 0): 639 continue 640 641 union += ' uint8_t %s : 1;\n' % ext.name[3:].lower() 642 643 union += ' };\n' 644 union += ' uint64_t padding[4];\n' 645 union += '};\n\n' 646 return union 647 648 # 649 # Creates the prototypes for the loader's core instance command terminators 650 def OutputLoaderTerminators(self): 651 terminators = '' 652 terminators += '// Loader core instance terminators\n' 653 654 for cur_cmd in self.core_commands: 655 is_inst_handle_type = cur_cmd.ext_type == 'instance' or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice' 656 if is_inst_handle_type: 657 mod_string = '' 658 new_terminator = cur_cmd.cdecl 659 mod_string = new_terminator.replace("VKAPI_CALL vk", "VKAPI_CALL terminator_") 660 661 if cur_cmd.name in PRE_INSTANCE_FUNCTIONS: 662 mod_string = mod_string.replace(cur_cmd.name[2:] + '(\n', cur_cmd.name[2:] + '(\n const Vk' + cur_cmd.name[2:] + 'Chain* chain,\n') 663 664 if (cur_cmd.protect != None): 665 terminators += '#ifdef %s\n' % cur_cmd.protect 666 667 terminators += mod_string 668 terminators += '\n' 669 670 if (cur_cmd.protect != None): 671 terminators += '#endif // %s\n' % cur_cmd.protect 672 673 terminators += '\n' 674 return terminators 675 676 # 677 # Creates code to initialize the various dispatch tables 678 def OutputLoaderDispatchTables(self): 679 commands = [] 680 tables = '' 681 gpa_param = '' 682 cur_type = '' 683 cur_extension_name = '' 684 685 for x in range(0, 4): 686 if x == 0: 687 cur_type = 'device' 688 gpa_param = 'dev' 689 commands = self.core_commands 690 691 tables += '// Init Device function pointer dispatch table with core commands\n' 692 tables += 'VKAPI_ATTR void VKAPI_CALL loader_init_device_dispatch_table(struct loader_dev_dispatch_table *dev_table, PFN_vkGetDeviceProcAddr gpa,\n' 693 tables += ' VkDevice dev) {\n' 694 tables += ' VkLayerDispatchTable *table = &dev_table->core_dispatch;\n' 695 tables += ' for (uint32_t i = 0; i < MAX_NUM_UNKNOWN_EXTS; i++) dev_table->ext_dispatch.dev_ext[i] = (PFN_vkDevExt)vkDevExtError;\n' 696 697 elif x == 1: 698 cur_type = 'device' 699 gpa_param = 'dev' 700 commands = self.ext_commands 701 702 tables += '// Init Device function pointer dispatch table with extension commands\n' 703 tables += 'VKAPI_ATTR void VKAPI_CALL loader_init_device_extension_dispatch_table(struct loader_dev_dispatch_table *dev_table,\n' 704 tables += ' PFN_vkGetDeviceProcAddr gpa, VkDevice dev) {\n' 705 tables += ' VkLayerDispatchTable *table = &dev_table->core_dispatch;\n' 706 707 elif x == 2: 708 cur_type = 'instance' 709 gpa_param = 'inst' 710 commands = self.core_commands 711 712 tables += '// Init Instance function pointer dispatch table with core commands\n' 713 tables += 'VKAPI_ATTR void VKAPI_CALL loader_init_instance_core_dispatch_table(VkLayerInstanceDispatchTable *table, PFN_vkGetInstanceProcAddr gpa,\n' 714 tables += ' VkInstance inst) {\n' 715 716 else: 717 cur_type = 'instance' 718 gpa_param = 'inst' 719 commands = self.ext_commands 720 721 tables += '// Init Instance function pointer dispatch table with core commands\n' 722 tables += 'VKAPI_ATTR void VKAPI_CALL loader_init_instance_extension_dispatch_table(VkLayerInstanceDispatchTable *table, PFN_vkGetInstanceProcAddr gpa,\n' 723 tables += ' VkInstance inst) {\n' 724 725 for cur_cmd in commands: 726 is_inst_handle_type = cur_cmd.ext_type == 'instance' or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice' 727 if ((cur_type == 'instance' and is_inst_handle_type) or (cur_type == 'device' and not is_inst_handle_type)): 728 if cur_cmd.ext_name != cur_extension_name: 729 if 'VK_VERSION_' in cur_cmd.ext_name: 730 tables += '\n // ---- Core %s commands\n' % cur_cmd.ext_name[11:] 731 else: 732 tables += '\n // ---- %s extension commands\n' % cur_cmd.ext_name 733 cur_extension_name = cur_cmd.ext_name 734 735 # Remove 'vk' from proto name 736 base_name = cur_cmd.name[2:] 737 738 # Names to skip 739 if (base_name == 'CreateInstance' or base_name == 'CreateDevice' or 740 base_name == 'EnumerateInstanceExtensionProperties' or 741 base_name == 'EnumerateInstanceLayerProperties'): 742 continue 743 744 if cur_cmd.protect is not None: 745 tables += '#ifdef %s\n' % cur_cmd.protect 746 747 # If we're looking for the proc we are passing in, just point the table to it. This fixes the issue where 748 # a layer overrides the function name for the loader. 749 if (x <= 1 and base_name == 'GetDeviceProcAddr'): 750 tables += ' table->GetDeviceProcAddr = gpa;\n' 751 elif (x > 1 and base_name == 'GetInstanceProcAddr'): 752 tables += ' table->GetInstanceProcAddr = gpa;\n' 753 else: 754 tables += ' table->%s = (PFN_%s)gpa(%s, "%s");\n' % (base_name, cur_cmd.name, gpa_param, cur_cmd.name) 755 756 if cur_cmd.protect is not None: 757 tables += '#endif // %s\n' % cur_cmd.protect 758 759 tables += '}\n\n' 760 return tables 761 762 # 763 # Create a lookup table function from the appropriate list of entrypoints and 764 # return it as a string 765 def OutputLoaderLookupFunc(self): 766 commands = [] 767 tables = '' 768 cur_type = '' 769 cur_extension_name = '' 770 771 for x in range(0, 2): 772 if x == 0: 773 cur_type = 'device' 774 775 tables += '// Device command lookup function\n' 776 tables += 'VKAPI_ATTR void* VKAPI_CALL loader_lookup_device_dispatch_table(const VkLayerDispatchTable *table, const char *name) {\n' 777 tables += ' if (!name || name[0] != \'v\' || name[1] != \'k\') return NULL;\n' 778 tables += '\n' 779 tables += ' name += 2;\n' 780 else: 781 cur_type = 'instance' 782 783 tables += '// Instance command lookup function\n' 784 tables += 'VKAPI_ATTR void* VKAPI_CALL loader_lookup_instance_dispatch_table(const VkLayerInstanceDispatchTable *table, const char *name,\n' 785 tables += ' bool *found_name) {\n' 786 tables += ' if (!name || name[0] != \'v\' || name[1] != \'k\') {\n' 787 tables += ' *found_name = false;\n' 788 tables += ' return NULL;\n' 789 tables += ' }\n' 790 tables += '\n' 791 tables += ' *found_name = true;\n' 792 tables += ' name += 2;\n' 793 794 for y in range(0, 2): 795 if y == 0: 796 commands = self.core_commands 797 else: 798 commands = self.ext_commands 799 800 for cur_cmd in commands: 801 is_inst_handle_type = cur_cmd.ext_type == 'instance' or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice' 802 if ((cur_type == 'instance' and is_inst_handle_type) or (cur_type == 'device' and not is_inst_handle_type)): 803 804 if cur_cmd.ext_name != cur_extension_name: 805 if 'VK_VERSION_' in cur_cmd.ext_name: 806 tables += '\n // ---- Core %s commands\n' % cur_cmd.ext_name[11:] 807 else: 808 tables += '\n // ---- %s extension commands\n' % cur_cmd.ext_name 809 cur_extension_name = cur_cmd.ext_name 810 811 # Remove 'vk' from proto name 812 base_name = cur_cmd.name[2:] 813 814 if (base_name == 'CreateInstance' or base_name == 'CreateDevice' or 815 base_name == 'EnumerateInstanceExtensionProperties' or 816 base_name == 'EnumerateInstanceLayerProperties'): 817 continue 818 819 if cur_cmd.protect is not None: 820 tables += '#ifdef %s\n' % cur_cmd.protect 821 822 tables += ' if (!strcmp(name, "%s")) return (void *)table->%s;\n' % (base_name, base_name) 823 824 if cur_cmd.protect is not None: 825 tables += '#endif // %s\n' % cur_cmd.protect 826 827 tables += '\n' 828 if x == 1: 829 tables += ' *found_name = false;\n' 830 tables += ' return NULL;\n' 831 tables += '}\n\n' 832 return tables 833 834 # 835 # Create the appropriate trampoline (and possibly terminator) functinos 836 def CreateTrampTermFuncs(self): 837 entries = [] 838 funcs = '' 839 cur_extension_name = '' 840 841 # Some extensions have to be manually added. Skip those in the automatic 842 # generation. They will be manually added later. 843 manual_ext_commands = ['vkEnumeratePhysicalDeviceGroupsKHX', 844 'vkGetPhysicalDeviceExternalImageFormatPropertiesNV', 845 'vkGetPhysicalDeviceFeatures2KHR', 846 'vkGetPhysicalDeviceProperties2KHR', 847 'vkGetPhysicalDeviceFormatProperties2KHR', 848 'vkGetPhysicalDeviceImageFormatProperties2KHR', 849 'vkGetPhysicalDeviceQueueFamilyProperties2KHR', 850 'vkGetPhysicalDeviceMemoryProperties2KHR', 851 'vkGetPhysicalDeviceSparseImageFormatProperties2KHR', 852 'vkGetPhysicalDeviceSurfaceCapabilities2KHR', 853 'vkGetPhysicalDeviceSurfaceFormats2KHR', 854 'vkGetPhysicalDeviceSurfaceCapabilities2EXT', 855 'vkReleaseDisplayEXT', 856 'vkAcquireXlibDisplayEXT', 857 'vkGetRandROutputDisplayEXT', 858 'vkGetPhysicalDeviceExternalBufferPropertiesKHR', 859 'vkGetPhysicalDeviceExternalSemaphorePropertiesKHR', 860 'vkGetPhysicalDeviceExternalFencePropertiesKHR'] 861 862 for ext_cmd in self.ext_commands: 863 if (ext_cmd.ext_name in WSI_EXT_NAMES or 864 ext_cmd.ext_name in AVOID_EXT_NAMES or 865 ext_cmd.name in manual_ext_commands): 866 continue 867 868 if ext_cmd.ext_name != cur_extension_name: 869 if 'VK_VERSION_' in ext_cmd.ext_name: 870 funcs += '\n// ---- Core %s trampoline/terminators\n\n' % ext_cmd.ext_name[11:] 871 else: 872 funcs += '\n// ---- %s extension trampoline/terminators\n\n' % ext_cmd.ext_name 873 cur_extension_name = ext_cmd.ext_name 874 875 if ext_cmd.protect is not None: 876 funcs += '#ifdef %s\n' % ext_cmd.protect 877 878 func_header = ext_cmd.cdecl.replace(";", " {\n") 879 tramp_header = func_header.replace("VKAPI_CALL vk", "VKAPI_CALL ") 880 return_prefix = ' ' 881 base_name = ext_cmd.name[2:] 882 has_surface = 0 883 update_structure_surface = 0 884 update_structure_string = '' 885 requires_terminator = 0 886 surface_var_name = '' 887 phys_dev_var_name = '' 888 has_return_type = False 889 always_use_param_name = True 890 surface_type_to_replace = '' 891 surface_name_replacement = '' 892 physdev_type_to_replace = '' 893 physdev_name_replacement = '' 894 895 for param in ext_cmd.params: 896 if param.type == 'VkSurfaceKHR': 897 has_surface = 1 898 surface_var_name = param.name 899 requires_terminator = 1 900 always_use_param_name = False 901 surface_type_to_replace = 'VkSurfaceKHR' 902 surface_name_replacement = 'icd_surface->real_icd_surfaces[icd_index]' 903 if param.type == 'VkPhysicalDeviceSurfaceInfo2KHR': 904 has_surface = 1 905 surface_var_name = param.name + '->surface' 906 requires_terminator = 1 907 update_structure_surface = 1 908 update_structure_string = ' VkPhysicalDeviceSurfaceInfo2KHR info_copy = *pSurfaceInfo;\n' 909 update_structure_string += ' info_copy.surface = icd_surface->real_icd_surfaces[icd_index];\n' 910 always_use_param_name = False 911 surface_type_to_replace = 'VkPhysicalDeviceSurfaceInfo2KHR' 912 surface_name_replacement = '&info_copy' 913 if param.type == 'VkPhysicalDevice': 914 requires_terminator = 1 915 phys_dev_var_name = param.name 916 always_use_param_name = False 917 physdev_type_to_replace = 'VkPhysicalDevice' 918 physdev_name_replacement = 'phys_dev_term->phys_dev' 919 920 if (ext_cmd.return_type != None): 921 return_prefix += 'return ' 922 has_return_type = True 923 924 if (ext_cmd.ext_type == 'instance' or ext_cmd.handle_type == 'VkPhysicalDevice' or 925 'DebugMarkerSetObject' in ext_cmd.name or ext_cmd.name in DEVICE_CMDS_NEED_TERM): 926 requires_terminator = 1 927 928 if requires_terminator == 1: 929 term_header = tramp_header.replace("VKAPI_CALL ", "VKAPI_CALL terminator_") 930 931 funcs += tramp_header 932 933 if ext_cmd.handle_type == 'VkPhysicalDevice': 934 funcs += ' const VkLayerInstanceDispatchTable *disp;\n' 935 funcs += ' VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(%s);\n' % (phys_dev_var_name) 936 funcs += ' disp = loader_get_instance_layer_dispatch(%s);\n' % (phys_dev_var_name) 937 elif ext_cmd.handle_type == 'VkInstance': 938 funcs += '#error("Not implemented. Likely needs to be manually generated!");\n' 939 else: 940 funcs += ' const VkLayerDispatchTable *disp = loader_get_dispatch(' 941 funcs += ext_cmd.params[0].name 942 funcs += ');\n' 943 944 if 'DebugMarkerSetObjectName' in ext_cmd.name: 945 funcs += ' VkDebugMarkerObjectNameInfoEXT local_name_info;\n' 946 funcs += ' memcpy(&local_name_info, pNameInfo, sizeof(VkDebugMarkerObjectNameInfoEXT));\n' 947 funcs += ' // If this is a physical device, we have to replace it with the proper one for the next call.\n' 948 funcs += ' if (pNameInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT) {\n' 949 funcs += ' struct loader_physical_device_tramp *phys_dev_tramp = (struct loader_physical_device_tramp *)(uintptr_t)pNameInfo->object;\n' 950 funcs += ' local_name_info.object = (uint64_t)(uintptr_t)phys_dev_tramp->phys_dev;\n' 951 funcs += ' }\n' 952 elif 'DebugMarkerSetObjectTag' in ext_cmd.name: 953 funcs += ' VkDebugMarkerObjectTagInfoEXT local_tag_info;\n' 954 funcs += ' memcpy(&local_tag_info, pTagInfo, sizeof(VkDebugMarkerObjectTagInfoEXT));\n' 955 funcs += ' // If this is a physical device, we have to replace it with the proper one for the next call.\n' 956 funcs += ' if (pTagInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT) {\n' 957 funcs += ' struct loader_physical_device_tramp *phys_dev_tramp = (struct loader_physical_device_tramp *)(uintptr_t)pTagInfo->object;\n' 958 funcs += ' local_tag_info.object = (uint64_t)(uintptr_t)phys_dev_tramp->phys_dev;\n' 959 funcs += ' }\n' 960 961 funcs += return_prefix 962 funcs += 'disp->' 963 funcs += base_name 964 funcs += '(' 965 count = 0 966 for param in ext_cmd.params: 967 if count != 0: 968 funcs += ', ' 969 970 if param.type == 'VkPhysicalDevice': 971 funcs += 'unwrapped_phys_dev' 972 elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pNameInfo': 973 funcs += '&local_name_info' 974 elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pTagInfo': 975 funcs += '&local_tag_info' 976 else: 977 funcs += param.name 978 979 count += 1 980 funcs += ');\n' 981 funcs += '}\n\n' 982 983 funcs += term_header 984 if ext_cmd.handle_type == 'VkPhysicalDevice': 985 funcs += ' struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)%s;\n' % (phys_dev_var_name) 986 funcs += ' struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;\n' 987 funcs += ' if (NULL == icd_term->dispatch.' 988 funcs += base_name 989 funcs += ') {\n' 990 funcs += ' loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,\n' 991 funcs += ' "ICD associated with VkPhysicalDevice does not support ' 992 funcs += base_name 993 funcs += '");\n' 994 funcs += ' }\n' 995 996 if has_surface == 1: 997 funcs += ' VkIcdSurface *icd_surface = (VkIcdSurface *)(%s);\n' % (surface_var_name) 998 funcs += ' uint8_t icd_index = phys_dev_term->icd_index;\n' 999 funcs += ' if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)icd_surface->real_icd_surfaces[icd_index]) {\n' 1000 1001 # If there's a structure with a surface, we need to update its internals with the correct surface for the ICD 1002 if update_structure_surface == 1: 1003 funcs += update_structure_string 1004 1005 funcs += ' ' + return_prefix + 'icd_term->dispatch.' 1006 funcs += base_name 1007 funcs += '(' 1008 count = 0 1009 for param in ext_cmd.params: 1010 if count != 0: 1011 funcs += ', ' 1012 1013 if not always_use_param_name: 1014 if surface_type_to_replace and surface_type_to_replace == param.type: 1015 funcs += surface_name_replacement 1016 elif physdev_type_to_replace and physdev_type_to_replace == param.type: 1017 funcs += physdev_name_replacement 1018 else: 1019 funcs += param.name 1020 else: 1021 funcs += param.name 1022 1023 count += 1 1024 funcs += ');\n' 1025 if not has_return_type: 1026 funcs += ' return;\n' 1027 funcs += ' }\n' 1028 1029 funcs += return_prefix 1030 funcs += 'icd_term->dispatch.' 1031 funcs += base_name 1032 funcs += '(' 1033 count = 0 1034 for param in ext_cmd.params: 1035 if count != 0: 1036 funcs += ', ' 1037 1038 if param.type == 'VkPhysicalDevice': 1039 funcs += 'phys_dev_term->phys_dev' 1040 else: 1041 funcs += param.name 1042 1043 count += 1 1044 funcs += ');\n' 1045 1046 elif has_surface == 1 and ext_cmd.ext_type == 'device': 1047 funcs += ' uint32_t icd_index = 0;\n' 1048 funcs += ' struct loader_device *dev;\n' 1049 funcs += ' struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);\n' 1050 funcs += ' if (NULL != icd_term && NULL != icd_term->dispatch.%s) {\n' % base_name 1051 funcs += ' VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)%s;\n' % (surface_var_name) 1052 funcs += ' if (NULL != icd_surface->real_icd_surfaces && (VkSurfaceKHR)NULL != icd_surface->real_icd_surfaces[icd_index]) {\n' 1053 funcs += ' %sicd_term->dispatch.%s(' % (return_prefix, base_name) 1054 count = 0 1055 for param in ext_cmd.params: 1056 if count != 0: 1057 funcs += ', ' 1058 1059 if param.type == 'VkSurfaceKHR': 1060 funcs += 'icd_surface->real_icd_surfaces[icd_index]' 1061 else: 1062 funcs += param.name 1063 1064 count += 1 1065 funcs += ');\n' 1066 if not has_return_type: 1067 funcs += ' return;\n' 1068 funcs += ' }\n' 1069 funcs += ' %sicd_term->dispatch.%s(' % (return_prefix, base_name) 1070 count = 0 1071 for param in ext_cmd.params: 1072 if count != 0: 1073 funcs += ', ' 1074 funcs += param.name 1075 count += 1 1076 funcs += ');\n' 1077 funcs += ' }\n' 1078 if has_return_type: 1079 funcs += ' return VK_SUCCESS;\n' 1080 1081 elif ext_cmd.handle_type == 'VkInstance': 1082 funcs += '#error("Not implemented. Likely needs to be manually generated!");\n' 1083 elif 'DebugMarkerSetObject' in ext_cmd.name: 1084 funcs += ' uint32_t icd_index = 0;\n' 1085 funcs += ' struct loader_device *dev;\n' 1086 funcs += ' struct loader_icd_term *icd_term = loader_get_icd_and_device(%s, &dev, &icd_index);\n' % (ext_cmd.params[0].name) 1087 funcs += ' if (NULL != icd_term && NULL != icd_term->dispatch.' 1088 funcs += base_name 1089 funcs += ') {\n' 1090 if 'DebugMarkerSetObjectName' in ext_cmd.name: 1091 funcs += ' VkDebugMarkerObjectNameInfoEXT local_name_info;\n' 1092 funcs += ' memcpy(&local_name_info, pNameInfo, sizeof(VkDebugMarkerObjectNameInfoEXT));\n' 1093 funcs += ' // If this is a physical device, we have to replace it with the proper one for the next call.\n' 1094 funcs += ' if (pNameInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT) {\n' 1095 funcs += ' struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)(uintptr_t)pNameInfo->object;\n' 1096 funcs += ' local_name_info.object = (uint64_t)(uintptr_t)phys_dev_term->phys_dev;\n' 1097 funcs += ' // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call.\n' 1098 funcs += ' } else if (pNameInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT) {\n' 1099 funcs += ' if (NULL != icd_term && NULL != icd_term->dispatch.CreateSwapchainKHR) {\n' 1100 funcs += ' VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pNameInfo->object;\n' 1101 funcs += ' if (NULL != icd_surface->real_icd_surfaces) {\n' 1102 funcs += ' local_name_info.object = (uint64_t)icd_surface->real_icd_surfaces[icd_index];\n' 1103 funcs += ' }\n' 1104 elif 'DebugMarkerSetObjectTag' in ext_cmd.name: 1105 funcs += ' VkDebugMarkerObjectTagInfoEXT local_tag_info;\n' 1106 funcs += ' memcpy(&local_tag_info, pTagInfo, sizeof(VkDebugMarkerObjectTagInfoEXT));\n' 1107 funcs += ' // If this is a physical device, we have to replace it with the proper one for the next call.\n' 1108 funcs += ' if (pTagInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT) {\n' 1109 funcs += ' struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)(uintptr_t)pTagInfo->object;\n' 1110 funcs += ' local_tag_info.object = (uint64_t)(uintptr_t)phys_dev_term->phys_dev;\n' 1111 funcs += ' // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call.\n' 1112 funcs += ' } else if (pTagInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT) {\n' 1113 funcs += ' if (NULL != icd_term && NULL != icd_term->dispatch.CreateSwapchainKHR) {\n' 1114 funcs += ' VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pTagInfo->object;\n' 1115 funcs += ' if (NULL != icd_surface->real_icd_surfaces) {\n' 1116 funcs += ' local_tag_info.object = (uint64_t)icd_surface->real_icd_surfaces[icd_index];\n' 1117 funcs += ' }\n' 1118 funcs += ' }\n' 1119 funcs += ' }\n' 1120 funcs += ' return icd_term->dispatch.' 1121 funcs += base_name 1122 funcs += '(' 1123 count = 0 1124 for param in ext_cmd.params: 1125 if count != 0: 1126 funcs += ', ' 1127 1128 if param.type == 'VkPhysicalDevice': 1129 funcs += 'phys_dev_term->phys_dev' 1130 elif param.type == 'VkSurfaceKHR': 1131 funcs += 'icd_surface->real_icd_surfaces[icd_index]' 1132 elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pNameInfo': 1133 funcs += '&local_name_info' 1134 elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pTagInfo': 1135 funcs += '&local_tag_info' 1136 else: 1137 funcs += param.name 1138 count += 1 1139 1140 funcs += ');\n' 1141 funcs += ' } else {\n' 1142 funcs += ' return VK_SUCCESS;\n' 1143 funcs += ' }\n' 1144 1145 else: 1146 funcs += '#error("Unknown error path!");\n' 1147 1148 funcs += '}\n\n' 1149 else: 1150 funcs += tramp_header 1151 1152 funcs += ' const VkLayerDispatchTable *disp = loader_get_dispatch(' 1153 funcs += ext_cmd.params[0].name 1154 funcs += ');\n' 1155 1156 funcs += return_prefix 1157 funcs += 'disp->' 1158 funcs += base_name 1159 funcs += '(' 1160 count = 0 1161 for param in ext_cmd.params: 1162 if count != 0: 1163 funcs += ', ' 1164 funcs += param.name 1165 count += 1 1166 funcs += ');\n' 1167 funcs += '}\n\n' 1168 1169 if ext_cmd.protect is not None: 1170 funcs += '#endif // %s\n' % ext_cmd.protect 1171 1172 return funcs 1173 1174 1175 # 1176 # Create a function for the extension GPA call 1177 def InstExtensionGPA(self): 1178 entries = [] 1179 gpa_func = '' 1180 cur_extension_name = '' 1181 1182 gpa_func += '// GPA helpers for extensions\n' 1183 gpa_func += 'bool extension_instance_gpa(struct loader_instance *ptr_instance, const char *name, void **addr) {\n' 1184 gpa_func += ' *addr = NULL;\n\n' 1185 1186 for cur_cmd in self.ext_commands: 1187 if ('VK_VERSION_' in cur_cmd.ext_name or 1188 cur_cmd.ext_name in WSI_EXT_NAMES or 1189 cur_cmd.ext_name in AVOID_EXT_NAMES): 1190 continue 1191 1192 if cur_cmd.ext_name != cur_extension_name: 1193 gpa_func += '\n // ---- %s extension commands\n' % cur_cmd.ext_name 1194 cur_extension_name = cur_cmd.ext_name 1195 1196 if cur_cmd.protect is not None: 1197 gpa_func += '#ifdef %s\n' % cur_cmd.protect 1198 1199 base_name = cur_cmd.name[2:] 1200 1201 if (cur_cmd.ext_type == 'instance'): 1202 gpa_func += ' if (!strcmp("%s", name)) {\n' % (cur_cmd.name) 1203 gpa_func += ' *addr = (ptr_instance->enabled_known_extensions.' 1204 gpa_func += cur_cmd.ext_name[3:].lower() 1205 gpa_func += ' == 1)\n' 1206 gpa_func += ' ? (void *)%s\n' % (base_name) 1207 gpa_func += ' : NULL;\n' 1208 gpa_func += ' return true;\n' 1209 gpa_func += ' }\n' 1210 else: 1211 gpa_func += ' if (!strcmp("%s", name)) {\n' % (cur_cmd.name) 1212 gpa_func += ' *addr = (void *)%s;\n' % (base_name) 1213 gpa_func += ' return true;\n' 1214 gpa_func += ' }\n' 1215 1216 if cur_cmd.protect is not None: 1217 gpa_func += '#endif // %s\n' % cur_cmd.protect 1218 1219 gpa_func += ' return false;\n' 1220 gpa_func += '}\n\n' 1221 1222 return gpa_func 1223 1224 # 1225 # Create the extension name init function 1226 def InstantExtensionCreate(self): 1227 entries = [] 1228 entries = self.instanceExtensions 1229 count = 0 1230 cur_extension_name = '' 1231 1232 create_func = '' 1233 create_func += '// A function that can be used to query enabled extensions during a vkCreateInstance call\n' 1234 create_func += 'void extensions_create_instance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo) {\n' 1235 create_func += ' for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {\n' 1236 for ext in entries: 1237 if ('VK_VERSION_' in ext.name or ext.name in WSI_EXT_NAMES or 1238 ext.name in AVOID_EXT_NAMES or ext.type == 'device' or 1239 ext.num_commands == 0): 1240 continue 1241 1242 if ext.name != cur_extension_name: 1243 create_func += '\n // ---- %s extension commands\n' % ext.name 1244 cur_extension_name = ext.name 1245 1246 if ext.protect is not None: 1247 create_func += '#ifdef %s\n' % ext.protect 1248 if count == 0: 1249 create_func += ' if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], ' 1250 else: 1251 create_func += ' } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], ' 1252 1253 create_func += ext.define + ')) {\n' 1254 create_func += ' ptr_instance->enabled_known_extensions.' 1255 create_func += ext.name[3:].lower() 1256 create_func += ' = 1;\n' 1257 1258 if ext.protect is not None: 1259 create_func += '#endif // %s\n' % ext.protect 1260 count += 1 1261 1262 create_func += ' }\n' 1263 create_func += ' }\n' 1264 create_func += '}\n\n' 1265 return create_func 1266 1267 # 1268 # Create code to initialize a dispatch table from the appropriate list of 1269 # extension entrypoints and return it as a string 1270 def DeviceExtensionGetTerminator(self): 1271 term_func = '' 1272 cur_extension_name = '' 1273 1274 term_func += '// Some device commands still need a terminator because the loader needs to unwrap something about them.\n' 1275 term_func += '// In many cases, the item needing unwrapping is a VkPhysicalDevice or VkSurfaceKHR object. But there may be other items\n' 1276 term_func += '// in the future.\n' 1277 term_func += 'PFN_vkVoidFunction get_extension_device_proc_terminator(const char *pName) {\n' 1278 term_func += ' PFN_vkVoidFunction addr = NULL;\n' 1279 1280 count = 0 1281 for ext_cmd in self.ext_commands: 1282 if ext_cmd.name in DEVICE_CMDS_NEED_TERM: 1283 if ext_cmd.ext_name != cur_extension_name: 1284 if 'VK_VERSION_' in ext_cmd.ext_name: 1285 term_func += '\n // ---- Core %s commands\n' % ext_cmd.ext_name[11:] 1286 else: 1287 term_func += '\n // ---- %s extension commands\n' % ext_cmd.ext_name 1288 cur_extension_name = ext_cmd.ext_name 1289 1290 if ext_cmd.protect is not None: 1291 term_func += '#ifdef %s\n' % ext_cmd.protect 1292 1293 if count == 0: 1294 term_func += ' if' 1295 else: 1296 term_func += ' } else if' 1297 term_func += '(!strcmp(pName, "%s")) {\n' % (ext_cmd.name) 1298 term_func += ' addr = (PFN_vkVoidFunction)terminator_%s;\n' % (ext_cmd.name[2:]) 1299 1300 if ext_cmd.protect is not None: 1301 term_func += '#endif // %s\n' % ext_cmd.protect 1302 1303 count += 1 1304 1305 if count > 0: 1306 term_func += ' }\n' 1307 1308 term_func += ' return addr;\n' 1309 term_func += '}\n\n' 1310 1311 return term_func 1312 1313 # 1314 # Create code to initialize a dispatch table from the appropriate list of 1315 # core and extension entrypoints and return it as a string 1316 def InitInstLoaderExtensionDispatchTable(self): 1317 commands = [] 1318 table = '' 1319 cur_extension_name = '' 1320 1321 table += '// This table contains the loader\'s instance dispatch table, which contains\n' 1322 table += '// default functions if no instance layers are activated. This contains\n' 1323 table += '// pointers to "terminator functions".\n' 1324 table += 'const VkLayerInstanceDispatchTable instance_disp = {\n' 1325 1326 for x in range(0, 2): 1327 if x == 0: 1328 commands = self.core_commands 1329 else: 1330 commands = self.ext_commands 1331 1332 for cur_cmd in commands: 1333 if cur_cmd.ext_type == 'instance' or (cur_cmd.ext_type == 'device' and cur_cmd.handle_type == 'VkPhysicalDevice'): 1334 if cur_cmd.ext_name != cur_extension_name: 1335 if 'VK_VERSION_' in cur_cmd.ext_name: 1336 table += '\n // ---- Core %s commands\n' % cur_cmd.ext_name[11:] 1337 else: 1338 table += '\n // ---- %s extension commands\n' % cur_cmd.ext_name 1339 cur_extension_name = cur_cmd.ext_name 1340 1341 # Remove 'vk' from proto name 1342 base_name = cur_cmd.name[2:] 1343 1344 if (base_name == 'CreateInstance' or base_name == 'CreateDevice' or 1345 base_name == 'EnumerateInstanceExtensionProperties' or 1346 base_name == 'EnumerateInstanceLayerProperties'): 1347 continue 1348 1349 if cur_cmd.protect is not None: 1350 table += '#ifdef %s\n' % cur_cmd.protect 1351 1352 if base_name == 'GetInstanceProcAddr': 1353 table += ' .%s = %s,\n' % (base_name, cur_cmd.name) 1354 else: 1355 table += ' .%s = terminator_%s,\n' % (base_name, base_name) 1356 1357 if cur_cmd.protect is not None: 1358 table += '#endif // %s\n' % cur_cmd.protect 1359 table += '};\n\n' 1360 1361 return table 1362 1363 # 1364 # Create the extension name whitelist array 1365 def OutputInstantExtensionWhitelistArray(self): 1366 extensions = self.instanceExtensions 1367 1368 table = '' 1369 table += '// A null-terminated list of all of the instance extensions supported by the loader.\n' 1370 table += '// If an instance extension name is not in this list, but it is exported by one or more of the\n' 1371 table += '// ICDs detected by the loader, then the extension name not in the list will be filtered out\n' 1372 table += '// before passing the list of extensions to the application.\n' 1373 table += 'const char *const LOADER_INSTANCE_EXTENSIONS[] = {\n' 1374 for ext in extensions: 1375 if ext.type == 'device' or 'VK_VERSION_' in ext.name: 1376 continue 1377 1378 if ext.protect is not None: 1379 table += '#ifdef %s\n' % ext.protect 1380 table += ' ' 1381 table += ext.define + ',\n' 1382 1383 if ext.protect is not None: 1384 table += '#endif // %s\n' % ext.protect 1385 table += ' NULL };\n' 1386 return table 1387 1388