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