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