blob: 69edb1acfb13d4ae2019e6892d454e1439aec310 [file] [log] [blame]
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001#!/usr/bin/env python3
2#
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06003# VK
Tobin Ehlis12076fc2014-10-22 09:06:33 -06004#
Courtney Goeltzenleuchterfcbe16f2015-10-29 13:50:34 -06005# Copyright (C) 2015 Valve Corporation
Michael Lentine64e2ebd2015-12-03 14:33:09 -08006# Copyright (C) 2015 Google Inc.
Tobin Ehlis12076fc2014-10-22 09:06:33 -06007#
8# Permission is hereby granted, free of charge, to any person obtaining a
9# copy of this software and associated documentation files (the "Software"),
10# to deal in the Software without restriction, including without limitation
11# the rights to use, copy, modify, merge, publish, distribute, sublicense,
12# and/or sell copies of the Software, and to permit persons to whom the
13# Software is furnished to do so, subject to the following conditions:
14#
15# The above copyright notice and this permission notice shall be included
16# in all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24# DEALINGS IN THE SOFTWARE.
25#
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060026# Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
27# Author: Jon Ashburn <jon@lunarg.com>
28# Author: Mark Lobodzinski <mark@lunarg.com>
29# Author: Mike Stroyan <mike@LunarG.com>
30# Author: Tony Barbour <tony@LunarG.com>
Jon Ashburnf2bad722015-11-03 11:57:00 -070031# Author: Chia-I Wu <olv@lunarg.com>
Tobin Ehlis12076fc2014-10-22 09:06:33 -060032
33import sys
Tobin Ehlis14ff0852014-12-17 17:44:50 -070034import os
Mark Lobodzinski7c75b852015-05-05 15:01:37 -050035import re
Tobin Ehlis12076fc2014-10-22 09:06:33 -060036
Courtney Goeltzenleuchterf53c3cb2015-04-14 14:55:44 -060037import vulkan
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060038import vk_helper
Tobin Ehlis08fafd02015-06-12 12:49:01 -060039from source_line_info import sourcelineinfo
Tobin Ehlis154e0462015-08-26 11:22:09 -060040from collections import defaultdict
Tobin Ehlis12076fc2014-10-22 09:06:33 -060041
Jon Ashburn95a77ba2015-05-15 15:09:35 -060042def proto_is_global(proto):
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -070043 global_function_names = [
44 "CreateInstance",
45 "EnumerateInstanceLayerProperties",
46 "EnumerateInstanceExtensionProperties",
47 "EnumerateDeviceLayerProperties",
48 "EnumerateDeviceExtensionProperties",
49 "CreateXcbSurfaceKHR",
50 "vkGetPhysicalDeviceXcbPresentationSupportKHR",
51 "CreateXlibSurfaceKHR",
52 "vkGetPhysicalDeviceXlibPresentationSupportKHR",
53 "CreateWaylandSurfaceKHR",
54 "vkGetPhysicalDeviceWaylandPresentationSupportKHR",
55 "CreateMirSurfaceKHR",
56 "vkGetPhysicalDeviceMirPresentationSupportKHR",
57 "CreateAndroidSurfaceKHR",
58 "CreateWin32SurfaceKHR",
59 "vkGetPhysicalDeviceWin32PresentationSupportKHR"
60 ]
61 if proto.params[0].ty == "VkInstance" or proto.params[0].ty == "VkPhysicalDevice" or proto.name in global_function_names:
Jon Ashburn95a77ba2015-05-15 15:09:35 -060062 return True
63 else:
64 return False
65
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -070066def wsi_name(ext_name):
67 wsi_prefix = ""
68 if 'Xcb' in ext_name:
69 wsi_prefix = 'XCB'
70 elif 'Xlib' in ext_name:
71 wsi_prefix = 'XLIB'
72 elif 'Win32' in ext_name:
73 wsi_prefix = 'WIN32'
74 elif 'Mir' in ext_name:
75 wsi_prefix = 'MIR'
76 elif 'Wayland' in ext_name:
77 wsi_prefix = 'WAYLAND'
78 elif 'Android' in ext_name:
79 wsi_prefix = 'ANDROID'
80 else:
81 wsi_prefix = ''
82 return wsi_prefix
83
84def wsi_ifdef(ext_name):
85 wsi_prefix = wsi_name(ext_name)
86 if not wsi_prefix:
87 return ''
88 else:
89 return "#ifdef VK_USE_PLATFORM_%s_KHR" % wsi_prefix
90
91def wsi_endif(ext_name):
92 wsi_prefix = wsi_name(ext_name)
93 if not wsi_prefix:
94 return ''
95 else:
96 return "#endif // VK_USE_PLATFORM_%s_KHR" % wsi_prefix
97
Mike Stroyan938c2532015-04-03 13:58:35 -060098def generate_get_proc_addr_check(name):
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060099 return " if (!%s || %s[0] != 'v' || %s[1] != 'k')\n" \
100 " return NULL;" % ((name,) * 3)
Mike Stroyan938c2532015-04-03 13:58:35 -0600101
Mark Lobodzinski7c75b852015-05-05 15:01:37 -0500102def ucc_to_U_C_C(CamelCase):
103 temp = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', CamelCase)
104 return re.sub('([a-z0-9])([A-Z])', r'\1_\2', temp).upper()
105
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600106class Subcommand(object):
107 def __init__(self, argv):
108 self.argv = argv
Courtney Goeltzenleuchterf53c3cb2015-04-14 14:55:44 -0600109 self.headers = vulkan.headers
110 self.protos = vulkan.protos
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600111 self.no_addr = False
112 self.layer_name = ""
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600113 self.lineinfo = sourcelineinfo()
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600114
115 def run(self):
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600116 print(self.generate())
117
118 def generate(self):
119 copyright = self.generate_copyright()
120 header = self.generate_header()
121 body = self.generate_body()
122 footer = self.generate_footer()
123
124 contents = []
125 if copyright:
126 contents.append(copyright)
127 if header:
128 contents.append(header)
129 if body:
130 contents.append(body)
131 if footer:
132 contents.append(footer)
133
134 return "\n\n".join(contents)
135
136 def generate_copyright(self):
137 return """/* THIS FILE IS GENERATED. DO NOT EDIT. */
138
139/*
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600140 *
Courtney Goeltzenleuchterfcbe16f2015-10-29 13:50:34 -0600141 * Copyright (C) 2015 Valve Corporation
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600142 *
143 * Permission is hereby granted, free of charge, to any person obtaining a
144 * copy of this software and associated documentation files (the "Software"),
145 * to deal in the Software without restriction, including without limitation
146 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
147 * and/or sell copies of the Software, and to permit persons to whom the
148 * Software is furnished to do so, subject to the following conditions:
149 *
150 * The above copyright notice and this permission notice shall be included
151 * in all copies or substantial portions of the Software.
152 *
153 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
154 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
155 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
156 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
157 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
158 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
159 * DEALINGS IN THE SOFTWARE.
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -0600160 *
161 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
162 * Author: Jon Ashburn <jon@lunarg.com>
163 * Author: Mark Lobodzinski <mark@lunarg.com>
164 * Author: Mike Stroyan <mike@LunarG.com>
165 * Author: Tony Barbour <tony@LunarG.com>
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600166 */"""
167
168 def generate_header(self):
169 return "\n".join(["#include <" + h + ">" for h in self.headers])
170
171 def generate_body(self):
172 pass
173
174 def generate_footer(self):
175 pass
176
177 # Return set of printf '%' qualifier and input to that qualifier
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600178 def _get_printf_params(self, vk_type, name, output_param, cpp=False):
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600179 # TODO : Need ENUM and STRUCT checks here
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600180 if vk_helper.is_type(vk_type, 'enum'):#"_TYPE" in vk_type: # TODO : This should be generic ENUM check
Courtney Goeltzenleuchter95487bc2015-04-14 18:48:46 -0600181 return ("%s", "string_%s(%s)" % (vk_type.replace('const ', '').strip('*'), name))
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600182 if "char*" == vk_type:
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600183 return ("%s", name)
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600184 if "uint64" in vk_type:
185 if '*' in vk_type:
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600186 return ("%lu", "*%s" % name)
187 return ("%lu", name)
Tobin Ehlisa30e7e52015-07-06 14:02:36 -0600188 if vk_type.strip('*') in vulkan.object_non_dispatch_list:
189 if '*' in vk_type:
Chia-I Wue2fc5522015-10-26 20:04:44 +0800190 return ("%lu", "%s" % name)
191 return ("%lu", "%s" % name)
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600192 if "size" in vk_type:
193 if '*' in vk_type:
Mark Lobodzinskia1456492015-10-06 09:57:52 -0600194 return ("%lu", "(unsigned long)*%s" % name)
195 return ("%lu", "(unsigned long)%s" % name)
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600196 if "float" in vk_type:
197 if '[' in vk_type: # handle array, current hard-coded to 4 (TODO: Make this dynamic)
Tobin Ehlis99f88672015-01-10 12:42:41 -0700198 if cpp:
199 return ("[%i, %i, %i, %i]", '"[" << %s[0] << "," << %s[1] << "," << %s[2] << "," << %s[3] << "]"' % (name, name, name, name))
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600200 return ("[%f, %f, %f, %f]", "%s[0], %s[1], %s[2], %s[3]" % (name, name, name, name))
201 return ("%f", name)
Courtney Goeltzenleuchtercd2a0992015-07-09 11:44:38 -0600202 if "bool" in vk_type.lower() or 'xcb_randr_crtc_t' in vk_type:
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600203 return ("%u", name)
Tobin Ehlisb870cbb2015-04-15 07:46:12 -0600204 if True in [t in vk_type.lower() for t in ["int", "flags", "mask", "xcb_window_t"]]:
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600205 if '[' in vk_type: # handle array, current hard-coded to 4 (TODO: Make this dynamic)
Tobin Ehlis99f88672015-01-10 12:42:41 -0700206 if cpp:
207 return ("[%i, %i, %i, %i]", "%s[0] << %s[1] << %s[2] << %s[3]" % (name, name, name, name))
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600208 return ("[%i, %i, %i, %i]", "%s[0], %s[1], %s[2], %s[3]" % (name, name, name, name))
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600209 if '*' in vk_type:
Tobin Ehlisd2b88e82015-02-04 15:15:11 -0700210 if 'pUserData' == name:
211 return ("%i", "((pUserData == 0) ? 0 : *(pUserData))")
Tobin Ehlisc62cb892015-04-17 13:26:33 -0600212 if 'const' in vk_type.lower():
213 return ("%p", "(void*)(%s)" % name)
Jon Ashburn52f79b52014-12-12 16:10:45 -0700214 return ("%i", "*(%s)" % name)
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600215 return ("%i", name)
Tobin Ehlis3a1cc8d2014-11-11 17:28:22 -0700216 # TODO : This is special-cased as there's only one "format" param currently and it's nice to expand it
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600217 if "VkFormat" == vk_type:
Tobin Ehlis99f88672015-01-10 12:42:41 -0700218 if cpp:
219 return ("%p", "&%s" % name)
Chia-I Wu1b99bb22015-10-27 19:25:11 +0800220 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))
Tobin Ehlise7271572014-11-19 15:52:46 -0700221 if output_param:
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600222 return ("%p", "(void*)*%s" % name)
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600223 if vk_helper.is_type(vk_type, 'struct') and '*' not in vk_type:
Courtney Goeltzenleuchterd462fba2015-04-03 16:35:32 -0600224 return ("%p", "(void*)(&%s)" % name)
Jon Ashburn52f79b52014-12-12 16:10:45 -0700225 return ("%p", "(void*)(%s)" % name)
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600226
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600227 def _gen_create_msg_callback(self):
Tobin Ehlise8185062014-12-17 08:01:59 -0700228 r_body = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600229 r_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700230 r_body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(')
231 r_body.append(' VkInstance instance,')
232 r_body.append(' const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,')
233 r_body.append(' const VkAllocationCallbacks* pAllocator,')
234 r_body.append(' VkDebugReportCallbackEXT* pCallback)')
Tobin Ehlise8185062014-12-17 08:01:59 -0700235 r_body.append('{')
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600236 # Switch to this code section for the new per-instance storage and debug callbacks
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700237 if self.layer_name == 'object_tracker' or self.layer_name == 'threading':
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600238 r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700239 r_body.append(' VkResult result = pInstanceTable->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);')
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600240 r_body.append(' if (VK_SUCCESS == result) {')
241 r_body.append(' layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700242 r_body.append(' result = layer_create_msg_callback(my_data->report_data,')
243 r_body.append(' pCreateInfo,')
244 r_body.append(' pAllocator,')
245 r_body.append(' pCallback);')
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600246 r_body.append(' }')
247 r_body.append(' return result;')
248 else:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700249 r_body.append(' VkResult result = instance_dispatch_table(instance)->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600250 r_body.append(' if (VK_SUCCESS == result) {')
251 r_body.append(' layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700252 r_body.append(' result = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pCallback);')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600253 r_body.append(' }')
254 r_body.append(' return result;')
Tobin Ehlise8185062014-12-17 08:01:59 -0700255 r_body.append('}')
256 return "\n".join(r_body)
257
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600258 def _gen_destroy_msg_callback(self):
259 r_body = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600260 r_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700261 r_body.append('VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, const VkAllocationCallbacks *pAllocator)')
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600262 r_body.append('{')
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600263 # Switch to this code section for the new per-instance storage and debug callbacks
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700264 if self.layer_name == 'object_tracker' or self.layer_name == 'threading':
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600265 r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600266 else:
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700267 r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = instance_dispatch_table(instance);')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700268 r_body.append(' pInstanceTable->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700269 r_body.append(' layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
270 r_body.append(' layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);')
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600271 r_body.append('}')
272 return "\n".join(r_body)
Tobin Ehlise8185062014-12-17 08:01:59 -0700273
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700274 def _gen_debug_report_msg(self):
275 r_body = []
276 r_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700277 r_body.append('VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg)')
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700278 r_body.append('{')
279 # Switch to this code section for the new per-instance storage and debug callbacks
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700280 if self.layer_name == 'object_tracker' or self.layer_name == 'threading':
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700281 r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
282 else:
283 r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = instance_dispatch_table(instance);')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700284 r_body.append(' pInstanceTable->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);')
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700285 r_body.append('}')
286 return "\n".join(r_body)
287
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700288 def _gen_layer_get_global_extension_props(self, layer="generic"):
Tony Barbour59a47322015-06-24 16:06:58 -0600289 ggep_body = []
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600290 # generated layers do not provide any global extensions
291 ggep_body.append('%s' % self.lineinfo.get())
292
293 ggep_body.append('')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700294 if self.layer_name == 'object_tracker' or self.layer_name == 'threading':
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700295 ggep_body.append('static const VkExtensionProperties instance_extensions[] = {')
296 ggep_body.append(' {')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700297 ggep_body.append(' VK_EXT_DEBUG_REPORT_EXTENSION_NAME,')
298 ggep_body.append(' VK_EXT_DEBUG_REPORT_REVISION')
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700299 ggep_body.append(' }')
300 ggep_body.append('};')
Chia-I Wu9ab61502015-11-06 06:42:02 +0800301 ggep_body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties* pProperties)')
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600302 ggep_body.append('{')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700303 if self.layer_name == 'object_tracker' or self.layer_name == 'threading':
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700304 ggep_body.append(' return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);')
305 else:
306 ggep_body.append(' return util_GetExtensionProperties(0, NULL, pCount, pProperties);')
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600307 ggep_body.append('}')
308 return "\n".join(ggep_body)
309
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700310 def _gen_layer_get_global_layer_props(self, layer="generic"):
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600311 ggep_body = []
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700312 if layer == 'generic':
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600313 # Do nothing, extension definition part of generic.h
Tony Barbour59a47322015-06-24 16:06:58 -0600314 ggep_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600315 else:
Michael Lentine03107b42015-12-11 10:49:51 -0800316 layer_name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', layer)
317 layer_name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', layer_name).lower()
Tony Barbour59a47322015-06-24 16:06:58 -0600318 ggep_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter79a5a962015-07-07 17:51:45 -0600319 ggep_body.append('static const VkLayerProperties globalLayerProps[] = {')
Tony Barbour59a47322015-06-24 16:06:58 -0600320 ggep_body.append(' {')
Michael Lentine03107b42015-12-11 10:49:51 -0800321 ggep_body.append(' "VK_LAYER_LUNARG_%s",' % layer_name)
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600322 ggep_body.append(' VK_API_VERSION, // specVersion')
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800323 ggep_body.append(' VK_MAKE_VERSION(0, 1, 0), // implementationVersion')
Tony Barbour59a47322015-06-24 16:06:58 -0600324 ggep_body.append(' "layer: %s",' % layer)
325 ggep_body.append(' }')
326 ggep_body.append('};')
327 ggep_body.append('')
328 ggep_body.append('%s' % self.lineinfo.get())
Tony Barbour59a47322015-06-24 16:06:58 -0600329 ggep_body.append('')
Chia-I Wu9ab61502015-11-06 06:42:02 +0800330 ggep_body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties* pProperties)')
Tony Barbour59a47322015-06-24 16:06:58 -0600331 ggep_body.append('{')
Courtney Goeltzenleuchter79a5a962015-07-07 17:51:45 -0600332 ggep_body.append(' return util_GetLayerProperties(ARRAY_SIZE(globalLayerProps), globalLayerProps, pCount, pProperties);')
Tony Barbour59a47322015-06-24 16:06:58 -0600333 ggep_body.append('}')
334 return "\n".join(ggep_body)
335
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700336 def _gen_layer_get_physical_device_layer_props(self, layer="generic"):
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600337 gpdlp_body = []
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700338 if layer == 'generic':
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600339 # Do nothing, extension definition part of generic.h
340 gpdlp_body.append('%s' % self.lineinfo.get())
341 else:
342 gpdlp_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter79a5a962015-07-07 17:51:45 -0600343 gpdlp_body.append('static const VkLayerProperties deviceLayerProps[] = {')
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600344 gpdlp_body.append(' {')
345 gpdlp_body.append(' "%s",' % layer)
346 gpdlp_body.append(' VK_API_VERSION,')
347 gpdlp_body.append(' VK_MAKE_VERSION(0, 1, 0),')
348 gpdlp_body.append(' "layer: %s",' % layer)
349 gpdlp_body.append(' }')
350 gpdlp_body.append('};')
Chia-I Wu9ab61502015-11-06 06:42:02 +0800351 gpdlp_body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties* pProperties)')
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600352 gpdlp_body.append('{')
Courtney Goeltzenleuchter79a5a962015-07-07 17:51:45 -0600353 gpdlp_body.append(' return util_GetLayerProperties(ARRAY_SIZE(deviceLayerProps), deviceLayerProps, pCount, pProperties);')
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600354 gpdlp_body.append('}')
355 gpdlp_body.append('')
356 return "\n".join(gpdlp_body)
357
Mike Stroyanbf237d72015-04-03 17:45:53 -0600358 def _generate_dispatch_entrypoints(self, qual=""):
Mike Stroyan938c2532015-04-03 13:58:35 -0600359 if qual:
360 qual += " "
361
Mike Stroyan938c2532015-04-03 13:58:35 -0600362 funcs = []
363 intercepted = []
364 for proto in self.protos:
Jon Ashburn8d1b0b52015-05-18 13:20:15 -0600365 if proto.name == "GetDeviceProcAddr" or proto.name == "GetInstanceProcAddr":
Jon Ashburn8fd08252015-05-28 16:25:02 -0600366 continue
Mike Stroyan70c05e82015-04-08 10:27:43 -0600367 else:
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600368 intercept = self.generate_intercept(proto, qual)
Mike Stroyan938c2532015-04-03 13:58:35 -0600369 if intercept is None:
370 # fill in default intercept for certain entrypoints
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700371 if 'CreateDebugReportCallbackEXT' == proto.name:
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600372 intercept = self._gen_layer_dbg_create_msg_callback()
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700373 elif 'DestroyDebugReportCallbackEXT' == proto.name:
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600374 intercept = self._gen_layer_dbg_destroy_msg_callback()
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700375 elif 'DebugReportMessageEXT' == proto.name:
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700376 intercept = self._gen_debug_report_msg()
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600377 elif 'CreateDevice' == proto.name:
378 funcs.append('/* CreateDevice HERE */')
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600379 elif 'EnumerateInstanceExtensionProperties' == proto.name:
Tony Barbour59a47322015-06-24 16:06:58 -0600380 intercept = self._gen_layer_get_global_extension_props(self.layer_name)
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600381 elif 'EnumerateInstanceLayerProperties' == proto.name:
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600382 intercept = self._gen_layer_get_global_layer_props(self.layer_name)
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600383 elif 'EnumerateDeviceLayerProperties' == proto.name:
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600384 intercept = self._gen_layer_get_physical_device_layer_props(self.layer_name)
Tony Barbour59a47322015-06-24 16:06:58 -0600385
Mike Stroyan938c2532015-04-03 13:58:35 -0600386 if intercept is not None:
387 funcs.append(intercept)
Ian Elliott7e40db92015-08-21 15:09:33 -0600388 if not "KHR" in proto.name:
Jon Ashburn747f2b62015-06-18 15:02:58 -0600389 intercepted.append(proto)
Mike Stroyan938c2532015-04-03 13:58:35 -0600390
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600391 prefix="vk"
Mike Stroyan938c2532015-04-03 13:58:35 -0600392 lookups = []
393 for proto in intercepted:
Mike Stroyan938c2532015-04-03 13:58:35 -0600394 lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600395 lookups.append(" return (PFN_vkVoidFunction) %s%s;" %
Mike Stroyan938c2532015-04-03 13:58:35 -0600396 (prefix, proto.name))
Mike Stroyan938c2532015-04-03 13:58:35 -0600397
398 # add customized layer_intercept_proc
399 body = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600400 body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600401 body.append("static inline PFN_vkVoidFunction layer_intercept_proc(const char *name)")
Mike Stroyan938c2532015-04-03 13:58:35 -0600402 body.append("{")
403 body.append(generate_get_proc_addr_check("name"))
404 body.append("")
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600405 body.append(" name += 2;")
Mike Stroyan938c2532015-04-03 13:58:35 -0600406 body.append(" %s" % "\n ".join(lookups))
407 body.append("")
408 body.append(" return NULL;")
409 body.append("}")
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600410 # add layer_intercept_instance_proc
411 lookups = []
412 for proto in self.protos:
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600413 if not proto_is_global(proto):
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600414 continue
415
416 if not proto in intercepted:
417 continue
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -0600418 if proto.name == "CreateDevice":
419 continue
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600420 lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600421 lookups.append(" return (PFN_vkVoidFunction) %s%s;" % (prefix, proto.name))
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600422
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600423 body.append("static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char *name)")
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600424 body.append("{")
425 body.append(generate_get_proc_addr_check("name"))
426 body.append("")
427 body.append(" name += 2;")
428 body.append(" %s" % "\n ".join(lookups))
429 body.append("")
430 body.append(" return NULL;")
431 body.append("}")
432
Mike Stroyan938c2532015-04-03 13:58:35 -0600433 funcs.append("\n".join(body))
Mike Stroyan938c2532015-04-03 13:58:35 -0600434 return "\n\n".join(funcs)
435
Tobin Ehlisca915872014-11-18 11:28:33 -0700436 def _generate_extensions(self):
437 exts = []
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600438 exts.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600439 exts.append(self._gen_create_msg_callback())
440 exts.append(self._gen_destroy_msg_callback())
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700441 exts.append(self._gen_debug_report_msg())
Tobin Ehlisb870cbb2015-04-15 07:46:12 -0600442 return "\n".join(exts)
443
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600444 def _generate_layer_gpa_function(self, extensions=[], instance_extensions=[]):
Jon Ashburnbacb0f52015-04-06 10:58:22 -0600445 func_body = []
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600446#
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600447# New style of GPA Functions for the new layer_data/layer_logging changes
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600448#
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700449 if self.layer_name == 'object_tracker' or self.layer_name == 'threading':
Chia-I Wu9ab61502015-11-06 06:42:02 +0800450 func_body.append("VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600451 "{\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600452 " PFN_vkVoidFunction addr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600453 " if (device == VK_NULL_HANDLE) {\n"
454 " return NULL;\n"
455 " }\n"
456 " /* loader uses this to force layer initialization; device object is wrapped */\n"
457 " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
458 " initDeviceTable(%s_device_table_map, (const VkBaseLayerObject *) device);\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600459 " return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600460 " }\n\n"
461 " addr = layer_intercept_proc(funcName);\n"
462 " if (addr)\n"
463 " return addr;" % self.layer_name)
464 if 0 != len(extensions):
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600465 func_body.append('%s' % self.lineinfo.get())
466 func_body.append(' layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);')
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600467 for (ext_enable, ext_list) in extensions:
468 extra_space = ""
469 if 0 != len(ext_enable):
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600470 func_body.append(' if (my_device_data->%s) {' % ext_enable)
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600471 extra_space = " "
472 for ext_name in ext_list:
473 func_body.append(' %sif (!strcmp("%s", funcName))\n'
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600474 ' %sreturn reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, extra_space, ext_name))
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600475 if 0 != len(ext_enable):
476 func_body.append(' }\n')
477 func_body.append("\n if (get_dispatch_table(%s_device_table_map, device)->GetDeviceProcAddr == NULL)\n"
478 " return NULL;\n"
479 " return get_dispatch_table(%s_device_table_map, device)->GetDeviceProcAddr(device, funcName);\n"
480 "}\n" % (self.layer_name, self.layer_name))
Chia-I Wu9ab61502015-11-06 06:42:02 +0800481 func_body.append("VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600482 "{\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600483 " PFN_vkVoidFunction addr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600484 " if (instance == VK_NULL_HANDLE) {\n"
485 " return NULL;\n"
486 " }\n"
487 " /* loader uses this to force layer initialization; instance object is wrapped */\n"
488 " if (!strcmp(\"vkGetInstanceProcAddr\", funcName)) {\n"
489 " initInstanceTable(%s_instance_table_map, (const VkBaseLayerObject *) instance);\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600490 " return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600491 " }\n\n"
492 " addr = layer_intercept_instance_proc(funcName);\n"
493 " if (addr) {\n"
494 " return addr;"
495 " }\n" % self.layer_name)
Jon Ashburnbacb0f52015-04-06 10:58:22 -0600496
Jon Ashburn3dc39382015-09-17 10:00:32 -0600497 table_declared = False
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600498 if 0 != len(instance_extensions):
Jon Ashburn3dc39382015-09-17 10:00:32 -0600499 for (ext_enable, ext_list) in instance_extensions:
500 extra_space = ""
501 if 0 != len(ext_enable):
502 if ext_enable == 'msg_callback_get_proc_addr':
503 func_body.append(" layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600504 " addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);\n"
505 " if (addr) {\n"
506 " return addr;\n"
Jon Ashburn3dc39382015-09-17 10:00:32 -0600507 " }\n")
508 else:
509 if table_declared == False:
510 func_body.append(" VkLayerInstanceDispatchTable* pTable = get_dispatch_table(%s_instance_table_map, instance);" % self.layer_name)
511 table_declared = True
512 func_body.append(' if (instanceExtMap.size() != 0 && instanceExtMap[pTable].%s)' % ext_enable)
513 func_body.append(' {')
514 extra_space = " "
515 for ext_name in ext_list:
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700516 if wsi_name(ext_name):
517 func_body.append('%s' % wsi_ifdef(ext_name))
Jon Ashburn3dc39382015-09-17 10:00:32 -0600518 func_body.append(' %sif (!strcmp("%s", funcName))\n'
519 ' return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700520 if wsi_name(ext_name):
521 func_body.append('%s' % wsi_endif(ext_name))
Jon Ashburn3dc39382015-09-17 10:00:32 -0600522 if 0 != len(ext_enable):
523 func_body.append(' }\n')
524
525 func_body.append(" if (get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr == NULL) {\n"
526 " return NULL;\n"
527 " }\n"
528 " return get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr(instance, funcName);\n"
529 "}\n" % (self.layer_name, self.layer_name))
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600530 return "\n".join(func_body)
531 else:
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600532 func_body.append('%s' % self.lineinfo.get())
Chia-I Wu9ab61502015-11-06 06:42:02 +0800533 func_body.append("VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600534 "{\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600535 " PFN_vkVoidFunction addr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600536 " if (device == VK_NULL_HANDLE) {\n"
537 " return NULL;\n"
Jon Ashburn3a278b72015-10-06 17:05:21 -0600538 " }\n")
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700539 if self.layer_name == 'generic':
Jon Ashburn3a278b72015-10-06 17:05:21 -0600540 func_body.append("\n"
541 " /* loader uses this to force layer initialization; device object is wrapped */\n"
542 " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
543 " initDeviceTable((const VkBaseLayerObject *) device);\n"
544 " return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
545 " }\n\n"
546 " addr = layer_intercept_proc(funcName);\n"
547 " if (addr)\n"
548 " return addr;")
549 else:
550 func_body.append("\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600551 " loader_platform_thread_once(&initOnce, init%s);\n\n"
552 " /* loader uses this to force layer initialization; device object is wrapped */\n"
553 " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
554 " initDeviceTable((const VkBaseLayerObject *) device);\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600555 " return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600556 " }\n\n"
557 " addr = layer_intercept_proc(funcName);\n"
558 " if (addr)\n"
559 " return addr;" % self.layer_name)
560 func_body.append('')
561 func_body.append(' VkLayerDispatchTable *pDisp = device_dispatch_table(device);')
562 if 0 != len(extensions):
563 extra_space = ""
564 for (ext_enable, ext_list) in extensions:
565 if 0 != len(ext_enable):
Jon Ashburn8acd2332015-09-16 18:08:32 -0600566 func_body.append(' if (deviceExtMap.size() != 0 && deviceExtMap[pDisp].%s)' % ext_enable)
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600567 func_body.append(' {')
568 extra_space = " "
569 for ext_name in ext_list:
570 func_body.append(' %sif (!strcmp("%s", funcName))\n'
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600571 ' return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600572 if 0 != len(ext_enable):
573 func_body.append(' }')
574 func_body.append('%s' % self.lineinfo.get())
575 func_body.append(" {\n"
576 " if (pDisp->GetDeviceProcAddr == NULL)\n"
577 " return NULL;\n"
578 " return pDisp->GetDeviceProcAddr(device, funcName);\n"
579 " }\n"
580 "}\n")
Jon Ashburn3dc39382015-09-17 10:00:32 -0600581 func_body.append('%s' % self.lineinfo.get())
Chia-I Wu9ab61502015-11-06 06:42:02 +0800582 func_body.append("VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600583 "{\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600584 " PFN_vkVoidFunction addr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600585 " if (instance == VK_NULL_HANDLE) {\n"
586 " return NULL;\n"
Jon Ashburn3a278b72015-10-06 17:05:21 -0600587 " }\n")
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700588 if self.layer_name == 'generic':
Jon Ashburn3a278b72015-10-06 17:05:21 -0600589 func_body.append("\n"
590 " /* loader uses this to force layer initialization; instance object is wrapped */\n"
591 " if (!strcmp(\"vkGetInstanceProcAddr\", funcName)) {\n"
592 " initInstanceTable((const VkBaseLayerObject *) instance);\n"
593 " return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
594 " }\n\n"
595 " addr = layer_intercept_instance_proc(funcName);\n"
596 " if (addr)\n"
597 " return addr;")
598 else:
599 func_body.append(
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600600 " loader_platform_thread_once(&initOnce, init%s);\n\n"
601 " /* loader uses this to force layer initialization; instance object is wrapped */\n"
602 " if (!strcmp(\"vkGetInstanceProcAddr\", funcName)) {\n"
603 " initInstanceTable((const VkBaseLayerObject *) instance);\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600604 " return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600605 " }\n\n"
606 " addr = layer_intercept_instance_proc(funcName);\n"
607 " if (addr)\n"
608 " return addr;" % self.layer_name)
Jon Ashburn3dc39382015-09-17 10:00:32 -0600609 func_body.append("")
610 func_body.append(" VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(instance);")
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600611 if 0 != len(instance_extensions):
Jon Ashburn3dc39382015-09-17 10:00:32 -0600612 extra_space = ""
613 for (ext_enable, ext_list) in instance_extensions:
614 if 0 != len(ext_enable):
Jon Ashburn3a278b72015-10-06 17:05:21 -0600615 if ext_enable == 'msg_callback_get_proc_addr':
616 func_body.append(" layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);\n"
617 " addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);\n"
618 " if (addr) {\n"
619 " return addr;\n"
620 " }\n")
621 else:
622 func_body.append(' if (instanceExtMap.size() != 0 && instanceExtMap[pTable].%s)' % ext_enable)
623 func_body.append(' {')
624 extra_space = " "
625 for ext_name in ext_list:
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700626 if wsi_name(ext_name):
627 func_body.append('%s' % wsi_ifdef(ext_name))
Jon Ashburn3a278b72015-10-06 17:05:21 -0600628 func_body.append(' %sif (!strcmp("%s", funcName))\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -0600629 ' return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700630 if wsi_name(ext_name):
631 func_body.append('%s' % wsi_endif(ext_name))
Jon Ashburn3a278b72015-10-06 17:05:21 -0600632 if 0 != len(ext_enable):
633 func_body.append(' }\n')
Jon Ashburn3dc39382015-09-17 10:00:32 -0600634
635 func_body.append(" if (pTable->GetInstanceProcAddr == NULL)\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600636 " return NULL;\n"
637 " return pTable->GetInstanceProcAddr(instance, funcName);\n"
638 "}\n")
639 return "\n".join(func_body)
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600640
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600641
Mike Stroyaned238bb2015-05-15 08:50:57 -0600642 def _generate_layer_initialization(self, init_opts=False, prefix='vk', lockname=None, condname=None):
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600643 func_body = ["#include \"vk_dispatch_table_helper.h\""]
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600644 func_body.append('%s' % self.lineinfo.get())
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700645 func_body.append('static void init_%s(layer_data *my_data, const VkAllocationCallbacks *pAllocator)\n'
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600646 '{\n' % self.layer_name)
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700647 if init_opts:
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600648 func_body.append('%s' % self.lineinfo.get())
Jon Ashburn3a278b72015-10-06 17:05:21 -0600649 func_body.append(' uint32_t report_flags = 0;')
650 func_body.append(' uint32_t debug_action = 0;')
651 func_body.append(' FILE *log_output = NULL;')
652 func_body.append(' const char *option_str;\n')
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600653 func_body.append(' // initialize %s options' % self.layer_name)
Jon Ashburn3a278b72015-10-06 17:05:21 -0600654 func_body.append(' report_flags = getLayerOptionFlags("%sReportFlags", 0);' % self.layer_name)
655 func_body.append(' getLayerOptionEnum("%sDebugAction", (uint32_t *) &debug_action);' % self.layer_name)
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700656 func_body.append('')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600657 func_body.append(' if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)')
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700658 func_body.append(' {')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600659 func_body.append(' option_str = getLayerOption("%sLogFilename");' % self.layer_name)
660 func_body.append(' log_output = getLayerLogOutput(option_str,"%s");' % self.layer_name)
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700661 func_body.append(' VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700662 func_body.append(' memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo));')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700663 func_body.append(' dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700664 func_body.append(' dbgCreateInfo.flags = report_flags;')
665 func_body.append(' dbgCreateInfo.pfnCallback = log_callback;')
666 func_body.append(' dbgCreateInfo.pUserData = NULL;')
667 func_body.append(' layer_create_msg_callback(my_data->report_data, &dbgCreateInfo, pAllocator,')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600668 func_body.append(' &my_data->logging_callback);')
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700669 func_body.append(' }')
670 func_body.append('')
Tobin Ehlis36f1b462015-02-23 14:09:16 -0700671 if lockname is not None:
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600672 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlis36f1b462015-02-23 14:09:16 -0700673 func_body.append(" if (!%sLockInitialized)" % lockname)
674 func_body.append(" {")
675 func_body.append(" // TODO/TBD: Need to delete this mutex sometime. How???")
676 func_body.append(" loader_platform_thread_create_mutex(&%sLock);" % lockname)
Mike Stroyaned238bb2015-05-15 08:50:57 -0600677 if condname is not None:
678 func_body.append(" loader_platform_thread_init_cond(&%sCond);" % condname)
Tobin Ehlis36f1b462015-02-23 14:09:16 -0700679 func_body.append(" %sLockInitialized = 1;" % lockname)
680 func_body.append(" }")
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600681 func_body.append("}\n")
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -0600682 func_body.append('')
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600683 return "\n".join(func_body)
684
Mike Stroyan313f7e62015-08-10 16:42:53 -0600685 def _generate_new_layer_initialization(self, init_opts=False, prefix='vk', lockname=None, condname=None):
686 func_body = ["#include \"vk_dispatch_table_helper.h\""]
687 func_body.append('%s' % self.lineinfo.get())
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700688 func_body.append('static void init_%s(layer_data *my_data, const VkAllocationCallbacks *pAllocator)\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -0600689 '{\n' % self.layer_name)
690 if init_opts:
691 func_body.append('%s' % self.lineinfo.get())
692 func_body.append(' uint32_t report_flags = 0;')
693 func_body.append(' uint32_t debug_action = 0;')
694 func_body.append(' FILE *log_output = NULL;')
695 func_body.append(' const char *strOpt;')
696 func_body.append(' // initialize %s options' % self.layer_name)
697 func_body.append(' report_flags = getLayerOptionFlags("%sReportFlags", 0);' % self.layer_name)
Jon Ashburn9ff6ae92015-10-06 17:20:01 -0600698 func_body.append(' getLayerOptionEnum("%sDebugAction", (uint32_t *) &debug_action);' % self.layer_name)
Mike Stroyan313f7e62015-08-10 16:42:53 -0600699 func_body.append('')
700 func_body.append(' if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)')
701 func_body.append(' {')
702 func_body.append(' strOpt = getLayerOption("%sLogFilename");' % self.layer_name)
Tobin Ehlisb1df55e2015-09-15 09:55:54 -0600703 func_body.append(' log_output = getLayerLogOutput(strOpt, "%s");' % self.layer_name)
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700704 func_body.append(' VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700705 func_body.append(' memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo));')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700706 func_body.append(' dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700707 func_body.append(' dbgCreateInfo.flags = report_flags;')
708 func_body.append(' dbgCreateInfo.pfnCallback = log_callback;')
709 func_body.append(' dbgCreateInfo.pUserData = log_output;')
710 func_body.append(' layer_create_msg_callback(my_data->report_data, &dbgCreateInfo, pAllocator,')
711 func_body.append(' &my_data->logging_callback);')
Mike Stroyan313f7e62015-08-10 16:42:53 -0600712 func_body.append(' }')
713 func_body.append('')
714 if lockname is not None:
715 func_body.append('%s' % self.lineinfo.get())
716 func_body.append(" if (!%sLockInitialized)" % lockname)
717 func_body.append(" {")
718 func_body.append(" // TODO/TBD: Need to delete this mutex sometime. How???")
719 func_body.append(" loader_platform_thread_create_mutex(&%sLock);" % lockname)
720 if condname is not None:
721 func_body.append(" loader_platform_thread_init_cond(&%sCond);" % condname)
722 func_body.append(" %sLockInitialized = 1;" % lockname)
723 func_body.append(" }")
724 func_body.append("}\n")
725 func_body.append('')
726 return "\n".join(func_body)
727
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600728class LayerFuncsSubcommand(Subcommand):
729 def generate_header(self):
David Pinedo9316d3b2015-11-06 12:54:48 -0700730 return '#include <vulkan/vk_layer.h>\n#include "loader.h"'
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600731
732 def generate_body(self):
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600733 return self._generate_dispatch_entrypoints("static")
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600734
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600735class GenericLayerSubcommand(Subcommand):
736 def generate_header(self):
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500737 gen_header = []
Courtney Goeltzenleuchter79a5a962015-07-07 17:51:45 -0600738 gen_header.append('%s' % self.lineinfo.get())
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500739 gen_header.append('#include <stdio.h>')
740 gen_header.append('#include <stdlib.h>')
741 gen_header.append('#include <string.h>')
742 gen_header.append('#include <unordered_map>')
Tobin Ehlisb835d1b2015-07-03 10:34:49 -0600743 gen_header.append('#include "vk_loader_platform.h"')
David Pinedo9316d3b2015-11-06 12:54:48 -0700744 gen_header.append('#include "vulkan/vk_layer.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -0600745 gen_header.append('#include "vk_layer_config.h"')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600746 gen_header.append('#include "vk_layer_logging.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -0600747 gen_header.append('#include "vk_layer_table.h"')
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600748 gen_header.append('#include "vk_layer_extension_utils.h"')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500749 gen_header.append('')
Courtney Goeltzenleuchter79a5a962015-07-07 17:51:45 -0600750 gen_header.append('#include "generic.h"')
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600751 gen_header.append('')
Tobin Ehlisa30e7e52015-07-06 14:02:36 -0600752 gen_header.append('%s' % self.lineinfo.get())
753 gen_header.append('#define LAYER_EXT_ARRAY_SIZE 1')
754 gen_header.append('#define LAYER_DEV_EXT_ARRAY_SIZE 1')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600755 gen_header.append('//static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
756 gen_header.append('static std::unordered_map<void *, layer_data *> layer_data_map;\n')
757 gen_header.append('template layer_data *get_my_data_ptr<layer_data>(')
758 gen_header.append(' void *data_key,')
759 gen_header.append(' std::unordered_map<void *, layer_data *> &data_map);\n')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500760 gen_header.append('')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500761 return "\n".join(gen_header)
Tobin Ehlis7a314ea2015-07-07 11:02:44 -0600762
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600763 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600764 if proto.name in [ 'EnumerateInstanceLayerProperties', 'EnumerateInstanceExtensionProperties', 'EnumerateDeviceLayerProperties', 'EnumerateDeviceExtensionProperties' ]:
Mike Stroyan00087e62015-04-03 14:39:16 -0600765 # use default version
766 return None
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600767 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyan938c2532015-04-03 13:58:35 -0600768 ret_val = ''
769 stmt = ''
770 funcs = []
Jon Ashburn71836d92015-05-12 17:23:55 -0600771 table = ''
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600772 if proto_is_global(proto):
Jon Ashburn71836d92015-05-12 17:23:55 -0600773 table = 'Instance'
Mike Stroyan938c2532015-04-03 13:58:35 -0600774 if proto.ret != "void":
Courtney Goeltzenleuchter0de9e212015-06-26 15:07:53 -0600775 funcs.append('%s' % self.lineinfo.get())
Jon Ashburnb0fbe912015-05-06 10:15:07 -0600776 ret_val = "%s result = " % proto.ret
Mike Stroyan938c2532015-04-03 13:58:35 -0600777 stmt = " return result;\n"
Jon Ashburn8ced4212015-05-22 12:01:50 -0600778 if proto.name == "CreateDevice":
Courtney Goeltzenleuchter0de9e212015-06-26 15:07:53 -0600779 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan938c2532015-04-03 13:58:35 -0600780 funcs.append('%s%s\n'
781 '{\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500782 ' char str[1024];\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600783 ' layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);\n'
784 ' sprintf(str, "At start of Generic layered %s\\n");\n'
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700785 ' log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,'
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -0700786 ' (uint64_t)physicalDevice, __LINE__, 0, (char *) "generic", "%%s", (char *) str);\n'
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -0600787 ' %sdevice_dispatch_table(*pDevice)->%s;\n'
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600788 ' if (result == VK_SUCCESS) {\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600789 ' my_data->report_data = layer_debug_report_create_device(my_data->report_data, *pDevice);\n'
Jon Ashburn747f2b62015-06-18 15:02:58 -0600790 ' createDeviceRegisterExtensions(pCreateInfo, *pDevice);\n'
Mike Stroyan938c2532015-04-03 13:58:35 -0600791 ' }\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700792 ' sprintf(str, "Completed generic layered %s\\n");\n'
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -0700793 ' log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, (uint64_t)physicalDevice, __LINE__, 0, (char *) "generic", "%%s", (char *) str);\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500794 ' %s'
795 '}' % (qual, decl, proto.name, ret_val, proto.c_call(), proto.name, stmt))
796 elif proto.name == "DestroyDevice":
Courtney Goeltzenleuchter0de9e212015-06-26 15:07:53 -0600797 funcs.append('%s' % self.lineinfo.get())
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500798 funcs.append('%s%s\n'
799 '{\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -0600800 ' dispatch_key key = get_dispatch_key(device);\n'
Jon Ashburn747f2b62015-06-18 15:02:58 -0600801 ' VkLayerDispatchTable *pDisp = device_dispatch_table(device);\n'
Chia-I Wuf7458c52015-10-26 21:10:41 +0800802 ' pDisp->DestroyDevice(device, pAllocator);\n'
Jon Ashburn747f2b62015-06-18 15:02:58 -0600803 ' deviceExtMap.erase(pDisp);\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -0600804 ' destroy_device_dispatch_table(key);\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500805 '}\n' % (qual, decl))
806 elif proto.name == "DestroyInstance":
Courtney Goeltzenleuchter0de9e212015-06-26 15:07:53 -0600807 funcs.append('%s' % self.lineinfo.get())
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500808 funcs.append('%s%s\n'
809 '{\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -0600810 ' dispatch_key key = get_dispatch_key(instance);\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -0600811 ' VkLayerInstanceDispatchTable *pDisp = instance_dispatch_table(instance);\n'
Chia-I Wuf7458c52015-10-26 21:10:41 +0800812 ' pDisp->DestroyInstance(instance, pAllocator);\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600813 ' // Clean up logging callback, if any\n'
814 ' layer_data *my_data = get_my_data_ptr(key, layer_data_map);\n'
815 ' if (my_data->logging_callback) {\n'
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700816 ' layer_destroy_msg_callback(my_data->report_data, my_data->logging_callback, pAllocator);\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600817 ' }\n\n'
818 ' layer_debug_report_destroy_instance(my_data->report_data);\n'
819 ' layer_data_map.erase(key);\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -0600820 ' instanceExtMap.erase(pDisp);\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -0600821 ' destroy_instance_dispatch_table(key);\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500822 '}\n' % (qual, decl))
Jon Ashburn3dc39382015-09-17 10:00:32 -0600823 elif proto.name == "CreateInstance":
Courtney Goeltzenleuchter0de9e212015-06-26 15:07:53 -0600824 funcs.append('%s' % self.lineinfo.get())
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500825 # CreateInstance needs to use the second parm instead of the first to set the correct dispatch table
Jon Ashburn3dc39382015-09-17 10:00:32 -0600826 funcs.append('%s%s\n'
827 '{\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600828 ' char str[1024];\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -0600829 ' %sinstance_dispatch_table(*pInstance)->%s;\n'
830 ' if (result == VK_SUCCESS) {\n'
831 ' createInstanceRegisterExtensions(pCreateInfo, *pInstance);\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600832 ' layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);\n'
833 ' my_data->report_data = debug_report_create_instance(\n'
834 ' instance_dispatch_table(*pInstance),\n'
835 ' *pInstance,\n'
Chia-I Wud50a7d72015-10-26 20:48:51 +0800836 ' pCreateInfo->enabledExtensionNameCount,\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600837 ' pCreateInfo->ppEnabledExtensionNames);\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700838 ' init_generic(my_data, pAllocator);\n'
839 ' sprintf(str, "Completed generic layered %s\\n");\n'
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -0700840 ' log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, (uint64_t)*pInstance, __LINE__, 0, (char *) "generic", "%%s", (char *) str);\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -0600841 ' }\n'
Tobin Ehlis1350a362015-09-17 16:27:04 -0600842 ' return result;\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600843 '}\n' % (qual, decl, ret_val, proto.c_call(), proto.name))
Jon Ashburn3dc39382015-09-17 10:00:32 -0600844 else:
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700845 if wsi_name(proto.name):
846 funcs.append('%s' % wsi_ifdef(proto.name))
Jon Ashburn3dc39382015-09-17 10:00:32 -0600847 funcs.append('%s' % self.lineinfo.get())
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500848 dispatch_param = proto.params[0].name
849 # Must use 'instance' table for these APIs, 'device' table otherwise
850 table_type = ""
851 if proto_is_global(proto):
852 table_type = "instance"
853 else:
854 table_type = "device"
Mike Stroyan938c2532015-04-03 13:58:35 -0600855 funcs.append('%s%s\n'
856 '{\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500857 ' %s%s_dispatch_table(%s)->%s;\n'
Mike Stroyan938c2532015-04-03 13:58:35 -0600858 '%s'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500859 '}' % (qual, decl, ret_val, table_type, dispatch_param, proto.c_call(), stmt))
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700860 if wsi_name(proto.name):
861 funcs.append('%s' % wsi_endif(proto.name))
Mike Stroyan938c2532015-04-03 13:58:35 -0600862 return "\n\n".join(funcs)
863
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600864 def generate_body(self):
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700865 self.layer_name = "generic"
Jon Ashburn3a278b72015-10-06 17:05:21 -0600866 instance_extensions=[('msg_callback_get_proc_addr', []),
867 ('wsi_enabled',
Ian Elliott05846062015-11-20 14:13:17 -0700868 ['vkGetPhysicalDeviceSurfaceSupportKHR',
869 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
870 'vkGetPhysicalDeviceSurfaceFormatsKHR',
871 'vkGetPhysicalDeviceSurfacePresentModesKHR'])]
Ian Elliott1064fe32015-07-06 14:31:32 -0600872 extensions=[('wsi_enabled',
Ian Elliott05846062015-11-20 14:13:17 -0700873 ['vkCreateSwapchainKHR',
Jon Ashburn8acd2332015-09-16 18:08:32 -0600874 'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
875 'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600876 body = [self._generate_layer_initialization(True),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600877 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600878 self._gen_create_msg_callback(),
879 self._gen_destroy_msg_callback(),
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700880 self._gen_debug_report_msg(),
Jon Ashburn3dc39382015-09-17 10:00:32 -0600881 self._generate_layer_gpa_function(extensions, instance_extensions)]
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600882
883 return "\n\n".join(body)
884
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600885class APIDumpSubcommand(Subcommand):
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600886 def generate_header(self):
Tobin Ehlisd009bae2014-11-24 15:46:55 -0700887 header_txt = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600888 header_txt.append('%s' % self.lineinfo.get())
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600889 header_txt.append('#include <fstream>')
890 header_txt.append('#include <iostream>')
891 header_txt.append('#include <string>')
Jon Ashburn747f2b62015-06-18 15:02:58 -0600892 header_txt.append('#include <string.h>')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600893 header_txt.append('')
Tobin Ehlis80d048e2015-08-28 09:57:53 -0600894 header_txt.append('#include "vk_loader_platform.h"')
David Pinedo9316d3b2015-11-06 12:54:48 -0700895 header_txt.append('#include "vulkan/vk_layer.h"')
Tobin Ehlis80d048e2015-08-28 09:57:53 -0600896 header_txt.append('#include "vk_struct_string_helper_cpp.h"')
897 header_txt.append('#include "vk_layer_table.h"')
898 header_txt.append('#include "vk_layer_extension_utils.h"')
899 header_txt.append('#include <unordered_map>')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700900 header_txt.append('#include "api_dump.h"')
Tobin Ehlis80d048e2015-08-28 09:57:53 -0600901 header_txt.append('')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600902 header_txt.append('static std::ofstream fileStream;')
903 header_txt.append('static std::string fileName = "vk_apidump.txt";')
904 header_txt.append('std::ostream* outputStream = NULL;')
905 header_txt.append('void ConfigureOutputStream(bool writeToFile, bool flushAfterWrite)')
906 header_txt.append('{')
907 header_txt.append(' if(writeToFile)')
908 header_txt.append(' {')
Tobin Ehlis93245a92015-09-18 14:32:12 -0600909 header_txt.append(' if (fileName == "stdout")')
910 header_txt.append(' {')
Tobin Ehlis80d048e2015-08-28 09:57:53 -0600911 header_txt.append(' outputStream = &std::cout;')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700912 header_txt.append(' (*outputStream) << endl << "api_dump output filename \'stdout\' specified. Writing to STDOUT instead of a file." << endl << endl;')
Tobin Ehlis93245a92015-09-18 14:32:12 -0600913 header_txt.append(' } else {')
914 header_txt.append(' fileStream.open(fileName);')
915 header_txt.append(' if ((fileStream.rdstate() & fileStream.failbit) != 0) {')
916 header_txt.append(' outputStream = &std::cout;')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700917 header_txt.append(' (*outputStream) << endl << "api_dump ERROR: Bad output filename specified: " << fileName << ". Writing to STDOUT instead" << endl << endl;')
Tobin Ehlis93245a92015-09-18 14:32:12 -0600918 header_txt.append(' }')
919 header_txt.append(' else')
920 header_txt.append(' outputStream = &fileStream;')
Tobin Ehlis80d048e2015-08-28 09:57:53 -0600921 header_txt.append(' }')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600922 header_txt.append(' }')
923 header_txt.append(' else')
924 header_txt.append(' {')
925 header_txt.append(' outputStream = &std::cout;')
926 header_txt.append(' }')
927 header_txt.append('')
928 header_txt.append(' if(flushAfterWrite)')
929 header_txt.append(' {')
930 header_txt.append(' outputStream->sync_with_stdio(true);')
931 header_txt.append(' }')
932 header_txt.append(' else')
933 header_txt.append(' {')
934 header_txt.append(' outputStream->sync_with_stdio(false);')
935 header_txt.append(' }')
936 header_txt.append('}')
937 header_txt.append('')
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600938 header_txt.append('%s' % self.lineinfo.get())
Jon Ashburnbacb0f52015-04-06 10:58:22 -0600939 header_txt.append('static VkBaseLayerObject *pCurObj;')
Tobin Ehlisa2b199c2015-04-27 17:30:04 -0600940 header_txt.append('static bool g_APIDumpDetailed = true;')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600941 header_txt.append('')
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -0600942 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -0500943 header_txt.append('')
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700944 header_txt.append('static int printLockInitialized = 0;')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600945 header_txt.append('static loader_platform_thread_mutex printLock;')
946 header_txt.append('')
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600947 header_txt.append('%s' % self.lineinfo.get())
Tobin Ehlisa30e7e52015-07-06 14:02:36 -0600948 header_txt.append('#define LAYER_EXT_ARRAY_SIZE 1')
949 header_txt.append('#define LAYER_DEV_EXT_ARRAY_SIZE 1')
Tobin Ehlisd009bae2014-11-24 15:46:55 -0700950 header_txt.append('#define MAX_TID 513')
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700951 header_txt.append('static loader_platform_thread_id tidMapping[MAX_TID] = {0};')
Tobin Ehlisd009bae2014-11-24 15:46:55 -0700952 header_txt.append('static uint32_t maxTID = 0;')
953 header_txt.append('// Map actual TID to an index value and return that index')
954 header_txt.append('// This keeps TIDs in range from 0-MAX_TID and simplifies compares between runs')
955 header_txt.append('static uint32_t getTIDIndex() {')
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700956 header_txt.append(' loader_platform_thread_id tid = loader_platform_get_thread_id();')
Tobin Ehlisd009bae2014-11-24 15:46:55 -0700957 header_txt.append(' for (uint32_t i = 0; i < maxTID; i++) {')
958 header_txt.append(' if (tid == tidMapping[i])')
959 header_txt.append(' return i;')
960 header_txt.append(' }')
961 header_txt.append(" // Don't yet have mapping, set it and return newly set index")
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700962 header_txt.append(' uint32_t retVal = (uint32_t) maxTID;')
Tobin Ehlisd009bae2014-11-24 15:46:55 -0700963 header_txt.append(' tidMapping[maxTID++] = tid;')
964 header_txt.append(' assert(maxTID < MAX_TID);')
965 header_txt.append(' return retVal;')
966 header_txt.append('}')
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -0500967 header_txt.append('')
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800968 header_txt.append('void interpret_memBarriers(const void* const* ppMemoryBarriers, uint32_t memoryBarrierCount)')
Mark Lobodzinskib9143d82015-07-30 10:11:32 -0600969 header_txt.append('{')
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800970 header_txt.append(' if (ppMemoryBarriers) {')
Mark Lobodzinskib9143d82015-07-30 10:11:32 -0600971 header_txt.append(' string tmp_str;')
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800972 header_txt.append(' for (uint32_t i = 0; i < memoryBarrierCount; i++) {')
973 header_txt.append(' switch(*(VkStructureType*)ppMemoryBarriers[i])')
Mark Lobodzinskib9143d82015-07-30 10:11:32 -0600974 header_txt.append(' {')
975 header_txt.append(' case VK_STRUCTURE_TYPE_MEMORY_BARRIER:')
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800976 header_txt.append(' tmp_str = vk_print_vkmemorybarrier((VkMemoryBarrier*)ppMemoryBarriers[i], " ");')
Mark Lobodzinskib9143d82015-07-30 10:11:32 -0600977 header_txt.append(' break;')
978 header_txt.append(' case VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER:')
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800979 header_txt.append(' tmp_str = vk_print_vkbuffermemorybarrier((VkBufferMemoryBarrier*)ppMemoryBarriers[i], " ");')
Mark Lobodzinskib9143d82015-07-30 10:11:32 -0600980 header_txt.append(' break;')
981 header_txt.append(' case VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER:')
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800982 header_txt.append(' tmp_str = vk_print_vkimagememorybarrier((VkImageMemoryBarrier*)ppMemoryBarriers[i], " ");')
Mark Lobodzinskib9143d82015-07-30 10:11:32 -0600983 header_txt.append(' break;')
984 header_txt.append(' default:')
985 header_txt.append(' break;')
986 header_txt.append(' }')
987 header_txt.append('')
988 header_txt.append(' if (StreamControl::writeAddress == true) {')
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800989 header_txt.append(' (*outputStream) << " ppMemoryBarriers[" << i << "] (" << &ppMemoryBarriers[i] << ")" << endl << tmp_str << endl;')
Mark Lobodzinskib9143d82015-07-30 10:11:32 -0600990 header_txt.append(' } else {')
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800991 header_txt.append(' (*outputStream) << " ppMemoryBarriers[" << i << "] (address)" << endl << " address" << endl;')
Mark Lobodzinskib9143d82015-07-30 10:11:32 -0600992 header_txt.append(' }')
993 header_txt.append(' }')
994 header_txt.append(' }')
995 header_txt.append('}')
996 header_txt.append('')
Tobin Ehlisd009bae2014-11-24 15:46:55 -0700997 return "\n".join(header_txt)
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600998
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600999 def generate_init(self):
1000 func_body = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001001 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001002 func_body.append('#include "vk_dispatch_table_helper.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -06001003 func_body.append('#include "vk_layer_config.h"')
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001004 func_body.append('')
1005 func_body.append('static void init%s(void)' % self.layer_name)
1006 func_body.append('{')
1007 func_body.append(' using namespace StreamControl;')
1008 func_body.append('')
Tobin Ehlisa8700972015-08-26 16:18:52 -06001009 func_body.append(' char const*const logName = getLayerOption("APIDumpLogFilename");')
1010 func_body.append(' if(logName != NULL)')
1011 func_body.append(' {')
1012 func_body.append(' fileName = logName;')
1013 func_body.append(' }')
1014 func_body.append('')
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001015 func_body.append(' char const*const detailedStr = getLayerOption("APIDumpDetailed");')
1016 func_body.append(' if(detailedStr != NULL)')
1017 func_body.append(' {')
1018 func_body.append(' if(strcmp(detailedStr, "TRUE") == 0)')
1019 func_body.append(' {')
1020 func_body.append(' g_APIDumpDetailed = true;')
1021 func_body.append(' }')
1022 func_body.append(' else if(strcmp(detailedStr, "FALSE") == 0)')
1023 func_body.append(' {')
1024 func_body.append(' g_APIDumpDetailed = false;')
1025 func_body.append(' }')
1026 func_body.append(' }')
1027 func_body.append('')
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001028 func_body.append(' char const*const writeToFileStr = getLayerOption("APIDumpFile");')
1029 func_body.append(' bool writeToFile = false;')
1030 func_body.append(' if(writeToFileStr != NULL)')
1031 func_body.append(' {')
1032 func_body.append(' if(strcmp(writeToFileStr, "TRUE") == 0)')
1033 func_body.append(' {')
1034 func_body.append(' writeToFile = true;')
1035 func_body.append(' }')
1036 func_body.append(' else if(strcmp(writeToFileStr, "FALSE") == 0)')
1037 func_body.append(' {')
1038 func_body.append(' writeToFile = false;')
1039 func_body.append(' }')
1040 func_body.append(' }')
1041 func_body.append('')
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001042 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001043 func_body.append(' char const*const noAddrStr = getLayerOption("APIDumpNoAddr");')
1044 func_body.append(' if(noAddrStr != NULL)')
1045 func_body.append(' {')
1046 func_body.append(' if(strcmp(noAddrStr, "FALSE") == 0)')
1047 func_body.append(' {')
1048 func_body.append(' StreamControl::writeAddress = true;')
1049 func_body.append(' }')
1050 func_body.append(' else if(strcmp(noAddrStr, "TRUE") == 0)')
1051 func_body.append(' {')
1052 func_body.append(' StreamControl::writeAddress = false;')
1053 func_body.append(' }')
1054 func_body.append(' }')
1055 func_body.append('')
1056 func_body.append(' char const*const flushAfterWriteStr = getLayerOption("APIDumpFlush");')
1057 func_body.append(' bool flushAfterWrite = false;')
1058 func_body.append(' if(flushAfterWriteStr != NULL)')
1059 func_body.append(' {')
1060 func_body.append(' if(strcmp(flushAfterWriteStr, "TRUE") == 0)')
1061 func_body.append(' {')
1062 func_body.append(' flushAfterWrite = true;')
1063 func_body.append(' }')
1064 func_body.append(' else if(strcmp(flushAfterWriteStr, "FALSE") == 0)')
1065 func_body.append(' {')
1066 func_body.append(' flushAfterWrite = false;')
1067 func_body.append(' }')
1068 func_body.append(' }')
1069 func_body.append('')
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001070 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001071 func_body.append(' ConfigureOutputStream(writeToFile, flushAfterWrite);')
1072 func_body.append('')
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001073 func_body.append(' if (!printLockInitialized)')
1074 func_body.append(' {')
1075 func_body.append(' // TODO/TBD: Need to delete this mutex sometime. How???')
1076 func_body.append(' loader_platform_thread_create_mutex(&printLock);')
1077 func_body.append(' printLockInitialized = 1;')
1078 func_body.append(' }')
1079 func_body.append('}')
1080 func_body.append('')
1081 return "\n".join(func_body)
Tobin Ehlis99f88672015-01-10 12:42:41 -07001082
Mike Stroyanbf237d72015-04-03 17:45:53 -06001083 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001084 if proto.name in [ 'EnumerateInstanceLayerProperties','EnumerateInstanceExtensionProperties','EnumerateDeviceLayerProperties','EnumerateDeviceExtensionProperties']:
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001085 return None
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001086 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyanbf237d72015-04-03 17:45:53 -06001087 ret_val = ''
1088 stmt = ''
1089 funcs = []
1090 sp_param_dict = {} # Store 'index' for struct param to print, or an name of binding "Count" param for array to print
1091 create_params = 0 # Num of params at end of function that are created and returned as output values
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001092 if 'AllocateDescriptorSets' in proto.name:
Cody Northrop1e4f8022015-08-03 12:47:29 -06001093 create_params = -1
Mike Stroyanbf237d72015-04-03 17:45:53 -06001094 elif 'Create' in proto.name or 'Alloc' in proto.name or 'MapMemory' in proto.name:
1095 create_params = -1
1096 if proto.ret != "void":
Jon Ashburnb0fbe912015-05-06 10:15:07 -06001097 ret_val = "%s result = " % proto.ret
Mike Stroyanbf237d72015-04-03 17:45:53 -06001098 stmt = " return result;\n"
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001099 f_open = 'loader_platform_thread_lock_mutex(&printLock);\n '
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001100 log_func = '%s\n' % self.lineinfo.get()
1101 log_func += ' if (StreamControl::writeAddress == true) {'
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001102 log_func += '\n (*outputStream) << "t{" << getTIDIndex() << "} vk%s(' % proto.name
1103 log_func_no_addr = '\n (*outputStream) << "t{" << getTIDIndex() << "} vk%s(' % proto.name
1104 f_close = '\n loader_platform_thread_unlock_mutex(&printLock);'
Mike Stroyanbf237d72015-04-03 17:45:53 -06001105 pindex = 0
1106 prev_count_name = ''
1107 for p in proto.params:
1108 cp = False
1109 if 0 != create_params:
1110 # If this is any of the N last params of the func, treat as output
1111 for y in range(-1, create_params-1, -1):
1112 if p.name == proto.params[y].name:
1113 cp = True
1114 (pft, pfi) = self._get_printf_params(p.ty, p.name, cp, cpp=True)
Jon Ashburn8acd2332015-09-16 18:08:32 -06001115 if p.name == "pSwapchain" or p.name == "pSwapchainImages":
Chia-I Wue2fc5522015-10-26 20:04:44 +08001116 log_func += '%s = " << %s << ", ' % (p.name, p.name)
Mark Lobodzinski25a2cc82015-12-02 16:12:08 -07001117 elif p.name == "swapchain" or p.name == "visual_id":
Chia-I Wue2fc5522015-10-26 20:04:44 +08001118 log_func += '%s = " << %s << ", ' % (p.name, p.name)
Ian Elliott1064fe32015-07-06 14:31:32 -06001119 else:
1120 log_func += '%s = " << %s << ", ' % (p.name, pfi)
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001121 if "%p" == pft:
1122 log_func_no_addr += '%s = address, ' % (p.name)
1123 else:
1124 log_func_no_addr += '%s = " << %s << ", ' % (p.name, pfi)
Tobin Ehlis08541742015-04-16 15:56:11 -06001125 if prev_count_name != '' and (prev_count_name.replace('Count', '')[1:] in p.name):
Mike Stroyanbf237d72015-04-03 17:45:53 -06001126 sp_param_dict[pindex] = prev_count_name
Tobin Ehlis08541742015-04-16 15:56:11 -06001127 prev_count_name = ''
Chia-I Wuf8693382015-04-16 22:02:10 +08001128 elif vk_helper.is_type(p.ty.strip('*').replace('const ', ''), 'struct'):
Mike Stroyanbf237d72015-04-03 17:45:53 -06001129 sp_param_dict[pindex] = 'index'
Mike Stroyanbf237d72015-04-03 17:45:53 -06001130 if p.name.endswith('Count'):
1131 if '*' in p.ty:
1132 prev_count_name = "*%s" % p.name
1133 else:
1134 prev_count_name = p.name
Courtney Goeltzenleuchterf260f6c2015-09-23 12:28:10 -06001135 else:
1136 prev_count_name = ''
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001137 pindex += 1
Mike Stroyanbf237d72015-04-03 17:45:53 -06001138 log_func = log_func.strip(', ')
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001139 log_func_no_addr = log_func_no_addr.strip(', ')
Jon Ashburnb0fbe912015-05-06 10:15:07 -06001140 if proto.ret == "VkResult":
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06001141 log_func += ') = " << string_VkResult((VkResult)result) << endl'
1142 log_func_no_addr += ') = " << string_VkResult((VkResult)result) << endl'
Jon Ashburnb0fbe912015-05-06 10:15:07 -06001143 elif proto.ret == "void*":
1144 log_func += ') = " << result << endl'
1145 log_func_no_addr += ') = " << result << endl'
Mike Stroyanbf237d72015-04-03 17:45:53 -06001146 else:
1147 log_func += ')\\n"'
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001148 log_func_no_addr += ')\\n"'
Mike Stroyanbf237d72015-04-03 17:45:53 -06001149 log_func += ';'
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001150 log_func_no_addr += ';'
Tobin Ehlisa30e7e52015-07-06 14:02:36 -06001151 log_func += '\n }\n else {%s\n }' % log_func_no_addr;
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001152 log_func += '\n%s' % self.lineinfo.get()
Courtney Goeltzenleuchterf260f6c2015-09-23 12:28:10 -06001153 # log_func += '\n// Proto %s has param_dict: %s' % (proto.name, sp_param_dict)
Mike Stroyanbf237d72015-04-03 17:45:53 -06001154 if len(sp_param_dict) > 0:
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001155 indent = ' '
1156 log_func += '\n%sif (g_APIDumpDetailed) {' % indent
1157 indent += ' '
Mike Stroyanbf237d72015-04-03 17:45:53 -06001158 i_decl = False
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001159 log_func += '\n%s' % self.lineinfo.get()
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001160 log_func += '\n%sstring tmp_str;' % indent
Mike Stroyanbf237d72015-04-03 17:45:53 -06001161 for sp_index in sp_param_dict:
Courtney Goeltzenleuchterf260f6c2015-09-23 12:28:10 -06001162 # log_func += '\n// sp_index: %s' % str(sp_index)
Mike Stroyanbf237d72015-04-03 17:45:53 -06001163 if 'index' == sp_param_dict[sp_index]:
Courtney Goeltzenleuchter95487bc2015-04-14 18:48:46 -06001164 cis_print_func = 'vk_print_%s' % (proto.params[sp_index].ty.replace('const ', '').strip('*').lower())
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001165 local_name = proto.params[sp_index].name
1166 if '*' not in proto.params[sp_index].ty:
1167 local_name = '&%s' % proto.params[sp_index].name
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001168 log_func += '\n%s' % self.lineinfo.get()
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001169 log_func += '\n%sif (%s) {' % (indent, local_name)
1170 indent += ' '
1171 log_func += '\n%stmp_str = %s(%s, " ");' % (indent, cis_print_func, local_name)
1172 log_func += '\n%s(*outputStream) << " %s (" << %s << ")" << endl << tmp_str << endl;' % (indent, local_name, local_name)
1173 indent = indent[4:]
1174 log_func += '\n%s}' % (indent)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001175 elif 'memoryBarrierCount' == sp_param_dict[sp_index]: # call helper function
1176 log_func += '\n%sif (ppMemoryBarriers) {' % (indent)
1177 log_func += '\n%s interpret_memBarriers(ppMemoryBarriers, memoryBarrierCount);' % (indent)
Mark Lobodzinskib9143d82015-07-30 10:11:32 -06001178 log_func += '\n%s}' % (indent)
Mike Stroyanbf237d72015-04-03 17:45:53 -06001179 else: # We have a count value stored to iterate over an array
1180 print_cast = ''
1181 print_func = ''
Courtney Goeltzenleuchter95487bc2015-04-14 18:48:46 -06001182 if vk_helper.is_type(proto.params[sp_index].ty.strip('*').replace('const ', ''), 'struct'):
Mike Stroyanbf237d72015-04-03 17:45:53 -06001183 print_cast = '&'
Courtney Goeltzenleuchter95487bc2015-04-14 18:48:46 -06001184 print_func = 'vk_print_%s' % proto.params[sp_index].ty.replace('const ', '').strip('*').lower()
Mike Stroyanbf237d72015-04-03 17:45:53 -06001185 else:
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001186 print_cast = ''
Mike Stroyanbf237d72015-04-03 17:45:53 -06001187 print_func = 'string_convert_helper'
1188 #cis_print_func = 'tmp_str = string_convert_helper((void*)%s[i], " ");' % proto.params[sp_index].name
Chia-I Wue2fc5522015-10-26 20:04:44 +08001189 cis_print_func = 'tmp_str = %s(%s%s[i], " ");' % (print_func, print_cast, proto.params[sp_index].name)
Mike Stroyanbf237d72015-04-03 17:45:53 -06001190 if not i_decl:
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001191 log_func += '\n%suint32_t i;' % (indent)
Mike Stroyanbf237d72015-04-03 17:45:53 -06001192 i_decl = True
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001193 log_func += '\n%sif (%s) {' % (indent, proto.params[sp_index].name)
1194 indent += ' '
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001195 log_func += '\n%s' % self.lineinfo.get()
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001196 log_func += '\n%sfor (i = 0; i < %s; i++) {' % (indent, sp_param_dict[sp_index])
1197 indent += ' '
1198 log_func += '\n%s%s' % (indent, cis_print_func)
Tobin Ehlis45a23a82015-04-28 10:58:20 -06001199 log_func += '\n%sif (StreamControl::writeAddress == true) {' % (indent)
1200 indent += ' '
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001201 log_func += '\n%s(*outputStream) << " %s[" << i << "] (" << %s%s[i] << ")" << endl << tmp_str << endl;' % (indent, proto.params[sp_index].name, '&', proto.params[sp_index].name)
1202 indent = indent[4:]
Tobin Ehlis45a23a82015-04-28 10:58:20 -06001203 log_func += '\n%s} else {' % (indent)
1204 indent += ' '
1205 log_func += '\n%s(*outputStream) << " %s[" << i << "] (address)" << endl << " address" << endl;' % (indent, proto.params[sp_index].name)
1206 indent = indent[4:]
1207 log_func += '\n%s}' % (indent)
1208 indent = indent[4:]
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001209 log_func += '\n%s}' % (indent)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001210 indent = indent[4:]
1211 log_func += '\n%s}' % (indent)
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001212 indent = indent[4:]
1213 log_func += '\n%s}' % (indent)
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001214 table_type = ''
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001215 if proto_is_global(proto):
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001216 table_type = 'instance'
1217 else:
1218 table_type = 'device'
Jon Ashburn3dc39382015-09-17 10:00:32 -06001219 dispatch_param = proto.params[0].name
Jon Ashburn71836d92015-05-12 17:23:55 -06001220
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001221 if proto.name == "CreateInstance":
1222 dispatch_param = '*' + proto.params[1].name
Jon Ashburn3dc39382015-09-17 10:00:32 -06001223 funcs.append('%s%s\n'
1224 '{\n'
1225 ' using namespace StreamControl;\n'
1226 ' %sinstance_dispatch_table(*pInstance)->%s;\n'
1227 ' if (result == VK_SUCCESS) {\n'
1228 ' createInstanceRegisterExtensions(pCreateInfo, *pInstance);\n'
1229 ' }\n'
1230 ' %s%s%s\n'
1231 '%s'
1232 '}\n' % (qual, decl, ret_val, proto.c_call(), f_open, log_func, f_close, stmt))
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001233
Jon Ashburn3dc39382015-09-17 10:00:32 -06001234 elif proto.name == "CreateDevice":
Courtney Goeltzenleuchter0de9e212015-06-26 15:07:53 -06001235 funcs.append('%s\n' % self.lineinfo.get())
Jon Ashburn747f2b62015-06-18 15:02:58 -06001236 funcs.append('%s%s\n'
1237 '{\n'
1238 ' using namespace StreamControl;\n'
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06001239 ' %sdevice_dispatch_table(*pDevice)->%s;\n'
Jon Ashburn747f2b62015-06-18 15:02:58 -06001240 ' if (result == VK_SUCCESS)\n'
1241 ' createDeviceRegisterExtensions(pCreateInfo, *pDevice);\n'
1242 ' %s%s%s\n'
1243 '%s'
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06001244 '}' % (qual, decl, ret_val, proto.c_call(), f_open, log_func, f_close, stmt))
Jon Ashburn747f2b62015-06-18 15:02:58 -06001245 elif proto.name == "DestroyDevice":
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001246 funcs.append('%s%s\n'
1247 '{\n'
1248 ' using namespace StreamControl;\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001249 ' dispatch_key key = get_dispatch_key(device);\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -06001250 ' VkLayerDispatchTable *pDisp = %s_dispatch_table(%s);\n'
Jon Ashburn747f2b62015-06-18 15:02:58 -06001251 ' %spDisp->%s;\n'
1252 ' deviceExtMap.erase(pDisp);\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001253 ' destroy_device_dispatch_table(key);\n'
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001254 ' %s%s%s\n'
1255 '%s'
Jon Ashburn747f2b62015-06-18 15:02:58 -06001256 '}' % (qual, decl, table_type, dispatch_param, ret_val, proto.c_call(), f_open, log_func, f_close, stmt))
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001257 elif proto.name == "DestroyInstance":
1258 funcs.append('%s%s\n'
1259 '{\n'
1260 ' using namespace StreamControl;\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001261 ' dispatch_key key = get_dispatch_key(instance);\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -06001262 ' VkLayerInstanceDispatchTable *pDisp = %s_dispatch_table(%s);\n'
1263 ' %spDisp->%s;\n'
1264 ' instanceExtMap.erase(pDisp);\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001265 ' destroy_instance_dispatch_table(key);\n'
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001266 ' %s%s%s\n'
1267 '%s'
Jon Ashburn3dc39382015-09-17 10:00:32 -06001268 '}' % (qual, decl, table_type, dispatch_param, ret_val, proto.c_call(), f_open, log_func, f_close, stmt))
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001269 else:
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001270 if wsi_name(decl):
1271 funcs.append('%s' % wsi_ifdef(decl))
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001272 funcs.append('%s%s\n'
1273 '{\n'
1274 ' using namespace StreamControl;\n'
1275 ' %s%s_dispatch_table(%s)->%s;\n'
Jon Ashburnbacb0f52015-04-06 10:58:22 -06001276 ' %s%s%s\n'
1277 '%s'
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001278 '}' % (qual, decl, ret_val, table_type, dispatch_param, proto.c_call(), f_open, log_func, f_close, stmt))
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001279 if wsi_name(decl):
1280 funcs.append('%s' % wsi_endif(decl))
Mike Stroyanbf237d72015-04-03 17:45:53 -06001281 return "\n\n".join(funcs)
1282
Tobin Ehlis99f88672015-01-10 12:42:41 -07001283 def generate_body(self):
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001284 self.layer_name = "api_dump"
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001285 if sys.platform.startswith('win32'):
Michael Lentine64e2ebd2015-12-03 14:33:09 -08001286 instance_extensions=[('wsi_enabled',
1287 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1288 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1289 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1290 'vkGetPhysicalDeviceSurfacePresentModesKHR',
1291 'vkCreateWin32SurfaceKHR',
1292 'vkGetPhysicalDeviceWin32PresentationSupportKHR'])]
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001293 elif sys.platform.startswith('linux'):
Michael Lentine64e2ebd2015-12-03 14:33:09 -08001294 instance_extensions=[('wsi_enabled',
1295 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1296 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1297 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1298 'vkGetPhysicalDeviceSurfacePresentModesKHR',
1299 'vkCreateXcbSurfaceKHR',
Mark Lobodzinskib49b6e52015-11-26 10:59:58 -07001300 'vkGetPhysicalDeviceXcbPresentationSupportKHR'])]
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001301 # TODO: Add cases for Mir, Xlib, Wayland
1302 else:
1303 instance_extensions=[('wsi_enabled',
1304 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1305 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1306 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1307 'vkGetPhysicalDeviceSurfacePresentModesKHR'])]
Ian Elliott1064fe32015-07-06 14:31:32 -06001308 extensions=[('wsi_enabled',
Ian Elliott05846062015-11-20 14:13:17 -07001309 ['vkCreateSwapchainKHR',
Jon Ashburn8acd2332015-09-16 18:08:32 -06001310 'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
1311 'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001312 body = [self.generate_init(),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001313 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Jon Ashburn3dc39382015-09-17 10:00:32 -06001314 self._generate_layer_gpa_function(extensions, instance_extensions)]
Tobin Ehlis99f88672015-01-10 12:42:41 -07001315 return "\n\n".join(body)
1316
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001317class ObjectTrackerSubcommand(Subcommand):
1318 def generate_header(self):
1319 header_txt = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001320 header_txt.append('%s' % self.lineinfo.get())
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001321 header_txt.append('#include <stdio.h>')
1322 header_txt.append('#include <stdlib.h>')
1323 header_txt.append('#include <string.h>')
1324 header_txt.append('#include <inttypes.h>')
1325 header_txt.append('')
David Pinedo9316d3b2015-11-06 12:54:48 -07001326 header_txt.append('#include "vulkan/vulkan.h"')
Tobin Ehlisb835d1b2015-07-03 10:34:49 -06001327 header_txt.append('#include "vk_loader_platform.h"')
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001328 header_txt.append('')
Tobin Ehlis803cc492015-06-08 17:36:28 -06001329 header_txt.append('#include <unordered_map>')
1330 header_txt.append('using namespace std;')
David Pinedo9316d3b2015-11-06 12:54:48 -07001331 header_txt.append('#include "vulkan/vk_layer.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -06001332 header_txt.append('#include "vk_layer_config.h"')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001333 header_txt.append('#include "vulkan/vk_ext_debug_report.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -06001334 header_txt.append('#include "vk_layer_table.h"')
1335 header_txt.append('#include "vk_layer_data.h"')
1336 header_txt.append('#include "vk_layer_logging.h"')
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001337 header_txt.append('')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001338# NOTE: The non-autoGenerated code is in the object_tracker.h header file
1339 header_txt.append('#include "object_tracker.h"')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001340 header_txt.append('')
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -06001341 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001342 header_txt.append('')
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001343 return "\n".join(header_txt)
1344
Tony Barboura05dbaa2015-07-09 17:31:46 -06001345 def generate_maps(self):
1346 maps_txt = []
1347 for o in vulkan.core.objects:
Michael Lentine13803dc2015-11-04 14:35:12 -08001348 maps_txt.append('unordered_map<uint64_t, OBJTRACK_NODE*> %sMap;' % (o))
1349 maps_txt.append('unordered_map<uint64_t, OBJTRACK_NODE*> VkSwapchainKHRMap;')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001350 return "\n".join(maps_txt)
1351
1352 def generate_procs(self):
1353 procs_txt = []
1354 for o in vulkan.core.objects:
1355 procs_txt.append('%s' % self.lineinfo.get())
Michael Lentine13803dc2015-11-04 14:35:12 -08001356 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o)
1357 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Tobin Ehlis154e0462015-08-26 11:22:09 -06001358 if o in vulkan.object_dispatch_list:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001359 procs_txt.append('static void create_%s(%s dispatchable_object, %s vkObj, VkDebugReportObjectTypeEXT objType)' % (name, o, o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001360 else:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001361 procs_txt.append('static void create_%s(VkDevice dispatchable_object, %s vkObj, VkDebugReportObjectTypeEXT objType)' % (name, o))
Chia-I Wue2fc5522015-10-26 20:04:44 +08001362 procs_txt.append('{')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001363 procs_txt.append(' log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFO_BIT_EXT, objType, reinterpret_cast<uint64_t>(vkObj), __LINE__, OBJTRACK_NONE, "OBJTRACK",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001364 procs_txt.append(' "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64 , object_track_index++, string_VkDebugReportObjectTypeEXT(objType),')
Chia-I Wue2fc5522015-10-26 20:04:44 +08001365 procs_txt.append(' reinterpret_cast<uint64_t>(vkObj));')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001366 procs_txt.append('')
1367 procs_txt.append(' OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE;')
1368 procs_txt.append(' pNewObjNode->objType = objType;')
1369 procs_txt.append(' pNewObjNode->status = OBJSTATUS_NONE;')
Chia-I Wue2fc5522015-10-26 20:04:44 +08001370 procs_txt.append(' pNewObjNode->vkObj = reinterpret_cast<uint64_t>(vkObj);')
Michael Lentine13803dc2015-11-04 14:35:12 -08001371 procs_txt.append(' %sMap[(uint64_t)vkObj] = pNewObjNode;' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001372 procs_txt.append(' uint32_t objIndex = objTypeToIndex(objType);')
1373 procs_txt.append(' numObjs[objIndex]++;')
1374 procs_txt.append(' numTotalObjs++;')
1375 procs_txt.append('}')
1376 procs_txt.append('')
1377 procs_txt.append('%s' % self.lineinfo.get())
Tobin Ehlisec598302015-09-15 15:02:17 -06001378 # TODO : This is not complete and currently requires some hand-coded function in the header
1379 # Really we want to capture the set of all objects and their associated dispatchable objects
1380 # that are bound by the API calls:
1381 # foreach API Call
1382 # foreach object type seen by call
1383 # create validate_object(disp_obj, object)
Tobin Ehlis154e0462015-08-26 11:22:09 -06001384 if o in vulkan.object_dispatch_list:
Michael Lentine13803dc2015-11-04 14:35:12 -08001385 procs_txt.append('static VkBool32 validate_%s(%s dispatchable_object, %s object)' % (name, o, o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001386 else:
Michael Lentine13803dc2015-11-04 14:35:12 -08001387 procs_txt.append('static VkBool32 validate_%s(VkDevice dispatchable_object, %s object)' % (name, o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001388 procs_txt.append('{')
Tobin Ehlis154e0462015-08-26 11:22:09 -06001389 if o in vulkan.object_dispatch_list:
Michael Lentine13803dc2015-11-04 14:35:12 -08001390 procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (o, o))
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001391 procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT ) 0, reinterpret_cast<uint64_t>(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
Michael Lentine010f4692015-11-03 16:19:46 -08001392 procs_txt.append(' "Invalid %s Object 0x%%" PRIx64 ,reinterpret_cast<uint64_t>(object));' % o)
Tony Barboura05dbaa2015-07-09 17:31:46 -06001393 else:
Mark Lobodzinskie6d3f2c2015-10-14 13:16:33 -06001394 if o == "VkImage":
1395 procs_txt.append(' // We need to validate normal image objects and those from the swapchain')
Michael Lentine13803dc2015-11-04 14:35:12 -08001396 procs_txt.append(' if ((%sMap.find((uint64_t)object) == %sMap.end()) &&' % (o, o))
1397 procs_txt.append(' (swapchainImageMap.find((uint64_t)object) == swapchainImageMap.end())) {')
Mark Lobodzinskie6d3f2c2015-10-14 13:16:33 -06001398 else:
Michael Lentine13803dc2015-11-04 14:35:12 -08001399 procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (o, o))
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001400 procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT ) 0, (uint64_t) object, __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
Michael Lentine010f4692015-11-03 16:19:46 -08001401 procs_txt.append(' "Invalid %s Object 0x%%" PRIx64, reinterpret_cast<uint64_t>(object));' % o)
Tony Barboura05dbaa2015-07-09 17:31:46 -06001402 procs_txt.append(' }')
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -06001403 procs_txt.append(' return VK_FALSE;')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001404 procs_txt.append('}')
1405 procs_txt.append('')
1406 procs_txt.append('')
1407 procs_txt.append('%s' % self.lineinfo.get())
Tobin Ehlis154e0462015-08-26 11:22:09 -06001408 if o in vulkan.object_dispatch_list:
Michael Lentine13803dc2015-11-04 14:35:12 -08001409 procs_txt.append('static void destroy_%s(%s dispatchable_object, %s object)' % (name, o, o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001410 else:
Michael Lentine13803dc2015-11-04 14:35:12 -08001411 procs_txt.append('static void destroy_%s(VkDevice dispatchable_object, %s object)' % (name, o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001412 procs_txt.append('{')
Michael Lentine13803dc2015-11-04 14:35:12 -08001413 procs_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
1414 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
1415 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[(uint64_t)object];' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001416 procs_txt.append(' uint32_t objIndex = objTypeToIndex(pNode->objType);')
1417 procs_txt.append(' assert(numTotalObjs > 0);')
1418 procs_txt.append(' numTotalObjs--;')
1419 procs_txt.append(' assert(numObjs[objIndex] > 0);')
1420 procs_txt.append(' numObjs[objIndex]--;')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001421 procs_txt.append(' log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFO_BIT_EXT, pNode->objType, object_handle, __LINE__, OBJTRACK_NONE, "OBJTRACK",')
Michael Lentine010f4692015-11-03 16:19:46 -08001422 procs_txt.append(' "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%" PRIu64 " total objs remain & %" PRIu64 " %s objs).",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001423 procs_txt.append(' string_VkDebugReportObjectTypeEXT(pNode->objType), reinterpret_cast<uint64_t>(object), numTotalObjs, numObjs[objIndex],')
1424 procs_txt.append(' string_VkDebugReportObjectTypeEXT(pNode->objType));')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001425 procs_txt.append(' delete pNode;')
Michael Lentine13803dc2015-11-04 14:35:12 -08001426 procs_txt.append(' %sMap.erase(object_handle);' % (o))
Chia-I Wue2fc5522015-10-26 20:04:44 +08001427 procs_txt.append(' } else {')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001428 procs_txt.append(' log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT ) 0, object_handle, __LINE__, OBJTRACK_NONE, "OBJTRACK",')
Chia-I Wue2fc5522015-10-26 20:04:44 +08001429 procs_txt.append(' "Unable to remove obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?",')
Michael Lentine13803dc2015-11-04 14:35:12 -08001430 procs_txt.append(' object_handle);')
Chia-I Wue2fc5522015-10-26 20:04:44 +08001431 procs_txt.append(' }')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001432 procs_txt.append('}')
1433 procs_txt.append('')
1434 procs_txt.append('%s' % self.lineinfo.get())
Tobin Ehlis154e0462015-08-26 11:22:09 -06001435 if o in vulkan.object_dispatch_list:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001436 procs_txt.append('static VkBool32 set_%s_status(%s dispatchable_object, %s object, VkDebugReportObjectTypeEXT objType, ObjectStatusFlags status_flag)' % (name, o, o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001437 else:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001438 procs_txt.append('static VkBool32 set_%s_status(VkDevice dispatchable_object, %s object, VkDebugReportObjectTypeEXT objType, ObjectStatusFlags status_flag)' % (name, o))
Chia-I Wue2fc5522015-10-26 20:04:44 +08001439 procs_txt.append('{')
1440 procs_txt.append(' if (object != VK_NULL_HANDLE) {')
Michael Lentine13803dc2015-11-04 14:35:12 -08001441 procs_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
1442 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
1443 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[object_handle];' % (o))
Tobin Ehlis154e0462015-08-26 11:22:09 -06001444 procs_txt.append(' pNode->status |= status_flag;')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001445 procs_txt.append(' }')
1446 procs_txt.append(' else {')
1447 procs_txt.append(' // If we do not find it print an error')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001448 procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT ) 0, object_handle, __LINE__, OBJTRACK_NONE, "OBJTRACK",')
Chia-I Wue2fc5522015-10-26 20:04:44 +08001449 procs_txt.append(' "Unable to set status for non-existent object 0x%" PRIxLEAST64 " of %s type",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001450 procs_txt.append(' object_handle, string_VkDebugReportObjectTypeEXT(objType));')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001451 procs_txt.append(' }')
1452 procs_txt.append(' }')
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -06001453 procs_txt.append(' return VK_FALSE;')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001454 procs_txt.append('}')
1455 procs_txt.append('')
1456 procs_txt.append('%s' % self.lineinfo.get())
Michael Lentine13803dc2015-11-04 14:35:12 -08001457 procs_txt.append('static VkBool32 validate_%s_status(' % (name))
Tobin Ehlis154e0462015-08-26 11:22:09 -06001458 if o in vulkan.object_dispatch_list:
Tony Barboura05dbaa2015-07-09 17:31:46 -06001459 procs_txt.append('%s dispatchable_object, %s object,' % (o, o))
1460 else:
1461 procs_txt.append('VkDevice dispatchable_object, %s object,' % (o))
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001462 procs_txt.append(' VkDebugReportObjectTypeEXT objType,')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001463 procs_txt.append(' ObjectStatusFlags status_mask,')
1464 procs_txt.append(' ObjectStatusFlags status_flag,')
1465 procs_txt.append(' VkFlags msg_flags,')
1466 procs_txt.append(' OBJECT_TRACK_ERROR error_code,')
1467 procs_txt.append(' const char *fail_msg)')
1468 procs_txt.append('{')
Michael Lentine13803dc2015-11-04 14:35:12 -08001469 procs_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
1470 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
1471 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[object_handle];' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001472 procs_txt.append(' if ((pNode->status & status_mask) != status_flag) {')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001473 procs_txt.append(' log_msg(mdd(dispatchable_object), msg_flags, pNode->objType, object_handle, __LINE__, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001474 procs_txt.append(' "OBJECT VALIDATION WARNING: %s object 0x%" PRIxLEAST64 ": %s", string_VkDebugReportObjectTypeEXT(objType),')
Michael Lentine13803dc2015-11-04 14:35:12 -08001475 procs_txt.append(' object_handle, fail_msg);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001476 procs_txt.append(' return VK_FALSE;')
1477 procs_txt.append(' }')
1478 procs_txt.append(' return VK_TRUE;')
1479 procs_txt.append(' }')
1480 procs_txt.append(' else {')
1481 procs_txt.append(' // If we do not find it print an error')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001482 procs_txt.append(' log_msg(mdd(dispatchable_object), msg_flags, (VkDebugReportObjectTypeEXT) 0, object_handle, __LINE__, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",')
Chia-I Wue2fc5522015-10-26 20:04:44 +08001483 procs_txt.append(' "Unable to obtain status for non-existent object 0x%" PRIxLEAST64 " of %s type",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001484 procs_txt.append(' object_handle, string_VkDebugReportObjectTypeEXT(objType));')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001485 procs_txt.append(' return VK_FALSE;')
1486 procs_txt.append(' }')
1487 procs_txt.append('}')
1488 procs_txt.append('')
1489 procs_txt.append('%s' % self.lineinfo.get())
Tobin Ehlis154e0462015-08-26 11:22:09 -06001490 if o in vulkan.object_dispatch_list:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001491 procs_txt.append('static VkBool32 reset_%s_status(%s dispatchable_object, %s object, VkDebugReportObjectTypeEXT objType, ObjectStatusFlags status_flag)' % (name, o, o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001492 else:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001493 procs_txt.append('static VkBool32 reset_%s_status(VkDevice dispatchable_object, %s object, VkDebugReportObjectTypeEXT objType, ObjectStatusFlags status_flag)' % (name, o))
Chia-I Wue2fc5522015-10-26 20:04:44 +08001494 procs_txt.append('{')
Michael Lentine13803dc2015-11-04 14:35:12 -08001495 procs_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
1496 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
1497 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[object_handle];' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001498 procs_txt.append(' pNode->status &= ~status_flag;')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001499 procs_txt.append(' }')
1500 procs_txt.append(' else {')
1501 procs_txt.append(' // If we do not find it print an error')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001502 procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, objType, object_handle, __LINE__, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",')
Chia-I Wue2fc5522015-10-26 20:04:44 +08001503 procs_txt.append(' "Unable to reset status for non-existent object 0x%" PRIxLEAST64 " of %s type",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001504 procs_txt.append(' object_handle, string_VkDebugReportObjectTypeEXT(objType));')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001505 procs_txt.append(' }')
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -06001506 procs_txt.append(' return VK_FALSE;')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001507 procs_txt.append('}')
1508 procs_txt.append('')
1509 return "\n".join(procs_txt)
1510
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001511 def generate_destroy_instance(self):
Tony Barboura05dbaa2015-07-09 17:31:46 -06001512 gedi_txt = []
1513 gedi_txt.append('%s' % self.lineinfo.get())
Mark Lobodzinski2141f652015-09-07 13:59:43 -06001514 gedi_txt.append('void vkDestroyInstance(')
Chia-I Wuf7458c52015-10-26 21:10:41 +08001515 gedi_txt.append('VkInstance instance,')
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001516 gedi_txt.append('const VkAllocationCallbacks* pAllocator)')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001517 gedi_txt.append('{')
1518 gedi_txt.append(' loader_platform_thread_lock_mutex(&objLock);')
Michael Lentine13803dc2015-11-04 14:35:12 -08001519 gedi_txt.append(' validate_instance(instance, instance);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001520 gedi_txt.append('')
Michael Lentine13803dc2015-11-04 14:35:12 -08001521 gedi_txt.append(' destroy_instance(instance, instance);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001522 gedi_txt.append(' // Report any remaining objects in LL')
1523 for o in vulkan.core.objects:
Mike Stroyan0699a792015-08-18 14:48:34 -06001524 if o in ['VkInstance', 'VkPhysicalDevice', 'VkQueue']:
Tony Barboura05dbaa2015-07-09 17:31:46 -06001525 continue
1526 gedi_txt.append(' for (auto it = %sMap.begin(); it != %sMap.end(); ++it) {' % (o, o))
1527 gedi_txt.append(' OBJTRACK_NODE* pNode = it->second;')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001528 gedi_txt.append(' log_msg(mid(instance), VK_DEBUG_REPORT_ERROR_BIT_EXT, pNode->objType, pNode->vkObj, __LINE__, OBJTRACK_OBJECT_LEAK, "OBJTRACK",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001529 gedi_txt.append(' "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),')
Tony Barbour343d6212015-07-10 18:32:33 -06001530 gedi_txt.append(' pNode->vkObj);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001531 gedi_txt.append(' }')
Mike Stroyan0699a792015-08-18 14:48:34 -06001532 gedi_txt.append(' %sMap.clear();' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001533 gedi_txt.append('')
1534 gedi_txt.append(' dispatch_key key = get_dispatch_key(instance);')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001535 gedi_txt.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(object_tracker_instance_table_map, instance);')
Chia-I Wuf7458c52015-10-26 21:10:41 +08001536 gedi_txt.append(' pInstanceTable->DestroyInstance(instance, pAllocator);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001537 gedi_txt.append('')
1538 gedi_txt.append(' // Clean up logging callback, if any')
1539 gedi_txt.append(' layer_data *my_data = get_my_data_ptr(key, layer_data_map);')
1540 gedi_txt.append(' if (my_data->logging_callback) {')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07001541 gedi_txt.append(' layer_destroy_msg_callback(my_data->report_data, my_data->logging_callback, pAllocator);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001542 gedi_txt.append(' }')
1543 gedi_txt.append('')
1544 gedi_txt.append(' layer_debug_report_destroy_instance(mid(instance));')
1545 gedi_txt.append(' layer_data_map.erase(pInstanceTable);')
1546 gedi_txt.append('')
Jon Ashburn3dc39382015-09-17 10:00:32 -06001547 gedi_txt.append(' instanceExtMap.erase(pInstanceTable);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001548 gedi_txt.append(' loader_platform_thread_unlock_mutex(&objLock);')
Mike Stroyan0699a792015-08-18 14:48:34 -06001549 # The loader holds a mutex that protects this from other threads
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001550 gedi_txt.append(' object_tracker_instance_table_map.erase(key);')
1551 gedi_txt.append(' if (object_tracker_instance_table_map.empty()) {')
Mike Stroyan0699a792015-08-18 14:48:34 -06001552 gedi_txt.append(' // Release mutex when destroying last instance.')
1553 gedi_txt.append(' loader_platform_thread_delete_mutex(&objLock);')
1554 gedi_txt.append(' objLockInitialized = 0;')
1555 gedi_txt.append(' }')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001556 gedi_txt.append('}')
1557 gedi_txt.append('')
1558 return "\n".join(gedi_txt)
1559
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001560 def generate_destroy_device(self):
Tony Barboura05dbaa2015-07-09 17:31:46 -06001561 gedd_txt = []
1562 gedd_txt.append('%s' % self.lineinfo.get())
Mark Lobodzinski2141f652015-09-07 13:59:43 -06001563 gedd_txt.append('void vkDestroyDevice(')
Chia-I Wuf7458c52015-10-26 21:10:41 +08001564 gedd_txt.append('VkDevice device,')
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001565 gedd_txt.append('const VkAllocationCallbacks* pAllocator)')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001566 gedd_txt.append('{')
1567 gedd_txt.append(' loader_platform_thread_lock_mutex(&objLock);')
Michael Lentine13803dc2015-11-04 14:35:12 -08001568 gedd_txt.append(' validate_device(device, device);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001569 gedd_txt.append('')
Michael Lentine13803dc2015-11-04 14:35:12 -08001570 gedd_txt.append(' destroy_device(device, device);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001571 gedd_txt.append(' // Report any remaining objects in LL')
1572 for o in vulkan.core.objects:
Mark Lobodzinski5f5c0e12015-11-12 16:02:35 -07001573 # DescriptorSets and Command Buffers are destroyed through their pools, not explicitly
1574 if o in ['VkInstance', 'VkPhysicalDevice', 'VkQueue', 'VkDevice', 'VkDescriptorSet', 'VkCommandBuffer']:
Tony Barboura05dbaa2015-07-09 17:31:46 -06001575 continue
Mark Lobodzinski5f5c0e12015-11-12 16:02:35 -07001576 gedd_txt.append(' for (auto it = %sMap.begin(); it != %sMap.end(); ++it) {' % (o, o))
1577 gedd_txt.append(' OBJTRACK_NODE* pNode = it->second;')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001578 gedd_txt.append(' log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, pNode->objType, pNode->vkObj, __LINE__, OBJTRACK_OBJECT_LEAK, "OBJTRACK",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001579 gedd_txt.append(' "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),')
Mark Lobodzinski5f5c0e12015-11-12 16:02:35 -07001580 gedd_txt.append(' pNode->vkObj);')
1581 gedd_txt.append(' }')
Mike Stroyan0699a792015-08-18 14:48:34 -06001582 gedd_txt.append(' %sMap.clear();' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001583 gedd_txt.append('')
1584 gedd_txt.append(" // Clean up Queue's MemRef Linked Lists")
1585 gedd_txt.append(' destroyQueueMemRefLists();')
1586 gedd_txt.append('')
1587 gedd_txt.append(' loader_platform_thread_unlock_mutex(&objLock);')
1588 gedd_txt.append('')
1589 gedd_txt.append(' dispatch_key key = get_dispatch_key(device);')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001590 gedd_txt.append(' VkLayerDispatchTable *pDisp = get_dispatch_table(object_tracker_device_table_map, device);')
Chia-I Wuf7458c52015-10-26 21:10:41 +08001591 gedd_txt.append(' pDisp->DestroyDevice(device, pAllocator);')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001592 gedd_txt.append(' object_tracker_device_table_map.erase(key);')
1593 gedd_txt.append(' assert(object_tracker_device_table_map.size() == 0 && "Should not have any instance mappings hanging around");')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001594 gedd_txt.append('')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001595 gedd_txt.append('}')
1596 gedd_txt.append('')
1597 return "\n".join(gedd_txt)
1598
1599 def generate_command_buffer_validates(self):
1600 cbv_txt = []
1601 cbv_txt.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06001602 for o in ['VkPipeline',
Tony Barboura05dbaa2015-07-09 17:31:46 -06001603 'VkPipelineLayout', 'VkBuffer', 'VkEvent', 'VkQueryPool', 'VkRenderPass', 'VkFramebuffer']:
Michael Lentine13803dc2015-11-04 14:35:12 -08001604 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o)
1605 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
1606 cbv_txt.append('static VkBool32 validate_%s(VkCommandBuffer dispatchable_object, %s object)' % (name, o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001607 cbv_txt.append('{')
Michael Lentine13803dc2015-11-04 14:35:12 -08001608 cbv_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
1609 cbv_txt.append(' if (%sMap.find(object_handle) == %sMap.end()) {' % (o, o))
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001610 cbv_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT ) 0, object_handle, __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
Michael Lentine13803dc2015-11-04 14:35:12 -08001611 cbv_txt.append(' "Invalid %s Object 0x%%" PRIx64, object_handle);' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001612 cbv_txt.append(' }')
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -06001613 cbv_txt.append(' return VK_FALSE;')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001614 cbv_txt.append('}')
1615 cbv_txt.append('')
1616 return "\n".join(cbv_txt)
1617
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -06001618 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001619 if proto.name in [ 'CreateDebugReportCallbackEXT', 'EnumerateInstanceLayerProperties', 'EnumerateInstanceExtensionProperties','EnumerateDeviceLayerProperties', 'EnumerateDeviceExtensionProperties' ]:
Mike Stroyan00087e62015-04-03 14:39:16 -06001620 # use default version
1621 return None
Mark Lobodzinski7c75b852015-05-05 15:01:37 -05001622
Tony Barboura05dbaa2015-07-09 17:31:46 -06001623 # Create map of object names to object type enums of the form VkName : VkObjectTypeName
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001624 obj_type_mapping = {base_t : base_t.replace("Vk", "VkDebugReportObjectType") for base_t in vulkan.object_type_list}
Mark Lobodzinski7c75b852015-05-05 15:01:37 -05001625 # Convert object type enum names from UpperCamelCase to UPPER_CASE_WITH_UNDERSCORES
1626 for objectName, objectTypeEnum in obj_type_mapping.items():
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001627 obj_type_mapping[objectName] = ucc_to_U_C_C(objectTypeEnum) + '_EXT';
Mark Lobodzinski7c75b852015-05-05 15:01:37 -05001628 # Command Buffer Object doesn't follow the rule.
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001629 obj_type_mapping['VkCommandBuffer'] = "VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT"
1630 obj_type_mapping['VkShaderModule'] = "VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT"
Mike Stroyan00087e62015-04-03 14:39:16 -06001631
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001632 explicit_object_tracker_functions = [
1633 "CreateInstance",
Tobin Ehlisec598302015-09-15 15:02:17 -06001634 "EnumeratePhysicalDevices",
Cody Northropd0802882015-08-03 17:04:53 -06001635 "GetPhysicalDeviceQueueFamilyProperties",
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001636 "CreateDevice",
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001637 "GetDeviceQueue",
Chia-I Wu1ff4c3d2015-10-26 16:55:27 +08001638 "QueueBindSparse",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001639 "AllocateDescriptorSets",
Tony Barbour770f80d2015-07-20 10:52:13 -06001640 "FreeDescriptorSets",
Mark Lobodzinski5f5c0e12015-11-12 16:02:35 -07001641 "AllocateCommandBuffers",
1642 "FreeCommandBuffers",
1643 "DestroyDescriptorPool",
1644 "DestroyCommandPool",
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001645 "MapMemory",
1646 "UnmapMemory",
1647 "FreeMemory",
Mark Lobodzinskie6d3f2c2015-10-14 13:16:33 -06001648 "DestroySwapchainKHR",
1649 "GetSwapchainImagesKHR"
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001650 ]
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001651 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyan00087e62015-04-03 14:39:16 -06001652 param0_name = proto.params[0].name
Mark Lobodzinski48bd16d2015-05-08 09:12:28 -05001653 using_line = ''
Mike Stroyan00087e62015-04-03 14:39:16 -06001654 create_line = ''
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001655 destroy_line = ''
Tobin Ehlis154e0462015-08-26 11:22:09 -06001656 # 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
1657 loop_params = defaultdict(list) # Dict uses loop count as key to make final code generation cleaner so params shared in single loop where needed
Michael Lentine13803dc2015-11-04 14:35:12 -08001658 loop_types = defaultdict(list)
Tobin Ehlis2717d132015-07-10 18:25:07 -06001659 # TODO : For now skipping objs that can be NULL. Really should check these and have special case that allows them to be NULL
Tobin Ehlis154e0462015-08-26 11:22:09 -06001660 # or better yet, these should be encoded into an API json definition and we generate checks from there
1661 # 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)
1662 # param names may be directly passed to the function, or may be a field in a struct param
1663 valid_null_object_names = {'CreateGraphicsPipelines' : ['basePipelineHandle'],
1664 'CreateComputePipelines' : ['basePipelineHandle'],
1665 'BeginCommandBuffer' : ['renderPass', 'framebuffer'],
Tobin Ehlisec598302015-09-15 15:02:17 -06001666 'QueueSubmit' : ['fence'],
Tobin Ehlisba31cab2015-11-02 15:24:32 -07001667 'UpdateDescriptorSets' : ['pTexelBufferView'],
Tobin Ehlis154e0462015-08-26 11:22:09 -06001668 }
Tobin Ehlis154e0462015-08-26 11:22:09 -06001669 param_count = 'NONE' # keep track of arrays passed directly into API functions
Tobin Ehlis803cc492015-06-08 17:36:28 -06001670 for p in proto.params:
Tobin Ehlisec598302015-09-15 15:02:17 -06001671 base_type = p.ty.replace('const ', '').strip('*')
Tobin Ehlis154e0462015-08-26 11:22:09 -06001672 if 'count' in p.name.lower():
1673 param_count = p.name
Tobin Ehlisec598302015-09-15 15:02:17 -06001674 if base_type in vulkan.core.objects:
1675 # This is an object to potentially check for validity. First see if it's an array
1676 if '*' in p.ty and 'const' in p.ty and param_count != 'NONE':
1677 loop_params[param_count].append(p.name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001678 loop_types[param_count].append(str(p.ty[6:-1]))
Tobin Ehlisec598302015-09-15 15:02:17 -06001679 # Not an array, check for just a base Object that's not in exceptions
1680 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]):
Tobin Ehlis154e0462015-08-26 11:22:09 -06001681 loop_params[0].append(p.name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001682 loop_types[0].append(str(p.ty))
Tobin Ehlisec598302015-09-15 15:02:17 -06001683 elif vk_helper.is_type(base_type, 'struct'):
1684 struct_type = base_type
Tobin Ehlis9d675942015-06-30 14:32:16 -06001685 if vk_helper.typedef_rev_dict[struct_type] in vk_helper.struct_dict:
1686 struct_type = vk_helper.typedef_rev_dict[struct_type]
Tobin Ehlis82b3db52015-10-23 17:52:53 -06001687 # Parse elements of this struct param to identify objects and/or arrays of objects
Tobin Ehlis9d675942015-06-30 14:32:16 -06001688 for m in sorted(vk_helper.struct_dict[struct_type]):
1689 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']:
Tobin Ehlis154e0462015-08-26 11:22:09 -06001690 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]:
Tobin Ehlis82b3db52015-10-23 17:52:53 -06001691 # This is not great, but gets the job done for now, but If we have a count and this param is a ptr w/
1692 # last letter 's' OR non-'count' string of count is in the param name, then this is a dynamically sized array param
1693 param_array = False
1694 if param_count != 'NONE':
1695 if '*' in p.ty:
1696 if 's' == p.name[-1] or param_count.lower().replace('count', '') in p.name.lower():
1697 param_array = True
1698 if param_array:
Tobin Ehlis154e0462015-08-26 11:22:09 -06001699 param_name = '%s[i].%s' % (p.name, vk_helper.struct_dict[struct_type][m]['name'])
Tobin Ehlis46d53622015-07-10 11:10:21 -06001700 else:
Tobin Ehlis154e0462015-08-26 11:22:09 -06001701 param_name = '%s->%s' % (p.name, vk_helper.struct_dict[struct_type][m]['name'])
1702 if vk_helper.struct_dict[struct_type][m]['dyn_array']:
Tobin Ehlis82b3db52015-10-23 17:52:53 -06001703 if param_count != 'NONE': # this will be a double-embedded loop, use comma delineated 'count,name' for param_name
1704 loop_count = '%s[i].%s' % (p.name, vk_helper.struct_dict[struct_type][m]['array_size'])
1705 loop_params[param_count].append('%s,%s' % (loop_count, param_name))
Michael Lentine13803dc2015-11-04 14:35:12 -08001706 loop_types[param_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Tobin Ehlis82b3db52015-10-23 17:52:53 -06001707 else:
1708 loop_count = '%s->%s' % (p.name, vk_helper.struct_dict[struct_type][m]['array_size'])
1709 loop_params[loop_count].append(param_name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001710 loop_types[loop_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Tobin Ehlis154e0462015-08-26 11:22:09 -06001711 else:
1712 if '[' in param_name: # dynamic array param, set size
1713 loop_params[param_count].append(param_name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001714 loop_types[param_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Tobin Ehlis154e0462015-08-26 11:22:09 -06001715 else:
1716 loop_params[0].append(param_name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001717 loop_types[0].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Mike Stroyan00087e62015-04-03 14:39:16 -06001718 funcs = []
Tobin Ehlis803cc492015-06-08 17:36:28 -06001719 mutex_unlock = False
Tobin Ehlis154e0462015-08-26 11:22:09 -06001720 funcs.append('%s\n' % self.lineinfo.get())
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001721 if proto.name in explicit_object_tracker_functions:
Jon Ashburn4d9f4652015-04-08 21:33:34 -06001722 funcs.append('%s%s\n'
1723 '{\n'
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001724 ' return explicit_%s;\n'
1725 '}' % (qual, decl, proto.c_call()))
1726 return "".join(funcs)
Mark Lobodzinski308d7792015-11-24 10:28:31 -07001727 # Temporarily prevent DestroySurface call from being generated until WSI layer support is fleshed out
Mark Lobodzinskib49b6e52015-11-26 10:59:58 -07001728 elif 'DestroyInstance' in proto.name or 'DestroyDevice' in proto.name: # LUGMAL or 'SurfaceKHR' in proto.name:
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001729 return ""
Jon Ashburn4d9f4652015-04-08 21:33:34 -06001730 else:
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001731 if 'Create' in proto.name or 'Alloc' in proto.name:
Michael Lentine13803dc2015-11-04 14:35:12 -08001732 typ = proto.params[-1].ty.strip('*').replace('const ', '');
1733 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1734 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001735 create_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
1736 create_line += ' if (result == VK_SUCCESS) {\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08001737 create_line += ' create_%s(%s, *%s, %s);\n' % (name, param0_name, proto.params[-1].name, obj_type_mapping[typ])
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001738 create_line += ' }\n'
1739 create_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06001740 if 'FreeCommandBuffers' in proto.name:
Michael Lentine13803dc2015-11-04 14:35:12 -08001741 typ = proto.params[-1].ty.strip('*').replace('const ', '');
1742 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1743 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06001744 funcs.append('%s\n' % self.lineinfo.get())
1745 destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Chia-I Wud50a7d72015-10-26 20:48:51 +08001746 destroy_line += ' for (uint32_t i = 0; i < commandBufferCount; i++) {\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08001747 destroy_line += ' destroy_%s(%s[i], %s[i]);\n' % (name, proto.params[-1].name, proto.params[-1].name)
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06001748 destroy_line += ' }\n'
1749 destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001750 if 'Destroy' in proto.name:
Michael Lentine13803dc2015-11-04 14:35:12 -08001751 typ = proto.params[-2].ty.strip('*').replace('const ', '');
1752 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1753 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06001754 funcs.append('%s\n' % self.lineinfo.get())
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001755 destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Mark Lobodzinski2141f652015-09-07 13:59:43 -06001756# destroy_line += ' if (result == VK_SUCCESS) {\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08001757 destroy_line += ' destroy_%s(%s, %s);\n' % (name, param0_name, proto.params[-2].name)
Mark Lobodzinski2141f652015-09-07 13:59:43 -06001758# destroy_line += ' }\n'
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001759 destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Tobin Ehlis154e0462015-08-26 11:22:09 -06001760 if len(loop_params) > 0:
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -06001761 using_line += ' VkBool32 skipCall = VK_FALSE;\n'
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001762 if not mutex_unlock:
1763 using_line += ' loader_platform_thread_lock_mutex(&objLock);\n'
1764 mutex_unlock = True
Michael Lentine13803dc2015-11-04 14:35:12 -08001765 for lc,lt in zip(loop_params,loop_types):
Tobin Ehlis154e0462015-08-26 11:22:09 -06001766 if 0 == lc: # No looping required for these params
Michael Lentine13803dc2015-11-04 14:35:12 -08001767 for opn,typ in zip(loop_params[lc],loop_types[lt]):
1768 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1769 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Tobin Ehlis154e0462015-08-26 11:22:09 -06001770 if '->' in opn:
1771 using_line += ' if (%s)\n' % (opn.split('-')[0])
Michael Lentine13803dc2015-11-04 14:35:12 -08001772 using_line += ' skipCall |= validate_%s(%s, %s);\n' % (name, param0_name, opn)
Tobin Ehlis154e0462015-08-26 11:22:09 -06001773 else:
Mark Lobodzinski308d7792015-11-24 10:28:31 -07001774 if 'AcquireNext' in proto.name and 'fence' == name:
1775 using_line += ' if (fence != VK_NULL_HANDLE) {\n'
1776 using_line += ' skipCall |= validate_%s(%s, %s);\n' % (name, param0_name, opn)
1777 using_line += ' }\n'
Mark Lobodzinskic0ed6d02015-12-07 15:55:11 -07001778 elif ('CreateGraphicsPipelines' in proto.name or 'CreateComputePipelines' in proto.name) and 'pipelineCache' == opn:
1779 using_line += ' // PipelineCache is optional, validate if present\n'
1780 using_line += ' if (pipelineCache != VK_NULL_HANDLE) {\n'
1781 using_line += ' skipCall |= validate_%s(%s, %s);\n' % (name, param0_name, opn)
1782 using_line += ' }\n'
Mark Lobodzinski308d7792015-11-24 10:28:31 -07001783 else:
1784 using_line += ' skipCall |= validate_%s(%s, %s);\n' % (name, param0_name, opn)
Tobin Ehlis9d675942015-06-30 14:32:16 -06001785 else:
Tobin Ehlis154e0462015-08-26 11:22:09 -06001786 base_param = loop_params[lc][0].split('-')[0].split('[')[0]
1787 using_line += ' if (%s) {\n' % base_param
Tobin Ehlisdaab02d2015-10-23 16:57:03 -06001788 using_line += ' for (uint32_t i=0; i<%s; i++) {\n' % lc
Michael Lentine13803dc2015-11-04 14:35:12 -08001789 for opn,typ in zip(loop_params[lc],loop_types[lt]):
1790 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1791 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Tobin Ehlis82b3db52015-10-23 17:52:53 -06001792 if ',' in opn: # double-embedded loop
1793 (inner_lc, inner_param) = opn.split(',')
1794 using_line += ' if (%s) {\n' % inner_param
1795 using_line += ' for (uint32_t j=0; j<%s; j++) {\n' % inner_lc
Michael Lentine13803dc2015-11-04 14:35:12 -08001796 using_line += ' skipCall |= validate_%s(%s, %s[j]);\n' % (name, param0_name, inner_param)
Tobin Ehlis82b3db52015-10-23 17:52:53 -06001797 using_line += ' }\n'
1798 using_line += ' }\n'
1799 elif '[' in opn: # API func param is array
Michael Lentine13803dc2015-11-04 14:35:12 -08001800 using_line += ' skipCall |= validate_%s(%s, %s);\n' % (name, param0_name, opn)
Tobin Ehlis154e0462015-08-26 11:22:09 -06001801 else: # struct element is array
Michael Lentine13803dc2015-11-04 14:35:12 -08001802 using_line += ' skipCall |= validate_%s(%s, %s[i]);\n' % (name, param0_name, opn)
Tobin Ehlis154e0462015-08-26 11:22:09 -06001803 using_line += ' }\n'
1804 using_line += ' }\n'
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001805 if mutex_unlock:
1806 using_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -06001807 if len(loop_params) > 0:
1808 using_line += ' if (skipCall)\n'
1809 if proto.ret != "void":
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07001810 using_line += ' return VK_ERROR_VALIDATION_FAILED_EXT;\n'
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -06001811 else:
1812 using_line += ' return;\n'
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001813 ret_val = ''
1814 stmt = ''
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001815 if proto.ret != "void":
1816 ret_val = "%s result = " % proto.ret
1817 stmt = " return result;\n"
1818
1819 dispatch_param = proto.params[0].name
1820 if 'CreateInstance' in proto.name:
1821 dispatch_param = '*' + proto.params[1].name
1822
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001823 # Must use 'instance' table for these APIs, 'device' table otherwise
1824 table_type = ""
1825 if proto_is_global(proto):
1826 table_type = "instance"
1827 else:
1828 table_type = "device"
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001829 if wsi_name(proto.name):
1830 funcs.append('%s' % wsi_ifdef(proto.name))
Mike Stroyan00087e62015-04-03 14:39:16 -06001831 funcs.append('%s%s\n'
1832 '{\n'
1833 '%s'
Mike Stroyan00087e62015-04-03 14:39:16 -06001834 '%s'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001835 ' %sget_dispatch_table(object_tracker_%s_table_map, %s)->%s;\n'
Mike Stroyan38820b32015-09-28 13:47:29 -06001836 '%s'
1837 '%s'
1838 '}' % (qual, decl, using_line, destroy_line, ret_val, table_type, dispatch_param, proto.c_call(), create_line, stmt))
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001839 if wsi_name(proto.name):
1840 funcs.append('%s' % wsi_endif(proto.name))
Mike Stroyan00087e62015-04-03 14:39:16 -06001841 return "\n\n".join(funcs)
1842
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001843 def generate_body(self):
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001844 self.layer_name = "object_tracker"
Ian Elliott1064fe32015-07-06 14:31:32 -06001845 extensions=[('wsi_enabled',
Ian Elliott05846062015-11-20 14:13:17 -07001846 ['vkCreateSwapchainKHR',
Jon Ashburn8acd2332015-09-16 18:08:32 -06001847 'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
1848 'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001849 if sys.platform.startswith('win32'):
Michael Lentine64e2ebd2015-12-03 14:33:09 -08001850 instance_extensions=[('msg_callback_get_proc_addr', []),
1851 ('wsi_enabled',
1852 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1853 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1854 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1855 'vkGetPhysicalDeviceSurfacePresentModesKHR',
1856 'vkCreateWin32SurfaceKHR',
1857 'vkGetPhysicalDeviceWin32PresentationSupportKHR'])]
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001858 elif sys.platform.startswith('linux'):
Michael Lentine64e2ebd2015-12-03 14:33:09 -08001859 instance_extensions=[('msg_callback_get_proc_addr', []),
1860 ('wsi_enabled',
1861 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1862 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1863 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1864 'vkGetPhysicalDeviceSurfacePresentModesKHR',
1865 'vkCreateXcbSurfaceKHR',
Mark Lobodzinskib49b6e52015-11-26 10:59:58 -07001866 'vkGetPhysicalDeviceXcbPresentationSupportKHR'])]
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001867 # TODO: Add cases for Mir, Wayland and Xlib
1868 else: # android
1869 instance_extensions=[('msg_callback_get_proc_addr', []),
1870 ('wsi_enabled',
1871 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1872 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1873 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1874 'vkGetPhysicalDeviceSurfacePresentModesKHR'])]
Tony Barboura05dbaa2015-07-09 17:31:46 -06001875 body = [self.generate_maps(),
1876 self.generate_procs(),
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001877 self.generate_destroy_instance(),
1878 self.generate_destroy_device(),
Tony Barboura05dbaa2015-07-09 17:31:46 -06001879 self.generate_command_buffer_validates(),
1880 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Tobin Ehlisca915872014-11-18 11:28:33 -07001881 self._generate_extensions(),
Jon Ashburn747f2b62015-06-18 15:02:58 -06001882 self._generate_layer_gpa_function(extensions,
Jon Ashburn3dc39382015-09-17 10:00:32 -06001883 instance_extensions)]
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001884 return "\n\n".join(body)
Courtney Goeltzenleuchterb412d212014-11-18 10:40:29 -07001885
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001886class ThreadingSubcommand(Subcommand):
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001887 thread_check_dispatchable_objects = [
1888 "VkQueue",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001889 "VkCommandBuffer",
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001890 ]
1891 thread_check_nondispatchable_objects = [
1892 "VkDeviceMemory",
1893 "VkBuffer",
1894 "VkImage",
1895 "VkDescriptorSet",
1896 "VkDescriptorPool",
1897 "VkSemaphore"
1898 ]
Mike Stroyan313f7e62015-08-10 16:42:53 -06001899 thread_check_object_types = {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001900 'VkInstance' : 'VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT',
1901 'VkPhysicalDevice' : 'VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT',
1902 'VkDevice' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT',
1903 'VkQueue' : 'VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT',
1904 'VkCommandBuffer' : 'VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT',
1905 'VkFence' : 'VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT',
1906 'VkDeviceMemory' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT',
1907 'VkBuffer' : 'VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT',
1908 'VkImage' : 'VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT',
1909 'VkSemaphore' : 'VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT',
1910 'VkEvent' : 'VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT',
1911 'VkQueryPool' : 'VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT',
1912 'VkBufferView' : 'VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT',
1913 'VkImageView' : 'VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT',
1914 'VkShaderModule' : 'VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT',
1915 'VkShader' : 'VK_DEBUG_REPORT_OBJECT_TYPE_SHADER',
1916 'VkPipelineCache' : 'VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT',
1917 'VkPipelineLayout' : 'VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT',
1918 'VkRenderPass' : 'VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT',
1919 'VkPipeline' : 'VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT',
1920 'VkDescriptorSetLayout' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT',
1921 'VkSampler' : 'VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT',
1922 'VkDescriptorPool' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT',
1923 'VkDescriptorSet' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT',
1924 'VkFramebuffer' : 'VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT',
1925 'VkCommandPool' : 'VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT',
Mike Stroyan313f7e62015-08-10 16:42:53 -06001926 }
1927 def generate_useObject(self, ty):
1928 obj_type = self.thread_check_object_types[ty]
Chia-I Wue2fc5522015-10-26 20:04:44 +08001929 key = "object"
1930 msg_object = "reinterpret_cast<uint64_t>(object)"
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001931 header_txt = []
1932 header_txt.append('%s' % self.lineinfo.get())
Michael Lentine13803dc2015-11-04 14:35:12 -08001933 header_txt.append('static void use%s(const void* dispatchable_object, %s object)' % (ty, ty))
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001934 header_txt.append('{')
1935 header_txt.append(' loader_platform_thread_id tid = loader_platform_get_thread_id();')
1936 header_txt.append(' loader_platform_thread_lock_mutex(&threadingLock);')
1937 header_txt.append(' if (%sObjectsInUse.find(%s) == %sObjectsInUse.end()) {' % (ty, key, ty))
1938 header_txt.append(' %sObjectsInUse[%s] = tid;' % (ty, key))
1939 header_txt.append(' } else {')
1940 header_txt.append(' if (%sObjectsInUse[%s] != tid) {' % (ty, key))
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001941 header_txt.append(' log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, %s, %s,' % (obj_type, msg_object))
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001942 header_txt.append(' __LINE__, THREADING_CHECKER_MULTIPLE_THREADS, "THREADING",')
Mike Stroyan313f7e62015-08-10 16:42:53 -06001943 header_txt.append(' "THREADING ERROR : object of type %s is simultaneously used in thread %%ld and thread %%ld",' % (ty))
1944 header_txt.append(' %sObjectsInUse[%s], tid);' % (ty, key))
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001945 header_txt.append(' // Wait for thread-safe access to object')
1946 header_txt.append(' while (%sObjectsInUse.find(%s) != %sObjectsInUse.end()) {' % (ty, key, ty))
1947 header_txt.append(' loader_platform_thread_cond_wait(&threadingCond, &threadingLock);')
1948 header_txt.append(' }')
1949 header_txt.append(' %sObjectsInUse[%s] = tid;' % (ty, key))
1950 header_txt.append(' } else {')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001951 header_txt.append(' log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, %s, %s,' % (obj_type, msg_object))
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001952 header_txt.append(' __LINE__, THREADING_CHECKER_MULTIPLE_THREADS, "THREADING",')
Mike Stroyan313f7e62015-08-10 16:42:53 -06001953 header_txt.append(' "THREADING ERROR : object of type %s is recursively used in thread %%ld",' % (ty))
1954 header_txt.append(' tid);')
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001955 header_txt.append(' }')
1956 header_txt.append(' }')
1957 header_txt.append(' loader_platform_thread_unlock_mutex(&threadingLock);')
1958 header_txt.append('}')
1959 return "\n".join(header_txt)
Mike Stroyan313f7e62015-08-10 16:42:53 -06001960 def generate_finishUsingObject(self, ty):
Chia-I Wue2fc5522015-10-26 20:04:44 +08001961 key = "object"
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001962 header_txt = []
1963 header_txt.append('%s' % self.lineinfo.get())
Michael Lentine13803dc2015-11-04 14:35:12 -08001964 header_txt.append('static void finishUsing%s(%s object)' % (ty, ty))
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001965 header_txt.append('{')
1966 header_txt.append(' // Object is no longer in use')
1967 header_txt.append(' loader_platform_thread_lock_mutex(&threadingLock);')
1968 header_txt.append(' %sObjectsInUse.erase(%s);' % (ty, key))
1969 header_txt.append(' loader_platform_thread_cond_broadcast(&threadingCond);')
1970 header_txt.append(' loader_platform_thread_unlock_mutex(&threadingLock);')
1971 header_txt.append('}')
1972 return "\n".join(header_txt)
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001973 def generate_header(self):
1974 header_txt = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001975 header_txt.append('%s' % self.lineinfo.get())
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001976 header_txt.append('#include <stdio.h>')
1977 header_txt.append('#include <stdlib.h>')
1978 header_txt.append('#include <string.h>')
1979 header_txt.append('#include <unordered_map>')
Tobin Ehlisb835d1b2015-07-03 10:34:49 -06001980 header_txt.append('#include "vk_loader_platform.h"')
David Pinedo9316d3b2015-11-06 12:54:48 -07001981 header_txt.append('#include "vulkan/vk_layer.h"')
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001982 header_txt.append('#include "threading.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -06001983 header_txt.append('#include "vk_layer_config.h"')
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -06001984 header_txt.append('#include "vk_layer_extension_utils.h"')
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001985 header_txt.append('#include "vk_enum_validate_helper.h"')
1986 header_txt.append('#include "vk_struct_validate_helper.h"')
Mike Stroyan313f7e62015-08-10 16:42:53 -06001987 header_txt.append('#include "vk_layer_table.h"')
1988 header_txt.append('#include "vk_layer_logging.h"')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001989 header_txt.append('')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001990 header_txt.append('')
1991 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
1992 header_txt.append('')
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001993 header_txt.append('using namespace std;')
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001994 for ty in self.thread_check_dispatchable_objects:
1995 header_txt.append('static unordered_map<%s, loader_platform_thread_id> %sObjectsInUse;' % (ty, ty))
1996 for ty in self.thread_check_nondispatchable_objects:
Chia-I Wue2fc5522015-10-26 20:04:44 +08001997 header_txt.append('static unordered_map<%s, loader_platform_thread_id> %sObjectsInUse;' % (ty, ty))
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001998 header_txt.append('static int threadingLockInitialized = 0;')
1999 header_txt.append('static loader_platform_thread_mutex threadingLock;')
Mike Stroyaned238bb2015-05-15 08:50:57 -06002000 header_txt.append('static loader_platform_thread_cond threadingCond;')
Tobin Ehlis08fafd02015-06-12 12:49:01 -06002001 header_txt.append('%s' % self.lineinfo.get())
Mike Stroyan313f7e62015-08-10 16:42:53 -06002002 for ty in self.thread_check_dispatchable_objects + self.thread_check_nondispatchable_objects:
2003 header_txt.append(self.generate_useObject(ty))
2004 header_txt.append(self.generate_finishUsingObject(ty))
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002005 header_txt.append('%s' % self.lineinfo.get())
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002006 return "\n".join(header_txt)
2007
2008 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002009 if proto.name in [ 'CreateDebugReportCallbackEXT' ]:
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002010 # use default version
2011 return None
2012 decl = proto.c_func(prefix="vk", attr="VKAPI")
2013 ret_val = ''
2014 stmt = ''
2015 funcs = []
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002016 table = 'device'
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002017 if proto.ret != "void":
Jon Ashburnb0fbe912015-05-06 10:15:07 -06002018 ret_val = "%s result = " % proto.ret
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002019 stmt = " return result;\n"
Jon Ashburn95a77ba2015-05-15 15:09:35 -06002020 if proto_is_global(proto):
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002021 table = 'instance'
Jon Ashburn71836d92015-05-12 17:23:55 -06002022
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002023 # Memory range calls are special in needed thread checking within structs
2024 if proto.name in ["FlushMappedMemoryRanges","InvalidateMappedMemoryRanges"]:
Mike Stroyan313f7e62015-08-10 16:42:53 -06002025 funcs.append('%s' % self.lineinfo.get())
2026 funcs.append('%s%s\n' % (qual, decl) +
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002027 '{\n'
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002028 ' for (uint32_t i=0; i<memoryRangeCount; i++) {\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08002029 ' useVkDeviceMemory((const void *) %s, pMemoryRanges[i].memory);\n' % proto.params[0].name +
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002030 ' }\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002031 ' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_%s_table_map, %s);\n' % (table, proto.params[0].name) +
Mike Stroyan313f7e62015-08-10 16:42:53 -06002032 ' %s pDeviceTable->%s;\n' % (ret_val, proto.c_call()) +
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002033 ' for (uint32_t i=0; i<memoryRangeCount; i++) {\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08002034 ' finishUsingVkDeviceMemory(pMemoryRanges[i].memory);\n'
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002035 ' }\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002036 '%s' % (stmt) +
2037 '}')
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002038 return "\n".join(funcs)
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002039 # All functions that do a Get are thread safe
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002040 if 'Get' in proto.name:
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002041 return None
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002042 # All WSI functions are thread safe
Ian Elliott7e40db92015-08-21 15:09:33 -06002043 if 'KHR' in proto.name:
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002044 return None
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002045 # Initialize in early calls
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002046 if proto.name == "CreateDevice":
2047 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan313f7e62015-08-10 16:42:53 -06002048 funcs.append('%s%s\n' % (qual, decl) +
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002049 '{\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002050 ' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_device_table_map, (void *) *pDevice);\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002051 ' VkResult result = pDeviceTable->%s;\n' % (proto.c_call()) +
2052 ' if (result == VK_SUCCESS) {\n'
2053 ' layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(%s), layer_data_map);\n' % proto.params[0].name +
2054 ' layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);\n'
2055 ' my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);\n'
2056 ' }\n'
2057 '\n'
2058 ' return result;'
2059 '}')
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002060 return "\n".join(funcs)
2061 elif proto.params[0].ty == "VkPhysicalDevice":
Mike Stroyan313f7e62015-08-10 16:42:53 -06002062 return None
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002063 # Functions changing command buffers need thread safe use of first parameter
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002064 if proto.params[0].ty == "VkCommandBuffer":
Tobin Ehlis08fafd02015-06-12 12:49:01 -06002065 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan313f7e62015-08-10 16:42:53 -06002066 funcs.append('%s%s\n' % (qual, decl) +
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002067 '{\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08002068 ' use%s((const void *) %s, %s);\n' % (proto.params[0].ty, proto.params[0].name, proto.params[0].name) +
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002069 ' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_%s_table_map, %s);\n' % (table, proto.params[0].name) +
Mike Stroyan313f7e62015-08-10 16:42:53 -06002070 ' %spDeviceTable->%s;\n' % (ret_val, proto.c_call()) +
Michael Lentine13803dc2015-11-04 14:35:12 -08002071 ' finishUsing%s(%s);\n' % (proto.params[0].ty, proto.params[0].name) +
Mike Stroyan313f7e62015-08-10 16:42:53 -06002072 '%s' % stmt +
2073 '}')
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002074 return "\n".join(funcs)
2075 # Non-Cmd functions that do a Wait are thread safe
2076 if 'Wait' in proto.name:
2077 return None
2078 # Watch use of certain types of objects passed as any parameter
2079 checked_params = []
2080 for param in proto.params:
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002081 if param.ty in self.thread_check_dispatchable_objects or param.ty in self.thread_check_nondispatchable_objects:
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002082 checked_params.append(param)
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002083 if proto.name == "DestroyDevice":
Mike Stroyan313f7e62015-08-10 16:42:53 -06002084 funcs.append('%s%s\n' % (qual, decl) +
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002085 '{\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06002086 ' dispatch_key key = get_dispatch_key(device);\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002087 ' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_%s_table_map, %s);\n' % (table, proto.params[0].name) +
Mike Stroyan313f7e62015-08-10 16:42:53 -06002088 ' %spDeviceTable->%s;\n' % (ret_val, proto.c_call()) +
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002089 ' threading_device_table_map.erase(key);\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002090 '}\n')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002091 return "\n".join(funcs);
2092 elif proto.name == "DestroyInstance":
Mike Stroyan313f7e62015-08-10 16:42:53 -06002093 funcs.append('%s%s\n' % (qual, decl) +
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002094 '{\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06002095 ' dispatch_key key = get_dispatch_key(instance);\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002096 ' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(threading_instance_table_map, %s);\n' % proto.params[0].name +
Mike Stroyan313f7e62015-08-10 16:42:53 -06002097 ' %spInstanceTable->%s;\n' % (ret_val, proto.c_call()) +
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06002098 ' destroy_instance_dispatch_table(key);\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002099 '\n'
2100 ' // Clean up logging callback, if any\n'
2101 ' layer_data *my_data = get_my_data_ptr(key, layer_data_map);\n'
2102 ' if (my_data->logging_callback) {\n'
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07002103 ' layer_destroy_msg_callback(my_data->report_data, my_data->logging_callback, pAllocator);\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002104 ' }\n'
2105 '\n'
2106 ' layer_debug_report_destroy_instance(my_data->report_data);\n'
2107 ' layer_data_map.erase(pInstanceTable);\n'
2108 '\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002109 ' threading_instance_table_map.erase(key);\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002110 '}\n')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002111 return "\n".join(funcs);
Courtney Goeltzenleuchterd02a9642015-06-08 14:58:39 -06002112 elif proto.name == "CreateInstance":
2113 funcs.append('%s%s\n'
2114 '{\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002115 ' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(threading_instance_table_map, *pInstance);\n'
Chia-I Wuf7458c52015-10-26 21:10:41 +08002116 ' VkResult result = pInstanceTable->CreateInstance(pCreateInfo, pAllocator, pInstance);\n'
Courtney Goeltzenleuchterd02a9642015-06-08 14:58:39 -06002117 '\n'
2118 ' if (result == VK_SUCCESS) {\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002119 ' layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);\n'
2120 ' my_data->report_data = debug_report_create_instance(\n'
2121 ' pInstanceTable,\n'
2122 ' *pInstance,\n'
Chia-I Wud50a7d72015-10-26 20:48:51 +08002123 ' pCreateInfo->enabledExtensionNameCount,\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002124 ' pCreateInfo->ppEnabledExtensionNames);\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002125 ' init_threading(my_data, pAllocator);\n'
Courtney Goeltzenleuchterd02a9642015-06-08 14:58:39 -06002126 ' }\n'
2127 ' return result;\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002128 '}\n' % (qual, decl))
Courtney Goeltzenleuchterd02a9642015-06-08 14:58:39 -06002129 return "\n".join(funcs);
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002130 if len(checked_params) == 0:
2131 return None
2132 # Surround call with useObject and finishUsingObject for each checked_param
Tobin Ehlis08fafd02015-06-12 12:49:01 -06002133 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002134 funcs.append('%s%s' % (qual, decl))
2135 funcs.append('{')
2136 for param in checked_params:
Michael Lentine13803dc2015-11-04 14:35:12 -08002137 funcs.append(' use%s((const void *) %s, %s);' % (param.ty, proto.params[0].name, param.name))
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002138 funcs.append(' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_%s_table_map, %s);' % (table, proto.params[0].name));
Mike Stroyan313f7e62015-08-10 16:42:53 -06002139 funcs.append(' %spDeviceTable->%s;' % (ret_val, proto.c_call()))
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002140 for param in checked_params:
Michael Lentine13803dc2015-11-04 14:35:12 -08002141 funcs.append(' finishUsing%s(%s);' % (param.ty, param.name))
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002142 funcs.append('%s'
2143 '}' % stmt)
2144 return "\n".join(funcs)
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002145
2146 def generate_body(self):
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002147 self.layer_name = "threading"
Mike Stroyan313f7e62015-08-10 16:42:53 -06002148 body = [self._generate_new_layer_initialization(True, lockname='threading', condname='threading'),
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002149 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Courtney Goeltzenleuchter17274172015-06-01 14:52:57 -06002150 self._generate_layer_gpa_function(extensions=[],
Jon Ashburn3dc39382015-09-17 10:00:32 -06002151 instance_extensions=[('msg_callback_get_proc_addr', [])]),
Courtney Goeltzenleuchter17274172015-06-01 14:52:57 -06002152 self._gen_create_msg_callback(),
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07002153 self._gen_destroy_msg_callback(),
2154 self._gen_debug_report_msg()]
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002155 return "\n\n".join(body)
2156
Tobin Ehlis12076fc2014-10-22 09:06:33 -06002157def main():
2158 subcommands = {
2159 "layer-funcs" : LayerFuncsSubcommand,
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002160 "generic" : GenericLayerSubcommand,
2161 "api_dump" : APIDumpSubcommand,
2162 "object_tracker" : ObjectTrackerSubcommand,
2163 "threading" : ThreadingSubcommand,
Tobin Ehlis12076fc2014-10-22 09:06:33 -06002164 }
2165
Tobin Ehlis14ff0852014-12-17 17:44:50 -07002166 if len(sys.argv) < 3 or sys.argv[1] not in subcommands or not os.path.exists(sys.argv[2]):
2167 print("Usage: %s <subcommand> <input_header> [options]" % sys.argv[0])
Tobin Ehlis12076fc2014-10-22 09:06:33 -06002168 print
Tobin Ehlis7e65d752015-01-15 17:51:52 -07002169 print("Available subcommands are: %s" % " ".join(subcommands))
Tobin Ehlis12076fc2014-10-22 09:06:33 -06002170 exit(1)
2171
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06002172 hfp = vk_helper.HeaderFileParser(sys.argv[2])
Tobin Ehlis14ff0852014-12-17 17:44:50 -07002173 hfp.parse()
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06002174 vk_helper.enum_val_dict = hfp.get_enum_val_dict()
2175 vk_helper.enum_type_dict = hfp.get_enum_type_dict()
2176 vk_helper.struct_dict = hfp.get_struct_dict()
2177 vk_helper.typedef_fwd_dict = hfp.get_typedef_fwd_dict()
2178 vk_helper.typedef_rev_dict = hfp.get_typedef_rev_dict()
2179 vk_helper.types_dict = hfp.get_types_dict()
Tobin Ehlis14ff0852014-12-17 17:44:50 -07002180
Tobin Ehlis12076fc2014-10-22 09:06:33 -06002181 subcmd = subcommands[sys.argv[1]](sys.argv[2:])
2182 subcmd.run()
2183
2184if __name__ == "__main__":
2185 main()