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