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