blob: 84cc4ca4bfdb706cfc594f4abe0d1f55addd52b6 [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',
Lenny Komow1d5b9152017-05-10 10:06:13 -0600838 'vkGetPhysicalDeviceExternalImageFormatPropertiesNV',
839 'vkGetPhysicalDeviceFeatures2KHR',
840 'vkGetPhysicalDeviceProperties2KHR',
841 'vkGetPhysicalDeviceFormatProperties2KHR',
842 'vkGetPhysicalDeviceImageFormatProperties2KHR',
843 'vkGetPhysicalDeviceQueueFamilyProperties2KHR',
844 'vkGetPhysicalDeviceMemoryProperties2KHR',
Lenny Komow4687c7f2017-05-30 13:04:46 -0600845 'vkGetPhysicalDeviceSparseImageFormatProperties2KHR',
846 'vkGetPhysicalDeviceSurfaceCapabilities2KHR',
Lenny Komow728ff062017-06-01 13:32:28 -0600847 'vkGetPhysicalDeviceSurfaceFormats2KHR',
848 'vkGetPhysicalDeviceSurfaceCapabilities2EXT',
849 'vkReleaseDisplayEXT',
850 'vkAcquireXlibDisplayEXT',
Mark Youngabc2d6e2017-07-07 07:59:56 -0600851 'vkGetRandROutputDisplayEXT',
852 'vkGetPhysicalDeviceExternalBufferPropertiesKHR',
853 'vkGetPhysicalDeviceExternalSemaphorePropertiesKHR',
854 'vkGetPhysicalDeviceExternalFencePropertiesKHR']
Mark Young0f183a82017-02-28 09:58:04 -0700855
856 for ext_cmd in self.ext_commands:
857 if (ext_cmd.ext_name in WSI_EXT_NAMES or
858 ext_cmd.ext_name in AVOID_EXT_NAMES or
859 ext_cmd.name in manual_ext_commands):
860 continue
861
862 if ext_cmd.ext_name != cur_extension_name:
863 if 'VK_VERSION_' in ext_cmd.ext_name:
864 funcs += '\n// ---- Core %s trampoline/terminators\n\n' % ext_cmd.ext_name[11:]
865 else:
866 funcs += '\n// ---- %s extension trampoline/terminators\n\n' % ext_cmd.ext_name
867 cur_extension_name = ext_cmd.ext_name
868
869 if ext_cmd.protect is not None:
870 funcs += '#ifdef %s\n' % ext_cmd.protect
871
Mark Youngd66edd52017-03-10 17:31:18 -0700872 func_header = ext_cmd.cdecl.replace(";", " {\n")
873 tramp_header = func_header.replace("VKAPI_CALL vk", "VKAPI_CALL ")
Mark Young0f183a82017-02-28 09:58:04 -0700874 return_prefix = ' '
875 base_name = ext_cmd.name[2:]
876 has_surface = 0
Lenny Komowd2585002017-05-22 16:17:05 -0600877 update_structure_surface = 0
878 update_structure_string = ''
Mark Young0f183a82017-02-28 09:58:04 -0700879 requires_terminator = 0
880 surface_var_name = ''
881 phys_dev_var_name = ''
882 has_return_type = False
Lenny Komowd2585002017-05-22 16:17:05 -0600883 always_use_param_name = True
884 surface_type_to_replace = ''
885 surface_name_replacement = ''
886 physdev_type_to_replace = ''
887 physdev_name_replacement = ''
Mark Young0f183a82017-02-28 09:58:04 -0700888
889 for param in ext_cmd.params:
890 if param.type == 'VkSurfaceKHR':
891 has_surface = 1
892 surface_var_name = param.name
893 requires_terminator = 1
Lenny Komowd2585002017-05-22 16:17:05 -0600894 always_use_param_name = False
895 surface_type_to_replace = 'VkSurfaceKHR'
896 surface_name_replacement = 'icd_surface->real_icd_surfaces[icd_index]'
897 if param.type == 'VkPhysicalDeviceSurfaceInfo2KHR':
898 has_surface = 1
899 surface_var_name = param.name + '->surface'
900 requires_terminator = 1
901 update_structure_surface = 1
902 update_structure_string = ' VkPhysicalDeviceSurfaceInfo2KHR info_copy = *pSurfaceInfo;\n'
903 update_structure_string += ' info_copy.surface = icd_surface->real_icd_surfaces[icd_index];\n'
904 always_use_param_name = False
905 surface_type_to_replace = 'VkPhysicalDeviceSurfaceInfo2KHR'
906 surface_name_replacement = '&info_copy'
Mark Young0f183a82017-02-28 09:58:04 -0700907 if param.type == 'VkPhysicalDevice':
908 requires_terminator = 1
909 phys_dev_var_name = param.name
Lenny Komowd2585002017-05-22 16:17:05 -0600910 always_use_param_name = False
911 physdev_type_to_replace = 'VkPhysicalDevice'
912 physdev_name_replacement = 'phys_dev_term->phys_dev'
Mark Young0f183a82017-02-28 09:58:04 -0700913
914 if (ext_cmd.return_type != None):
915 return_prefix += 'return '
916 has_return_type = True
917
918 if (ext_cmd.ext_type == 'instance' or ext_cmd.handle_type == 'VkPhysicalDevice' or
919 'DebugMarkerSetObject' in ext_cmd.name or ext_cmd.name in DEVICE_CMDS_NEED_TERM):
920 requires_terminator = 1
921
922 if requires_terminator == 1:
Mark Youngd66edd52017-03-10 17:31:18 -0700923 term_header = tramp_header.replace("VKAPI_CALL ", "VKAPI_CALL terminator_")
Mark Young0f183a82017-02-28 09:58:04 -0700924
925 funcs += tramp_header
926
927 if ext_cmd.handle_type == 'VkPhysicalDevice':
928 funcs += ' const VkLayerInstanceDispatchTable *disp;\n'
929 funcs += ' VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(%s);\n' % (phys_dev_var_name)
930 funcs += ' disp = loader_get_instance_layer_dispatch(%s);\n' % (phys_dev_var_name)
931 elif ext_cmd.handle_type == 'VkInstance':
932 funcs += '#error("Not implemented. Likely needs to be manually generated!");\n'
933 else:
934 funcs += ' const VkLayerDispatchTable *disp = loader_get_dispatch('
935 funcs += ext_cmd.params[0].name
936 funcs += ');\n'
937
Mark Youngd8821062017-06-20 10:59:42 -0600938 if 'DebugMarkerSetObjectName' in ext_cmd.name:
939 funcs += ' VkDebugMarkerObjectNameInfoEXT local_name_info;\n'
940 funcs += ' memcpy(&local_name_info, pNameInfo, sizeof(VkDebugMarkerObjectNameInfoEXT));\n'
Mark Young0f183a82017-02-28 09:58:04 -0700941 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 -0600942 funcs += ' if (pNameInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT) {\n'
943 funcs += ' struct loader_physical_device_tramp *phys_dev_tramp = (struct loader_physical_device_tramp *)(uintptr_t)pNameInfo->object;\n'
944 funcs += ' local_name_info.object = (uint64_t)(uintptr_t)phys_dev_tramp->phys_dev;\n'
945 funcs += ' }\n'
946 elif 'DebugMarkerSetObjectTag' in ext_cmd.name:
947 funcs += ' VkDebugMarkerObjectTagInfoEXT local_tag_info;\n'
948 funcs += ' memcpy(&local_tag_info, pTagInfo, sizeof(VkDebugMarkerObjectTagInfoEXT));\n'
949 funcs += ' // If this is a physical device, we have to replace it with the proper one for the next call.\n'
950 funcs += ' if (pTagInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT) {\n'
951 funcs += ' struct loader_physical_device_tramp *phys_dev_tramp = (struct loader_physical_device_tramp *)(uintptr_t)pTagInfo->object;\n'
952 funcs += ' local_tag_info.object = (uint64_t)(uintptr_t)phys_dev_tramp->phys_dev;\n'
Mark Young0f183a82017-02-28 09:58:04 -0700953 funcs += ' }\n'
954
955 funcs += return_prefix
956 funcs += 'disp->'
957 funcs += base_name
958 funcs += '('
959 count = 0
960 for param in ext_cmd.params:
961 if count != 0:
962 funcs += ', '
963
964 if param.type == 'VkPhysicalDevice':
965 funcs += 'unwrapped_phys_dev'
Mark Youngd8821062017-06-20 10:59:42 -0600966 elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pNameInfo':
967 funcs += '&local_name_info'
968 elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pTagInfo':
969 funcs += '&local_tag_info'
Mark Young0f183a82017-02-28 09:58:04 -0700970 else:
971 funcs += param.name
972
973 count += 1
974 funcs += ');\n'
975 funcs += '}\n\n'
976
977 funcs += term_header
978 if ext_cmd.handle_type == 'VkPhysicalDevice':
979 funcs += ' struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)%s;\n' % (phys_dev_var_name)
980 funcs += ' struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;\n'
981 funcs += ' if (NULL == icd_term->dispatch.'
982 funcs += base_name
983 funcs += ') {\n'
984 funcs += ' loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,\n'
985 funcs += ' "ICD associated with VkPhysicalDevice does not support '
986 funcs += base_name
987 funcs += '");\n'
James Jonese9e0a122017-02-28 17:26:09 -0800988 funcs += ' }\n'
Mark Young0f183a82017-02-28 09:58:04 -0700989
990 if has_surface == 1:
Lenny Komowd2585002017-05-22 16:17:05 -0600991 funcs += ' VkIcdSurface *icd_surface = (VkIcdSurface *)(%s);\n' % (surface_var_name)
James Jonese9e0a122017-02-28 17:26:09 -0800992 funcs += ' uint8_t icd_index = phys_dev_term->icd_index;\n'
Mark Young8aed3ed2017-03-01 16:22:23 -0700993 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 -0600994
995 # If there's a structure with a surface, we need to update its internals with the correct surface for the ICD
996 if update_structure_surface == 1:
997 funcs += update_structure_string
998
Mark Young8aed3ed2017-03-01 16:22:23 -0700999 funcs += ' ' + return_prefix + 'icd_term->dispatch.'
Mark Young0f183a82017-02-28 09:58:04 -07001000 funcs += base_name
1001 funcs += '('
1002 count = 0
1003 for param in ext_cmd.params:
1004 if count != 0:
1005 funcs += ', '
1006
Lenny Komowd2585002017-05-22 16:17:05 -06001007 if not always_use_param_name:
1008 if surface_type_to_replace and surface_type_to_replace == param.type:
1009 funcs += surface_name_replacement
1010 elif physdev_type_to_replace and physdev_type_to_replace == param.type:
1011 funcs += physdev_name_replacement
1012 else:
1013 funcs += param.name
Mark Young0f183a82017-02-28 09:58:04 -07001014 else:
1015 funcs += param.name
1016
1017 count += 1
1018 funcs += ');\n'
James Jonese9e0a122017-02-28 17:26:09 -08001019 if not has_return_type:
Mark Young8aed3ed2017-03-01 16:22:23 -07001020 funcs += ' return;\n'
James Jonese9e0a122017-02-28 17:26:09 -08001021 funcs += ' }\n'
Mark Young0f183a82017-02-28 09:58:04 -07001022
1023 funcs += return_prefix
1024 funcs += 'icd_term->dispatch.'
1025 funcs += base_name
1026 funcs += '('
1027 count = 0
1028 for param in ext_cmd.params:
1029 if count != 0:
1030 funcs += ', '
1031
1032 if param.type == 'VkPhysicalDevice':
1033 funcs += 'phys_dev_term->phys_dev'
1034 else:
1035 funcs += param.name
1036
1037 count += 1
1038 funcs += ');\n'
1039
1040 elif has_surface == 1 and ext_cmd.ext_type == 'device':
1041 funcs += ' uint32_t icd_index = 0;\n'
1042 funcs += ' struct loader_device *dev;\n'
1043 funcs += ' struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);\n'
1044 funcs += ' if (NULL != icd_term && NULL != icd_term->dispatch.%s) {\n' % base_name
1045 funcs += ' VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)%s;\n' % (surface_var_name)
Mark Young8aed3ed2017-03-01 16:22:23 -07001046 funcs += ' if (NULL != icd_surface->real_icd_surfaces && (VkSurfaceKHR)NULL != icd_surface->real_icd_surfaces[icd_index]) {\n'
1047 funcs += ' %sicd_term->dispatch.%s(' % (return_prefix, base_name)
Mark Young0f183a82017-02-28 09:58:04 -07001048 count = 0
1049 for param in ext_cmd.params:
1050 if count != 0:
1051 funcs += ', '
1052
1053 if param.type == 'VkSurfaceKHR':
1054 funcs += 'icd_surface->real_icd_surfaces[icd_index]'
1055 else:
1056 funcs += param.name
1057
1058 count += 1
1059 funcs += ');\n'
1060 if not has_return_type:
1061 funcs += ' return;\n'
Mark Young0f183a82017-02-28 09:58:04 -07001062 funcs += ' }\n'
Mark Young8aed3ed2017-03-01 16:22:23 -07001063 funcs += ' %sicd_term->dispatch.%s(' % (return_prefix, base_name)
Mark Young0f183a82017-02-28 09:58:04 -07001064 count = 0
1065 for param in ext_cmd.params:
1066 if count != 0:
1067 funcs += ', '
1068 funcs += param.name
1069 count += 1
1070 funcs += ');\n'
James Jonese9e0a122017-02-28 17:26:09 -08001071 funcs += ' }\n'
Mark Young0f183a82017-02-28 09:58:04 -07001072 if has_return_type:
1073 funcs += ' return VK_SUCCESS;\n'
1074
1075 elif ext_cmd.handle_type == 'VkInstance':
1076 funcs += '#error("Not implemented. Likely needs to be manually generated!");\n'
Mark Young0f183a82017-02-28 09:58:04 -07001077 elif 'DebugMarkerSetObject' in ext_cmd.name:
1078 funcs += ' uint32_t icd_index = 0;\n'
1079 funcs += ' struct loader_device *dev;\n'
1080 funcs += ' struct loader_icd_term *icd_term = loader_get_icd_and_device(%s, &dev, &icd_index);\n' % (ext_cmd.params[0].name)
1081 funcs += ' if (NULL != icd_term && NULL != icd_term->dispatch.'
1082 funcs += base_name
1083 funcs += ') {\n'
Mark Youngd8821062017-06-20 10:59:42 -06001084 if 'DebugMarkerSetObjectName' in ext_cmd.name:
1085 funcs += ' VkDebugMarkerObjectNameInfoEXT local_name_info;\n'
1086 funcs += ' memcpy(&local_name_info, pNameInfo, sizeof(VkDebugMarkerObjectNameInfoEXT));\n'
1087 funcs += ' // If this is a physical device, we have to replace it with the proper one for the next call.\n'
1088 funcs += ' if (pNameInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT) {\n'
1089 funcs += ' struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)(uintptr_t)pNameInfo->object;\n'
1090 funcs += ' local_name_info.object = (uint64_t)(uintptr_t)phys_dev_term->phys_dev;\n'
1091 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'
1092 funcs += ' } else if (pNameInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT) {\n'
1093 funcs += ' if (NULL != icd_term && NULL != icd_term->dispatch.CreateSwapchainKHR) {\n'
1094 funcs += ' VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pNameInfo->object;\n'
1095 funcs += ' if (NULL != icd_surface->real_icd_surfaces) {\n'
1096 funcs += ' local_name_info.object = (uint64_t)icd_surface->real_icd_surfaces[icd_index];\n'
1097 funcs += ' }\n'
1098 elif 'DebugMarkerSetObjectTag' in ext_cmd.name:
1099 funcs += ' VkDebugMarkerObjectTagInfoEXT local_tag_info;\n'
1100 funcs += ' memcpy(&local_tag_info, pTagInfo, sizeof(VkDebugMarkerObjectTagInfoEXT));\n'
1101 funcs += ' // If this is a physical device, we have to replace it with the proper one for the next call.\n'
1102 funcs += ' if (pTagInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT) {\n'
1103 funcs += ' struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)(uintptr_t)pTagInfo->object;\n'
1104 funcs += ' local_tag_info.object = (uint64_t)(uintptr_t)phys_dev_term->phys_dev;\n'
1105 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'
1106 funcs += ' } else if (pTagInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT) {\n'
1107 funcs += ' if (NULL != icd_term && NULL != icd_term->dispatch.CreateSwapchainKHR) {\n'
1108 funcs += ' VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pTagInfo->object;\n'
1109 funcs += ' if (NULL != icd_surface->real_icd_surfaces) {\n'
1110 funcs += ' local_tag_info.object = (uint64_t)icd_surface->real_icd_surfaces[icd_index];\n'
1111 funcs += ' }\n'
Mark Young0f183a82017-02-28 09:58:04 -07001112 funcs += ' }\n'
1113 funcs += ' }\n'
1114 funcs += ' return icd_term->dispatch.'
1115 funcs += base_name
1116 funcs += '('
1117 count = 0
1118 for param in ext_cmd.params:
1119 if count != 0:
1120 funcs += ', '
1121
1122 if param.type == 'VkPhysicalDevice':
1123 funcs += 'phys_dev_term->phys_dev'
1124 elif param.type == 'VkSurfaceKHR':
1125 funcs += 'icd_surface->real_icd_surfaces[icd_index]'
Mark Youngd8821062017-06-20 10:59:42 -06001126 elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pNameInfo':
1127 funcs += '&local_name_info'
1128 elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pTagInfo':
1129 funcs += '&local_tag_info'
Mark Young0f183a82017-02-28 09:58:04 -07001130 else:
1131 funcs += param.name
1132 count += 1
1133
1134 funcs += ');\n'
1135 funcs += ' } else {\n'
1136 funcs += ' return VK_SUCCESS;\n'
1137 funcs += ' }\n'
1138
1139 else:
1140 funcs += '#error("Unknown error path!");\n'
1141
1142 funcs += '}\n\n'
1143 else:
1144 funcs += tramp_header
1145
1146 funcs += ' const VkLayerDispatchTable *disp = loader_get_dispatch('
1147 funcs += ext_cmd.params[0].name
1148 funcs += ');\n'
1149
1150 funcs += return_prefix
1151 funcs += 'disp->'
1152 funcs += base_name
1153 funcs += '('
1154 count = 0
1155 for param in ext_cmd.params:
1156 if count != 0:
1157 funcs += ', '
1158 funcs += param.name
1159 count += 1
1160 funcs += ');\n'
1161 funcs += '}\n\n'
1162
1163 if ext_cmd.protect is not None:
1164 funcs += '#endif // %s\n' % ext_cmd.protect
1165
Mark Young0f183a82017-02-28 09:58:04 -07001166 return funcs
1167
1168
1169 #
1170 # Create a function for the extension GPA call
1171 def InstExtensionGPA(self):
1172 entries = []
1173 gpa_func = ''
1174 cur_extension_name = ''
1175
1176 gpa_func += '// GPA helpers for extensions\n'
1177 gpa_func += 'bool extension_instance_gpa(struct loader_instance *ptr_instance, const char *name, void **addr) {\n'
1178 gpa_func += ' *addr = NULL;\n\n'
1179
1180 for cur_cmd in self.ext_commands:
1181 if ('VK_VERSION_' in cur_cmd.ext_name or
1182 cur_cmd.ext_name in WSI_EXT_NAMES or
1183 cur_cmd.ext_name in AVOID_EXT_NAMES):
1184 continue
1185
1186 if cur_cmd.ext_name != cur_extension_name:
1187 gpa_func += '\n // ---- %s extension commands\n' % cur_cmd.ext_name
1188 cur_extension_name = cur_cmd.ext_name
1189
1190 if cur_cmd.protect is not None:
1191 gpa_func += '#ifdef %s\n' % cur_cmd.protect
1192
Mark Youngd66edd52017-03-10 17:31:18 -07001193 base_name = cur_cmd.name[2:]
1194
Mark Young0f183a82017-02-28 09:58:04 -07001195 if (cur_cmd.ext_type == 'instance'):
1196 gpa_func += ' if (!strcmp("%s", name)) {\n' % (cur_cmd.name)
1197 gpa_func += ' *addr = (ptr_instance->enabled_known_extensions.'
1198 gpa_func += cur_cmd.ext_name[3:].lower()
1199 gpa_func += ' == 1)\n'
Mark Youngd66edd52017-03-10 17:31:18 -07001200 gpa_func += ' ? (void *)%s\n' % (base_name)
Mark Young0f183a82017-02-28 09:58:04 -07001201 gpa_func += ' : NULL;\n'
1202 gpa_func += ' return true;\n'
1203 gpa_func += ' }\n'
1204 else:
1205 gpa_func += ' if (!strcmp("%s", name)) {\n' % (cur_cmd.name)
Mark Youngd66edd52017-03-10 17:31:18 -07001206 gpa_func += ' *addr = (void *)%s;\n' % (base_name)
Mark Young0f183a82017-02-28 09:58:04 -07001207 gpa_func += ' return true;\n'
1208 gpa_func += ' }\n'
1209
1210 if cur_cmd.protect is not None:
1211 gpa_func += '#endif // %s\n' % cur_cmd.protect
1212
1213 gpa_func += ' return false;\n'
1214 gpa_func += '}\n\n'
1215
1216 return gpa_func
1217
1218 #
1219 # Create the extension name init function
1220 def InstantExtensionCreate(self):
1221 entries = []
1222 entries = self.instanceExtensions
1223 count = 0
1224 cur_extension_name = ''
1225
1226 create_func = ''
1227 create_func += '// A function that can be used to query enabled extensions during a vkCreateInstance call\n'
1228 create_func += 'void extensions_create_instance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo) {\n'
1229 create_func += ' for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {\n'
1230 for ext in entries:
1231 if ('VK_VERSION_' in ext.name or ext.name in WSI_EXT_NAMES or
1232 ext.name in AVOID_EXT_NAMES or ext.type == 'device' or
1233 ext.num_commands == 0):
1234 continue
1235
1236 if ext.name != cur_extension_name:
1237 create_func += '\n // ---- %s extension commands\n' % ext.name
1238 cur_extension_name = ext.name
1239
1240 if ext.protect is not None:
1241 create_func += '#ifdef %s\n' % ext.protect
1242 if count == 0:
1243 create_func += ' if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], '
1244 else:
1245 create_func += ' } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], '
1246
Mark Lobodzinski602dacc2017-03-27 15:47:01 -06001247 create_func += ext.define + ')) {\n'
Mark Young0f183a82017-02-28 09:58:04 -07001248 create_func += ' ptr_instance->enabled_known_extensions.'
1249 create_func += ext.name[3:].lower()
1250 create_func += ' = 1;\n'
1251
1252 if ext.protect is not None:
1253 create_func += '#endif // %s\n' % ext.protect
1254 count += 1
1255
1256 create_func += ' }\n'
1257 create_func += ' }\n'
1258 create_func += '}\n\n'
1259 return create_func
1260
1261 #
1262 # Create code to initialize a dispatch table from the appropriate list of
1263 # extension entrypoints and return it as a string
1264 def DeviceExtensionGetTerminator(self):
1265 term_func = ''
1266 cur_extension_name = ''
1267
1268 term_func += '// Some device commands still need a terminator because the loader needs to unwrap something about them.\n'
1269 term_func += '// In many cases, the item needing unwrapping is a VkPhysicalDevice or VkSurfaceKHR object. But there may be other items\n'
1270 term_func += '// in the future.\n'
1271 term_func += 'PFN_vkVoidFunction get_extension_device_proc_terminator(const char *pName) {\n'
1272 term_func += ' PFN_vkVoidFunction addr = NULL;\n'
1273
1274 count = 0
1275 for ext_cmd in self.ext_commands:
1276 if ext_cmd.name in DEVICE_CMDS_NEED_TERM:
1277 if ext_cmd.ext_name != cur_extension_name:
1278 if 'VK_VERSION_' in ext_cmd.ext_name:
1279 term_func += '\n // ---- Core %s commands\n' % ext_cmd.ext_name[11:]
1280 else:
1281 term_func += '\n // ---- %s extension commands\n' % ext_cmd.ext_name
1282 cur_extension_name = ext_cmd.ext_name
1283
1284 if ext_cmd.protect is not None:
1285 term_func += '#ifdef %s\n' % ext_cmd.protect
1286
1287 if count == 0:
1288 term_func += ' if'
1289 else:
1290 term_func += ' } else if'
1291 term_func += '(!strcmp(pName, "%s")) {\n' % (ext_cmd.name)
1292 term_func += ' addr = (PFN_vkVoidFunction)terminator_%s;\n' % (ext_cmd.name[2:])
1293
1294 if ext_cmd.protect is not None:
1295 term_func += '#endif // %s\n' % ext_cmd.protect
1296
1297 count += 1
1298
1299 if count > 0:
1300 term_func += ' }\n'
1301
1302 term_func += ' return addr;\n'
1303 term_func += '}\n\n'
1304
1305 return term_func
1306
1307 #
1308 # Create code to initialize a dispatch table from the appropriate list of
1309 # core and extension entrypoints and return it as a string
1310 def InitInstLoaderExtensionDispatchTable(self):
1311 commands = []
1312 table = ''
1313 cur_extension_name = ''
1314
1315 table += '// This table contains the loader\'s instance dispatch table, which contains\n'
1316 table += '// default functions if no instance layers are activated. This contains\n'
1317 table += '// pointers to "terminator functions".\n'
1318 table += 'const VkLayerInstanceDispatchTable instance_disp = {\n'
1319
1320 for x in range(0, 2):
1321 if x == 0:
1322 commands = self.core_commands
1323 else:
1324 commands = self.ext_commands
1325
1326 for cur_cmd in commands:
Lenny Komow3c3f1572017-05-08 14:38:08 -06001327 if cur_cmd.ext_type == 'instance' or (cur_cmd.ext_type == 'device' and cur_cmd.handle_type == 'VkPhysicalDevice'):
Mark Young0f183a82017-02-28 09:58:04 -07001328 if cur_cmd.ext_name != cur_extension_name:
1329 if 'VK_VERSION_' in cur_cmd.ext_name:
1330 table += '\n // ---- Core %s commands\n' % cur_cmd.ext_name[11:]
1331 else:
1332 table += '\n // ---- %s extension commands\n' % cur_cmd.ext_name
1333 cur_extension_name = cur_cmd.ext_name
1334
1335 # Remove 'vk' from proto name
1336 base_name = cur_cmd.name[2:]
1337
1338 if (base_name == 'CreateInstance' or base_name == 'CreateDevice' or
1339 base_name == 'EnumerateInstanceExtensionProperties' or
1340 base_name == 'EnumerateInstanceLayerProperties'):
1341 continue
1342
1343 if cur_cmd.protect is not None:
1344 table += '#ifdef %s\n' % cur_cmd.protect
1345
1346 if base_name == 'GetInstanceProcAddr':
1347 table += ' .%s = %s,\n' % (base_name, cur_cmd.name)
1348 else:
1349 table += ' .%s = terminator_%s,\n' % (base_name, base_name)
1350
1351 if cur_cmd.protect is not None:
1352 table += '#endif // %s\n' % cur_cmd.protect
1353 table += '};\n\n'
1354
1355 return table
1356
1357 #
1358 # Create the extension name whitelist array
1359 def OutputInstantExtensionWhitelistArray(self):
1360 extensions = self.instanceExtensions
1361
1362 table = ''
1363 table += '// A null-terminated list of all of the instance extensions supported by the loader.\n'
1364 table += '// If an instance extension name is not in this list, but it is exported by one or more of the\n'
1365 table += '// ICDs detected by the loader, then the extension name not in the list will be filtered out\n'
1366 table += '// before passing the list of extensions to the application.\n'
1367 table += 'const char *const LOADER_INSTANCE_EXTENSIONS[] = {\n'
1368 for ext in extensions:
1369 if ext.type == 'device' or 'VK_VERSION_' in ext.name:
1370 continue
1371
1372 if ext.protect is not None:
1373 table += '#ifdef %s\n' % ext.protect
1374 table += ' '
Mark Lobodzinski602dacc2017-03-27 15:47:01 -06001375 table += ext.define + ',\n'
Mark Young0f183a82017-02-28 09:58:04 -07001376
1377 if ext.protect is not None:
1378 table += '#endif // %s\n' % ext.protect
1379 table += ' NULL };\n'
1380 return table
1381