111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#!/usr/bin/env python3
211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#
311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# VK
411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#
511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# Copyright (c) 2015-2016 The Khronos Group Inc.
611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# Copyright (c) 2015-2016 Valve Corporation
711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# Copyright (c) 2015-2016 LunarG, Inc.
811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# Copyright (c) 2015-2016 Google Inc.
911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#
1011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# Licensed under the Apache License, Version 2.0 (the "License");
1111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# you may not use this file except in compliance with the License.
1211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# You may obtain a copy of the License at
1311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#
1411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#     http://www.apache.org/licenses/LICENSE-2.0
1511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#
1611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# Unless required by applicable law or agreed to in writing, software
1711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# distributed under the License is distributed on an "AS IS" BASIS,
1811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# See the License for the specific language governing permissions and
2011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# limitations under the License.
2111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#
2211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# Author: Tobin Ehlis <tobine@google.com>
2311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# Author: Courtney Goeltzenleuchter <courtneygo@google.com>
2411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# Author: Jon Ashburn <jon@lunarg.com>
2511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# Author: Mark Lobodzinski <mark@lunarg.com>
2611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# Author: Mike Stroyan <stroyan@google.com>
2711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# Author: Tony Barbour <tony@LunarG.com>
2811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# Author: Chia-I Wu <olv@google.com>
2911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# Author: Gwan-gyeong Mun <kk.moon@samsung.com>
3011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
3111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertimport sys
3211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertimport os
3311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertimport re
3411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
3511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertimport vulkan
3611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertimport vk_helper
3711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertfrom source_line_info import sourcelineinfo
3811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertfrom collections import defaultdict
3911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
4011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertdef proto_is_global(proto):
4111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    global_function_names = [
4211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        "CreateInstance",
4311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        "EnumerateInstanceLayerProperties",
4411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        "EnumerateInstanceExtensionProperties",
4511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        "EnumerateDeviceLayerProperties",
4611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        "EnumerateDeviceExtensionProperties",
4711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        "CreateXcbSurfaceKHR",
4811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        "GetPhysicalDeviceXcbPresentationSupportKHR",
4911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        "CreateXlibSurfaceKHR",
5011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        "GetPhysicalDeviceXlibPresentationSupportKHR",
5111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        "CreateWaylandSurfaceKHR",
5211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        "GetPhysicalDeviceWaylandPresentationSupportKHR",
5311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        "CreateMirSurfaceKHR",
5411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        "GetPhysicalDeviceMirPresentationSupportKHR",
5511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        "CreateAndroidSurfaceKHR",
5611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        "CreateWin32SurfaceKHR",
5711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        "GetPhysicalDeviceWin32PresentationSupportKHR"
5811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    ]
5911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if proto.params[0].ty == "VkInstance" or proto.params[0].ty == "VkPhysicalDevice" or proto.name in global_function_names:
6011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert       return True
6111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    else:
6211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert       return False
6311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
6411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertdef wsi_name(ext_name):
6511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    wsi_prefix = ""
6611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if 'Xcb' in ext_name:
6711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        wsi_prefix = 'XCB'
6811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    elif 'Xlib' in ext_name:
6911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        wsi_prefix = 'XLIB'
7011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    elif 'Win32' in ext_name:
7111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        wsi_prefix = 'WIN32'
7211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    elif 'Mir' in ext_name:
7311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        wsi_prefix = 'MIR'
7411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    elif 'Wayland' in ext_name:
7511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        wsi_prefix = 'WAYLAND'
7611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    elif 'Android' in ext_name:
7711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        wsi_prefix = 'ANDROID'
7811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    else:
7911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        wsi_prefix = ''
8011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return wsi_prefix
8111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertdef wsi_ifdef(ext_name):
8311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    wsi_prefix = wsi_name(ext_name)
8411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if not wsi_prefix:
8511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return ''
8611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    else:
8711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "#ifdef VK_USE_PLATFORM_%s_KHR" % wsi_prefix
8811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertdef wsi_endif(ext_name):
9011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    wsi_prefix = wsi_name(ext_name)
9111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if not wsi_prefix:
9211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return ''
9311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    else:
9411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "#endif  // VK_USE_PLATFORM_%s_KHR" % wsi_prefix
9511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
9611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertdef generate_get_proc_addr_check(name):
9711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return "    if (!%s || %s[0] != 'v' || %s[1] != 'k')\n" \
9811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert           "        return NULL;" % ((name,) * 3)
9911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
10011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertdef ucc_to_U_C_C(CamelCase):
10111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    temp = re.sub('(.)([A-Z][a-z]+)',  r'\1_\2', CamelCase)
10211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return re.sub('([a-z0-9])([A-Z])', r'\1_\2', temp).upper()
10311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
10411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# Parse complete struct chain and add any new ndo_uses to the dict
10511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertdef gather_object_uses_in_struct(obj_list, struct_type):
10611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    struct_uses = {}
10711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if vk_helper.typedef_rev_dict[struct_type] in vk_helper.struct_dict:
10811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        struct_type = vk_helper.typedef_rev_dict[struct_type]
10911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # Parse elements of this struct param to identify objects and/or arrays of objects
11011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for m in sorted(vk_helper.struct_dict[struct_type]):
11111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            array_len = "%s" % (str(vk_helper.struct_dict[struct_type][m]['array_size']))
11211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            base_type = vk_helper.struct_dict[struct_type][m]['type']
11311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            mem_name = vk_helper.struct_dict[struct_type][m]['name']
11411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if array_len != '0':
11511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                mem_name = "%s[%s]" % (mem_name, array_len)
11611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if base_type in obj_list:
11711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                #if array_len not in ndo_uses:
11811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                #    struct_uses[array_len] = []
11911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                #struct_uses[array_len].append("%s%s,%s" % (name_prefix, struct_name, base_type))
12011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                struct_uses[mem_name] = base_type
12111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            elif vk_helper.is_type(base_type, 'struct'):
12211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                sub_uses = gather_object_uses_in_struct(obj_list, base_type)
12311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if len(sub_uses) > 0:
12411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    struct_uses[mem_name] = sub_uses
12511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return struct_uses
12611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
12711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# For the given list of object types, Parse the given list of params
12811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#  and return dict of params that use one of the obj_list types
12911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# Format of the dict is that terminal elements have <name>,<type>
13011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#  non-terminal elements will have <name>[<array_size>]
13111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# TODO : This analysis could be done up-front at vk_helper time
13211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertdef get_object_uses(obj_list, params):
13311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    obj_uses = {}
13411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    local_decls = {}
13511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    param_count = 'NONE' # track params that give array sizes
13611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    for p in params:
13711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        base_type = p.ty.replace('const ', '').strip('*')
13811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        array_len = ''
13911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        is_ptr = False
14011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if 'count' in p.name.lower():
14111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            param_count = p.name
14211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        ptr_txt = ''
14311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if '*' in p.ty:
14411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            is_ptr = True
14511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            ptr_txt = '*'
14611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if base_type in obj_list:
14711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if is_ptr and 'const' in p.ty and param_count != 'NONE':
14811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                array_len = "[%s]" % param_count
14911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                # Non-arrays we can overwrite in place, but need local decl for arrays
15011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                local_decls[p.name] = '%s%s' % (base_type, ptr_txt)
15111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            #if array_len not in obj_uses:
15211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            #    obj_uses[array_len] = {}
15311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            # obj_uses[array_len][p.name] = base_type
15411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            obj_uses["%s%s" % (p.name, array_len)] = base_type
15511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        elif vk_helper.is_type(base_type, 'struct'):
15611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            struct_name = p.name
15711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if 'NONE' != param_count:
15811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                struct_name = "%s[%s]" % (struct_name, param_count)
15911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            struct_uses = gather_object_uses_in_struct(obj_list, base_type)
16011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if len(struct_uses) > 0:
16111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                obj_uses[struct_name] = struct_uses
16211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                # This is a top-level struct w/ uses below it, so need local decl
16311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                local_decls['%s' % (p.name)] = '%s%s' % (base_type, ptr_txt)
16411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return (obj_uses, local_decls)
16511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
16611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertclass Subcommand(object):
16711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def __init__(self, outfile):
16811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        self.outfile = outfile
16911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        self.headers = vulkan.headers
17011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        self.protos = vulkan.protos
17111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        self.no_addr = False
17211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        self.layer_name = ""
17311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        self.lineinfo = sourcelineinfo()
17411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        self.wsi = sys.argv[1]
17511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
17611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def run(self):
17711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if self.outfile:
17811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            with open(self.outfile, "w") as outfile:
17911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                outfile.write(self.generate())
18011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        else:
18111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            print(self.generate())
18211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
18311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def generate(self):
18411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        copyright = self.generate_copyright()
18511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header = self.generate_header()
18611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body = self.generate_body()
18711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        footer = self.generate_footer()
18811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
18911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        contents = []
19011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if copyright:
19111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            contents.append(copyright)
19211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if header:
19311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            contents.append(header)
19411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if body:
19511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            contents.append(body)
19611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if footer:
19711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            contents.append(footer)
19811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
19911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n\n".join(contents)
20011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
20111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def generate_copyright(self):
20211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return """/* THIS FILE IS GENERATED.  DO NOT EDIT. */
20311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
20411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/*
20511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Copyright (c) 2015-2016 The Khronos Group Inc.
20611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Copyright (c) 2015-2016 Valve Corporation
20711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Copyright (c) 2015-2016 LunarG, Inc.
20811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Copyright (c) 2015-2016 Google, Inc.
20911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
21011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Licensed under the Apache License, Version 2.0 (the "License");
21111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * you may not use this file except in compliance with the License.
21211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * You may obtain a copy of the License at
21311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
21411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *     http://www.apache.org/licenses/LICENSE-2.0
21511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
21611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Unless required by applicable law or agreed to in writing, software
21711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * distributed under the License is distributed on an "AS IS" BASIS,
21811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * See the License for the specific language governing permissions and
22011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * limitations under the License.
22111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
22211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Author: Tobin Ehlis <tobine@google.com>
22311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Author: Courtney Goeltzenleuchter <courtneygo@google.com>
22411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Author: Jon Ashburn <jon@lunarg.com>
22511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Author: Mark Lobodzinski <mark@lunarg.com>
22611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Author: Mike Stroyan <stroyan@google.com>
22711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Author: Tony Barbour <tony@LunarG.com>
22811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */"""
22911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
23011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def generate_header(self):
23111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n".join(["#include <" + h + ">" for h in self.headers])
23211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
23311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def generate_body(self):
23411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pass
23511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
23611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def generate_footer(self):
23711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pass
23811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
23911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    # Return set of printf '%' qualifier and input to that qualifier
24011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def _get_printf_params(self, vk_type, name, output_param, cpp=False):
24111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # TODO : Need ENUM and STRUCT checks here
24211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if vk_helper.is_type(vk_type, 'enum'):#"_TYPE" in vk_type: # TODO : This should be generic ENUM check
24311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return ("%s", "string_%s(%s)" % (vk_type.replace('const ', '').strip('*'), name))
24411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if "char*" == vk_type:
24511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return ("%s", name)
24611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if "uint64" in vk_type:
24711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if '*' in vk_type:
24811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                return ("%lu", "*%s" % name)
24911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return ("%lu", name)
25011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if vk_type.strip('*') in vulkan.object_non_dispatch_list:
25111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if '*' in vk_type:
25211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                return ("%lu", "%s" % name)
25311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return ("%lu", "%s" % name)
25411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if "size" in vk_type:
25511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if '*' in vk_type:
25611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                return ("%lu", "(unsigned long)*%s" % name)
25711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return ("%lu", "(unsigned long)%s" % name)
25811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if "float" in vk_type:
25911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if '[' in vk_type: # handle array, current hard-coded to 4 (TODO: Make this dynamic)
26011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if cpp:
26111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    return ("[%i, %i, %i, %i]", '"[" << %s[0] << "," << %s[1] << "," << %s[2] << "," << %s[3] << "]"' % (name, name, name, name))
26211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                return ("[%f, %f, %f, %f]", "%s[0], %s[1], %s[2], %s[3]" % (name, name, name, name))
26311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return ("%f", name)
26411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if "bool" in vk_type.lower() or 'xcb_randr_crtc_t' in vk_type:
26511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return ("%u", name)
26611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if True in [t in vk_type.lower() for t in ["int", "flags", "mask", "xcb_window_t"]]:
26711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if '[' in vk_type: # handle array, current hard-coded to 4 (TODO: Make this dynamic)
26811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if cpp:
26911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    return ("[%i, %i, %i, %i]", "%s[0] << %s[1] << %s[2] << %s[3]" % (name, name, name, name))
27011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                return ("[%i, %i, %i, %i]", "%s[0], %s[1], %s[2], %s[3]" % (name, name, name, name))
27111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if '*' in vk_type:
27211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if 'pUserData' == name:
27311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    return ("%i", "((pUserData == 0) ? 0 : *(pUserData))")
27411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if 'const' in vk_type.lower():
27511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    return ("0x%p", "(void*)(%s)" % name)
27611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                return ("%i", "*(%s)" % name)
27711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return ("%i", name)
27811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # TODO : This is special-cased as there's only one "format" param currently and it's nice to expand it
27911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if "VkFormat" == vk_type:
28011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if cpp:
28111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                return ("0x%p", "&%s" % name)
28211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return ("{%s.channelFormat = %%s, %s.numericFormat = %%s}" % (name, name), "string_VK_COLOR_COMPONENT_FORMAT(%s.channelFormat), string_VK_FORMAT_RANGE_SIZE(%s.numericFormat)" % (name, name))
28311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if output_param:
28411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return ("0x%p", "(void*)*%s" % name)
28511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if vk_helper.is_type(vk_type, 'struct') and '*' not in vk_type:
28611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return ("0x%p", "(void*)(&%s)" % name)
28711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return ("0x%p", "(void*)(%s)" % name)
28811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
28911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def _gen_create_msg_callback(self):
29011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body = []
29111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('%s' % self.lineinfo.get())
29211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(')
29311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('        VkInstance                                   instance,')
29411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('        const VkDebugReportCallbackCreateInfoEXT*    pCreateInfo,')
29511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('        const VkAllocationCallbacks*                 pAllocator,')
29611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('        VkDebugReportCallbackEXT*                    pCallback)')
29711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('{')
29811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # Switch to this code section for the new per-instance storage and debug callbacks
29911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if self.layer_name in ['object_tracker', 'unique_objects']:
30011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('    VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
30111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('    VkResult result = pInstanceTable->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);')
30211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('    if (VK_SUCCESS == result) {')
30311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('        layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
30411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('        result = layer_create_msg_callback(my_data->report_data,')
30511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('                                           pCreateInfo,')
30611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('                                           pAllocator,')
30711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('                                           pCallback);')
30811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('    }')
30911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('    return result;')
31011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        else:
31111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('    VkResult result = instance_dispatch_table(instance)->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);')
31211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('    if (VK_SUCCESS == result) {')
31311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('        layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
31411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('        result = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pCallback);')
31511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('    }')
31611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('    return result;')
31711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('}')
31811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n".join(r_body)
31911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
32011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def _gen_destroy_msg_callback(self):
32111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body = []
32211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('%s' % self.lineinfo.get())
32311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, const VkAllocationCallbacks *pAllocator)')
32411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('{')
32511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # Switch to this code section for the new per-instance storage and debug callbacks
32611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if self.layer_name in ['object_tracker', 'unique_objects']:
32711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('    VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
32811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        else:
32911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('    VkLayerInstanceDispatchTable *pInstanceTable = instance_dispatch_table(instance);')
33011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('    pInstanceTable->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);')
33111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
33211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('    layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);')
33311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('}')
33411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n".join(r_body)
33511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
33611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def _gen_debug_report_msg(self):
33711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body = []
33811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('%s' % self.lineinfo.get())
33911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('VKAPI_ATTR void VKAPI_CALL DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT    flags, VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg)')
34011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('{')
34111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # Switch to this code section for the new per-instance storage and debug callbacks
34211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if self.layer_name == 'object_tracker':
34311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('    VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
34411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        else:
34511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            r_body.append('    VkLayerInstanceDispatchTable *pInstanceTable = instance_dispatch_table(instance);')
34611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('    pInstanceTable->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);')
34711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        r_body.append('}')
34811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n".join(r_body)
34911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
35011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def _gen_layer_logging_workaround(self):
35111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body = []
35211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('%s' % self.lineinfo.get())
35311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('// vk_layer_logging.h expects these to be defined')
35411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('')
35511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('VKAPI_ATTR VkResult VKAPI_CALL')
35611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,')
35711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('                               const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {')
35811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('    return %s::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);' % self.layer_name)
35911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('}')
36011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('')
36111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance,')
36211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('                                                                           VkDebugReportCallbackEXT msgCallback,')
36311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('                                                                           const VkAllocationCallbacks *pAllocator) {')
36411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('    %s::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);' % self.layer_name)
36511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('}')
36611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('')
36711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('VKAPI_ATTR void VKAPI_CALL')
36811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,')
36911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('                        size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {')
37011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('    %s::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);' % self.layer_name)
37111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('}')
37211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
37311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n".join(body)
37411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
37511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def _gen_layer_interface_v0_functions(self):
37611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body = []
37711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('%s' % self.lineinfo.get())
37811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('// loader-layer interface v0')
37911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('')
38011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
38111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if self.layer_name == 'object_tracker':
38211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('static const VkExtensionProperties instance_extensions[] = {')
38311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('    {')
38411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('        VK_EXT_DEBUG_REPORT_EXTENSION_NAME,')
38511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('        VK_EXT_DEBUG_REPORT_SPEC_VERSION')
38611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('    }')
38711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('};')
38811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('')
38911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
39011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('static const VkLayerProperties globalLayerProps = {')
39111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('    "VK_LAYER_LUNARG_%s",' % self.layer_name)
39211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('    VK_LAYER_API_VERSION, // specVersion')
39311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('    1, // implementationVersion')
39411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('    "LunarG Validation Layer"')
39511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('};')
39611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('')
39711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        else:
39811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('static const VkLayerProperties globalLayerProps = {')
39911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('    "VK_LAYER_GOOGLE_%s",' % self.layer_name)
40011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('    VK_LAYER_API_VERSION, // specVersion')
40111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('    1, // implementationVersion')
40211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('    "Google Validation Layer"')
40311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('};')
40411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            body.append('')
40511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
40611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,  VkExtensionProperties* pProperties)')
40711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('{')
40811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if self.layer_name == 'object_tracker':
40911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          body.append('    return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);')
41011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        else:
41111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          body.append('    return util_GetExtensionProperties(0, NULL, pCount, pProperties);')
41211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('}')
41311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('')
41411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,  VkLayerProperties* pProperties)')
41511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('{')
41611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('    return util_GetLayerProperties(1, &globalLayerProps, pCount, pProperties);')
41711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('}')
41811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('')
41911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties* pProperties)')
42011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('{')
42111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('    return util_GetLayerProperties(1, &globalLayerProps, pCount, pProperties);')
42211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('}')
42311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('')
42411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName)')
42511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('{')
42611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('    return %s::GetDeviceProcAddr(dev, funcName);' % self.layer_name)
42711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('}')
42811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('')
42911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName)')
43011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('{')
43111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('    if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))')
43211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('        return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateInstanceLayerProperties);')
43311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('    if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties"))')
43411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('        return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateDeviceLayerProperties);')
43511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('    if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))')
43611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('        return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateInstanceExtensionProperties);')
43711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('    if (!strcmp(funcName, "vkGetInstanceProcAddr"))')
43811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('        return reinterpret_cast<PFN_vkVoidFunction>(vkGetInstanceProcAddr);')
43911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('')
44011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('    return %s::GetInstanceProcAddr(instance, funcName);' % self.layer_name)
44111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('}')
44211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
44311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n".join(body)
44411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
44511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def _generate_dispatch_entrypoints(self, qual=""):
44611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if qual:
44711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            qual += " "
44811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
44911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        funcs = []
45011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        intercepted = []
45111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for proto in self.protos:
45211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if proto.name in ["EnumerateInstanceExtensionProperties",
45311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "EnumerateInstanceLayerProperties",
45411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "EnumerateDeviceLayerProperties"]:
45511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                # the layer do not need to define these
45611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                continue
45711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            elif proto.name in ["GetDeviceProcAddr",
45811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                "GetInstanceProcAddr"]:
45911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                funcs.append(proto.c_func(attr="VKAPI") + ';')
46011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                intercepted.append(proto)
46111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            else:
46211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                intercept = self.generate_intercept(proto, qual)
46311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if intercept is None:
46411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    # fill in default intercept for certain entrypoints
46511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if 'CreateDebugReportCallbackEXT' == proto.name:
46611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        intercept = self._gen_layer_dbg_create_msg_callback()
46711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    elif 'DestroyDebugReportCallbackEXT' == proto.name:
46811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        intercept = self._gen_layer_dbg_destroy_msg_callback()
46911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    elif 'DebugReportMessageEXT' == proto.name:
47011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        intercept = self._gen_debug_report_msg()
47111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    elif 'CreateDevice' == proto.name:
47211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        funcs.append('/* CreateDevice HERE */')
47311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
47411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if intercept is not None:
47511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    funcs.append(intercept)
47611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if not "KHR" in proto.name:
47711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        intercepted.append(proto)
47811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
47911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        instance_lookups = []
48011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        device_lookups = []
48111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for proto in intercepted:
48211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if proto_is_global(proto):
48311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                instance_lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
48411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                instance_lookups.append("    return (PFN_vkVoidFunction) %s;" % (proto.name))
48511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            else:
48611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                device_lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
48711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                device_lookups.append("    return (PFN_vkVoidFunction) %s;" % (proto.name))
48811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
48911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # add customized intercept_core_device_command
49011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body = []
49111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append('%s' % self.lineinfo.get())
49211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("static inline PFN_vkVoidFunction intercept_core_device_command(const char *name)")
49311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("{")
49411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append(generate_get_proc_addr_check("name"))
49511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("")
49611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("    name += 2;")
49711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("    %s" % "\n    ".join(device_lookups))
49811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("")
49911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("    return NULL;")
50011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("}")
50111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # add intercept_core_instance_command
50211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("static inline PFN_vkVoidFunction intercept_core_instance_command(const char *name)")
50311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("{")
50411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append(generate_get_proc_addr_check("name"))
50511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("")
50611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("    // we should never be queried for these commands")
50711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("    assert(strcmp(name, \"vkEnumerateInstanceLayerProperties\") &&")
50811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("           strcmp(name, \"vkEnumerateInstanceExtensionProperties\") &&")
50911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("           strcmp(name, \"vkEnumerateDeviceLayerProperties\"));")
51011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("")
51111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("    name += 2;")
51211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("    %s" % "\n    ".join(instance_lookups))
51311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("")
51411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("    return NULL;")
51511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body.append("}")
51611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
51711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        funcs.append("\n".join(body))
51811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n\n".join(funcs)
51911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
52011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def _generate_extensions(self):
52111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        exts = []
52211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        exts.append('%s' % self.lineinfo.get())
52311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        exts.append(self._gen_create_msg_callback())
52411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        exts.append(self._gen_destroy_msg_callback())
52511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        exts.append(self._gen_debug_report_msg())
52611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n".join(exts)
52711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
52811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def _generate_layer_gpa_function(self, extensions=[], instance_extensions=[]):
52911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        func_body = []
53011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#
53111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# New style of GPA Functions for the new layer_data/layer_logging changes
53211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#
53311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if self.layer_name in ['object_tracker', 'unique_objects']:
53411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            for ext_enable, ext_list in extensions:
53511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append('%s' % self.lineinfo.get())
53611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append('static inline PFN_vkVoidFunction intercept_%s_command(const char *name, VkDevice dev)' % ext_enable)
53711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append('{')
53811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append('    if (dev) {')
53911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append('        layer_data *my_data = get_my_data_ptr(get_dispatch_key(dev), layer_data_map);')
54011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append('        if (!my_data->%s)' % ext_enable)
54111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append('            return nullptr;')
54211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append('    }\n')
54311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
54411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                for ext_name in ext_list:
54511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    func_body.append('    if (!strcmp("%s", name))\n'
54611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                     '        return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (ext_name, ext_name[2:]))
54711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append('\n    return nullptr;')
54811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append('}\n')
54911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
55011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char* funcName)\n"
55111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "{\n"
55211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    PFN_vkVoidFunction addr;\n"
55311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    addr = intercept_core_device_command(funcName);\n"
55411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    if (addr)\n"
55511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "        return addr;\n"
55611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    assert(device);\n")
55711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            for ext_enable, _ in extensions:
55811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append('    addr = intercept_%s_command(funcName, device);' % ext_enable)
55911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append('    if (addr)\n'
56011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                 '        return addr;')
56111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("\n    if (get_dispatch_table(%s_device_table_map, device)->GetDeviceProcAddr == NULL)\n"
56211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "        return NULL;\n"
56311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    return get_dispatch_table(%s_device_table_map, device)->GetDeviceProcAddr(device, funcName);\n"
56411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "}\n" % (self.layer_name, self.layer_name))
56511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
56611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            for ext_enable, ext_list in instance_extensions:
56711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append('%s' % self.lineinfo.get())
56811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append('static inline PFN_vkVoidFunction intercept_%s_command(const char *name, VkInstance instance)' % ext_enable)
56911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append('{')
57011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if ext_enable == 'msg_callback_get_proc_addr':
57111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    func_body.append("    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);\n"
57211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                     "    return debug_report_get_instance_proc_addr(my_data->report_data, name);")
57311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                else:
57411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    func_body.append("    VkLayerInstanceDispatchTable* pTable = get_dispatch_table(%s_instance_table_map, instance);" % self.layer_name)
57511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    func_body.append('    if (instanceExtMap.size() == 0 || !instanceExtMap[pTable].%s)' % ext_enable)
57611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    func_body.append('        return nullptr;\n')
57711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
57811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    for ext_name in ext_list:
57911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        if wsi_name(ext_name):
58011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            func_body.append('%s' % wsi_ifdef(ext_name))
58111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        func_body.append('    if (!strcmp("%s", name))\n'
58211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                         '        return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (ext_name, ext_name[2:]))
58311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        if wsi_name(ext_name):
58411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            func_body.append('%s' % wsi_endif(ext_name))
58511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
58611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    func_body.append('\n    return nullptr;')
58711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append('}\n')
58811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
58911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
59011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "{\n"
59111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    PFN_vkVoidFunction addr;\n"
59211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    addr = intercept_core_instance_command(funcName);\n"
59311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    if (!addr) {\n"
59411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "        addr = intercept_core_device_command(funcName);\n"
59511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    }")
59611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
59711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            for ext_enable, _ in extensions:
59811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append("    if (!addr) {\n"
59911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                 "        addr = intercept_%s_command(funcName, VkDevice(VK_NULL_HANDLE));\n"
60011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                 "    }" % ext_enable)
60111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
60211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("    if (addr) {\n"
60311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "        return addr;\n"
60411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    }\n"
60511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    assert(instance);\n"
60611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             )
60711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
60811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            for ext_enable, _ in instance_extensions:
60911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append('    addr = intercept_%s_command(funcName, instance);' % ext_enable)
61011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append('    if (addr)\n'
61111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                 '        return addr;\n')
61211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
61311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("    if (get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr == NULL) {\n"
61411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "        return NULL;\n"
61511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    }\n"
61611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    return get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr(instance, funcName);\n"
61711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "}\n" % (self.layer_name, self.layer_name))
61811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return "\n".join(func_body)
61911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        else:
62011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append('%s' % self.lineinfo.get())
62111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char* funcName)\n"
62211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "{\n"
62311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    PFN_vkVoidFunction addr;\n")
62411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("\n"
62511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    loader_platform_thread_once(&initOnce, init%s);\n\n"
62611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    addr = intercept_core_device_command(funcName);\n"
62711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    if (addr)\n"
62811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "        return addr;" % self.layer_name)
62911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("    assert(device);\n")
63011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append('')
63111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append('    VkLayerDispatchTable *pDisp =  device_dispatch_table(device);')
63211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if 0 != len(extensions):
63311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                extra_space = ""
63411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                for (ext_enable, ext_list) in extensions:
63511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if 0 != len(ext_enable):
63611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        func_body.append('    if (deviceExtMap.size() != 0 && deviceExtMap[pDisp].%s)' % ext_enable)
63711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        func_body.append('    {')
63811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        extra_space = "    "
63911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    for ext_name in ext_list:
64011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        func_body.append('    %sif (!strcmp("%s", funcName))\n'
64111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                         '            return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
64211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if 0 != len(ext_enable):
64311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        func_body.append('    }')
64411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append('%s' % self.lineinfo.get())
64511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("    {\n"
64611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "        if (pDisp->GetDeviceProcAddr == NULL)\n"
64711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "            return NULL;\n"
64811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "        return pDisp->GetDeviceProcAddr(device, funcName);\n"
64911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    }\n"
65011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "}\n")
65111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append('%s' % self.lineinfo.get())
65211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
65311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "{\n"
65411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    PFN_vkVoidFunction addr;\n"
65511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             )
65611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append(
65711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    loader_platform_thread_once(&initOnce, init%s);\n\n"
65811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    addr = intercept_core_instance_command(funcName);\n"
65911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    if (addr)\n"
66011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "        return addr;" % self.layer_name)
66111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("    assert(instance);\n")
66211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("")
66311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("    VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(instance);\n")
66411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if 0 != len(instance_extensions):
66511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                extra_space = ""
66611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                for (ext_enable, ext_list) in instance_extensions:
66711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if 0 != len(ext_enable):
66811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        if ext_enable == 'msg_callback_get_proc_addr':
66911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            func_body.append("    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);\n"
67011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                     "    addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);\n"
67111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                     "    if (addr) {\n"
67211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                     "        return addr;\n"
67311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                     "    }\n")
67411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        else:
67511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            func_body.append('    if (instanceExtMap.size() != 0 && instanceExtMap[pTable].%s)' % ext_enable)
67611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            func_body.append('    {')
67711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            extra_space = "    "
67811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            for ext_name in ext_list:
67911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                if wsi_name(ext_name):
68011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    func_body.append('%s' % wsi_ifdef(ext_name))
68111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                func_body.append('    %sif (!strcmp("%s", funcName))\n'
68211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                         '            return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
68311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                if wsi_name(ext_name):
68411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    func_body.append('%s' % wsi_endif(ext_name))
68511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            if 0 != len(ext_enable):
68611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                func_body.append('    }\n')
68711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
68811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("    if (pTable->GetInstanceProcAddr == NULL)\n"
68911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "        return NULL;\n"
69011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "    return pTable->GetInstanceProcAddr(instance, funcName);\n"
69111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             "}\n")
69211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return "\n".join(func_body)
69311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
69411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
69511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def _generate_layer_initialization(self, init_opts=False, prefix='vk', lockname=None, condname=None):
69611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        func_body = ["#include \"vk_dispatch_table_helper.h\""]
69711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        func_body.append('%s' % self.lineinfo.get())
69811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        func_body.append('static void init_%s(layer_data *my_data, const VkAllocationCallbacks *pAllocator)\n'
69911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                         '{\n' % self.layer_name)
70011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if init_opts:
70111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append('%s' % self.lineinfo.get())
70211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append('')
70311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append('    layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_%s");' % self.layer_name)
70411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append('')
70511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if lockname is not None:
70611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append('%s' % self.lineinfo.get())
70711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("    if (!%sLockInitialized)" % lockname)
70811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("    {")
70911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("        // TODO/TBD: Need to delete this mutex sometime.  How???")
71011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("        loader_platform_thread_create_mutex(&%sLock);" % lockname)
71111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if condname is not None:
71211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                func_body.append("        loader_platform_thread_init_cond(&%sCond);" % condname)
71311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("        %sLockInitialized = 1;" % lockname)
71411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            func_body.append("    }")
71511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        func_body.append("}\n")
71611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        func_body.append('')
71711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n".join(func_body)
71811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
71911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertclass ObjectTrackerSubcommand(Subcommand):
72011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def generate_header(self):
72111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt = []
72211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('%s' % self.lineinfo.get())
72311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('#include "vk_loader_platform.h"')
72411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('#include "vulkan/vulkan.h"')
72511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('')
72611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('#include <stdio.h>')
72711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('#include <stdlib.h>')
72811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('#include <string.h>')
72911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('#include <cinttypes>')
73011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('')
73111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('#include <unordered_map>')
73211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('')
73311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('#include "vulkan/vk_layer.h"')
73411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('#include "vk_layer_config.h"')
73511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('#include "vk_layer_table.h"')
73611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('#include "vk_layer_data.h"')
73711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('#include "vk_layer_logging.h"')
73811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('')
73911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#       NOTE:  The non-autoGenerated code is in the object_tracker.h header file
74011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('#include "object_tracker.h"')
74111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('')
74211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n".join(header_txt)
74311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
74411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def generate_maps(self):
74511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        maps_txt = []
74611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for o in vulkan.object_type_list:
74711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            maps_txt.append('std::unordered_map<uint64_t, OBJTRACK_NODE*> %sMap;' % (o))
74811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n".join(maps_txt)
74911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
75011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def _gather_object_uses(self, obj_list, struct_type, obj_set):
75111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    # for each member of struct_type
75211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    #     add objs in obj_list to obj_set
75311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    #     call self for structs
75411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for m in sorted(vk_helper.struct_dict[struct_type]):
75511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if vk_helper.struct_dict[struct_type][m]['type'] in obj_list:
75611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                obj_set.add(vk_helper.struct_dict[struct_type][m]['type'])
75711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            elif vk_helper.is_type(vk_helper.struct_dict[struct_type][m]['type'], 'struct'):
75811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                obj_set = obj_set.union(self._gather_object_uses(obj_list, vk_helper.struct_dict[struct_type][m]['type'], obj_set))
75911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return obj_set
76011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
76111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def generate_procs(self):
76211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        procs_txt = []
76311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # First parse through funcs and gather dict of all objects seen by each call
76411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        obj_use_dict = {}
76511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        proto_list = vulkan.core.protos + vulkan.ext_khr_surface.protos + vulkan.ext_khr_surface.protos + vulkan.ext_khr_win32_surface.protos + vulkan.ext_khr_device_swapchain.protos
76611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for proto in proto_list:
76711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            disp_obj = proto.params[0].ty.strip('*').replace('const ', '')
76811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if disp_obj in vulkan.object_dispatch_list:
76911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if disp_obj not in obj_use_dict:
77011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    obj_use_dict[disp_obj] = set()
77111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                for p in proto.params[1:]:
77211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    base_type = p.ty.strip('*').replace('const ', '')
77311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if base_type in vulkan.object_type_list:
77411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        obj_use_dict[disp_obj].add(base_type)
77511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if vk_helper.is_type(base_type, 'struct'):
77611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        obj_use_dict[disp_obj] = self._gather_object_uses(vulkan.object_type_list, base_type, obj_use_dict[disp_obj])
77711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        #for do in obj_use_dict:
77811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        #    print "Disp obj %s has uses for objs: %s" % (do, ', '.join(obj_use_dict[do]))
77911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
78011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for o in vulkan.object_type_list:# vulkan.core.objects:
78111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('%s' % self.lineinfo.get())
78211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o)
78311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
78411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if o in vulkan.object_dispatch_list:
78511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                procs_txt.append('static void create_%s(%s dispatchable_object, %s vkObj, VkDebugReportObjectTypeEXT objType)' % (name, o, o))
78611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            else:
78711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                procs_txt.append('static void create_%s(VkDevice dispatchable_object, %s vkObj, VkDebugReportObjectTypeEXT objType)' % (name, o))
78811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('{')
78911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFORMATION_BIT_EXT, objType,(uint64_t)(vkObj), __LINE__, OBJTRACK_NONE, "OBJTRACK",')
79011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('        "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64 , object_track_index++, string_VkDebugReportObjectTypeEXT(objType),')
79111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('        (uint64_t)(vkObj));')
79211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('')
79311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE;')
79411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    pNewObjNode->belongsTo = (uint64_t)dispatchable_object;')
79511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    pNewObjNode->objType = objType;')
79611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    pNewObjNode->status  = OBJSTATUS_NONE;')
79711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    pNewObjNode->vkObj  = (uint64_t)(vkObj);')
79811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    %sMap[(uint64_t)vkObj] = pNewObjNode;' % (o))
79911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    uint32_t objIndex = objTypeToIndex(objType);')
80011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    numObjs[objIndex]++;')
80111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    numTotalObjs++;')
80211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('}')
80311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('')
80411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('%s' % self.lineinfo.get())
80511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if o in vulkan.object_dispatch_list:
80611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                procs_txt.append('static void destroy_%s(%s dispatchable_object, %s object)' % (name, o, o))
80711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            else:
80811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                procs_txt.append('static void destroy_%s(VkDevice dispatchable_object, %s object)' % (name, o))
80911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('{')
81011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    uint64_t object_handle = (uint64_t)(object);')
81111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    auto it = %sMap.find(object_handle);' % o)
81211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    if (it != %sMap.end()) {' % o)
81311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('        OBJTRACK_NODE* pNode = it->second;')
81411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('        uint32_t objIndex = objTypeToIndex(pNode->objType);')
81511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('        assert(numTotalObjs > 0);')
81611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('        numTotalObjs--;')
81711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('        assert(numObjs[objIndex] > 0);')
81811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('        numObjs[objIndex]--;')
81911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('        log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFORMATION_BIT_EXT, pNode->objType, object_handle, __LINE__, OBJTRACK_NONE, "OBJTRACK",')
82011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('           "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%" PRIu64 " total objs remain & %" PRIu64 " %s objs).",')
82111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('            string_VkDebugReportObjectTypeEXT(pNode->objType), (uint64_t)(object), numTotalObjs, numObjs[objIndex],')
82211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('            string_VkDebugReportObjectTypeEXT(pNode->objType));')
82311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('        delete pNode;')
82411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('        %sMap.erase(it);' % (o))
82511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    } else {')
82611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('        log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT ) 0,')
82711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('            object_handle, __LINE__, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",')
82811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('            "Unable to remove obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?",')
82911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('            object_handle);')
83011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    }')
83111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('}')
83211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('')
83311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # Generate the permutations of validate_* functions where for each
83411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        #  dispatchable object type, we have a corresponding validate_* function
83511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        #  for that object and all non-dispatchable objects that are used in API
83611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        #  calls with that dispatchable object.
83711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        procs_txt.append('//%s' % str(sorted(obj_use_dict)))
83811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for do in sorted(obj_use_dict):
83911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', do)
84011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
84111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            # First create validate_* func for disp obj
84211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('%s' % self.lineinfo.get())
84311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('static bool validate_%s(%s dispatchable_object, %s object, VkDebugReportObjectTypeEXT objType, bool null_allowed)' % (name, do, do))
84411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('{')
84511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    if (null_allowed && (object == VK_NULL_HANDLE))')
84611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('        return false;')
84711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (do, do))
84811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('        return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, objType, (uint64_t)(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
84911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('            "Invalid %s Object 0x%%" PRIx64 ,(uint64_t)(object));' % do)
85011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    }')
85111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('    return false;')
85211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('}')
85311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('')
85411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            for o in sorted(obj_use_dict[do]):
85511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if o == do: # We already generated this case above so skip here
85611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    continue
85711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o)
85811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
85911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                procs_txt.append('%s' % self.lineinfo.get())
86011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                procs_txt.append('static bool validate_%s(%s dispatchable_object, %s object, VkDebugReportObjectTypeEXT objType, bool null_allowed)' % (name, do, o))
86111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                procs_txt.append('{')
86211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                procs_txt.append('    if (null_allowed && (object == VK_NULL_HANDLE))')
86311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                procs_txt.append('        return false;')
86411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if o == "VkImage":
86511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    procs_txt.append('    // We need to validate normal image objects and those from the swapchain')
86611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    procs_txt.append('    if ((%sMap.find((uint64_t)object) == %sMap.end()) &&' % (o, o))
86711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    procs_txt.append('        (swapchainImageMap.find((uint64_t)object) == swapchainImageMap.end())) {')
86811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                else:
86911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    procs_txt.append('    if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (o, o))
87011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                procs_txt.append('        return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, objType, (uint64_t)(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
87111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                procs_txt.append('            "Invalid %s Object 0x%%" PRIx64, (uint64_t)(object));' % o)
87211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                procs_txt.append('    }')
87311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                procs_txt.append('    return false;')
87411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                procs_txt.append('}')
87511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            procs_txt.append('')
87611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        procs_txt.append('')
87711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n".join(procs_txt)
87811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
87911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def generate_destroy_instance(self):
88011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt = []
88111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('%s' % self.lineinfo.get())
88211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('VKAPI_ATTR void VKAPI_CALL DestroyInstance(')
88311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('VkInstance instance,')
88411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('const VkAllocationCallbacks* pAllocator)')
88511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('{')
88611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    std::unique_lock<std::mutex> lock(global_lock);')
88711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('')
88811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    dispatch_key key = get_dispatch_key(instance);')
88911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    layer_data *my_data = get_my_data_ptr(key, layer_data_map);')
89011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('')
89111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    // Enable the temporary callback(s) here to catch cleanup issues:')
89211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    bool callback_setup = false;')
89311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    if (my_data->num_tmp_callbacks > 0) {')
89411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('        if (!layer_enable_tmp_callbacks(my_data->report_data,')
89511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('                                        my_data->num_tmp_callbacks,')
89611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('                                        my_data->tmp_dbg_create_infos,')
89711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('                                        my_data->tmp_callbacks)) {')
89811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('            callback_setup = true;')
89911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('        }')
90011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    }')
90111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('')
90211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    validate_instance(instance, instance, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, false);')
90311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('')
90411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    destroy_instance(instance, instance);')
90511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    // Report any remaining objects in LL')
90611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('')
90711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    for (auto iit = VkDeviceMap.begin(); iit != VkDeviceMap.end();) {')
90811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('        OBJTRACK_NODE* pNode = iit->second;')
90911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('        if (pNode->belongsTo == (uint64_t)instance) {')
91011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('            log_msg(mid(instance), VK_DEBUG_REPORT_ERROR_BIT_EXT, pNode->objType, pNode->vkObj, __LINE__, OBJTRACK_OBJECT_LEAK, "OBJTRACK",')
91111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('                    "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),')
91211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('                    pNode->vkObj);')
91311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for o in vulkan.core.objects:
91411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if o in ['VkInstance', 'VkPhysicalDevice', 'VkQueue', 'VkDevice']:
91511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                continue
91611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedi_txt.append('            for (auto idt = %sMap.begin(); idt != %sMap.end();) {' % (o, o))
91711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedi_txt.append('                OBJTRACK_NODE* pNode = idt->second;')
91811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedi_txt.append('                if (pNode->belongsTo == iit->first) {')
91911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedi_txt.append('                    log_msg(mid(instance), VK_DEBUG_REPORT_ERROR_BIT_EXT, pNode->objType, pNode->vkObj, __LINE__, OBJTRACK_OBJECT_LEAK, "OBJTRACK",')
92011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedi_txt.append('                            "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),')
92111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedi_txt.append('                            pNode->vkObj);')
92211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedi_txt.append('                    %sMap.erase(idt++);' % o )
92311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedi_txt.append('                } else {')
92411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedi_txt.append('                    ++idt;')
92511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedi_txt.append('                }')
92611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedi_txt.append('            }')
92711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('            VkDeviceMap.erase(iit++);')
92811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('        } else {')
92911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('            ++iit;')
93011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('        }')
93111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    }')
93211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('')
93311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(object_tracker_instance_table_map, instance);')
93411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    pInstanceTable->DestroyInstance(instance, pAllocator);')
93511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('')
93611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    // Disable and cleanup the temporary callback(s):')
93711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    if (callback_setup) {')
93811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('        layer_disable_tmp_callbacks(my_data->report_data,')
93911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('                                    my_data->num_tmp_callbacks,')
94011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('                                    my_data->tmp_callbacks);')
94111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    }')
94211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    if (my_data->num_tmp_callbacks > 0) {')
94311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('        layer_free_tmp_callbacks(my_data->tmp_dbg_create_infos,')
94411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('                                 my_data->tmp_callbacks);')
94511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('        my_data->num_tmp_callbacks = 0;')
94611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    }')
94711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('')
94811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    // Clean up logging callback, if any')
94911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    while (my_data->logging_callback.size() > 0) {')
95011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('        VkDebugReportCallbackEXT callback = my_data->logging_callback.back();')
95111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('        layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);')
95211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('        my_data->logging_callback.pop_back();')
95311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    }')
95411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('')
95511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    layer_debug_report_destroy_instance(mid(instance));')
95611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    layer_data_map.erase(key);')
95711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('')
95811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    instanceExtMap.erase(pInstanceTable);')
95911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    lock.unlock();')
96011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # The loader holds a mutex that protects this from other threads
96111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('    object_tracker_instance_table_map.erase(key);')
96211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('}')
96311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedi_txt.append('')
96411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n".join(gedi_txt)
96511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
96611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def generate_destroy_device(self):
96711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt = []
96811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('%s' % self.lineinfo.get())
96911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('VKAPI_ATTR void VKAPI_CALL DestroyDevice(')
97011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('VkDevice device,')
97111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('const VkAllocationCallbacks* pAllocator)')
97211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('{')
97311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('    std::unique_lock<std::mutex> lock(global_lock);')
97411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('    validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);')
97511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('')
97611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('    destroy_device(device, device);')
97711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('    // Report any remaining objects associated with this VkDevice object in LL')
97811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for o in vulkan.core.objects:
97911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            # DescriptorSets and Command Buffers are destroyed through their pools, not explicitly
98011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if o in ['VkInstance', 'VkPhysicalDevice', 'VkQueue', 'VkDevice', 'VkDescriptorSet', 'VkCommandBuffer']:
98111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                continue
98211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedd_txt.append('    for (auto it = %sMap.begin(); it != %sMap.end();) {' % (o, o))
98311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedd_txt.append('        OBJTRACK_NODE* pNode = it->second;')
98411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedd_txt.append('        if (pNode->belongsTo == (uint64_t)device) {')
98511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedd_txt.append('            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, pNode->objType, pNode->vkObj, __LINE__, OBJTRACK_OBJECT_LEAK, "OBJTRACK",')
98611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedd_txt.append('                    "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),')
98711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedd_txt.append('                    pNode->vkObj);')
98811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedd_txt.append('            %sMap.erase(it++);' % o )
98911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedd_txt.append('        } else {')
99011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedd_txt.append('            ++it;')
99111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedd_txt.append('        }')
99211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedd_txt.append('    }')
99311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            gedd_txt.append('')
99411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append("    // Clean up Queue's MemRef Linked Lists")
99511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('    destroyQueueMemRefLists();')
99611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('')
99711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('    lock.unlock();')
99811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('')
99911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('    dispatch_key key = get_dispatch_key(device);')
100011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('    VkLayerDispatchTable *pDisp = get_dispatch_table(object_tracker_device_table_map, device);')
100111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('    pDisp->DestroyDevice(device, pAllocator);')
100211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('    object_tracker_device_table_map.erase(key);')
100311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('')
100411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('}')
100511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        gedd_txt.append('')
100611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n".join(gedd_txt)
100711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
100811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    # Special-case validating some objects -- they may be non-NULL but should
100911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    # only be validated upon meeting some condition specified below.
101011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def _dereference_conditionally(self, indent, prefix, type_name, name):
101111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        s_code = ''
101211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if type_name == 'pBufferInfo':
101311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            s_code += '%sif ((%sdescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)         ||\n'    % (indent, prefix)
101411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            s_code += '%s    (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)         ||\n'    % (indent, prefix)
101511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            s_code += '%s    (%sdescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||\n'    % (indent, prefix)
101611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            s_code += '%s    (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)   ) {\n' % (indent, prefix)
101711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        elif type_name == 'pImageInfo':
101811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            s_code += '%sif ((%sdescriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)                ||\n'    % (indent, prefix)
101911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            s_code += '%s    (%sdescriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||\n'    % (indent, prefix)
102011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            s_code += '%s    (%sdescriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)       ||\n'    % (indent, prefix)
102111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            s_code += '%s    (%sdescriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)          ||\n'    % (indent, prefix)
102211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            s_code += '%s    (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)            ) {\n' % (indent, prefix)
102311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        elif type_name == 'pTexelBufferView':
102411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            s_code += '%sif ((%sdescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) ||\n'      % (indent, prefix)
102511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            s_code += '%s    (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)   ) {\n'   % (indent, prefix)
102611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        elif name == 'pBeginInfo->pInheritanceInfo':
102711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            s_code += '%sOBJTRACK_NODE* pNode = VkCommandBufferMap[(uint64_t)commandBuffer];\n'       % (indent)
102811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            s_code += '%sif ((%s) && (pNode->status & OBJSTATUS_COMMAND_BUFFER_SECONDARY)) {\n'       % (indent, name)
102911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        else:
103011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            s_code += '%sif (%s) {\n' % (indent, name)
103111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return s_code
103211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
103311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def _gen_obj_validate_code(self, struct_uses, obj_type_mapping, func_name, valid_null_dict, param0_name, indent, prefix, array_index):
103411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pre_code = ''
103511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for obj in sorted(struct_uses):
103611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            name = obj
103711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            array = ''
103811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            type_name = ''
103911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if '[' in obj:
104011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                (name, array) = obj.split('[')
104111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                type_name = name
104211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                array = array.strip(']')
104311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if isinstance(struct_uses[obj], dict):
104411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                local_prefix = ''
104511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                name = '%s%s' % (prefix, name)
104611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                ptr_type = False
104711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if 'p' == obj[0]:
104811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    ptr_type = True
104911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    tmp_pre = self._dereference_conditionally(indent, prefix, type_name, name)
105011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_code += tmp_pre
105111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    indent += '    '
105211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if array != '':
105311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    idx = 'idx%s' % str(array_index)
105411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    array_index += 1
105511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_code += '%s\n' % self.lineinfo.get()
105611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
105711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    indent += '    '
105811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    local_prefix = '%s[%s].' % (name, idx)
105911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                elif ptr_type:
106011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    local_prefix = '%s->' % (name)
106111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                else:
106211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    local_prefix = '%s.' % (name)
106311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                tmp_pre = self._gen_obj_validate_code(struct_uses[obj], obj_type_mapping, func_name, valid_null_dict, param0_name, indent, local_prefix, array_index)
106411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pre_code += tmp_pre
106511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if array != '':
106611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    indent = indent[4:]
106711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_code += '%s}\n' % (indent)
106811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if ptr_type:
106911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    indent = indent[4:]
107011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_code += '%s}\n' % (indent)
107111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            else:
107211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                ptype = struct_uses[obj]
107311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                dbg_obj_type = obj_type_mapping[ptype]
107411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                fname = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', ptype)
107511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                fname = re.sub('([a-z0-9])([A-Z])', r'\1_\2', fname).lower()[3:]
107611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                full_name = '%s%s' % (prefix, name)
107711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                null_obj_ok = 'false'
107811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                # If a valid null param is defined for this func and we have a match, allow NULL
107911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if func_name in valid_null_dict and True in [name in pn for pn in sorted(valid_null_dict[func_name])]:
108011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    null_obj_ok = 'true'
108111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if (array_index > 0) or '' != array:
108211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    tmp_pre = self._dereference_conditionally(indent, prefix, type_name, full_name)
108311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_code += tmp_pre
108411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    indent += '    '
108511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if array != '':
108611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        idx = 'idx%s' % str(array_index)
108711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        array_index += 1
108811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
108911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        indent += '    '
109011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        full_name = '%s[%s]' % (full_name, idx)
109111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_code += '%s\n' % self.lineinfo.get()
109211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_code += '%sskipCall |= validate_%s(%s, %s, %s, %s);\n' %(indent, fname, param0_name, full_name, dbg_obj_type, null_obj_ok)
109311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if array != '':
109411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        indent = indent[4:]
109511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        pre_code += '%s}\n' % (indent)
109611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    indent = indent[4:]
109711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_code += '%s}\n' % (indent)
109811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                else:
109911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_code += '%s\n' % self.lineinfo.get()
110011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_code += '%sskipCall |= validate_%s(%s, %s, %s, %s);\n' %(indent, fname, param0_name, full_name, dbg_obj_type, null_obj_ok)
110111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return pre_code
110211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
110311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def generate_intercept(self, proto, qual):
110411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if proto.name in [ 'CreateDebugReportCallbackEXT', 'EnumerateInstanceLayerProperties', 'EnumerateInstanceExtensionProperties','EnumerateDeviceLayerProperties', 'EnumerateDeviceExtensionProperties' ]:
110511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            # use default version
110611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return None
110711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
110811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # Create map of object names to object type enums of the form VkName : VkObjectTypeName
110911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        obj_type_mapping = {base_t : base_t.replace("Vk", "VkDebugReportObjectType") for base_t in vulkan.object_type_list}
111011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # Convert object type enum names from UpperCamelCase to UPPER_CASE_WITH_UNDERSCORES
111111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for objectName, objectTypeEnum in obj_type_mapping.items():
111211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            obj_type_mapping[objectName] = ucc_to_U_C_C(objectTypeEnum) + '_EXT';
111311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # Command Buffer Object doesn't follow the rule.
111411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        obj_type_mapping['VkCommandBuffer'] = "VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT"
111511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        obj_type_mapping['VkShaderModule'] = "VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT"
111611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
111711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        explicit_object_tracker_functions = [
111811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "CreateInstance",
111911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "EnumeratePhysicalDevices",
112011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "GetPhysicalDeviceQueueFamilyProperties",
112111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "CreateDevice",
112211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "GetDeviceQueue",
112311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "QueueBindSparse",
112411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "AllocateDescriptorSets",
112511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "FreeDescriptorSets",
112611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "CreateGraphicsPipelines",
112711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "CreateComputePipelines",
112811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "AllocateCommandBuffers",
112911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "FreeCommandBuffers",
113011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "DestroyDescriptorPool",
113111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "DestroyCommandPool",
113211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "MapMemory",
113311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "UnmapMemory",
113411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "FreeMemory",
113511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "DestroySwapchainKHR",
113611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "GetSwapchainImagesKHR"
113711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        ]
113811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        decl = proto.c_func(attr="VKAPI")
113911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        param0_name = proto.params[0].name
114011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        using_line = ''
114111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        create_line = ''
114211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        destroy_line = ''
114311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # Dict below tracks params that are vk objects. Dict is "loop count"->["params w/ that loop count"] where '0' is params that aren't in an array
114411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # TODO : Should integrate slightly better code for this purpose from unique_objects layer
114511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        loop_params = defaultdict(list) # Dict uses loop count as key to make final code generation cleaner so params shared in single loop where needed
114611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        loop_types = defaultdict(list)
114711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # TODO : For now skipping objs that can be NULL. Really should check these and have special case that allows them to be NULL
114811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        #  or better yet, these should be encoded into an API json definition and we generate checks from there
114911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        #  Until then, this is a dict where each func name is a list of object params that can be null (so don't need to be validated)
115011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        #   param names may be directly passed to the function, or may be a field in a struct param
115111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        valid_null_object_names = {'CreateGraphicsPipelines' : ['basePipelineHandle'],
115211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'CreateComputePipelines' : ['basePipelineHandle'],
115311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'BeginCommandBuffer' : ['renderPass', 'framebuffer'],
115411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'QueueSubmit' : ['fence'],
115511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'AcquireNextImageKHR' : ['fence', 'semaphore' ],
115611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'UpdateDescriptorSets' : ['pTexelBufferView'],
115711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'CreateSwapchainKHR' : ['oldSwapchain'],
115811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  }
115911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        param_count = 'NONE' # keep track of arrays passed directly into API functions
116011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for p in proto.params:
116111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            base_type = p.ty.replace('const ', '').strip('*')
116211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if 'count' in p.name.lower():
116311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                param_count = p.name
116411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if base_type in vulkan.core.objects:
116511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                # This is an object to potentially check for validity. First see if it's an array
116611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if '*' in p.ty and 'const' in p.ty and param_count != 'NONE':
116711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    loop_params[param_count].append(p.name)
116811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    loop_types[param_count].append(str(p.ty[6:-1]))
116911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                # Not an array, check for just a base Object that's not in exceptions
117011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                elif '*' not in p.ty and (proto.name not in valid_null_object_names or p.name not in valid_null_object_names[proto.name]):
117111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    loop_params[0].append(p.name)
117211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    loop_types[0].append(str(p.ty))
117311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            elif vk_helper.is_type(base_type, 'struct'):
117411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                struct_type = base_type
117511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if vk_helper.typedef_rev_dict[struct_type] in vk_helper.struct_dict:
117611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    struct_type = vk_helper.typedef_rev_dict[struct_type]
117711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                # Parse elements of this struct param to identify objects and/or arrays of objects
117811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                for m in sorted(vk_helper.struct_dict[struct_type]):
117911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if vk_helper.struct_dict[struct_type][m]['type'] in vulkan.core.objects and vk_helper.struct_dict[struct_type][m]['type'] not in ['VkPhysicalDevice', 'VkQueue', 'VkFence', 'VkImage', 'VkDeviceMemory']:
118011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        if proto.name not in valid_null_object_names or vk_helper.struct_dict[struct_type][m]['name'] not in valid_null_object_names[proto.name]:
118111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            # This is not great, but gets the job done for now, but If we have a count and this param is a ptr w/
118211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            #  last letter 's' OR non-'count' string of count is in the param name, then this is a dynamically sized array param
118311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            param_array = False
118411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            if param_count != 'NONE':
118511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                if '*' in p.ty:
118611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    if 's' == p.name[-1] or param_count.lower().replace('count', '') in p.name.lower():
118711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        param_array = True
118811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            if param_array:
118911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                param_name = '%s[i].%s' % (p.name, vk_helper.struct_dict[struct_type][m]['name'])
119011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            else:
119111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                param_name = '%s->%s' % (p.name, vk_helper.struct_dict[struct_type][m]['name'])
119211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            if vk_helper.struct_dict[struct_type][m]['dyn_array']:
119311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                if param_count != 'NONE': # this will be a double-embedded loop, use comma delineated 'count,name' for param_name
119411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    loop_count = '%s[i].%s' % (p.name, vk_helper.struct_dict[struct_type][m]['array_size'])
119511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    loop_params[param_count].append('%s,%s' % (loop_count, param_name))
119611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    loop_types[param_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
119711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                else:
119811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    loop_count = '%s->%s' % (p.name, vk_helper.struct_dict[struct_type][m]['array_size'])
119911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    loop_params[loop_count].append(param_name)
120011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    loop_types[loop_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
120111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            else:
120211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                if '[' in param_name: # dynamic array param, set size
120311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    loop_params[param_count].append(param_name)
120411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    loop_types[param_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
120511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                else:
120611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    loop_params[0].append(param_name)
120711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    loop_types[0].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
120811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        last_param_index = None
120911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        create_func = False
121011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if True in [create_txt in proto.name for create_txt in ['Create', 'Allocate']]:
121111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            create_func = True
121211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            last_param_index = -1 # For create funcs don't validate last object
121311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        (struct_uses, local_decls) = get_object_uses(vulkan.object_type_list, proto.params[:last_param_index])
121411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        funcs = []
121511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        mutex_unlock = False
121611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        funcs.append('%s\n' % self.lineinfo.get())
121711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if proto.name in explicit_object_tracker_functions:
121811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            funcs.append('%s%s\n'
121911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '{\n'
122011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '    return explicit_%s;\n'
122111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '}' % (qual, decl, proto.c_call()))
122211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return "".join(funcs)
122311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # Temporarily prevent  DestroySurface call from being generated until WSI layer support is fleshed out
122411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        elif 'DestroyInstance' in proto.name or 'DestroyDevice' in proto.name:
122511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return ""
122611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        else:
122711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if create_func:
122811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                typ = proto.params[-1].ty.strip('*').replace('const ', '');
122911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
123011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
123111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                create_line =  '    {\n'
123211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                create_line += '        std::lock_guard<std::mutex> lock(global_lock);\n'
123311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                create_line += '        if (result == VK_SUCCESS) {\n'
123411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                create_line += '            create_%s(%s, *%s, %s);\n' % (name, param0_name, proto.params[-1].name, obj_type_mapping[typ])
123511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                create_line += '        }\n'
123611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                create_line += '    }\n'
123711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if 'FreeCommandBuffers' in proto.name:
123811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                typ = proto.params[-1].ty.strip('*').replace('const ', '');
123911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
124011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
124111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                funcs.append('%s\n' % self.lineinfo.get())
124211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                destroy_line =  '    loader_platform_thread_lock_mutex(&objLock);\n'
124311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                destroy_line += '    for (uint32_t i = 0; i < commandBufferCount; i++) {\n'
124411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                destroy_line += '        destroy_%s(%s[i], %s[i]);\n' % (name, proto.params[-1].name, proto.params[-1].name)
124511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                destroy_line += '    }\n'
124611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                destroy_line += '    loader_platform_thread_unlock_mutex(&objLock);\n'
124711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if 'Destroy' in proto.name:
124811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                typ = proto.params[-2].ty.strip('*').replace('const ', '');
124911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
125011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
125111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                funcs.append('%s\n' % self.lineinfo.get())
125211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                destroy_line =  '    {\n'
125311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                destroy_line += '        std::lock_guard<std::mutex> lock(global_lock);\n'
125411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                destroy_line += '        destroy_%s(%s, %s);\n' % (name, param0_name, proto.params[-2].name)
125511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                destroy_line += '    }\n'
125611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            indent = '    '
125711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if len(struct_uses) > 0:
125811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                using_line += '%sbool skipCall = false;\n' % (indent)
125911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if not mutex_unlock:
126011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    using_line += '%s{\n' % (indent)
126111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    indent += '    '
126211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    using_line += '%sstd::lock_guard<std::mutex> lock(global_lock);\n' % (indent)
126311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    mutex_unlock = True
126411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                using_line += '// objects to validate: %s\n' % str(sorted(struct_uses))
126511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                using_line += self._gen_obj_validate_code(struct_uses, obj_type_mapping, proto.name, valid_null_object_names, param0_name, indent, '', 0)
126611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if mutex_unlock:
126711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                indent = indent[4:]
126811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                using_line += '%s}\n' % (indent)
126911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if len(struct_uses) > 0:
127011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                using_line += '    if (skipCall)\n'
127111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if proto.ret == "bool":
127211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    using_line += '        return false;\n'
127311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                elif proto.ret == "VkBool32":
127411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    using_line += '        return VK_FALSE;\n'
127511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                elif proto.ret != "void":
127611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    using_line += '        return VK_ERROR_VALIDATION_FAILED_EXT;\n'
127711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                else:
127811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    using_line += '        return;\n'
127911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            ret_val = ''
128011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            stmt = ''
128111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if proto.ret != "void":
128211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                ret_val = "%s result = " % proto.ret
128311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                stmt = "    return result;\n"
128411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
128511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            dispatch_param = proto.params[0].name
128611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if 'CreateInstance' in proto.name:
128711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert               dispatch_param = '*' + proto.params[1].name
128811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
128911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            # Must use 'instance' table for these APIs, 'device' table otherwise
129011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            table_type = ""
129111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if proto_is_global(proto):
129211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                table_type = "instance"
129311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            else:
129411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                table_type = "device"
129511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if wsi_name(proto.name):
129611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                funcs.append('%s' % wsi_ifdef(proto.name))
129711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            funcs.append('%s%s\n'
129811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '{\n'
129911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '%s'
130011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '%s'
130111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '    %sget_dispatch_table(object_tracker_%s_table_map, %s)->%s;\n'
130211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '%s'
130311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '%s'
130411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '}' % (qual, decl, using_line, destroy_line, ret_val, table_type, dispatch_param, proto.c_call(), create_line, stmt))
130511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if wsi_name(proto.name):
130611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                funcs.append('%s' % wsi_endif(proto.name))
130711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n\n".join(funcs)
130811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
130911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def generate_body(self):
131011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        self.layer_name = "object_tracker"
131111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        extensions=[('wsi_enabled',
131211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     ['vkCreateSwapchainKHR',
131311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
131411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
131511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if self.wsi == 'Win32':
131611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            instance_extensions=[('msg_callback_get_proc_addr', []),
131711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  ('wsi_enabled',
131811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  ['vkDestroySurfaceKHR',
131911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfaceSupportKHR',
132011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
132111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfaceFormatsKHR',
132211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfacePresentModesKHR',
132311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkCreateWin32SurfaceKHR',
132411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceWin32PresentationSupportKHR'])]
132511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        elif self.wsi == 'Android':
132611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            instance_extensions=[('msg_callback_get_proc_addr', []),
132711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  ('wsi_enabled',
132811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  ['vkDestroySurfaceKHR',
132911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfaceSupportKHR',
133011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
133111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfaceFormatsKHR',
133211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfacePresentModesKHR',
133311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkCreateAndroidSurfaceKHR'])]
133411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        elif self.wsi == 'Xcb' or self.wsi == 'Xlib' or self.wsi == 'Wayland' or self.wsi == 'Mir':
133511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            instance_extensions=[('msg_callback_get_proc_addr', []),
133611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  ('wsi_enabled',
133711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  ['vkDestroySurfaceKHR',
133811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfaceSupportKHR',
133911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
134011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfaceFormatsKHR',
134111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfacePresentModesKHR',
134211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkCreateXcbSurfaceKHR',
134311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceXcbPresentationSupportKHR',
134411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkCreateXlibSurfaceKHR',
134511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceXlibPresentationSupportKHR',
134611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkCreateWaylandSurfaceKHR',
134711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceWaylandPresentationSupportKHR',
134811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkCreateMirSurfaceKHR',
134911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceMirPresentationSupportKHR'])]
135011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        else:
135111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            print('Error: Undefined DisplayServer')
135211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            instance_extensions=[]
135311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
135411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body = ["namespace %s {" % self.layer_name,
135511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                self.generate_maps(),
135611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                self.generate_procs(),
135711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                self.generate_destroy_instance(),
135811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                self.generate_destroy_device(),
135911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                self._generate_dispatch_entrypoints(),
136011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                self._generate_extensions(),
136111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                self._generate_layer_gpa_function(extensions,
136211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                  instance_extensions),
136311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                "} // namespace %s" % self.layer_name,
136411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                self._gen_layer_logging_workaround(),
136511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                self._gen_layer_interface_v0_functions()]
136611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n\n".join(body)
136711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
136811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertclass UniqueObjectsSubcommand(Subcommand):
136911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def generate_header(self):
137011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt = []
137111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('%s' % self.lineinfo.get())
137211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        header_txt.append('#include "unique_objects.h"')
137311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n".join(header_txt)
137411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
137511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    # Generate UniqueObjects code for given struct_uses dict of objects that need to be unwrapped
137611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    # vector_name_set is used to make sure we don't replicate vector names
137711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    # first_level_param indicates if elements are passed directly into the function else they're below a ptr/struct
137811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    # TODO : Comment this code
137911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def _gen_obj_code(self, struct_uses, param_type, indent, prefix, array_index, vector_name_set, first_level_param):
138011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        decls = ''
138111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pre_code = ''
138211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        post_code = ''
138311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for obj in sorted(struct_uses):
138411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            name = obj
138511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            array = ''
138611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if '[' in obj:
138711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                (name, array) = obj.split('[')
138811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                array = array.strip(']')
138911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            ptr_type = False
139011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if 'p' == obj[0] and obj[1] != obj[1].lower(): # TODO : Not ideal way to determine ptr
139111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                ptr_type = True
139211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if isinstance(struct_uses[obj], dict):
139311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                local_prefix = ''
139411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                name = '%s%s' % (prefix, name)
139511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if ptr_type:
139611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if first_level_param and name in param_type:
139711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        pre_code += '%sif (%s) {\n' % (indent, name)
139811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    else: # shadow ptr will have been initialized at this point so check it vs. source ptr
139911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        pre_code += '%sif (local_%s) {\n' % (indent, name)
140011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    indent += '    '
140111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if array != '':
140211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    idx = 'idx%s' % str(array_index)
140311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    array_index += 1
140411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if first_level_param and name in param_type:
140511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        pre_code += '%slocal_%s = new safe_%s[%s];\n' % (indent, name, param_type[name].strip('*'), array)
140611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        post_code += '    if (local_%s)\n' % (name)
140711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        post_code += '        delete[] local_%s;\n' % (name)
140811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
140911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    indent += '    '
141011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if first_level_param:
141111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        pre_code += '%slocal_%s[%s].initialize(&%s[%s]);\n' % (indent, name, idx, name, idx)
141211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    local_prefix = '%s[%s].' % (name, idx)
141311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                elif ptr_type:
141411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if first_level_param and name in param_type:
141511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        pre_code += '%slocal_%s = new safe_%s(%s);\n' % (indent, name, param_type[name].strip('*'), name)
141611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        post_code += '    if (local_%s)\n' % (name)
141711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        post_code += '        delete local_%s;\n' % (name)
141811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    local_prefix = '%s->' % (name)
141911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                else:
142011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    local_prefix = '%s.' % (name)
142111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                assert isinstance(decls, object)
142211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                (tmp_decl, tmp_pre, tmp_post) = self._gen_obj_code(struct_uses[obj], param_type, indent, local_prefix, array_index, vector_name_set, False)
142311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                decls += tmp_decl
142411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pre_code += tmp_pre
142511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                post_code += tmp_post
142611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if array != '':
142711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    indent = indent[4:]
142811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_code += '%s}\n' % (indent)
142911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if ptr_type:
143011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    indent = indent[4:]
143111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_code += '%s}\n' % (indent)
143211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            else:
143311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if (array_index > 0) or array != '': # TODO : This is not ideal, really want to know if we're anywhere under an array
143411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if first_level_param:
143511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        decls += '%s%s* local_%s = NULL;\n' % (indent, struct_uses[obj], name)
143611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if array != '' and not first_level_param: # ptrs under structs will have been initialized so use local_*
143711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        pre_code += '%sif (local_%s%s) {\n' %(indent, prefix, name)
143811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    else:
143911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        pre_code += '%sif (%s%s) {\n' %(indent, prefix, name)
144011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    indent += '    '
144111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if array != '':
144211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        idx = 'idx%s' % str(array_index)
144311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        array_index += 1
144411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        if first_level_param:
144511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            pre_code += '%slocal_%s = new %s[%s];\n' % (indent, name, struct_uses[obj], array)
144611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            post_code += '    if (local_%s)\n' % (name)
144711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            post_code += '        delete[] local_%s;\n' % (name)
144811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
144911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        indent += '    '
145011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        name = '%s[%s]' % (name, idx)
145111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pName = 'p%s' % (struct_uses[obj][2:])
145211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if name not in vector_name_set:
145311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        vector_name_set.add(name)
145411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_code += '%slocal_%s%s = (%s)my_map_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(%s%s)];\n' % (indent, prefix, name, struct_uses[obj], prefix, name)
145511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if array != '':
145611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        indent = indent[4:]
145711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        pre_code += '%s}\n' % (indent)
145811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    indent = indent[4:]
145911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_code += '%s}\n' % (indent)
146011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                else:
146111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_code += '%s\n' % (self.lineinfo.get())
146211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    deref_txt = '&'
146311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if ptr_type:
146411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        deref_txt = ''
146511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if '->' in prefix: # need to update local struct
146611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        pre_code += '%slocal_%s%s = (%s)my_map_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(%s%s)];\n' % (indent, prefix, name, struct_uses[obj], prefix, name)
146711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    else:
146811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        pre_code += '%s%s = (%s)my_map_data->unique_id_mapping[reinterpret_cast<uint64_t &>(%s)];\n' % (indent, name, struct_uses[obj], name)
146911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return decls, pre_code, post_code
147011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
147111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def generate_intercept(self, proto, qual):
147211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        create_func = False
147311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        destroy_func = False
147411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        last_param_index = None #typcially we look at all params for ndos
147511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pre_call_txt = '' # code prior to calling down chain such as unwrap uses of ndos
147611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        post_call_txt = '' # code following call down chain such to wrap newly created ndos, or destroy local wrap struct
147711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        funcs = []
147811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        indent = '    ' # indent level for generated code
147911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        decl = proto.c_func(attr="VKAPI")
148011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # A few API cases that are manual code
148111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # TODO : Special case Create*Pipelines funcs to handle creating multiple unique objects
148211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        explicit_object_tracker_functions = ['GetSwapchainImagesKHR',
148311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                             'CreateSwapchainKHR',
148411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                             'CreateInstance',
148511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                             'DestroyInstance',
148611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                             'CreateDevice',
148711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                             'DestroyDevice',
148811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                             'CreateComputePipelines',
148911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                             'CreateGraphicsPipelines'
149011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                             ]
149111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # TODO : This is hacky, need to make this a more general-purpose solution for all layers
149211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        ifdef_dict = {'CreateXcbSurfaceKHR': 'VK_USE_PLATFORM_XCB_KHR',
149311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      'CreateAndroidSurfaceKHR': 'VK_USE_PLATFORM_ANDROID_KHR',
149411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      'CreateWin32SurfaceKHR': 'VK_USE_PLATFORM_WIN32_KHR',
149511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      'CreateXlibSurfaceKHR': 'VK_USE_PLATFORM_XLIB_KHR',
149611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      'CreateWaylandSurfaceKHR': 'VK_USE_PLATFORM_WAYLAND_KHR',
149711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      'CreateMirSurfaceKHR': 'VK_USE_PLATFORM_MIR_KHR'}
149811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # Give special treatment to create functions that return multiple new objects
149911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # This dict stores array name and size of array
150011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        custom_create_dict = {'pDescriptorSets' : 'pAllocateInfo->descriptorSetCount'}
150111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pre_call_txt += '%s\n' % (self.lineinfo.get())
150211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if proto.name in explicit_object_tracker_functions:
150311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            funcs.append('%s%s\n'
150411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '{\n'
150511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '    return explicit_%s;\n'
150611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '}' % (qual, decl, proto.c_call()))
150711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return "".join(funcs)
150811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if True in [create_txt in proto.name for create_txt in ['Create', 'Allocate']]:
150911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            create_func = True
151011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            last_param_index = -1 # For create funcs don't care if last param is ndo
151111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if True in [destroy_txt in proto.name for destroy_txt in ['Destroy', 'Free']]:
151211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            destroy_obj_type = proto.params[-2].ty
151311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if destroy_obj_type in vulkan.object_non_dispatch_list:
151411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                destroy_func = True
151511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
151611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # First thing we need to do is gather uses of non-dispatchable-objects (ndos)
151711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        (struct_uses, local_decls) = get_object_uses(vulkan.object_non_dispatch_list, proto.params[1:last_param_index])
151811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
151911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        dispatch_param = proto.params[0].name
152011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if 'CreateInstance' in proto.name:
152111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert           dispatch_param = '*' + proto.params[1].name
152211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pre_call_txt += '%slayer_data *my_map_data = get_my_data_ptr(get_dispatch_key(%s), layer_data_map);\n' % (indent, dispatch_param)
152311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if len(struct_uses) > 0:
152411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pre_call_txt += '// STRUCT USES:%s\n' % sorted(struct_uses)
152511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if len(local_decls) > 0:
152611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pre_call_txt += '//LOCAL DECLS:%s\n' % sorted(local_decls)
152711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if destroy_func: # only one object
152811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pre_call_txt += '%sstd::unique_lock<std::mutex> lock(global_lock);\n' % (indent)
152911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                for del_obj in sorted(struct_uses):
153011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_call_txt += '%suint64_t local_%s = reinterpret_cast<uint64_t &>(%s);\n' % (indent, del_obj, del_obj)
153111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_call_txt += '%s%s = (%s)my_map_data->unique_id_mapping[local_%s];\n' % (indent, del_obj, struct_uses[del_obj], del_obj)
153211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pre_call_txt += '%slock.unlock();\n' % (indent)
153311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                (pre_decl, pre_code, post_code) = ('', '', '')
153411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            else:
153511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                (pre_decl, pre_code, post_code) = self._gen_obj_code(struct_uses, local_decls, '    ', '', 0, set(), True)
153611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            # This is a bit hacky but works for now. Need to decl local versions of top-level structs
153711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            for ld in sorted(local_decls):
153811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                init_null_txt = 'NULL';
153911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if '*' not in local_decls[ld]:
154011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    init_null_txt = '{}';
154111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if local_decls[ld].strip('*') not in vulkan.object_non_dispatch_list:
154211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pre_decl += '    safe_%s local_%s = %s;\n' % (local_decls[ld], ld, init_null_txt)
154311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if pre_code != '': # lock around map uses
154411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pre_code = '%s{\n%sstd::lock_guard<std::mutex> lock(global_lock);\n%s%s}\n' % (indent, indent, pre_code, indent)
154511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pre_call_txt += '%s%s' % (pre_decl, pre_code)
154611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            post_call_txt += '%s' % (post_code)
154711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        elif create_func:
154811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            base_type = proto.params[-1].ty.replace('const ', '').strip('*')
154911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if base_type not in vulkan.object_non_dispatch_list:
155011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                return None
155111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        else:
155211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return None
155311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
155411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        ret_val = ''
155511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        ret_stmt = ''
155611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if proto.ret != "void":
155711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            ret_val = "%s result = " % proto.ret
155811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            ret_stmt = "    return result;\n"
155911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if create_func:
156011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            obj_type = proto.params[-1].ty.strip('*')
156111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            obj_name = proto.params[-1].name
156211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if obj_type in vulkan.object_non_dispatch_list:
156311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                local_name = "unique%s" % obj_type[2:]
156411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                post_call_txt += '%sif (VK_SUCCESS == result) {\n' % (indent)
156511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                indent += '    '
156611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                post_call_txt += '%sstd::lock_guard<std::mutex> lock(global_lock);\n' % (indent)
156711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if obj_name in custom_create_dict:
156811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    post_call_txt += '%s\n' % (self.lineinfo.get())
156911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    local_name = '%ss' % (local_name) # add 's' to end for vector of many
157011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    post_call_txt += '%sfor (uint32_t i=0; i<%s; ++i) {\n' % (indent, custom_create_dict[obj_name])
157111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    indent += '    '
157211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    post_call_txt += '%suint64_t unique_id = global_unique_id++;\n' % (indent)
157311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    post_call_txt += '%smy_map_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t &>(%s[i]);\n' % (indent, obj_name)
157411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    post_call_txt += '%s%s[i] = reinterpret_cast<%s&>(unique_id);\n' % (indent, obj_name, obj_type)
157511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    indent = indent[4:]
157611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    post_call_txt += '%s}\n' % (indent)
157711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                else:
157811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    post_call_txt += '%s\n' % (self.lineinfo.get())
157911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    post_call_txt += '%suint64_t unique_id = global_unique_id++;\n' % (indent)
158011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    post_call_txt += '%smy_map_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t &>(*%s);\n' % (indent, obj_name)
158111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    post_call_txt += '%s*%s = reinterpret_cast<%s&>(unique_id);\n' % (indent, obj_name, obj_type)
158211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                indent = indent[4:]
158311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                post_call_txt += '%s}\n' % (indent)
158411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        elif destroy_func:
158511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            del_obj = proto.params[-2].name
158611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if 'count' in del_obj.lower():
158711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                post_call_txt += '%s\n' % (self.lineinfo.get())
158811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                post_call_txt += '%sfor (uint32_t i=0; i<%s; ++i) {\n' % (indent, del_obj)
158911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                del_obj = proto.params[-1].name
159011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                indent += '    '
159111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                post_call_txt += '%sdelete (VkUniqueObject*)%s[i];\n' % (indent, del_obj)
159211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                indent = indent[4:]
159311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                post_call_txt += '%s}\n' % (indent)
159411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            else:
159511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                post_call_txt += '%s\n' % (self.lineinfo.get())
159611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                post_call_txt += '%slock.lock();\n' % (indent)
159711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                post_call_txt += '%smy_map_data->unique_id_mapping.erase(local_%s);\n' % (indent, proto.params[-2].name)
159811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
159911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        call_sig = proto.c_call()
160011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        # Replace default params with any custom local params
160111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for ld in local_decls:
160211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            call_sig = call_sig.replace(ld, '(const %s)local_%s' % (local_decls[ld], ld))
160311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if proto_is_global(proto):
160411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            table_type = "instance"
160511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        else:
160611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            table_type = "device"
160711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pre_call_txt += '%s\n' % (self.lineinfo.get())
160811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        open_ifdef = ''
160911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        close_ifdef = ''
161011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if proto.name in ifdef_dict:
161111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            open_ifdef = '#ifdef %s\n' % (ifdef_dict[proto.name])
161211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            close_ifdef = '#endif\n'
161311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        funcs.append('%s'
161411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '%s%s\n'
161511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '{\n'
161611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '%s'
161711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '    %sget_dispatch_table(unique_objects_%s_table_map, %s)->%s;\n'
161811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '%s'
161911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '%s'
162011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '}\n'
162111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     '%s' % (open_ifdef, qual, decl, pre_call_txt, ret_val, table_type, dispatch_param, call_sig, post_call_txt, ret_stmt, close_ifdef))
162211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n\n".join(funcs)
162311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
162411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    def generate_body(self):
162511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        self.layer_name = "unique_objects"
162611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        extensions=[('wsi_enabled',
162711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     ['vkCreateSwapchainKHR',
162811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
162911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
163011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if self.wsi == 'Win32':
163111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            instance_extensions=[('wsi_enabled',
163211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  ['vkDestroySurfaceKHR',
163311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfaceSupportKHR',
163411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
163511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfaceFormatsKHR',
163611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfacePresentModesKHR',
163711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkCreateWin32SurfaceKHR'
163811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   ])]
163911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        elif self.wsi == 'Android':
164011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            instance_extensions=[('wsi_enabled',
164111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  ['vkDestroySurfaceKHR',
164211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfaceSupportKHR',
164311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
164411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfaceFormatsKHR',
164511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfacePresentModesKHR',
164611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkCreateAndroidSurfaceKHR'])]
164711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        elif self.wsi == 'Xcb' or self.wsi == 'Xlib' or self.wsi == 'Wayland' or self.wsi == 'Mir':
164811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            instance_extensions=[('wsi_enabled',
164911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  ['vkDestroySurfaceKHR',
165011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfaceSupportKHR',
165111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
165211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfaceFormatsKHR',
165311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkGetPhysicalDeviceSurfacePresentModesKHR',
165411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkCreateXcbSurfaceKHR',
165511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkCreateXlibSurfaceKHR',
165611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkCreateWaylandSurfaceKHR',
165711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   'vkCreateMirSurfaceKHR'
165811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   ])]
165911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        else:
166011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            print('Error: Undefined DisplayServer')
166111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            instance_extensions=[]
166211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
166311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        body = ["namespace %s {" % self.layer_name,
166411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                self._generate_dispatch_entrypoints(),
166511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                self._generate_layer_gpa_function(extensions,
166611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                  instance_extensions),
166711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                "} // namespace %s" % self.layer_name,
166811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                self._gen_layer_interface_v0_functions()]
166911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return "\n\n".join(body)
167011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
167111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertdef main():
167211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    wsi = {
167311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "Win32",
167411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "Android",
167511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "Xcb",
167611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "Xlib",
167711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "Wayland",
167811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "Mir",
167911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
168011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
168111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    subcommands = {
168211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "object_tracker" : ObjectTrackerSubcommand,
168311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "unique_objects" : UniqueObjectsSubcommand,
168411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
168511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
168611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if len(sys.argv) < 4 or sys.argv[1] not in wsi or sys.argv[2] not in subcommands or not os.path.exists(sys.argv[3]):
168711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        print("Usage: %s <wsi> <subcommand> <input_header> [outdir]" % sys.argv[0])
168811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        print
168911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        print("Available subcommands are: %s" % " ".join(subcommands))
169011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        exit(1)
169111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
169211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    hfp = vk_helper.HeaderFileParser(sys.argv[3])
169311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    hfp.parse()
169411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    vk_helper.enum_val_dict = hfp.get_enum_val_dict()
169511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    vk_helper.enum_type_dict = hfp.get_enum_type_dict()
169611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    vk_helper.struct_dict = hfp.get_struct_dict()
169711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    vk_helper.typedef_fwd_dict = hfp.get_typedef_fwd_dict()
169811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    vk_helper.typedef_rev_dict = hfp.get_typedef_rev_dict()
169911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    vk_helper.types_dict = hfp.get_types_dict()
170011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
170111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    outfile = None
170211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if len(sys.argv) >= 5:
170311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        outfile = sys.argv[4]
170411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
170511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    subcmd = subcommands[sys.argv[2]](outfile)
170611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    subcmd.run()
170711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
170811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertif __name__ == "__main__":
170911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    main()
1710