blob: d9f5564c9d380b1db87a53f9f6ac42d05cdf0019 [file] [log] [blame]
Mark Young0f183a82017-02-28 09:58:04 -07001#!/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 Lobodzinski62f71562017-10-24 13:41:18 -060021# Author: Mark Lobodzinski <mark@lunarg.com>
Mark Young0f183a82017-02-28 09:58:04 -070022
23import os,re,sys
24import xml.etree.ElementTree as etree
25from generator import *
26from collections import namedtuple
Mark Lobodzinski62f71562017-10-24 13:41:18 -060027from common_codegen import *
28
Mark Young0f183a82017-02-28 09:58:04 -070029
30WSI_EXT_NAMES = ['VK_KHR_surface',
31 'VK_KHR_display',
32 'VK_KHR_xlib_surface',
33 'VK_KHR_xcb_surface',
34 'VK_KHR_wayland_surface',
35 'VK_KHR_mir_surface',
36 'VK_KHR_win32_surface',
37 'VK_KHR_android_surface',
Karl Schultz2e5ed332017-12-12 10:33:01 -050038 'VK_MVK_macos_surface',
39 'VK_MVK_ios_surface',
Mark Young0f183a82017-02-28 09:58:04 -070040 'VK_KHR_swapchain',
41 'VK_KHR_display_swapchain']
42
Mark Young6ba8abe2017-11-09 10:37:04 -070043ADD_INST_CMDS = ['vkCreateInstance',
44 'vkEnumerateInstanceExtensionProperties',
45 'vkEnumerateInstanceLayerProperties',
46 'vkEnumerateInstanceVersion']
47
Mark Young0f183a82017-02-28 09:58:04 -070048AVOID_EXT_NAMES = ['VK_EXT_debug_report']
49
Mark Young6ba8abe2017-11-09 10:37:04 -070050AVOID_CMD_NAMES = ['vkCreateDebugUtilsMessengerEXT',
51 'vkDestroyDebugUtilsMessengerEXT',
52 'vkSubmitDebugUtilsMessageEXT']
53
Mark Young0f183a82017-02-28 09:58:04 -070054DEVICE_CMDS_NEED_TERM = ['vkGetDeviceProcAddr',
55 'vkCreateSwapchainKHR',
56 'vkCreateSharedSwapchainsKHR',
Lenny Komowfccf6d22017-10-10 13:50:20 -060057 'vkGetDeviceGroupSurfacePresentModesKHR',
Mark Young0f183a82017-02-28 09:58:04 -070058 'vkDebugMarkerSetObjectTagEXT',
Mark Young6ba8abe2017-11-09 10:37:04 -070059 'vkDebugMarkerSetObjectNameEXT',
60 'vkSetDebugUtilsObjectNameEXT',
61 'vkSetDebugUtilsObjectTagEXT']
Lenny Komow82e15e02017-10-02 15:08:53 -060062
63ALIASED_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 Young0f183a82017-02-28 09:58:04 -070076
Lenny Komow3cf3ac72017-12-19 16:38:37 -070077PRE_INSTANCE_FUNCTIONS = ['vkEnumerateInstanceExtensionProperties',
Lenny Komow16586112018-02-13 15:58:47 -070078 'vkEnumerateInstanceLayerProperties',
79 'vkEnumerateInstanceVersion']
Lenny Komow3cf3ac72017-12-19 16:38:37 -070080
Mark Young0f183a82017-02-28 09:58:04 -070081#
82# LoaderExtensionGeneratorOptions - subclass of GeneratorOptions.
83class 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 Lobodzinski62f71562017-10-24 13:41:18 -060094 emitExtensions = None,
Mark Young0f183a82017-02-28 09:58:04 -070095 sortProcedure = regSortFeatures,
96 prefixText = "",
97 genFuncPointers = True,
98 protectFile = True,
99 protectFeature = True,
Mark Young0f183a82017-02-28 09:58:04 -0700100 apicall = '',
101 apientry = '',
102 apientryp = '',
Mark Lobodzinski62f71562017-10-24 13:41:18 -0600103 indentFuncProto = True,
104 indentFuncPointer = False,
Mark Young0f183a82017-02-28 09:58:04 -0700105 alignFuncParam = 0,
Mark Lobodzinski62f71562017-10-24 13:41:18 -0600106 expandEnumerants = True):
Mark Young0f183a82017-02-28 09:58:04 -0700107 GeneratorOptions.__init__(self, filename, directory, apiname, profile,
108 versions, emitversions, defaultExtensions,
Mark Lobodzinski62f71562017-10-24 13:41:18 -0600109 addExtensions, removeExtensions, emitExtensions, sortProcedure)
Mark Young0f183a82017-02-28 09:58:04 -0700110 self.prefixText = prefixText
Mark Young0f183a82017-02-28 09:58:04 -0700111 self.prefixText = None
Mark Young0f183a82017-02-28 09:58:04 -0700112 self.apicall = apicall
113 self.apientry = apientry
114 self.apientryp = apientryp
115 self.alignFuncParam = alignFuncParam
Mark Lobodzinski62f71562017-10-24 13:41:18 -0600116 self.expandEnumerants = expandEnumerants
117
Mark Young0f183a82017-02-28 09:58:04 -0700118#
119# LoaderExtensionOutputGenerator - subclass of OutputGenerator.
120# Generates dispatch table helper header files for LVL
121class 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 Lobodzinski602dacc2017-03-27 15:47:01 -0600137 self.ExtensionData = namedtuple('ExtensionData', ['name', 'type', 'protect', 'define', 'num_commands'])
Mark Young0f183a82017-02-28 09:58:04 -0700138
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 Young6ba8abe2017-11-09 10:37:04 -0700191 preamble += '#include "debug_utils.h"\n'
Mark Youngd66edd52017-03-10 17:31:18 -0700192 preamble += '#include "extension_manual.h"\n'
Mark Young0f183a82017-02-28 09:58:04 -0700193
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 Lobodzinski62f71562017-10-24 13:41:18 -0600237 self.featureExtraProtect = GetFeatureProtect(interface)
Mark Young0f183a82017-02-28 09:58:04 -0700238
Mark Lobodzinski602dacc2017-03-27 15:47:01 -0600239 enums = interface[0].findall('enum')
Mark Young0f183a82017-02-28 09:58:04 -0700240 self.currentExtension = ''
Mark Lobodzinski602dacc2017-03-27 15:47:01 -0600241 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 Young0f183a82017-02-28 09:58:04 -0700248 self.type = interface.get('type')
249 self.num_commands = 0
Mark Young0f183a82017-02-28 09:58:04 -0700250 name = interface.get('name')
251 self.currentExtension = name
252
253 #
254 # Process commands, adding to appropriate dispatch tables
Mike Schuchardtf375c7c2017-12-28 11:23:48 -0700255 def genCmd(self, cmdinfo, name, alias):
256 OutputGenerator.genCmd(self, cmdinfo, name, alias)
Mark Young0f183a82017-02-28 09:58:04 -0700257
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 Lobodzinski602dacc2017-03-27 15:47:01 -0600273 define=self.name_definition,
Mark Young0f183a82017-02-28 09:58:04 -0700274 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 Komow002db5f2018-03-29 13:25:38 -0600386 protos += 'struct loader_device;\n'
Mark Young0f183a82017-02-28 09:58:04 -0700387 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 Komow002db5f2018-03-29 13:25:38 -0600405 protos += 'PFN_vkVoidFunction get_extension_device_proc_terminator(struct loader_device *dev, const char *pName);\n'
Mark Young0f183a82017-02-28 09:58:04 -0700406 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 Young6ba8abe2017-11-09 10:37:04 -0700483 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 Young0f183a82017-02-28 09:58:04 -0700486 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 Young6ba8abe2017-11-09 10:37:04 -0700524 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 Young0f183a82017-02-28 09:58:04 -0700527 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 Young6ba8abe2017-11-09 10:37:04 -0700565 is_inst_handle_type = cur_cmd.name in ADD_INST_CMDS or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
Mark Young0f183a82017-02-28 09:58:04 -0700566 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 Komowfccf6d22017-10-10 13:50:20 -0600616 'vkEnumerateInstanceVersion',
Mark Young0f183a82017-02-28 09:58:04 -0700617 ]
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 Komoweb9fd4d2017-10-02 15:32:55 -0600625 required = False
Mark Young0f183a82017-02-28 09:58:04 -0700626 for cur_cmd in commands:
Mark Young6ba8abe2017-11-09 10:37:04 -0700627 is_inst_handle_type = cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
Mark Young0f183a82017-02-28 09:58:04 -0700628 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 Komoweb9fd4d2017-10-02 15:32:55 -0600633 required = cur_cmd.ext_name == 'VK_VERSION_1_0'
Mark Young0f183a82017-02-28 09:58:04 -0700634 else:
635 table += '\n // ---- %s extension commands\n' % cur_cmd.ext_name
Lenny Komoweb9fd4d2017-10-02 15:32:55 -0600636 required = False
Mark Young0f183a82017-02-28 09:58:04 -0700637 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 Komoweb9fd4d2017-10-02 15:32:55 -0600647 table += ' LOOKUP_GIPA(%s, %s);\n' % (base_name, 'true' if required else 'false')
Mark Young0f183a82017-02-28 09:58:04 -0700648
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 Young6ba8abe2017-11-09 10:37:04 -0700686 is_inst_handle_type = cur_cmd.name in ADD_INST_CMDS or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
Mark Young0f183a82017-02-28 09:58:04 -0700687 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 Komow3cf3ac72017-12-19 16:38:37 -0700692 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 Young0f183a82017-02-28 09:58:04 -0700695 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 Young0f183a82017-02-28 09:58:04 -0700727
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 Young0f183a82017-02-28 09:58:04 -0700737
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 Komow82e15e02017-10-02 15:08:53 -0600757 is_inst_handle_type = cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
Mark Young0f183a82017-02-28 09:58:04 -0700758 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 Komowfccf6d22017-10-10 13:50:20 -0600772 base_name == 'EnumerateInstanceLayerProperties' or
773 base_name == 'EnumerateInstanceVersion'):
Mark Young0f183a82017-02-28 09:58:04 -0700774 continue
775
776 if cur_cmd.protect is not None:
777 tables += '#ifdef %s\n' % cur_cmd.protect
778
Mark Young46ed1192017-05-04 15:10:59 -0600779 # 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 Young0f183a82017-02-28 09:58:04 -0700787
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 Komow82e15e02017-10-02 15:08:53 -0600833 is_inst_handle_type = cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
Mark Young0f183a82017-02-28 09:58:04 -0700834 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 Komowfccf6d22017-10-10 13:50:20 -0600848 base_name == 'EnumerateInstanceLayerProperties' or
849 base_name == 'EnumerateInstanceVersion'):
Mark Young0f183a82017-02-28 09:58:04 -0700850 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 Young0f183a82017-02-28 09:58:04 -0700868 # 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 Komow82e15e02017-10-02 15:08:53 -0600876 manual_ext_commands = ['vkEnumeratePhysicalDeviceGroupsKHR',
Lenny Komow1d5b9152017-05-10 10:06:13 -0600877 'vkGetPhysicalDeviceExternalImageFormatPropertiesNV',
878 'vkGetPhysicalDeviceFeatures2KHR',
879 'vkGetPhysicalDeviceProperties2KHR',
880 'vkGetPhysicalDeviceFormatProperties2KHR',
881 'vkGetPhysicalDeviceImageFormatProperties2KHR',
882 'vkGetPhysicalDeviceQueueFamilyProperties2KHR',
883 'vkGetPhysicalDeviceMemoryProperties2KHR',
Lenny Komow4687c7f2017-05-30 13:04:46 -0600884 'vkGetPhysicalDeviceSparseImageFormatProperties2KHR',
885 'vkGetPhysicalDeviceSurfaceCapabilities2KHR',
Lenny Komow728ff062017-06-01 13:32:28 -0600886 'vkGetPhysicalDeviceSurfaceFormats2KHR',
887 'vkGetPhysicalDeviceSurfaceCapabilities2EXT',
888 'vkReleaseDisplayEXT',
889 'vkAcquireXlibDisplayEXT',
Mark Youngabc2d6e2017-07-07 07:59:56 -0600890 'vkGetRandROutputDisplayEXT',
891 'vkGetPhysicalDeviceExternalBufferPropertiesKHR',
892 'vkGetPhysicalDeviceExternalSemaphorePropertiesKHR',
893 'vkGetPhysicalDeviceExternalFencePropertiesKHR']
Mark Young0f183a82017-02-28 09:58:04 -0700894
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 Young6ba8abe2017-11-09 10:37:04 -0700898 ext_cmd.name in AVOID_CMD_NAMES or
Mark Young0f183a82017-02-28 09:58:04 -0700899 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 Youngd66edd52017-03-10 17:31:18 -0700912 func_header = ext_cmd.cdecl.replace(";", " {\n")
913 tramp_header = func_header.replace("VKAPI_CALL vk", "VKAPI_CALL ")
Mark Young0f183a82017-02-28 09:58:04 -0700914 return_prefix = ' '
915 base_name = ext_cmd.name[2:]
916 has_surface = 0
Lenny Komowd2585002017-05-22 16:17:05 -0600917 update_structure_surface = 0
918 update_structure_string = ''
Mark Young0f183a82017-02-28 09:58:04 -0700919 requires_terminator = 0
920 surface_var_name = ''
921 phys_dev_var_name = ''
922 has_return_type = False
Lenny Komowd2585002017-05-22 16:17:05 -0600923 always_use_param_name = True
924 surface_type_to_replace = ''
925 surface_name_replacement = ''
926 physdev_type_to_replace = ''
927 physdev_name_replacement = ''
Mark Young0f183a82017-02-28 09:58:04 -0700928
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 Komowd2585002017-05-22 16:17:05 -0600934 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 Young0f183a82017-02-28 09:58:04 -0700947 if param.type == 'VkPhysicalDevice':
948 requires_terminator = 1
949 phys_dev_var_name = param.name
Lenny Komowd2585002017-05-22 16:17:05 -0600950 always_use_param_name = False
951 physdev_type_to_replace = 'VkPhysicalDevice'
952 physdev_name_replacement = 'phys_dev_term->phys_dev'
Mark Young0f183a82017-02-28 09:58:04 -0700953
954 if (ext_cmd.return_type != None):
955 return_prefix += 'return '
956 has_return_type = True
957
Mark Young6ba8abe2017-11-09 10:37:04 -0700958 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 Young0f183a82017-02-28 09:58:04 -0700961 requires_terminator = 1
962
963 if requires_terminator == 1:
Mark Youngd66edd52017-03-10 17:31:18 -0700964 term_header = tramp_header.replace("VKAPI_CALL ", "VKAPI_CALL terminator_")
Mark Young0f183a82017-02-28 09:58:04 -0700965
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 Youngd8821062017-06-20 10:59:42 -0600979 if 'DebugMarkerSetObjectName' in ext_cmd.name:
980 funcs += ' VkDebugMarkerObjectNameInfoEXT local_name_info;\n'
981 funcs += ' memcpy(&local_name_info, pNameInfo, sizeof(VkDebugMarkerObjectNameInfoEXT));\n'
Mark Young0f183a82017-02-28 09:58:04 -0700982 funcs += ' // If this is a physical device, we have to replace it with the proper one for the next call.\n'
Mark Youngd8821062017-06-20 10:59:42 -0600983 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 Young0f183a82017-02-28 09:58:04 -0700994 funcs += ' }\n'
Mark Young6ba8abe2017-11-09 10:37:04 -0700995 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 Young0f183a82017-02-28 09:58:04 -07001011
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 Young6ba8abe2017-11-09 10:37:04 -07001023 elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pNameInfo':
Mark Youngd8821062017-06-20 10:59:42 -06001024 funcs += '&local_name_info'
Mark Young6ba8abe2017-11-09 10:37:04 -07001025 elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pTagInfo':
Mark Youngd8821062017-06-20 10:59:42 -06001026 funcs += '&local_tag_info'
Mark Young0f183a82017-02-28 09:58:04 -07001027 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 Jonese9e0a122017-02-28 17:26:09 -08001045 funcs += ' }\n'
Mark Young0f183a82017-02-28 09:58:04 -07001046
1047 if has_surface == 1:
Lenny Komowd2585002017-05-22 16:17:05 -06001048 funcs += ' VkIcdSurface *icd_surface = (VkIcdSurface *)(%s);\n' % (surface_var_name)
James Jonese9e0a122017-02-28 17:26:09 -08001049 funcs += ' uint8_t icd_index = phys_dev_term->icd_index;\n'
Mark Young8aed3ed2017-03-01 16:22:23 -07001050 funcs += ' if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)icd_surface->real_icd_surfaces[icd_index]) {\n'
Lenny Komowd2585002017-05-22 16:17:05 -06001051
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 Young8aed3ed2017-03-01 16:22:23 -07001056 funcs += ' ' + return_prefix + 'icd_term->dispatch.'
Mark Young0f183a82017-02-28 09:58:04 -07001057 funcs += base_name
1058 funcs += '('
1059 count = 0
1060 for param in ext_cmd.params:
1061 if count != 0:
1062 funcs += ', '
1063
Lenny Komowd2585002017-05-22 16:17:05 -06001064 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 Young0f183a82017-02-28 09:58:04 -07001071 else:
1072 funcs += param.name
1073
1074 count += 1
1075 funcs += ');\n'
James Jonese9e0a122017-02-28 17:26:09 -08001076 if not has_return_type:
Mark Young8aed3ed2017-03-01 16:22:23 -07001077 funcs += ' return;\n'
James Jonese9e0a122017-02-28 17:26:09 -08001078 funcs += ' }\n'
Mark Young0f183a82017-02-28 09:58:04 -07001079
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 Young6ba8abe2017-11-09 10:37:04 -07001097 elif has_surface == 1 and not (ext_cmd.handle_type == 'VkPhysicalDevice' or ext_cmd.handle_type == 'VkInstance'):
Mark Young0f183a82017-02-28 09:58:04 -07001098 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 Young8aed3ed2017-03-01 16:22:23 -07001103 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 Young0f183a82017-02-28 09:58:04 -07001105 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 Young0f183a82017-02-28 09:58:04 -07001119 funcs += ' }\n'
Mark Young8aed3ed2017-03-01 16:22:23 -07001120 funcs += ' %sicd_term->dispatch.%s(' % (return_prefix, base_name)
Mark Young0f183a82017-02-28 09:58:04 -07001121 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 Jonese9e0a122017-02-28 17:26:09 -08001128 funcs += ' }\n'
Mark Young0f183a82017-02-28 09:58:04 -07001129 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 Young6ba8abe2017-11-09 10:37:04 -07001134 elif 'DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name:
Mark Young0f183a82017-02-28 09:58:04 -07001135 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 Youngd8821062017-06-20 10:59:42 -06001141 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 Young6ba8abe2017-11-09 10:37:04 -07001169 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 Young0f183a82017-02-28 09:58:04 -07001208 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 Young6ba8abe2017-11-09 10:37:04 -07001222 elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pNameInfo':
Mark Youngd8821062017-06-20 10:59:42 -06001223 funcs += '&local_name_info'
Mark Young6ba8abe2017-11-09 10:37:04 -07001224 elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pTagInfo':
Mark Youngd8821062017-06-20 10:59:42 -06001225 funcs += '&local_tag_info'
Mark Young0f183a82017-02-28 09:58:04 -07001226 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 Young0f183a82017-02-28 09:58:04 -07001262 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 Young6ba8abe2017-11-09 10:37:04 -07001279 cur_cmd.ext_name in AVOID_EXT_NAMES or
1280 cur_cmd.name in AVOID_CMD_NAMES ):
Mark Young0f183a82017-02-28 09:58:04 -07001281 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 Komow82e15e02017-10-02 15:08:53 -06001290 #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 Youngd66edd52017-03-10 17:31:18 -07001292
Mark Young0f183a82017-02-28 09:58:04 -07001293 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 Youngd66edd52017-03-10 17:31:18 -07001298 gpa_func += ' ? (void *)%s\n' % (base_name)
Mark Young0f183a82017-02-28 09:58:04 -07001299 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 Youngd66edd52017-03-10 17:31:18 -07001304 gpa_func += ' *addr = (void *)%s;\n' % (base_name)
Mark Young0f183a82017-02-28 09:58:04 -07001305 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 Young6ba8abe2017-11-09 10:37:04 -07001330 ext.name in AVOID_EXT_NAMES or ext.name in AVOID_CMD_NAMES or
1331 ext.type == 'device' or ext.num_commands == 0):
Mark Young0f183a82017-02-28 09:58:04 -07001332 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 Lobodzinski602dacc2017-03-27 15:47:01 -06001345 create_func += ext.define + ')) {\n'
Mark Young0f183a82017-02-28 09:58:04 -07001346 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 Komow002db5f2018-03-29 13:25:38 -06001369 term_func += 'PFN_vkVoidFunction get_extension_device_proc_terminator(struct loader_device *dev, const char *pName) {\n'
Mark Young0f183a82017-02-28 09:58:04 -07001370 term_func += ' PFN_vkVoidFunction addr = NULL;\n'
1371
1372 count = 0
Lenny Komow002db5f2018-03-29 13:25:38 -06001373 is_extension = False
Mark Young0f183a82017-02-28 09:58:04 -07001374 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 Komow002db5f2018-03-29 13:25:38 -06001377 if count > 0:
1378 count = 0;
1379 term_func += ' }\n'
1380 if is_extension:
1381 term_func += ' }\n'
1382 is_extension = False
1383
Mark Young0f183a82017-02-28 09:58:04 -07001384 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 Komow002db5f2018-03-29 13:25:38 -06001388 term_func += ' if (dev->extensions.%s_enabled) {\n' % ext_cmd.ext_name[3:].lower()
1389 is_extension = True
Mark Young0f183a82017-02-28 09:58:04 -07001390 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 Komow002db5f2018-03-29 13:25:38 -06001396 term_func += ' if'
Mark Young0f183a82017-02-28 09:58:04 -07001397 else:
Lenny Komow002db5f2018-03-29 13:25:38 -06001398 term_func += ' } else if'
Mark Young0f183a82017-02-28 09:58:04 -07001399 term_func += '(!strcmp(pName, "%s")) {\n' % (ext_cmd.name)
Lenny Komow002db5f2018-03-29 13:25:38 -06001400 term_func += ' addr = (PFN_vkVoidFunction)terminator_%s;\n' % (ext_cmd.name[2:])
Mark Young0f183a82017-02-28 09:58:04 -07001401
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 Komow002db5f2018-03-29 13:25:38 -06001408 term_func += ' }\n'
1409 if is_extension:
Mark Young0f183a82017-02-28 09:58:04 -07001410 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 Komow82e15e02017-10-02 15:08:53 -06001437
1438 if cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice':
Mark Young0f183a82017-02-28 09:58:04 -07001439 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 Komowfccf6d22017-10-10 13:50:20 -06001448 aliased_name = ALIASED_CMDS[cur_cmd.name][2:] if cur_cmd.name in ALIASED_CMDS else base_name
Mark Young0f183a82017-02-28 09:58:04 -07001449
1450 if (base_name == 'CreateInstance' or base_name == 'CreateDevice' or
1451 base_name == 'EnumerateInstanceExtensionProperties' or
Lenny Komowfccf6d22017-10-10 13:50:20 -06001452 base_name == 'EnumerateInstanceLayerProperties' or
1453 base_name == 'EnumerateInstanceVersion'):
Mark Young0f183a82017-02-28 09:58:04 -07001454 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 Komowfccf6d22017-10-10 13:50:20 -06001462 table += ' .%s = terminator_%s,\n' % (base_name, aliased_name)
Mark Young0f183a82017-02-28 09:58:04 -07001463
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 Lobodzinski602dacc2017-03-27 15:47:01 -06001488 table += ext.define + ',\n'
Mark Young0f183a82017-02-28 09:58:04 -07001489
1490 if ext.protect is not None:
1491 table += '#endif // %s\n' % ext.protect
1492 table += ' NULL };\n'
1493 return table
1494