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