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