blob: ea44ceef6839d6dba5c0e3e6b6fd257d1dbc251b [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
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07006# 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#
Tobin Ehlisd34a4c52015-12-08 10:50:10 -070026# Author: Tobin Ehlis <tobine@google.com>
27# Author: Courtney Goeltzenleuchter <courtneygo@google.com>
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060028# Author: Jon Ashburn <jon@lunarg.com>
29# Author: Mark Lobodzinski <mark@lunarg.com>
Tobin Ehlisd34a4c52015-12-08 10:50:10 -070030# Author: Mike Stroyan <stroyan@google.com>
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060031# Author: Tony Barbour <tony@LunarG.com>
Tobin Ehlisd34a4c52015-12-08 10:50:10 -070032# Author: Chia-I Wu <olv@google.com>
Tobin Ehlis12076fc2014-10-22 09:06:33 -060033
34import sys
Tobin Ehlis14ff0852014-12-17 17:44:50 -070035import os
Mark Lobodzinski7c75b852015-05-05 15:01:37 -050036import re
Tobin Ehlis12076fc2014-10-22 09:06:33 -060037
Courtney Goeltzenleuchterf53c3cb2015-04-14 14:55:44 -060038import vulkan
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060039import vk_helper
Tobin Ehlis08fafd02015-06-12 12:49:01 -060040from source_line_info import sourcelineinfo
Tobin Ehlis154e0462015-08-26 11:22:09 -060041from collections import defaultdict
Tobin Ehlis12076fc2014-10-22 09:06:33 -060042
Jon Ashburn95a77ba2015-05-15 15:09:35 -060043def proto_is_global(proto):
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -070044 global_function_names = [
45 "CreateInstance",
46 "EnumerateInstanceLayerProperties",
47 "EnumerateInstanceExtensionProperties",
48 "EnumerateDeviceLayerProperties",
49 "EnumerateDeviceExtensionProperties",
50 "CreateXcbSurfaceKHR",
Jon Ashburn00dc7412016-01-07 16:13:06 -070051 "GetPhysicalDeviceXcbPresentationSupportKHR",
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -070052 "CreateXlibSurfaceKHR",
Jon Ashburn00dc7412016-01-07 16:13:06 -070053 "GetPhysicalDeviceXlibPresentationSupportKHR",
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -070054 "CreateWaylandSurfaceKHR",
Jon Ashburn00dc7412016-01-07 16:13:06 -070055 "GetPhysicalDeviceWaylandPresentationSupportKHR",
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -070056 "CreateMirSurfaceKHR",
Jon Ashburn00dc7412016-01-07 16:13:06 -070057 "GetPhysicalDeviceMirPresentationSupportKHR",
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -070058 "CreateAndroidSurfaceKHR",
59 "CreateWin32SurfaceKHR",
Jon Ashburn00dc7412016-01-07 16:13:06 -070060 "GetPhysicalDeviceWin32PresentationSupportKHR"
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -070061 ]
62 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 -060063 return True
64 else:
65 return False
66
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -070067def wsi_name(ext_name):
68 wsi_prefix = ""
69 if 'Xcb' in ext_name:
70 wsi_prefix = 'XCB'
71 elif 'Xlib' in ext_name:
72 wsi_prefix = 'XLIB'
73 elif 'Win32' in ext_name:
74 wsi_prefix = 'WIN32'
75 elif 'Mir' in ext_name:
76 wsi_prefix = 'MIR'
77 elif 'Wayland' in ext_name:
78 wsi_prefix = 'WAYLAND'
79 elif 'Android' in ext_name:
80 wsi_prefix = 'ANDROID'
81 else:
82 wsi_prefix = ''
83 return wsi_prefix
84
85def wsi_ifdef(ext_name):
86 wsi_prefix = wsi_name(ext_name)
87 if not wsi_prefix:
88 return ''
89 else:
90 return "#ifdef VK_USE_PLATFORM_%s_KHR" % wsi_prefix
91
92def wsi_endif(ext_name):
93 wsi_prefix = wsi_name(ext_name)
94 if not wsi_prefix:
95 return ''
96 else:
97 return "#endif // VK_USE_PLATFORM_%s_KHR" % wsi_prefix
98
Mike Stroyan938c2532015-04-03 13:58:35 -060099def generate_get_proc_addr_check(name):
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600100 return " if (!%s || %s[0] != 'v' || %s[1] != 'k')\n" \
101 " return NULL;" % ((name,) * 3)
Mike Stroyan938c2532015-04-03 13:58:35 -0600102
Mark Lobodzinski7c75b852015-05-05 15:01:37 -0500103def ucc_to_U_C_C(CamelCase):
104 temp = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', CamelCase)
105 return re.sub('([a-z0-9])([A-Z])', r'\1_\2', temp).upper()
106
Tobin Ehlis65f44e42016-01-05 09:46:03 -0700107# Parse complete struct chain and add any new ndo_uses to the dict
108def gather_object_uses_in_struct(obj_list, struct_type):
109 struct_uses = {}
110 if vk_helper.typedef_rev_dict[struct_type] in vk_helper.struct_dict:
111 struct_type = vk_helper.typedef_rev_dict[struct_type]
112 # Parse elements of this struct param to identify objects and/or arrays of objects
113 for m in sorted(vk_helper.struct_dict[struct_type]):
114 array_len = "%s" % (str(vk_helper.struct_dict[struct_type][m]['array_size']))
115 base_type = vk_helper.struct_dict[struct_type][m]['type']
116 mem_name = vk_helper.struct_dict[struct_type][m]['name']
117 if array_len != '0':
118 mem_name = "%s[%s]" % (mem_name, array_len)
119 if base_type in obj_list:
120 #if array_len not in ndo_uses:
121 # struct_uses[array_len] = []
122 #struct_uses[array_len].append("%s%s,%s" % (name_prefix, struct_name, base_type))
123 struct_uses[mem_name] = base_type
124 elif vk_helper.is_type(base_type, 'struct'):
125 sub_uses = gather_object_uses_in_struct(obj_list, base_type)
126 if len(sub_uses) > 0:
127 struct_uses[mem_name] = sub_uses
128 return struct_uses
129
130# For the given list of object types, Parse the given list of params
131# and return dict of params that use one of the obj_list types
132# Format of the dict is that terminal elements have <name>,<type>
133# non-terminal elements will have <name>[<array_size>]
134# TODO : This analysis could be done up-front at vk_helper time
135def get_object_uses(obj_list, params):
136 obj_uses = {}
137 param_count = 'NONE' # track params that give array sizes
138 for p in params:
139 base_type = p.ty.replace('const ', '').strip('*')
140 array_len = ''
141 is_ptr = False
142 if 'count' in p.name.lower():
143 param_count = p.name
144 if '*' in p.ty:
145 is_ptr = True
146 if base_type in obj_list:
147 if is_ptr and 'const' in p.ty and param_count != 'NONE':
148 array_len = "[%s]" % param_count
149 #if array_len not in obj_uses:
150 # obj_uses[array_len] = {}
151 # obj_uses[array_len][p.name] = base_type
152 obj_uses["%s%s" % (p.name, array_len)] = base_type
153 elif vk_helper.is_type(base_type, 'struct'):
154 struct_name = p.name
155 if 'NONE' != param_count:
156 struct_name = "%s[%s]" % (struct_name, param_count)
157 struct_uses = gather_object_uses_in_struct(obj_list, base_type)
158 if len(struct_uses) > 0:
159 obj_uses[struct_name] = struct_uses
160 return obj_uses
161
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600162class Subcommand(object):
163 def __init__(self, argv):
164 self.argv = argv
Courtney Goeltzenleuchterf53c3cb2015-04-14 14:55:44 -0600165 self.headers = vulkan.headers
166 self.protos = vulkan.protos
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600167 self.no_addr = False
168 self.layer_name = ""
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600169 self.lineinfo = sourcelineinfo()
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600170
171 def run(self):
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600172 print(self.generate())
173
174 def generate(self):
175 copyright = self.generate_copyright()
176 header = self.generate_header()
177 body = self.generate_body()
178 footer = self.generate_footer()
179
180 contents = []
181 if copyright:
182 contents.append(copyright)
183 if header:
184 contents.append(header)
185 if body:
186 contents.append(body)
187 if footer:
188 contents.append(footer)
189
190 return "\n\n".join(contents)
191
192 def generate_copyright(self):
193 return """/* THIS FILE IS GENERATED. DO NOT EDIT. */
194
195/*
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600196 *
Courtney Goeltzenleuchterfcbe16f2015-10-29 13:50:34 -0600197 * Copyright (C) 2015 Valve Corporation
Tobin Ehlisd34a4c52015-12-08 10:50:10 -0700198 * Copyright (C) 2015 Google, Inc.
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600199 *
200 * Permission is hereby granted, free of charge, to any person obtaining a
201 * copy of this software and associated documentation files (the "Software"),
202 * to deal in the Software without restriction, including without limitation
203 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
204 * and/or sell copies of the Software, and to permit persons to whom the
205 * Software is furnished to do so, subject to the following conditions:
206 *
207 * The above copyright notice and this permission notice shall be included
208 * in all copies or substantial portions of the Software.
209 *
210 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
211 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
212 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
213 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
214 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
215 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
216 * DEALINGS IN THE SOFTWARE.
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -0600217 *
Tobin Ehlisd34a4c52015-12-08 10:50:10 -0700218 * Author: Tobin Ehlis <tobine@google.com>
219 * Author: Courtney Goeltzenleuchter <courtneygo@google.com>
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -0600220 * Author: Jon Ashburn <jon@lunarg.com>
221 * Author: Mark Lobodzinski <mark@lunarg.com>
Tobin Ehlisd34a4c52015-12-08 10:50:10 -0700222 * Author: Mike Stroyan <stroyan@google.com>
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -0600223 * Author: Tony Barbour <tony@LunarG.com>
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600224 */"""
225
226 def generate_header(self):
227 return "\n".join(["#include <" + h + ">" for h in self.headers])
228
229 def generate_body(self):
230 pass
231
232 def generate_footer(self):
233 pass
234
235 # Return set of printf '%' qualifier and input to that qualifier
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600236 def _get_printf_params(self, vk_type, name, output_param, cpp=False):
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600237 # TODO : Need ENUM and STRUCT checks here
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600238 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 -0600239 return ("%s", "string_%s(%s)" % (vk_type.replace('const ', '').strip('*'), name))
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600240 if "char*" == vk_type:
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600241 return ("%s", name)
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600242 if "uint64" in vk_type:
243 if '*' in vk_type:
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600244 return ("%lu", "*%s" % name)
245 return ("%lu", name)
Tobin Ehlisa30e7e52015-07-06 14:02:36 -0600246 if vk_type.strip('*') in vulkan.object_non_dispatch_list:
247 if '*' in vk_type:
Chia-I Wue2fc5522015-10-26 20:04:44 +0800248 return ("%lu", "%s" % name)
249 return ("%lu", "%s" % name)
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600250 if "size" in vk_type:
251 if '*' in vk_type:
Mark Lobodzinskia1456492015-10-06 09:57:52 -0600252 return ("%lu", "(unsigned long)*%s" % name)
253 return ("%lu", "(unsigned long)%s" % name)
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600254 if "float" in vk_type:
255 if '[' in vk_type: # handle array, current hard-coded to 4 (TODO: Make this dynamic)
Tobin Ehlis99f88672015-01-10 12:42:41 -0700256 if cpp:
257 return ("[%i, %i, %i, %i]", '"[" << %s[0] << "," << %s[1] << "," << %s[2] << "," << %s[3] << "]"' % (name, name, name, name))
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600258 return ("[%f, %f, %f, %f]", "%s[0], %s[1], %s[2], %s[3]" % (name, name, name, name))
259 return ("%f", name)
Courtney Goeltzenleuchtercd2a0992015-07-09 11:44:38 -0600260 if "bool" in vk_type.lower() or 'xcb_randr_crtc_t' in vk_type:
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600261 return ("%u", name)
Tobin Ehlisb870cbb2015-04-15 07:46:12 -0600262 if True in [t in vk_type.lower() for t in ["int", "flags", "mask", "xcb_window_t"]]:
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600263 if '[' in vk_type: # handle array, current hard-coded to 4 (TODO: Make this dynamic)
Tobin Ehlis99f88672015-01-10 12:42:41 -0700264 if cpp:
265 return ("[%i, %i, %i, %i]", "%s[0] << %s[1] << %s[2] << %s[3]" % (name, name, name, name))
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600266 return ("[%i, %i, %i, %i]", "%s[0], %s[1], %s[2], %s[3]" % (name, name, name, name))
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600267 if '*' in vk_type:
Tobin Ehlisd2b88e82015-02-04 15:15:11 -0700268 if 'pUserData' == name:
269 return ("%i", "((pUserData == 0) ? 0 : *(pUserData))")
Tobin Ehlisc62cb892015-04-17 13:26:33 -0600270 if 'const' in vk_type.lower():
271 return ("%p", "(void*)(%s)" % name)
Jon Ashburn52f79b52014-12-12 16:10:45 -0700272 return ("%i", "*(%s)" % name)
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600273 return ("%i", name)
Tobin Ehlis3a1cc8d2014-11-11 17:28:22 -0700274 # 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 -0600275 if "VkFormat" == vk_type:
Tobin Ehlis99f88672015-01-10 12:42:41 -0700276 if cpp:
277 return ("%p", "&%s" % name)
Chia-I Wu1b99bb22015-10-27 19:25:11 +0800278 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 -0700279 if output_param:
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600280 return ("%p", "(void*)*%s" % name)
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600281 if vk_helper.is_type(vk_type, 'struct') and '*' not in vk_type:
Courtney Goeltzenleuchterd462fba2015-04-03 16:35:32 -0600282 return ("%p", "(void*)(&%s)" % name)
Jon Ashburn52f79b52014-12-12 16:10:45 -0700283 return ("%p", "(void*)(%s)" % name)
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600284
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600285 def _gen_create_msg_callback(self):
Tobin Ehlise8185062014-12-17 08:01:59 -0700286 r_body = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600287 r_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700288 r_body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(')
289 r_body.append(' VkInstance instance,')
290 r_body.append(' const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,')
291 r_body.append(' const VkAllocationCallbacks* pAllocator,')
292 r_body.append(' VkDebugReportCallbackEXT* pCallback)')
Tobin Ehlise8185062014-12-17 08:01:59 -0700293 r_body.append('{')
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600294 # Switch to this code section for the new per-instance storage and debug callbacks
Tobin Ehlisd34a4c52015-12-08 10:50:10 -0700295 if self.layer_name in ['object_tracker', 'threading', 'unique_objects']:
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600296 r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700297 r_body.append(' VkResult result = pInstanceTable->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);')
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600298 r_body.append(' if (VK_SUCCESS == result) {')
299 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 -0700300 r_body.append(' result = layer_create_msg_callback(my_data->report_data,')
301 r_body.append(' pCreateInfo,')
302 r_body.append(' pAllocator,')
303 r_body.append(' pCallback);')
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600304 r_body.append(' }')
305 r_body.append(' return result;')
306 else:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700307 r_body.append(' VkResult result = instance_dispatch_table(instance)->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600308 r_body.append(' if (VK_SUCCESS == result) {')
309 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 -0700310 r_body.append(' result = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pCallback);')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600311 r_body.append(' }')
312 r_body.append(' return result;')
Tobin Ehlise8185062014-12-17 08:01:59 -0700313 r_body.append('}')
314 return "\n".join(r_body)
315
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600316 def _gen_destroy_msg_callback(self):
317 r_body = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600318 r_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700319 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 -0600320 r_body.append('{')
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600321 # Switch to this code section for the new per-instance storage and debug callbacks
Tobin Ehlisd34a4c52015-12-08 10:50:10 -0700322 if self.layer_name in ['object_tracker', 'threading', 'unique_objects']:
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600323 r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600324 else:
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700325 r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = instance_dispatch_table(instance);')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700326 r_body.append(' pInstanceTable->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700327 r_body.append(' layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
328 r_body.append(' layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);')
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600329 r_body.append('}')
330 return "\n".join(r_body)
Tobin Ehlise8185062014-12-17 08:01:59 -0700331
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700332 def _gen_debug_report_msg(self):
333 r_body = []
334 r_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700335 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 -0700336 r_body.append('{')
337 # Switch to this code section for the new per-instance storage and debug callbacks
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700338 if self.layer_name == 'object_tracker' or self.layer_name == 'threading':
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700339 r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
340 else:
341 r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = instance_dispatch_table(instance);')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700342 r_body.append(' pInstanceTable->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);')
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700343 r_body.append('}')
344 return "\n".join(r_body)
345
Jon Ashburn1f32a442016-02-02 13:13:01 -0700346 def _gen_layer_get_global_extension_props(self, layer="object_tracker"):
Tony Barbour59a47322015-06-24 16:06:58 -0600347 ggep_body = []
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600348 # generated layers do not provide any global extensions
349 ggep_body.append('%s' % self.lineinfo.get())
350
351 ggep_body.append('')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700352 if self.layer_name == 'object_tracker' or self.layer_name == 'threading':
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700353 ggep_body.append('static const VkExtensionProperties instance_extensions[] = {')
354 ggep_body.append(' {')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700355 ggep_body.append(' VK_EXT_DEBUG_REPORT_EXTENSION_NAME,')
Courtney Goeltzenleuchterb69cd592016-01-19 16:08:39 -0700356 ggep_body.append(' VK_EXT_DEBUG_REPORT_SPEC_VERSION')
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700357 ggep_body.append(' }')
358 ggep_body.append('};')
Chia-I Wu9ab61502015-11-06 06:42:02 +0800359 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 -0600360 ggep_body.append('{')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700361 if self.layer_name == 'object_tracker' or self.layer_name == 'threading':
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700362 ggep_body.append(' return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);')
363 else:
364 ggep_body.append(' return util_GetExtensionProperties(0, NULL, pCount, pProperties);')
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600365 ggep_body.append('}')
366 return "\n".join(ggep_body)
367
Jon Ashburn1f32a442016-02-02 13:13:01 -0700368 def _gen_layer_get_global_layer_props(self, layer="object_tracker"):
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600369 ggep_body = []
Jon Ashburn1f32a442016-02-02 13:13:01 -0700370 layer_name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', layer)
371 layer_name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', layer_name).lower()
372 ggep_body.append('%s' % self.lineinfo.get())
373 ggep_body.append('static const VkLayerProperties globalLayerProps[] = {')
374 ggep_body.append(' {')
375 ggep_body.append(' "VK_LAYER_LUNARG_%s",' % layer_name)
376 ggep_body.append(' VK_API_VERSION, // specVersion')
377 ggep_body.append(' VK_MAKE_VERSION(0, 1, 0), // implementationVersion')
378 ggep_body.append(' "layer: %s",' % layer)
379 ggep_body.append(' }')
380 ggep_body.append('};')
Tony Barbour59a47322015-06-24 16:06:58 -0600381 ggep_body.append('')
382 ggep_body.append('%s' % self.lineinfo.get())
Tony Barbour59a47322015-06-24 16:06:58 -0600383 ggep_body.append('')
Chia-I Wu9ab61502015-11-06 06:42:02 +0800384 ggep_body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties* pProperties)')
Tony Barbour59a47322015-06-24 16:06:58 -0600385 ggep_body.append('{')
Courtney Goeltzenleuchter79a5a962015-07-07 17:51:45 -0600386 ggep_body.append(' return util_GetLayerProperties(ARRAY_SIZE(globalLayerProps), globalLayerProps, pCount, pProperties);')
Tony Barbour59a47322015-06-24 16:06:58 -0600387 ggep_body.append('}')
388 return "\n".join(ggep_body)
389
Jon Ashburn1f32a442016-02-02 13:13:01 -0700390 def _gen_layer_get_physical_device_layer_props(self, layer="object_tracker"):
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600391 gpdlp_body = []
Jon Ashburn1f32a442016-02-02 13:13:01 -0700392 gpdlp_body.append('%s' % self.lineinfo.get())
393 gpdlp_body.append('static const VkLayerProperties deviceLayerProps[] = {')
394 gpdlp_body.append(' {')
395 gpdlp_body.append(' "VK_LAYER_LUNARG_%s",' % layer)
396 gpdlp_body.append(' VK_API_VERSION,')
397 gpdlp_body.append(' VK_MAKE_VERSION(0, 1, 0),')
398 gpdlp_body.append(' "layer: %s",' % layer)
399 gpdlp_body.append(' }')
400 gpdlp_body.append('};')
Chia-I Wu9ab61502015-11-06 06:42:02 +0800401 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 -0600402 gpdlp_body.append('{')
Courtney Goeltzenleuchter79a5a962015-07-07 17:51:45 -0600403 gpdlp_body.append(' return util_GetLayerProperties(ARRAY_SIZE(deviceLayerProps), deviceLayerProps, pCount, pProperties);')
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600404 gpdlp_body.append('}')
405 gpdlp_body.append('')
406 return "\n".join(gpdlp_body)
407
Mike Stroyanbf237d72015-04-03 17:45:53 -0600408 def _generate_dispatch_entrypoints(self, qual=""):
Mike Stroyan938c2532015-04-03 13:58:35 -0600409 if qual:
410 qual += " "
411
Mike Stroyan938c2532015-04-03 13:58:35 -0600412 funcs = []
413 intercepted = []
414 for proto in self.protos:
Jon Ashburn8d1b0b52015-05-18 13:20:15 -0600415 if proto.name == "GetDeviceProcAddr" or proto.name == "GetInstanceProcAddr":
Jon Ashburn8fd08252015-05-28 16:25:02 -0600416 continue
Mike Stroyan70c05e82015-04-08 10:27:43 -0600417 else:
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600418 intercept = self.generate_intercept(proto, qual)
Mike Stroyan938c2532015-04-03 13:58:35 -0600419 if intercept is None:
420 # fill in default intercept for certain entrypoints
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700421 if 'CreateDebugReportCallbackEXT' == proto.name:
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600422 intercept = self._gen_layer_dbg_create_msg_callback()
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700423 elif 'DestroyDebugReportCallbackEXT' == proto.name:
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600424 intercept = self._gen_layer_dbg_destroy_msg_callback()
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700425 elif 'DebugReportMessageEXT' == proto.name:
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700426 intercept = self._gen_debug_report_msg()
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600427 elif 'CreateDevice' == proto.name:
428 funcs.append('/* CreateDevice HERE */')
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600429 elif 'EnumerateInstanceExtensionProperties' == proto.name:
Tony Barbour59a47322015-06-24 16:06:58 -0600430 intercept = self._gen_layer_get_global_extension_props(self.layer_name)
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600431 elif 'EnumerateInstanceLayerProperties' == proto.name:
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600432 intercept = self._gen_layer_get_global_layer_props(self.layer_name)
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600433 elif 'EnumerateDeviceLayerProperties' == proto.name:
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600434 intercept = self._gen_layer_get_physical_device_layer_props(self.layer_name)
Tony Barbour59a47322015-06-24 16:06:58 -0600435
Mike Stroyan938c2532015-04-03 13:58:35 -0600436 if intercept is not None:
437 funcs.append(intercept)
Ian Elliott7e40db92015-08-21 15:09:33 -0600438 if not "KHR" in proto.name:
Jon Ashburn747f2b62015-06-18 15:02:58 -0600439 intercepted.append(proto)
Mike Stroyan938c2532015-04-03 13:58:35 -0600440
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600441 prefix="vk"
Mike Stroyan938c2532015-04-03 13:58:35 -0600442 lookups = []
443 for proto in intercepted:
Mike Stroyan938c2532015-04-03 13:58:35 -0600444 lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600445 lookups.append(" return (PFN_vkVoidFunction) %s%s;" %
Mike Stroyan938c2532015-04-03 13:58:35 -0600446 (prefix, proto.name))
Mike Stroyan938c2532015-04-03 13:58:35 -0600447
448 # add customized layer_intercept_proc
449 body = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600450 body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600451 body.append("static inline PFN_vkVoidFunction layer_intercept_proc(const char *name)")
Mike Stroyan938c2532015-04-03 13:58:35 -0600452 body.append("{")
453 body.append(generate_get_proc_addr_check("name"))
454 body.append("")
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600455 body.append(" name += 2;")
Mike Stroyan938c2532015-04-03 13:58:35 -0600456 body.append(" %s" % "\n ".join(lookups))
457 body.append("")
458 body.append(" return NULL;")
459 body.append("}")
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600460 # add layer_intercept_instance_proc
461 lookups = []
462 for proto in self.protos:
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600463 if not proto_is_global(proto):
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600464 continue
465
466 if not proto in intercepted:
467 continue
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700468 if proto.name == "CreateInstance":
469 continue
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -0600470 if proto.name == "CreateDevice":
471 continue
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600472 lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600473 lookups.append(" return (PFN_vkVoidFunction) %s%s;" % (prefix, proto.name))
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600474
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600475 body.append("static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char *name)")
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600476 body.append("{")
477 body.append(generate_get_proc_addr_check("name"))
478 body.append("")
479 body.append(" name += 2;")
480 body.append(" %s" % "\n ".join(lookups))
481 body.append("")
482 body.append(" return NULL;")
483 body.append("}")
484
Mike Stroyan938c2532015-04-03 13:58:35 -0600485 funcs.append("\n".join(body))
Mike Stroyan938c2532015-04-03 13:58:35 -0600486 return "\n\n".join(funcs)
487
Tobin Ehlisca915872014-11-18 11:28:33 -0700488 def _generate_extensions(self):
489 exts = []
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600490 exts.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600491 exts.append(self._gen_create_msg_callback())
492 exts.append(self._gen_destroy_msg_callback())
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700493 exts.append(self._gen_debug_report_msg())
Tobin Ehlisb870cbb2015-04-15 07:46:12 -0600494 return "\n".join(exts)
495
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600496 def _generate_layer_gpa_function(self, extensions=[], instance_extensions=[]):
Jon Ashburnbacb0f52015-04-06 10:58:22 -0600497 func_body = []
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600498#
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600499# New style of GPA Functions for the new layer_data/layer_logging changes
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600500#
Tobin Ehlisd34a4c52015-12-08 10:50:10 -0700501 if self.layer_name in ['object_tracker', 'threading', 'unique_objects']:
Chia-I Wu9ab61502015-11-06 06:42:02 +0800502 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 -0600503 "{\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600504 " PFN_vkVoidFunction addr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600505 " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600506 " return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600507 " }\n\n"
508 " addr = layer_intercept_proc(funcName);\n"
509 " if (addr)\n"
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700510 " return addr;\n"
511 " if (device == VK_NULL_HANDLE) {\n"
512 " return NULL;\n"
513 " }\n")
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600514 if 0 != len(extensions):
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600515 func_body.append('%s' % self.lineinfo.get())
516 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 -0600517 for (ext_enable, ext_list) in extensions:
518 extra_space = ""
519 if 0 != len(ext_enable):
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600520 func_body.append(' if (my_device_data->%s) {' % ext_enable)
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600521 extra_space = " "
522 for ext_name in ext_list:
523 func_body.append(' %sif (!strcmp("%s", funcName))\n'
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600524 ' %sreturn reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, extra_space, ext_name))
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600525 if 0 != len(ext_enable):
526 func_body.append(' }\n')
527 func_body.append("\n if (get_dispatch_table(%s_device_table_map, device)->GetDeviceProcAddr == NULL)\n"
528 " return NULL;\n"
529 " return get_dispatch_table(%s_device_table_map, device)->GetDeviceProcAddr(device, funcName);\n"
530 "}\n" % (self.layer_name, self.layer_name))
Chia-I Wu9ab61502015-11-06 06:42:02 +0800531 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 -0600532 "{\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600533 " PFN_vkVoidFunction addr;\n"
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700534 " if (!strcmp(funcName, \"vkGetInstanceProcAddr\"))\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600535 " return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700536 " if (!strcmp(funcName, \"vkCreateInstance\"))\n"
537 " return (PFN_vkVoidFunction) vkCreateInstance;\n"
538 " if (!strcmp(funcName, \"vkCreateDevice\"))\n"
539 " return (PFN_vkVoidFunction) vkCreateDevice;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600540 " addr = layer_intercept_instance_proc(funcName);\n"
541 " if (addr) {\n"
542 " return addr;"
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700543 " }\n"
544 " if (instance == VK_NULL_HANDLE) {\n"
545 " return NULL;\n"
546 " }\n"
547 )
Jon Ashburnbacb0f52015-04-06 10:58:22 -0600548
Jon Ashburn3dc39382015-09-17 10:00:32 -0600549 table_declared = False
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600550 if 0 != len(instance_extensions):
Jon Ashburn3dc39382015-09-17 10:00:32 -0600551 for (ext_enable, ext_list) in instance_extensions:
552 extra_space = ""
553 if 0 != len(ext_enable):
554 if ext_enable == 'msg_callback_get_proc_addr':
555 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 -0600556 " addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);\n"
557 " if (addr) {\n"
558 " return addr;\n"
Jon Ashburn3dc39382015-09-17 10:00:32 -0600559 " }\n")
560 else:
561 if table_declared == False:
562 func_body.append(" VkLayerInstanceDispatchTable* pTable = get_dispatch_table(%s_instance_table_map, instance);" % self.layer_name)
563 table_declared = True
564 func_body.append(' if (instanceExtMap.size() != 0 && instanceExtMap[pTable].%s)' % ext_enable)
565 func_body.append(' {')
566 extra_space = " "
567 for ext_name in ext_list:
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700568 if wsi_name(ext_name):
569 func_body.append('%s' % wsi_ifdef(ext_name))
Jon Ashburn3dc39382015-09-17 10:00:32 -0600570 func_body.append(' %sif (!strcmp("%s", funcName))\n'
571 ' return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700572 if wsi_name(ext_name):
573 func_body.append('%s' % wsi_endif(ext_name))
Jon Ashburn3dc39382015-09-17 10:00:32 -0600574 if 0 != len(ext_enable):
575 func_body.append(' }\n')
576
577 func_body.append(" if (get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr == NULL) {\n"
578 " return NULL;\n"
579 " }\n"
580 " return get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr(instance, funcName);\n"
581 "}\n" % (self.layer_name, self.layer_name))
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600582 return "\n".join(func_body)
583 else:
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600584 func_body.append('%s' % self.lineinfo.get())
Chia-I Wu9ab61502015-11-06 06:42:02 +0800585 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 -0600586 "{\n"
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700587 " PFN_vkVoidFunction addr;\n")
Jon Ashburn1f32a442016-02-02 13:13:01 -0700588 func_body.append("\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600589 " loader_platform_thread_once(&initOnce, init%s);\n\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600590 " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600591 " return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600592 " }\n\n"
593 " addr = layer_intercept_proc(funcName);\n"
594 " if (addr)\n"
595 " return addr;" % self.layer_name)
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700596 func_body.append(" if (device == VK_NULL_HANDLE) {\n"
597 " return NULL;\n"
598 " }\n")
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600599 func_body.append('')
600 func_body.append(' VkLayerDispatchTable *pDisp = device_dispatch_table(device);')
601 if 0 != len(extensions):
602 extra_space = ""
603 for (ext_enable, ext_list) in extensions:
604 if 0 != len(ext_enable):
Jon Ashburn8acd2332015-09-16 18:08:32 -0600605 func_body.append(' if (deviceExtMap.size() != 0 && deviceExtMap[pDisp].%s)' % ext_enable)
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600606 func_body.append(' {')
607 extra_space = " "
608 for ext_name in ext_list:
609 func_body.append(' %sif (!strcmp("%s", funcName))\n'
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600610 ' return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600611 if 0 != len(ext_enable):
612 func_body.append(' }')
613 func_body.append('%s' % self.lineinfo.get())
614 func_body.append(" {\n"
615 " if (pDisp->GetDeviceProcAddr == NULL)\n"
616 " return NULL;\n"
617 " return pDisp->GetDeviceProcAddr(device, funcName);\n"
618 " }\n"
619 "}\n")
Jon Ashburn3dc39382015-09-17 10:00:32 -0600620 func_body.append('%s' % self.lineinfo.get())
Chia-I Wu9ab61502015-11-06 06:42:02 +0800621 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 -0600622 "{\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600623 " PFN_vkVoidFunction addr;\n"
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700624 " if (!strcmp(funcName, \"vkGetInstanceProcAddr\"))\n"
625 " return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
626 " if (!strcmp(funcName, \"vkCreateInstance\"))\n"
627 " return (PFN_vkVoidFunction) vkCreateInstance;\n"
628 " if (!strcmp(funcName, \"vkCreateDevice\"))\n"
629 " return (PFN_vkVoidFunction) vkCreateDevice;\n"
630 )
Jon Ashburn1f32a442016-02-02 13:13:01 -0700631 func_body.append(
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600632 " loader_platform_thread_once(&initOnce, init%s);\n\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600633 " addr = layer_intercept_instance_proc(funcName);\n"
634 " if (addr)\n"
635 " return addr;" % self.layer_name)
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700636 func_body.append(" if (instance == VK_NULL_HANDLE) {\n"
637 " return NULL;\n"
638 " }\n")
Jon Ashburn3dc39382015-09-17 10:00:32 -0600639 func_body.append("")
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700640 func_body.append(" VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(instance);\n")
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600641 if 0 != len(instance_extensions):
Jon Ashburn3dc39382015-09-17 10:00:32 -0600642 extra_space = ""
643 for (ext_enable, ext_list) in instance_extensions:
644 if 0 != len(ext_enable):
Jon Ashburn3a278b72015-10-06 17:05:21 -0600645 if ext_enable == 'msg_callback_get_proc_addr':
646 func_body.append(" layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);\n"
647 " addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);\n"
648 " if (addr) {\n"
649 " return addr;\n"
650 " }\n")
651 else:
652 func_body.append(' if (instanceExtMap.size() != 0 && instanceExtMap[pTable].%s)' % ext_enable)
653 func_body.append(' {')
654 extra_space = " "
655 for ext_name in ext_list:
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700656 if wsi_name(ext_name):
657 func_body.append('%s' % wsi_ifdef(ext_name))
Jon Ashburn3a278b72015-10-06 17:05:21 -0600658 func_body.append(' %sif (!strcmp("%s", funcName))\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -0600659 ' return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700660 if wsi_name(ext_name):
661 func_body.append('%s' % wsi_endif(ext_name))
Jon Ashburn3a278b72015-10-06 17:05:21 -0600662 if 0 != len(ext_enable):
663 func_body.append(' }\n')
Jon Ashburn3dc39382015-09-17 10:00:32 -0600664
665 func_body.append(" if (pTable->GetInstanceProcAddr == NULL)\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600666 " return NULL;\n"
667 " return pTable->GetInstanceProcAddr(instance, funcName);\n"
668 "}\n")
669 return "\n".join(func_body)
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600670
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600671
Mike Stroyaned238bb2015-05-15 08:50:57 -0600672 def _generate_layer_initialization(self, init_opts=False, prefix='vk', lockname=None, condname=None):
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600673 func_body = ["#include \"vk_dispatch_table_helper.h\""]
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600674 func_body.append('%s' % self.lineinfo.get())
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700675 func_body.append('static void init_%s(layer_data *my_data, const VkAllocationCallbacks *pAllocator)\n'
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600676 '{\n' % self.layer_name)
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700677 if init_opts:
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600678 func_body.append('%s' % self.lineinfo.get())
Jon Ashburn3a278b72015-10-06 17:05:21 -0600679 func_body.append(' uint32_t report_flags = 0;')
680 func_body.append(' uint32_t debug_action = 0;')
681 func_body.append(' FILE *log_output = NULL;')
682 func_body.append(' const char *option_str;\n')
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600683 func_body.append(' // initialize %s options' % self.layer_name)
Jon Ashburn3a278b72015-10-06 17:05:21 -0600684 func_body.append(' report_flags = getLayerOptionFlags("%sReportFlags", 0);' % self.layer_name)
685 func_body.append(' getLayerOptionEnum("%sDebugAction", (uint32_t *) &debug_action);' % self.layer_name)
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700686 func_body.append('')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600687 func_body.append(' if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)')
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700688 func_body.append(' {')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600689 func_body.append(' option_str = getLayerOption("%sLogFilename");' % self.layer_name)
690 func_body.append(' log_output = getLayerLogOutput(option_str,"%s");' % self.layer_name)
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700691 func_body.append(' VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700692 func_body.append(' memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo));')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700693 func_body.append(' dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700694 func_body.append(' dbgCreateInfo.flags = report_flags;')
695 func_body.append(' dbgCreateInfo.pfnCallback = log_callback;')
696 func_body.append(' dbgCreateInfo.pUserData = NULL;')
697 func_body.append(' layer_create_msg_callback(my_data->report_data, &dbgCreateInfo, pAllocator,')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600698 func_body.append(' &my_data->logging_callback);')
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700699 func_body.append(' }')
700 func_body.append('')
Tobin Ehlis36f1b462015-02-23 14:09:16 -0700701 if lockname is not None:
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600702 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlis36f1b462015-02-23 14:09:16 -0700703 func_body.append(" if (!%sLockInitialized)" % lockname)
704 func_body.append(" {")
705 func_body.append(" // TODO/TBD: Need to delete this mutex sometime. How???")
706 func_body.append(" loader_platform_thread_create_mutex(&%sLock);" % lockname)
Mike Stroyaned238bb2015-05-15 08:50:57 -0600707 if condname is not None:
708 func_body.append(" loader_platform_thread_init_cond(&%sCond);" % condname)
Tobin Ehlis36f1b462015-02-23 14:09:16 -0700709 func_body.append(" %sLockInitialized = 1;" % lockname)
710 func_body.append(" }")
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600711 func_body.append("}\n")
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -0600712 func_body.append('')
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600713 return "\n".join(func_body)
714
Mike Stroyan313f7e62015-08-10 16:42:53 -0600715 def _generate_new_layer_initialization(self, init_opts=False, prefix='vk', lockname=None, condname=None):
716 func_body = ["#include \"vk_dispatch_table_helper.h\""]
717 func_body.append('%s' % self.lineinfo.get())
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700718 func_body.append('static void init_%s(layer_data *my_data, const VkAllocationCallbacks *pAllocator)\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -0600719 '{\n' % self.layer_name)
720 if init_opts:
721 func_body.append('%s' % self.lineinfo.get())
722 func_body.append(' uint32_t report_flags = 0;')
723 func_body.append(' uint32_t debug_action = 0;')
724 func_body.append(' FILE *log_output = NULL;')
725 func_body.append(' const char *strOpt;')
726 func_body.append(' // initialize %s options' % self.layer_name)
727 func_body.append(' report_flags = getLayerOptionFlags("%sReportFlags", 0);' % self.layer_name)
Jon Ashburn9ff6ae92015-10-06 17:20:01 -0600728 func_body.append(' getLayerOptionEnum("%sDebugAction", (uint32_t *) &debug_action);' % self.layer_name)
Mike Stroyan313f7e62015-08-10 16:42:53 -0600729 func_body.append('')
730 func_body.append(' if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)')
731 func_body.append(' {')
732 func_body.append(' strOpt = getLayerOption("%sLogFilename");' % self.layer_name)
Tobin Ehlisb1df55e2015-09-15 09:55:54 -0600733 func_body.append(' log_output = getLayerLogOutput(strOpt, "%s");' % self.layer_name)
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700734 func_body.append(' VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700735 func_body.append(' memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo));')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700736 func_body.append(' dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700737 func_body.append(' dbgCreateInfo.flags = report_flags;')
738 func_body.append(' dbgCreateInfo.pfnCallback = log_callback;')
739 func_body.append(' dbgCreateInfo.pUserData = log_output;')
740 func_body.append(' layer_create_msg_callback(my_data->report_data, &dbgCreateInfo, pAllocator,')
741 func_body.append(' &my_data->logging_callback);')
Mike Stroyan313f7e62015-08-10 16:42:53 -0600742 func_body.append(' }')
743 func_body.append('')
744 if lockname is not None:
745 func_body.append('%s' % self.lineinfo.get())
746 func_body.append(" if (!%sLockInitialized)" % lockname)
747 func_body.append(" {")
748 func_body.append(" // TODO/TBD: Need to delete this mutex sometime. How???")
749 func_body.append(" loader_platform_thread_create_mutex(&%sLock);" % lockname)
750 if condname is not None:
751 func_body.append(" loader_platform_thread_init_cond(&%sCond);" % condname)
752 func_body.append(" %sLockInitialized = 1;" % lockname)
753 func_body.append(" }")
754 func_body.append("}\n")
755 func_body.append('')
756 return "\n".join(func_body)
757
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600758class ObjectTrackerSubcommand(Subcommand):
759 def generate_header(self):
760 header_txt = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600761 header_txt.append('%s' % self.lineinfo.get())
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600762 header_txt.append('#include <stdio.h>')
763 header_txt.append('#include <stdlib.h>')
764 header_txt.append('#include <string.h>')
765 header_txt.append('#include <inttypes.h>')
766 header_txt.append('')
David Pinedo9316d3b2015-11-06 12:54:48 -0700767 header_txt.append('#include "vulkan/vulkan.h"')
Tobin Ehlisb835d1b2015-07-03 10:34:49 -0600768 header_txt.append('#include "vk_loader_platform.h"')
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600769 header_txt.append('')
Tobin Ehlis803cc492015-06-08 17:36:28 -0600770 header_txt.append('#include <unordered_map>')
771 header_txt.append('using namespace std;')
David Pinedo9316d3b2015-11-06 12:54:48 -0700772 header_txt.append('#include "vulkan/vk_layer.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -0600773 header_txt.append('#include "vk_layer_config.h"')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700774 header_txt.append('#include "vulkan/vk_ext_debug_report.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -0600775 header_txt.append('#include "vk_layer_table.h"')
776 header_txt.append('#include "vk_layer_data.h"')
777 header_txt.append('#include "vk_layer_logging.h"')
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600778 header_txt.append('')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700779# NOTE: The non-autoGenerated code is in the object_tracker.h header file
780 header_txt.append('#include "object_tracker.h"')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500781 header_txt.append('')
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -0600782 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500783 header_txt.append('')
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600784 return "\n".join(header_txt)
785
Tony Barboura05dbaa2015-07-09 17:31:46 -0600786 def generate_maps(self):
787 maps_txt = []
Tobin Ehlis86684f92016-01-05 10:33:58 -0700788 for o in vulkan.object_type_list:
Michael Lentine13803dc2015-11-04 14:35:12 -0800789 maps_txt.append('unordered_map<uint64_t, OBJTRACK_NODE*> %sMap;' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -0600790 return "\n".join(maps_txt)
791
Tobin Ehlis86684f92016-01-05 10:33:58 -0700792 def _gather_object_uses(self, obj_list, struct_type, obj_set):
793 # for each member of struct_type
794 # add objs in obj_list to obj_set
795 # call self for structs
796 for m in vk_helper.struct_dict[struct_type]:
797 if vk_helper.struct_dict[struct_type][m]['type'] in obj_list:
798 obj_set.add(vk_helper.struct_dict[struct_type][m]['type'])
799 elif vk_helper.is_type(vk_helper.struct_dict[struct_type][m]['type'], 'struct'):
800 obj_set = obj_set.union(self._gather_object_uses(obj_list, vk_helper.struct_dict[struct_type][m]['type'], obj_set))
801 return obj_set
802
Tony Barboura05dbaa2015-07-09 17:31:46 -0600803 def generate_procs(self):
804 procs_txt = []
Tobin Ehlis86684f92016-01-05 10:33:58 -0700805 # First parse through funcs and gather dict of all objects seen by each call
806 obj_use_dict = {}
807 proto_list = vulkan.core.protos + vulkan.ext_khr_surface.protos + vulkan.ext_khr_surface.protos + vulkan.ext_khr_win32_surface.protos + vulkan.ext_khr_device_swapchain.protos
808 for proto in proto_list:
809 disp_obj = proto.params[0].ty.strip('*').replace('const ', '')
810 if disp_obj in vulkan.object_dispatch_list:
811 if disp_obj not in obj_use_dict:
812 obj_use_dict[disp_obj] = set()
813 for p in proto.params[1:]:
814 base_type = p.ty.strip('*').replace('const ', '')
815 if base_type in vulkan.object_type_list:
816 obj_use_dict[disp_obj].add(base_type)
817 if vk_helper.is_type(base_type, 'struct'):
818 obj_use_dict[disp_obj] = self._gather_object_uses(vulkan.object_type_list, base_type, obj_use_dict[disp_obj])
819 #for do in obj_use_dict:
820 # print "Disp obj %s has uses for objs: %s" % (do, ', '.join(obj_use_dict[do]))
821
822 for o in vulkan.object_type_list:# vulkan.core.objects:
Tony Barboura05dbaa2015-07-09 17:31:46 -0600823 procs_txt.append('%s' % self.lineinfo.get())
Michael Lentine13803dc2015-11-04 14:35:12 -0800824 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o)
825 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Tobin Ehlis154e0462015-08-26 11:22:09 -0600826 if o in vulkan.object_dispatch_list:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700827 procs_txt.append('static void create_%s(%s dispatchable_object, %s vkObj, VkDebugReportObjectTypeEXT objType)' % (name, o, o))
Tony Barboura05dbaa2015-07-09 17:31:46 -0600828 else:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700829 procs_txt.append('static void create_%s(VkDevice dispatchable_object, %s vkObj, VkDebugReportObjectTypeEXT objType)' % (name, o))
Chia-I Wue2fc5522015-10-26 20:04:44 +0800830 procs_txt.append('{')
Mark Young93ecb1d2016-01-13 13:47:16 -0700831 procs_txt.append(' log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFO_BIT_EXT, objType,(uint64_t)(vkObj), __LINE__, OBJTRACK_NONE, "OBJTRACK",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700832 procs_txt.append(' "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64 , object_track_index++, string_VkDebugReportObjectTypeEXT(objType),')
Mark Young93ecb1d2016-01-13 13:47:16 -0700833 procs_txt.append(' (uint64_t)(vkObj));')
Tony Barboura05dbaa2015-07-09 17:31:46 -0600834 procs_txt.append('')
835 procs_txt.append(' OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE;')
836 procs_txt.append(' pNewObjNode->objType = objType;')
837 procs_txt.append(' pNewObjNode->status = OBJSTATUS_NONE;')
Mark Young93ecb1d2016-01-13 13:47:16 -0700838 procs_txt.append(' pNewObjNode->vkObj = (uint64_t)(vkObj);')
Michael Lentine13803dc2015-11-04 14:35:12 -0800839 procs_txt.append(' %sMap[(uint64_t)vkObj] = pNewObjNode;' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -0600840 procs_txt.append(' uint32_t objIndex = objTypeToIndex(objType);')
841 procs_txt.append(' numObjs[objIndex]++;')
842 procs_txt.append(' numTotalObjs++;')
843 procs_txt.append('}')
844 procs_txt.append('')
845 procs_txt.append('%s' % self.lineinfo.get())
Tobin Ehlis154e0462015-08-26 11:22:09 -0600846 if o in vulkan.object_dispatch_list:
Michael Lentine13803dc2015-11-04 14:35:12 -0800847 procs_txt.append('static void destroy_%s(%s dispatchable_object, %s object)' % (name, o, o))
Tony Barboura05dbaa2015-07-09 17:31:46 -0600848 else:
Michael Lentine13803dc2015-11-04 14:35:12 -0800849 procs_txt.append('static void destroy_%s(VkDevice dispatchable_object, %s object)' % (name, o))
Tony Barboura05dbaa2015-07-09 17:31:46 -0600850 procs_txt.append('{')
Mark Young93ecb1d2016-01-13 13:47:16 -0700851 procs_txt.append(' uint64_t object_handle = (uint64_t)(object);')
Michael Lentine13803dc2015-11-04 14:35:12 -0800852 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
853 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[(uint64_t)object];' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -0600854 procs_txt.append(' uint32_t objIndex = objTypeToIndex(pNode->objType);')
855 procs_txt.append(' assert(numTotalObjs > 0);')
856 procs_txt.append(' numTotalObjs--;')
857 procs_txt.append(' assert(numObjs[objIndex] > 0);')
858 procs_txt.append(' numObjs[objIndex]--;')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -0700859 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 -0800860 procs_txt.append(' "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%" PRIu64 " total objs remain & %" PRIu64 " %s objs).",')
Mark Young93ecb1d2016-01-13 13:47:16 -0700861 procs_txt.append(' string_VkDebugReportObjectTypeEXT(pNode->objType), (uint64_t)(object), numTotalObjs, numObjs[objIndex],')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700862 procs_txt.append(' string_VkDebugReportObjectTypeEXT(pNode->objType));')
Tony Barboura05dbaa2015-07-09 17:31:46 -0600863 procs_txt.append(' delete pNode;')
Michael Lentine13803dc2015-11-04 14:35:12 -0800864 procs_txt.append(' %sMap.erase(object_handle);' % (o))
Chia-I Wue2fc5522015-10-26 20:04:44 +0800865 procs_txt.append(' } else {')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -0700866 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 +0800867 procs_txt.append(' "Unable to remove obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?",')
Michael Lentine13803dc2015-11-04 14:35:12 -0800868 procs_txt.append(' object_handle);')
Chia-I Wue2fc5522015-10-26 20:04:44 +0800869 procs_txt.append(' }')
Tony Barboura05dbaa2015-07-09 17:31:46 -0600870 procs_txt.append('}')
871 procs_txt.append('')
872 procs_txt.append('%s' % self.lineinfo.get())
Tobin Ehlis154e0462015-08-26 11:22:09 -0600873 if o in vulkan.object_dispatch_list:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700874 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 -0600875 else:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700876 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 +0800877 procs_txt.append('{')
878 procs_txt.append(' if (object != VK_NULL_HANDLE) {')
Mark Young93ecb1d2016-01-13 13:47:16 -0700879 procs_txt.append(' uint64_t object_handle = (uint64_t)(object);')
Michael Lentine13803dc2015-11-04 14:35:12 -0800880 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
881 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[object_handle];' % (o))
Tobin Ehlis154e0462015-08-26 11:22:09 -0600882 procs_txt.append(' pNode->status |= status_flag;')
Tony Barboura05dbaa2015-07-09 17:31:46 -0600883 procs_txt.append(' }')
884 procs_txt.append(' else {')
885 procs_txt.append(' // If we do not find it print an error')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -0700886 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 +0800887 procs_txt.append(' "Unable to set status for non-existent object 0x%" PRIxLEAST64 " of %s type",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700888 procs_txt.append(' object_handle, string_VkDebugReportObjectTypeEXT(objType));')
Tony Barboura05dbaa2015-07-09 17:31:46 -0600889 procs_txt.append(' }')
890 procs_txt.append(' }')
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -0600891 procs_txt.append(' return VK_FALSE;')
Tony Barboura05dbaa2015-07-09 17:31:46 -0600892 procs_txt.append('}')
893 procs_txt.append('')
894 procs_txt.append('%s' % self.lineinfo.get())
Michael Lentine13803dc2015-11-04 14:35:12 -0800895 procs_txt.append('static VkBool32 validate_%s_status(' % (name))
Tobin Ehlis154e0462015-08-26 11:22:09 -0600896 if o in vulkan.object_dispatch_list:
Tony Barboura05dbaa2015-07-09 17:31:46 -0600897 procs_txt.append('%s dispatchable_object, %s object,' % (o, o))
898 else:
899 procs_txt.append('VkDevice dispatchable_object, %s object,' % (o))
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700900 procs_txt.append(' VkDebugReportObjectTypeEXT objType,')
Tony Barboura05dbaa2015-07-09 17:31:46 -0600901 procs_txt.append(' ObjectStatusFlags status_mask,')
902 procs_txt.append(' ObjectStatusFlags status_flag,')
903 procs_txt.append(' VkFlags msg_flags,')
904 procs_txt.append(' OBJECT_TRACK_ERROR error_code,')
905 procs_txt.append(' const char *fail_msg)')
906 procs_txt.append('{')
Mark Young93ecb1d2016-01-13 13:47:16 -0700907 procs_txt.append(' uint64_t object_handle = (uint64_t)(object);')
Michael Lentine13803dc2015-11-04 14:35:12 -0800908 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
909 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[object_handle];' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -0600910 procs_txt.append(' if ((pNode->status & status_mask) != status_flag) {')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -0700911 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 -0700912 procs_txt.append(' "OBJECT VALIDATION WARNING: %s object 0x%" PRIxLEAST64 ": %s", string_VkDebugReportObjectTypeEXT(objType),')
Michael Lentine13803dc2015-11-04 14:35:12 -0800913 procs_txt.append(' object_handle, fail_msg);')
Tony Barboura05dbaa2015-07-09 17:31:46 -0600914 procs_txt.append(' return VK_FALSE;')
915 procs_txt.append(' }')
916 procs_txt.append(' return VK_TRUE;')
917 procs_txt.append(' }')
918 procs_txt.append(' else {')
919 procs_txt.append(' // If we do not find it print an error')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -0700920 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 +0800921 procs_txt.append(' "Unable to obtain status for non-existent object 0x%" PRIxLEAST64 " of %s type",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700922 procs_txt.append(' object_handle, string_VkDebugReportObjectTypeEXT(objType));')
Tony Barboura05dbaa2015-07-09 17:31:46 -0600923 procs_txt.append(' return VK_FALSE;')
924 procs_txt.append(' }')
925 procs_txt.append('}')
926 procs_txt.append('')
927 procs_txt.append('%s' % self.lineinfo.get())
Tobin Ehlis154e0462015-08-26 11:22:09 -0600928 if o in vulkan.object_dispatch_list:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700929 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 -0600930 else:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700931 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 +0800932 procs_txt.append('{')
Mark Young93ecb1d2016-01-13 13:47:16 -0700933 procs_txt.append(' uint64_t object_handle = (uint64_t)(object);')
Michael Lentine13803dc2015-11-04 14:35:12 -0800934 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
935 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[object_handle];' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -0600936 procs_txt.append(' pNode->status &= ~status_flag;')
Tony Barboura05dbaa2015-07-09 17:31:46 -0600937 procs_txt.append(' }')
938 procs_txt.append(' else {')
939 procs_txt.append(' // If we do not find it print an error')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -0700940 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 +0800941 procs_txt.append(' "Unable to reset status for non-existent object 0x%" PRIxLEAST64 " of %s type",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700942 procs_txt.append(' object_handle, string_VkDebugReportObjectTypeEXT(objType));')
Tony Barboura05dbaa2015-07-09 17:31:46 -0600943 procs_txt.append(' }')
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -0600944 procs_txt.append(' return VK_FALSE;')
Tony Barboura05dbaa2015-07-09 17:31:46 -0600945 procs_txt.append('}')
946 procs_txt.append('')
Tobin Ehlis86684f92016-01-05 10:33:58 -0700947 procs_txt.append('%s' % self.lineinfo.get())
948 # Generate the permutations of validate_* functions where for each
949 # dispatchable object type, we have a corresponding validate_* function
950 # for that object and all non-dispatchable objects that are used in API
951 # calls with that dispatchable object.
952 procs_txt.append('//%s' % str(obj_use_dict))
953 for do in obj_use_dict:
954 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', do)
955 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
956 # First create validate_* func for disp obj
957 procs_txt.append('%s' % self.lineinfo.get())
958 procs_txt.append('static VkBool32 validate_%s(%s dispatchable_object, %s object, VkDebugReportObjectTypeEXT objType, bool null_allowed)' % (name, do, do))
959 procs_txt.append('{')
960 procs_txt.append(' if (null_allowed && (object == VK_NULL_HANDLE))')
961 procs_txt.append(' return VK_FALSE;')
962 procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (do, do))
Mark Young93ecb1d2016-01-13 13:47:16 -0700963 procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, objType, (uint64_t)(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
964 procs_txt.append(' "Invalid %s Object 0x%%" PRIx64 ,(uint64_t)(object));' % do)
Tobin Ehlis86684f92016-01-05 10:33:58 -0700965 procs_txt.append(' }')
966 procs_txt.append(' return VK_FALSE;')
967 procs_txt.append('}')
968 procs_txt.append('')
969 for o in obj_use_dict[do]:
970 if o == do: # We already generated this case above so skip here
971 continue
972 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o)
973 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
974 procs_txt.append('%s' % self.lineinfo.get())
975 procs_txt.append('static VkBool32 validate_%s(%s dispatchable_object, %s object, VkDebugReportObjectTypeEXT objType, bool null_allowed)' % (name, do, o))
976 procs_txt.append('{')
977 procs_txt.append(' if (null_allowed && (object == VK_NULL_HANDLE))')
978 procs_txt.append(' return VK_FALSE;')
979 if o == "VkImage":
980 procs_txt.append(' // We need to validate normal image objects and those from the swapchain')
981 procs_txt.append(' if ((%sMap.find((uint64_t)object) == %sMap.end()) &&' % (o, o))
982 procs_txt.append(' (swapchainImageMap.find((uint64_t)object) == swapchainImageMap.end())) {')
983 else:
984 procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (o, o))
Mark Young93ecb1d2016-01-13 13:47:16 -0700985 procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, objType, (uint64_t)(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
986 procs_txt.append(' "Invalid %s Object 0x%%" PRIx64, (uint64_t)(object));' % o)
Tobin Ehlis86684f92016-01-05 10:33:58 -0700987 procs_txt.append(' }')
988 procs_txt.append(' return VK_FALSE;')
989 procs_txt.append('}')
990 procs_txt.append('')
991 procs_txt.append('')
Tony Barboura05dbaa2015-07-09 17:31:46 -0600992 return "\n".join(procs_txt)
993
Mark Lobodzinski64d57752015-07-17 11:51:24 -0600994 def generate_destroy_instance(self):
Tony Barboura05dbaa2015-07-09 17:31:46 -0600995 gedi_txt = []
996 gedi_txt.append('%s' % self.lineinfo.get())
Mark Young93ecb1d2016-01-13 13:47:16 -0700997 gedi_txt.append('VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(')
Chia-I Wuf7458c52015-10-26 21:10:41 +0800998 gedi_txt.append('VkInstance instance,')
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800999 gedi_txt.append('const VkAllocationCallbacks* pAllocator)')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001000 gedi_txt.append('{')
1001 gedi_txt.append(' loader_platform_thread_lock_mutex(&objLock);')
Tobin Ehlis86684f92016-01-05 10:33:58 -07001002 gedi_txt.append(' validate_instance(instance, instance, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, false);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001003 gedi_txt.append('')
Michael Lentine13803dc2015-11-04 14:35:12 -08001004 gedi_txt.append(' destroy_instance(instance, instance);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001005 gedi_txt.append(' // Report any remaining objects in LL')
1006 for o in vulkan.core.objects:
Mike Stroyan0699a792015-08-18 14:48:34 -06001007 if o in ['VkInstance', 'VkPhysicalDevice', 'VkQueue']:
Tony Barboura05dbaa2015-07-09 17:31:46 -06001008 continue
1009 gedi_txt.append(' for (auto it = %sMap.begin(); it != %sMap.end(); ++it) {' % (o, o))
1010 gedi_txt.append(' OBJTRACK_NODE* pNode = it->second;')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001011 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 -07001012 gedi_txt.append(' "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),')
Tony Barbour343d6212015-07-10 18:32:33 -06001013 gedi_txt.append(' pNode->vkObj);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001014 gedi_txt.append(' }')
Mike Stroyan0699a792015-08-18 14:48:34 -06001015 gedi_txt.append(' %sMap.clear();' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001016 gedi_txt.append('')
1017 gedi_txt.append(' dispatch_key key = get_dispatch_key(instance);')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001018 gedi_txt.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(object_tracker_instance_table_map, instance);')
Chia-I Wuf7458c52015-10-26 21:10:41 +08001019 gedi_txt.append(' pInstanceTable->DestroyInstance(instance, pAllocator);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001020 gedi_txt.append('')
1021 gedi_txt.append(' // Clean up logging callback, if any')
1022 gedi_txt.append(' layer_data *my_data = get_my_data_ptr(key, layer_data_map);')
1023 gedi_txt.append(' if (my_data->logging_callback) {')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07001024 gedi_txt.append(' layer_destroy_msg_callback(my_data->report_data, my_data->logging_callback, pAllocator);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001025 gedi_txt.append(' }')
1026 gedi_txt.append('')
1027 gedi_txt.append(' layer_debug_report_destroy_instance(mid(instance));')
1028 gedi_txt.append(' layer_data_map.erase(pInstanceTable);')
1029 gedi_txt.append('')
Jon Ashburn3dc39382015-09-17 10:00:32 -06001030 gedi_txt.append(' instanceExtMap.erase(pInstanceTable);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001031 gedi_txt.append(' loader_platform_thread_unlock_mutex(&objLock);')
Mike Stroyan0699a792015-08-18 14:48:34 -06001032 # The loader holds a mutex that protects this from other threads
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001033 gedi_txt.append(' object_tracker_instance_table_map.erase(key);')
1034 gedi_txt.append(' if (object_tracker_instance_table_map.empty()) {')
Mike Stroyan0699a792015-08-18 14:48:34 -06001035 gedi_txt.append(' // Release mutex when destroying last instance.')
1036 gedi_txt.append(' loader_platform_thread_delete_mutex(&objLock);')
1037 gedi_txt.append(' objLockInitialized = 0;')
1038 gedi_txt.append(' }')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001039 gedi_txt.append('}')
1040 gedi_txt.append('')
1041 return "\n".join(gedi_txt)
1042
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001043 def generate_destroy_device(self):
Tony Barboura05dbaa2015-07-09 17:31:46 -06001044 gedd_txt = []
1045 gedd_txt.append('%s' % self.lineinfo.get())
Mark Young93ecb1d2016-01-13 13:47:16 -07001046 gedd_txt.append('VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(')
Chia-I Wuf7458c52015-10-26 21:10:41 +08001047 gedd_txt.append('VkDevice device,')
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001048 gedd_txt.append('const VkAllocationCallbacks* pAllocator)')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001049 gedd_txt.append('{')
1050 gedd_txt.append(' loader_platform_thread_lock_mutex(&objLock);')
Tobin Ehlis86684f92016-01-05 10:33:58 -07001051 gedd_txt.append(' validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001052 gedd_txt.append('')
Michael Lentine13803dc2015-11-04 14:35:12 -08001053 gedd_txt.append(' destroy_device(device, device);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001054 gedd_txt.append(' // Report any remaining objects in LL')
1055 for o in vulkan.core.objects:
Mark Lobodzinski5f5c0e12015-11-12 16:02:35 -07001056 # DescriptorSets and Command Buffers are destroyed through their pools, not explicitly
1057 if o in ['VkInstance', 'VkPhysicalDevice', 'VkQueue', 'VkDevice', 'VkDescriptorSet', 'VkCommandBuffer']:
Tony Barboura05dbaa2015-07-09 17:31:46 -06001058 continue
Mark Lobodzinski5f5c0e12015-11-12 16:02:35 -07001059 gedd_txt.append(' for (auto it = %sMap.begin(); it != %sMap.end(); ++it) {' % (o, o))
1060 gedd_txt.append(' OBJTRACK_NODE* pNode = it->second;')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001061 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 -07001062 gedd_txt.append(' "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),')
Mark Lobodzinski5f5c0e12015-11-12 16:02:35 -07001063 gedd_txt.append(' pNode->vkObj);')
1064 gedd_txt.append(' }')
Mike Stroyan0699a792015-08-18 14:48:34 -06001065 gedd_txt.append(' %sMap.clear();' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001066 gedd_txt.append('')
1067 gedd_txt.append(" // Clean up Queue's MemRef Linked Lists")
1068 gedd_txt.append(' destroyQueueMemRefLists();')
1069 gedd_txt.append('')
1070 gedd_txt.append(' loader_platform_thread_unlock_mutex(&objLock);')
1071 gedd_txt.append('')
1072 gedd_txt.append(' dispatch_key key = get_dispatch_key(device);')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001073 gedd_txt.append(' VkLayerDispatchTable *pDisp = get_dispatch_table(object_tracker_device_table_map, device);')
Chia-I Wuf7458c52015-10-26 21:10:41 +08001074 gedd_txt.append(' pDisp->DestroyDevice(device, pAllocator);')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001075 gedd_txt.append(' object_tracker_device_table_map.erase(key);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001076 gedd_txt.append('')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001077 gedd_txt.append('}')
1078 gedd_txt.append('')
1079 return "\n".join(gedd_txt)
1080
Mark Lobodzinski2fba0322016-01-23 18:31:23 -07001081 # Special-case validating some objects -- they may be non-NULL but should
1082 # only be validated upon meeting some condition specified below.
1083 def _dereference_conditionally(self, indent, prefix, type_name, name):
Mark Lobodzinski9fde6392016-01-19 09:57:24 -07001084 s_code = ''
1085 if type_name == 'pBufferInfo':
1086 s_code += '%sif ((%sdescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||\n' % (indent, prefix)
1087 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||\n' % (indent, prefix)
1088 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||\n' % (indent, prefix)
1089 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) ) {\n' % (indent, prefix)
1090 elif type_name == 'pImageInfo':
1091 s_code += '%sif ((%sdescriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) ||\n' % (indent, prefix)
1092 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||\n' % (indent, prefix)
1093 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) ||\n' % (indent, prefix)
1094 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||\n' % (indent, prefix)
1095 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ) {\n' % (indent, prefix)
1096 elif type_name == 'pTexelBufferView':
Mark Lobodzinski2fba0322016-01-23 18:31:23 -07001097 s_code += '%sif ((%sdescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) ||\n' % (indent, prefix)
1098 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) ) {\n' % (indent, prefix)
1099 elif name == 'pBeginInfo->pInheritanceInfo':
1100 s_code += '%sOBJTRACK_NODE* pNode = VkCommandBufferMap[(uint64_t)commandBuffer];\n' % (indent)
1101 s_code += '%sif ((%s) && (pNode->status & OBJSTATUS_COMMAND_BUFFER_SECONDARY)) {\n' % (indent, name)
Mark Lobodzinski9fde6392016-01-19 09:57:24 -07001102 else:
1103 s_code += '%sif (%s) {\n' % (indent, name)
1104 return s_code
1105
Tobin Ehlis86684f92016-01-05 10:33:58 -07001106 def _gen_obj_validate_code(self, struct_uses, obj_type_mapping, func_name, valid_null_dict, param0_name, indent, prefix, array_index):
1107 pre_code = ''
1108 for obj in sorted(struct_uses):
1109 name = obj
1110 array = ''
Mark Lobodzinski9fde6392016-01-19 09:57:24 -07001111 type_name = ''
Tobin Ehlis86684f92016-01-05 10:33:58 -07001112 if '[' in obj:
1113 (name, array) = obj.split('[')
Mark Lobodzinski9fde6392016-01-19 09:57:24 -07001114 type_name = name
Tobin Ehlis86684f92016-01-05 10:33:58 -07001115 array = array.strip(']')
1116 if isinstance(struct_uses[obj], dict):
1117 local_prefix = ''
1118 name = '%s%s' % (prefix, name)
1119 ptr_type = False
1120 if 'p' == obj[0]:
1121 ptr_type = True
Mark Lobodzinski2fba0322016-01-23 18:31:23 -07001122 tmp_pre = self._dereference_conditionally(indent, prefix, type_name, name)
Mark Lobodzinski9fde6392016-01-19 09:57:24 -07001123 pre_code += tmp_pre
Tobin Ehlis86684f92016-01-05 10:33:58 -07001124 indent += ' '
1125 if array != '':
1126 idx = 'idx%s' % str(array_index)
1127 array_index += 1
1128 pre_code += '%s\n' % self.lineinfo.get()
1129 pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
1130 indent += ' '
1131 local_prefix = '%s[%s].' % (name, idx)
1132 elif ptr_type:
1133 local_prefix = '%s->' % (name)
1134 else:
1135 local_prefix = '%s.' % (name)
1136 tmp_pre = self._gen_obj_validate_code(struct_uses[obj], obj_type_mapping, func_name, valid_null_dict, param0_name, indent, local_prefix, array_index)
1137 pre_code += tmp_pre
1138 if array != '':
1139 indent = indent[4:]
1140 pre_code += '%s}\n' % (indent)
1141 if ptr_type:
1142 indent = indent[4:]
1143 pre_code += '%s}\n' % (indent)
1144 else:
1145 ptype = struct_uses[obj]
1146 dbg_obj_type = obj_type_mapping[ptype]
1147 fname = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', ptype)
1148 fname = re.sub('([a-z0-9])([A-Z])', r'\1_\2', fname).lower()[3:]
1149 full_name = '%s%s' % (prefix, name)
1150 null_obj_ok = 'false'
1151 # If a valid null param is defined for this func and we have a match, allow NULL
1152 if func_name in valid_null_dict and True in [name in pn for pn in valid_null_dict[func_name]]:
1153 null_obj_ok = 'true'
1154 if (array_index > 0) or '' != array:
Mark Lobodzinski2fba0322016-01-23 18:31:23 -07001155 tmp_pre = self._dereference_conditionally(indent, prefix, type_name, full_name)
Mark Lobodzinski9fde6392016-01-19 09:57:24 -07001156 pre_code += tmp_pre
Tobin Ehlis86684f92016-01-05 10:33:58 -07001157 indent += ' '
1158 if array != '':
1159 idx = 'idx%s' % str(array_index)
1160 array_index += 1
1161 pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
1162 indent += ' '
1163 full_name = '%s[%s]' % (full_name, idx)
1164 pre_code += '%s\n' % self.lineinfo.get()
1165 pre_code += '%sskipCall |= validate_%s(%s, %s, %s, %s);\n' %(indent, fname, param0_name, full_name, dbg_obj_type, null_obj_ok)
1166 if array != '':
1167 indent = indent[4:]
1168 pre_code += '%s}\n' % (indent)
1169 indent = indent[4:]
1170 pre_code += '%s}\n' % (indent)
1171 else:
1172 pre_code += '%s\n' % self.lineinfo.get()
1173 pre_code += '%sskipCall |= validate_%s(%s, %s, %s, %s);\n' %(indent, fname, param0_name, full_name, dbg_obj_type, null_obj_ok)
1174 return pre_code
Tony Barboura05dbaa2015-07-09 17:31:46 -06001175
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -06001176 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001177 if proto.name in [ 'CreateDebugReportCallbackEXT', 'EnumerateInstanceLayerProperties', 'EnumerateInstanceExtensionProperties','EnumerateDeviceLayerProperties', 'EnumerateDeviceExtensionProperties' ]:
Mike Stroyan00087e62015-04-03 14:39:16 -06001178 # use default version
1179 return None
Mark Lobodzinski7c75b852015-05-05 15:01:37 -05001180
Tony Barboura05dbaa2015-07-09 17:31:46 -06001181 # Create map of object names to object type enums of the form VkName : VkObjectTypeName
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001182 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 -05001183 # Convert object type enum names from UpperCamelCase to UPPER_CASE_WITH_UNDERSCORES
1184 for objectName, objectTypeEnum in obj_type_mapping.items():
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001185 obj_type_mapping[objectName] = ucc_to_U_C_C(objectTypeEnum) + '_EXT';
Mark Lobodzinski7c75b852015-05-05 15:01:37 -05001186 # Command Buffer Object doesn't follow the rule.
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001187 obj_type_mapping['VkCommandBuffer'] = "VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT"
1188 obj_type_mapping['VkShaderModule'] = "VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT"
Mike Stroyan00087e62015-04-03 14:39:16 -06001189
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001190 explicit_object_tracker_functions = [
1191 "CreateInstance",
Tobin Ehlisec598302015-09-15 15:02:17 -06001192 "EnumeratePhysicalDevices",
Cody Northropd0802882015-08-03 17:04:53 -06001193 "GetPhysicalDeviceQueueFamilyProperties",
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001194 "CreateDevice",
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001195 "GetDeviceQueue",
Chia-I Wu1ff4c3d2015-10-26 16:55:27 +08001196 "QueueBindSparse",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001197 "AllocateDescriptorSets",
Tony Barbour770f80d2015-07-20 10:52:13 -06001198 "FreeDescriptorSets",
Mark Lobodzinski154329b2016-01-26 09:55:28 -07001199 "CreateGraphicsPipelines",
1200 "CreateComputePipelines",
Mark Lobodzinski5f5c0e12015-11-12 16:02:35 -07001201 "AllocateCommandBuffers",
1202 "FreeCommandBuffers",
1203 "DestroyDescriptorPool",
1204 "DestroyCommandPool",
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001205 "MapMemory",
1206 "UnmapMemory",
1207 "FreeMemory",
Mark Lobodzinskie6d3f2c2015-10-14 13:16:33 -06001208 "DestroySwapchainKHR",
1209 "GetSwapchainImagesKHR"
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001210 ]
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001211 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyan00087e62015-04-03 14:39:16 -06001212 param0_name = proto.params[0].name
Mark Lobodzinski48bd16d2015-05-08 09:12:28 -05001213 using_line = ''
Mike Stroyan00087e62015-04-03 14:39:16 -06001214 create_line = ''
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001215 destroy_line = ''
Tobin Ehlis154e0462015-08-26 11:22:09 -06001216 # 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
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07001217 # TODO : Should integrate slightly better code for this purpose from unique_objects layer
Tobin Ehlis154e0462015-08-26 11:22:09 -06001218 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 -08001219 loop_types = defaultdict(list)
Tobin Ehlis2717d132015-07-10 18:25:07 -06001220 # 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 -06001221 # or better yet, these should be encoded into an API json definition and we generate checks from there
1222 # 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)
1223 # param names may be directly passed to the function, or may be a field in a struct param
1224 valid_null_object_names = {'CreateGraphicsPipelines' : ['basePipelineHandle'],
1225 'CreateComputePipelines' : ['basePipelineHandle'],
1226 'BeginCommandBuffer' : ['renderPass', 'framebuffer'],
Tobin Ehlisec598302015-09-15 15:02:17 -06001227 'QueueSubmit' : ['fence'],
Jon Ashburn9216ae42016-01-14 15:11:55 -07001228 'AcquireNextImageKHR' : ['fence', 'semaphore' ],
Tobin Ehlisba31cab2015-11-02 15:24:32 -07001229 'UpdateDescriptorSets' : ['pTexelBufferView'],
Tobin Ehlis86684f92016-01-05 10:33:58 -07001230 'CreateSwapchainKHR' : ['oldSwapchain'],
Tobin Ehlis154e0462015-08-26 11:22:09 -06001231 }
Tobin Ehlis154e0462015-08-26 11:22:09 -06001232 param_count = 'NONE' # keep track of arrays passed directly into API functions
Tobin Ehlis803cc492015-06-08 17:36:28 -06001233 for p in proto.params:
Tobin Ehlisec598302015-09-15 15:02:17 -06001234 base_type = p.ty.replace('const ', '').strip('*')
Tobin Ehlis154e0462015-08-26 11:22:09 -06001235 if 'count' in p.name.lower():
1236 param_count = p.name
Tobin Ehlisec598302015-09-15 15:02:17 -06001237 if base_type in vulkan.core.objects:
1238 # This is an object to potentially check for validity. First see if it's an array
1239 if '*' in p.ty and 'const' in p.ty and param_count != 'NONE':
1240 loop_params[param_count].append(p.name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001241 loop_types[param_count].append(str(p.ty[6:-1]))
Tobin Ehlisec598302015-09-15 15:02:17 -06001242 # Not an array, check for just a base Object that's not in exceptions
1243 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 -06001244 loop_params[0].append(p.name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001245 loop_types[0].append(str(p.ty))
Tobin Ehlisec598302015-09-15 15:02:17 -06001246 elif vk_helper.is_type(base_type, 'struct'):
1247 struct_type = base_type
Tobin Ehlis9d675942015-06-30 14:32:16 -06001248 if vk_helper.typedef_rev_dict[struct_type] in vk_helper.struct_dict:
1249 struct_type = vk_helper.typedef_rev_dict[struct_type]
Tobin Ehlis82b3db52015-10-23 17:52:53 -06001250 # Parse elements of this struct param to identify objects and/or arrays of objects
Tobin Ehlis9d675942015-06-30 14:32:16 -06001251 for m in sorted(vk_helper.struct_dict[struct_type]):
1252 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 -06001253 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 -06001254 # This is not great, but gets the job done for now, but If we have a count and this param is a ptr w/
1255 # last letter 's' OR non-'count' string of count is in the param name, then this is a dynamically sized array param
1256 param_array = False
1257 if param_count != 'NONE':
1258 if '*' in p.ty:
1259 if 's' == p.name[-1] or param_count.lower().replace('count', '') in p.name.lower():
1260 param_array = True
1261 if param_array:
Tobin Ehlis154e0462015-08-26 11:22:09 -06001262 param_name = '%s[i].%s' % (p.name, vk_helper.struct_dict[struct_type][m]['name'])
Tobin Ehlis46d53622015-07-10 11:10:21 -06001263 else:
Tobin Ehlis154e0462015-08-26 11:22:09 -06001264 param_name = '%s->%s' % (p.name, vk_helper.struct_dict[struct_type][m]['name'])
1265 if vk_helper.struct_dict[struct_type][m]['dyn_array']:
Tobin Ehlis82b3db52015-10-23 17:52:53 -06001266 if param_count != 'NONE': # this will be a double-embedded loop, use comma delineated 'count,name' for param_name
1267 loop_count = '%s[i].%s' % (p.name, vk_helper.struct_dict[struct_type][m]['array_size'])
1268 loop_params[param_count].append('%s,%s' % (loop_count, param_name))
Michael Lentine13803dc2015-11-04 14:35:12 -08001269 loop_types[param_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Tobin Ehlis82b3db52015-10-23 17:52:53 -06001270 else:
1271 loop_count = '%s->%s' % (p.name, vk_helper.struct_dict[struct_type][m]['array_size'])
1272 loop_params[loop_count].append(param_name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001273 loop_types[loop_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Tobin Ehlis154e0462015-08-26 11:22:09 -06001274 else:
1275 if '[' in param_name: # dynamic array param, set size
1276 loop_params[param_count].append(param_name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001277 loop_types[param_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Tobin Ehlis154e0462015-08-26 11:22:09 -06001278 else:
1279 loop_params[0].append(param_name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001280 loop_types[0].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Tobin Ehlis86684f92016-01-05 10:33:58 -07001281 last_param_index = None
1282 create_func = False
1283 if True in [create_txt in proto.name for create_txt in ['Create', 'Allocate']]:
1284 create_func = True
1285 last_param_index = -1 # For create funcs don't validate last object
1286 struct_uses = get_object_uses(vulkan.object_type_list, proto.params[:last_param_index])
Mike Stroyan00087e62015-04-03 14:39:16 -06001287 funcs = []
Tobin Ehlis803cc492015-06-08 17:36:28 -06001288 mutex_unlock = False
Tobin Ehlis154e0462015-08-26 11:22:09 -06001289 funcs.append('%s\n' % self.lineinfo.get())
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001290 if proto.name in explicit_object_tracker_functions:
Jon Ashburn4d9f4652015-04-08 21:33:34 -06001291 funcs.append('%s%s\n'
1292 '{\n'
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001293 ' return explicit_%s;\n'
1294 '}' % (qual, decl, proto.c_call()))
1295 return "".join(funcs)
Mark Lobodzinski308d7792015-11-24 10:28:31 -07001296 # Temporarily prevent DestroySurface call from being generated until WSI layer support is fleshed out
Mark Lobodzinski882655d2016-01-05 11:32:53 -07001297 elif 'DestroyInstance' in proto.name or 'DestroyDevice' in proto.name:
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001298 return ""
Jon Ashburn4d9f4652015-04-08 21:33:34 -06001299 else:
Tobin Ehlis86684f92016-01-05 10:33:58 -07001300 if create_func:
Michael Lentine13803dc2015-11-04 14:35:12 -08001301 typ = proto.params[-1].ty.strip('*').replace('const ', '');
1302 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1303 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001304 create_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
1305 create_line += ' if (result == VK_SUCCESS) {\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08001306 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 -06001307 create_line += ' }\n'
1308 create_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06001309 if 'FreeCommandBuffers' in proto.name:
Michael Lentine13803dc2015-11-04 14:35:12 -08001310 typ = proto.params[-1].ty.strip('*').replace('const ', '');
1311 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1312 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06001313 funcs.append('%s\n' % self.lineinfo.get())
1314 destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Chia-I Wud50a7d72015-10-26 20:48:51 +08001315 destroy_line += ' for (uint32_t i = 0; i < commandBufferCount; i++) {\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08001316 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 -06001317 destroy_line += ' }\n'
1318 destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001319 if 'Destroy' in proto.name:
Michael Lentine13803dc2015-11-04 14:35:12 -08001320 typ = proto.params[-2].ty.strip('*').replace('const ', '');
1321 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1322 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06001323 funcs.append('%s\n' % self.lineinfo.get())
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001324 destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08001325 destroy_line += ' destroy_%s(%s, %s);\n' % (name, param0_name, proto.params[-2].name)
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001326 destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Tobin Ehlis86684f92016-01-05 10:33:58 -07001327 indent = ' '
1328 if len(struct_uses) > 0:
1329 using_line += '%sVkBool32 skipCall = VK_FALSE;\n' % (indent)
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001330 if not mutex_unlock:
Tobin Ehlis86684f92016-01-05 10:33:58 -07001331 using_line += '%sloader_platform_thread_lock_mutex(&objLock);\n' % (indent)
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001332 mutex_unlock = True
Tobin Ehlis86684f92016-01-05 10:33:58 -07001333 using_line += '// objects to validate: %s\n' % str(struct_uses)
1334 using_line += self._gen_obj_validate_code(struct_uses, obj_type_mapping, proto.name, valid_null_object_names, param0_name, ' ', '', 0)
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001335 if mutex_unlock:
Tobin Ehlis86684f92016-01-05 10:33:58 -07001336 using_line += '%sloader_platform_thread_unlock_mutex(&objLock);\n' % (indent)
1337 if len(struct_uses) > 0:
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -06001338 using_line += ' if (skipCall)\n'
1339 if proto.ret != "void":
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07001340 using_line += ' return VK_ERROR_VALIDATION_FAILED_EXT;\n'
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -06001341 else:
1342 using_line += ' return;\n'
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001343 ret_val = ''
1344 stmt = ''
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001345 if proto.ret != "void":
1346 ret_val = "%s result = " % proto.ret
1347 stmt = " return result;\n"
1348
1349 dispatch_param = proto.params[0].name
1350 if 'CreateInstance' in proto.name:
1351 dispatch_param = '*' + proto.params[1].name
1352
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001353 # Must use 'instance' table for these APIs, 'device' table otherwise
1354 table_type = ""
1355 if proto_is_global(proto):
1356 table_type = "instance"
1357 else:
1358 table_type = "device"
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001359 if wsi_name(proto.name):
1360 funcs.append('%s' % wsi_ifdef(proto.name))
Mike Stroyan00087e62015-04-03 14:39:16 -06001361 funcs.append('%s%s\n'
1362 '{\n'
1363 '%s'
Mike Stroyan00087e62015-04-03 14:39:16 -06001364 '%s'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001365 ' %sget_dispatch_table(object_tracker_%s_table_map, %s)->%s;\n'
Mike Stroyan38820b32015-09-28 13:47:29 -06001366 '%s'
1367 '%s'
1368 '}' % (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 -07001369 if wsi_name(proto.name):
1370 funcs.append('%s' % wsi_endif(proto.name))
Mike Stroyan00087e62015-04-03 14:39:16 -06001371 return "\n\n".join(funcs)
1372
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001373 def generate_body(self):
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001374 self.layer_name = "object_tracker"
Ian Elliott1064fe32015-07-06 14:31:32 -06001375 extensions=[('wsi_enabled',
Ian Elliott05846062015-11-20 14:13:17 -07001376 ['vkCreateSwapchainKHR',
Jon Ashburn8acd2332015-09-16 18:08:32 -06001377 'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
1378 'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001379 if sys.platform.startswith('win32'):
Michael Lentine64e2ebd2015-12-03 14:33:09 -08001380 instance_extensions=[('msg_callback_get_proc_addr', []),
1381 ('wsi_enabled',
1382 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1383 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1384 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1385 'vkGetPhysicalDeviceSurfacePresentModesKHR',
1386 'vkCreateWin32SurfaceKHR',
1387 'vkGetPhysicalDeviceWin32PresentationSupportKHR'])]
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001388 elif sys.platform.startswith('linux'):
Michael Lentine64e2ebd2015-12-03 14:33:09 -08001389 instance_extensions=[('msg_callback_get_proc_addr', []),
1390 ('wsi_enabled',
1391 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1392 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1393 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1394 'vkGetPhysicalDeviceSurfacePresentModesKHR',
1395 'vkCreateXcbSurfaceKHR',
Mark Lobodzinskib49b6e52015-11-26 10:59:58 -07001396 'vkGetPhysicalDeviceXcbPresentationSupportKHR'])]
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001397 # TODO: Add cases for Mir, Wayland and Xlib
1398 else: # android
1399 instance_extensions=[('msg_callback_get_proc_addr', []),
1400 ('wsi_enabled',
1401 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1402 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1403 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1404 'vkGetPhysicalDeviceSurfacePresentModesKHR'])]
Tony Barboura05dbaa2015-07-09 17:31:46 -06001405 body = [self.generate_maps(),
1406 self.generate_procs(),
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001407 self.generate_destroy_instance(),
1408 self.generate_destroy_device(),
Tony Barboura05dbaa2015-07-09 17:31:46 -06001409 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Tobin Ehlisca915872014-11-18 11:28:33 -07001410 self._generate_extensions(),
Jon Ashburn747f2b62015-06-18 15:02:58 -06001411 self._generate_layer_gpa_function(extensions,
Jon Ashburn3dc39382015-09-17 10:00:32 -06001412 instance_extensions)]
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001413 return "\n\n".join(body)
Courtney Goeltzenleuchterb412d212014-11-18 10:40:29 -07001414
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07001415class UniqueObjectsSubcommand(Subcommand):
1416 def generate_header(self):
1417 header_txt = []
1418 header_txt.append('%s' % self.lineinfo.get())
1419 header_txt.append('#include "unique_objects.h"')
1420 header_txt.append('')
1421 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
1422 return "\n".join(header_txt)
1423
Tobin Ehlis65f44e42016-01-05 09:46:03 -07001424 # Generate UniqueObjects code for given struct_uses dict of objects that need to be unwrapped
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07001425 # vector_name_set is used to make sure we don't replicate vector names
1426 # first_level_param indicates if elements are passed directly into the function else they're below a ptr/struct
Tobin Ehlis65f44e42016-01-05 09:46:03 -07001427 # TODO : Comment this code
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07001428 def _gen_obj_code(self, struct_uses, indent, prefix, array_index, vector_name_set, first_level_param):
Tobin Ehlis65f44e42016-01-05 09:46:03 -07001429 decls = ''
1430 pre_code = ''
1431 post_code = ''
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07001432 for obj in sorted(struct_uses):
Tobin Ehlis65f44e42016-01-05 09:46:03 -07001433 name = obj
1434 array = ''
1435 if '[' in obj:
1436 (name, array) = obj.split('[')
1437 array = array.strip(']')
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07001438 ptr_type = False
Tobin Ehlis991d45a2016-01-06 08:48:41 -07001439 if 'p' == obj[0] and obj[1] != obj[1].lower(): # TODO : Not idea way to determine ptr
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07001440 ptr_type = True
Tobin Ehlis65f44e42016-01-05 09:46:03 -07001441 if isinstance(struct_uses[obj], dict):
1442 local_prefix = ''
1443 name = '%s%s' % (prefix, name)
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07001444 if ptr_type:
Tobin Ehlis65f44e42016-01-05 09:46:03 -07001445 pre_code += '%sif (%s) {\n' % (indent, name)
1446 post_code += '%sif (%s) {\n' % (indent, name)
1447 indent += ' '
1448 if array != '':
1449 idx = 'idx%s' % str(array_index)
1450 array_index += 1
1451 pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
1452 post_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
1453 indent += ' '
1454 local_prefix = '%s[%s].' % (name, idx)
1455 elif ptr_type:
1456 local_prefix = '%s->' % (name)
1457 else:
1458 local_prefix = '%s.' % (name)
1459 assert isinstance(decls, object)
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07001460 (tmp_decl, tmp_pre, tmp_post) = self._gen_obj_code(struct_uses[obj], indent, local_prefix, array_index, vector_name_set, False)
Tobin Ehlis65f44e42016-01-05 09:46:03 -07001461 decls += tmp_decl
1462 pre_code += tmp_pre
1463 post_code += tmp_post
1464 if array != '':
1465 indent = indent[4:]
1466 pre_code += '%s}\n' % (indent)
1467 post_code += '%s}\n' % (indent)
1468 if ptr_type:
1469 indent = indent[4:]
1470 pre_code += '%s}\n' % (indent)
1471 post_code += '%s}\n' % (indent)
1472 else:
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07001473 if (array_index > 0) or array != '': # TODO : This is not ideal, really want to know if we're anywhere under an array
Tobin Ehlis65f44e42016-01-05 09:46:03 -07001474 pre_code += '%sif (%s%s) {\n' %(indent, prefix, name)
1475 post_code += '%sif (%s%s) {\n' %(indent, prefix, name)
1476 indent += ' '
1477 # Append unique_count to make sure name is unique (some aliasing for "buffer" and "image" names
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07001478 vec_name = 'original_%s' % (name)
Tobin Ehlis65f44e42016-01-05 09:46:03 -07001479 if array != '':
1480 idx = 'idx%s' % str(array_index)
1481 array_index += 1
1482 pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
1483 post_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
1484 indent += ' '
1485 name = '%s[%s]' % (name, idx)
1486 pName = 'p%s' % (struct_uses[obj][2:])
1487 pre_code += '%s%s* %s = (%s*)&(%s%s);\n' % (indent, struct_uses[obj], pName, struct_uses[obj], prefix, name)
1488 post_code += '%s%s* %s = (%s*)&(%s%s);\n' % (indent, struct_uses[obj], pName, struct_uses[obj], prefix, name)
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07001489 if name not in vector_name_set:
1490 vector_name_set.add(name)
1491 decls += ' std::vector<%s> %s = {};\n' % (struct_uses[obj], vec_name)
Tobin Ehlis65f44e42016-01-05 09:46:03 -07001492 pre_code += '%s%s.push_back(%s%s);\n' % (indent, vec_name, prefix, name)
1493 pre_code += '%s*(%s) = (%s)((VkUniqueObject*)%s%s)->actualObject;\n' % (indent, pName, struct_uses[obj], prefix, name)
1494 post_code += '%s*(%s) = %s.front();\n' % (indent, pName, vec_name)
1495 post_code += '%s%s.erase(%s.begin());\n' % (indent, vec_name, vec_name)
1496 if array != '':
1497 indent = indent[4:]
1498 pre_code += '%s}\n' % (indent)
1499 post_code += '%s}\n' % (indent)
1500 indent = indent[4:]
1501 pre_code += '%s}\n' % (indent)
1502 post_code += '%s}\n' % (indent)
1503 else:
1504 pre_code += '%sif (%s%s) {\n' %(indent, prefix, name)
1505 indent += ' '
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07001506 deref_txt = '&'
1507 if ptr_type:
1508 deref_txt = ''
1509 pre_code += '%s%s* p%s = (%s*)%s%s%s;\n' % (indent, struct_uses[obj], name, struct_uses[obj], deref_txt, prefix, name)
Tobin Ehlis65f44e42016-01-05 09:46:03 -07001510 pre_code += '%s*p%s = (%s)((VkUniqueObject*)%s%s)->actualObject;\n' % (indent, name, struct_uses[obj], prefix, name)
1511 indent = indent[4:]
1512 pre_code += '%s}\n' % (indent)
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07001513 if not first_level_param: # embedded in a ptr/struct so need to undo the update
Tobin Ehlis1ac05592016-01-29 09:24:46 -07001514 if '->' in prefix:
1515 # Since this variable is embedded under a ptr, need to decl up front, but wait
1516 # to assign it inside of the "if" block(s) for surrounding ptr(s)
1517 decls += ' %s local_%s = VK_NULL_HANDLE;\n' % (struct_uses[obj], name)
1518 pre_code = '%slocal_%s = %s%s;\n%s' % (indent, name, prefix, name, pre_code)
1519 else:
1520 decls += ' %s local_%s = %s%s;\n' % (struct_uses[obj], name, prefix, name)
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07001521 post_code += '%sif (%s%s) {\n' %(indent, prefix, name)
1522 post_code += '%s %s* p%s = (%s*)%s%s%s;\n' % (indent, struct_uses[obj], name, struct_uses[obj], deref_txt, prefix, name)
1523 post_code += '%s *p%s = local_%s;\n' % (indent, name, name)
1524 post_code += '%s}\n' % (indent)
Tobin Ehlis65f44e42016-01-05 09:46:03 -07001525 return decls, pre_code, post_code
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07001526
1527 def generate_intercept(self, proto, qual):
1528 create_func = False
1529 destroy_func = False
1530 last_param_index = None #typcially we look at all params for ndos
1531 pre_call_txt = '' # code prior to calling down chain such as unwrap uses of ndos
1532 post_call_txt = '' # code following call down chain such to wrap newly created ndos, or destroy local wrap struct
1533 funcs = []
1534 indent = ' ' # indent level for generated code
1535 decl = proto.c_func(prefix="vk", attr="VKAPI")
Tobin Ehlis65f44e42016-01-05 09:46:03 -07001536 # A few API cases that are manual code
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07001537 # TODO : Special case Create*Pipelines funcs to handle creating multiple unique objects
Tobin Ehlis65f44e42016-01-05 09:46:03 -07001538 explicit_object_tracker_functions = ['GetSwapchainImagesKHR',
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07001539 'CreateInstance',
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07001540 'CreateDevice',
1541 'CreateComputePipelines',
1542 'CreateGraphicsPipelines']
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07001543 # Give special treatment to create functions that return multiple new objects
1544 # This dict stores array name and size of array
Jon Ashburnf19916e2016-01-11 13:12:43 -07001545 custom_create_dict = {'pDescriptorSets' : 'pAllocateInfo->descriptorSetCount'}
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07001546 if proto.name in explicit_object_tracker_functions:
1547 funcs.append('%s%s\n'
1548 '{\n'
1549 ' return explicit_%s;\n'
1550 '}' % (qual, decl, proto.c_call()))
1551 return "".join(funcs)
1552 if True in [create_txt in proto.name for create_txt in ['Create', 'Allocate']]:
1553 create_func = True
1554 last_param_index = -1 # For create funcs don't care if last param is ndo
1555 if True in [destroy_txt in proto.name for destroy_txt in ['Destroy', 'Free']]:
1556 destroy_obj_type = proto.params[-2].ty
1557 if destroy_obj_type in vulkan.object_non_dispatch_list:
1558 destroy_func = True
1559
Tobin Ehlis65f44e42016-01-05 09:46:03 -07001560 # First thing we need to do is gather uses of non-dispatchable-objects (ndos)
1561 struct_uses = get_object_uses(vulkan.object_non_dispatch_list, proto.params[1:last_param_index])
1562
1563 if len(struct_uses) > 0:
1564 pre_call_txt += '// STRUCT USES:%s\n' % struct_uses
1565 if destroy_func: # only one object
1566 for del_obj in struct_uses:
1567 pre_call_txt += '%s%s local_%s = %s;\n' % (indent, struct_uses[del_obj], del_obj, del_obj)
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07001568 (pre_decl, pre_code, post_code) = self._gen_obj_code(struct_uses, ' ', '', 0, set(), True)
Tobin Ehlis65f44e42016-01-05 09:46:03 -07001569 pre_call_txt += '%s%s' % (pre_decl, pre_code)
1570 post_call_txt += post_code
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07001571 elif create_func:
1572 base_type = proto.params[-1].ty.replace('const ', '').strip('*')
1573 if base_type not in vulkan.object_non_dispatch_list:
1574 return None
1575 else:
1576 return None
1577
1578 ret_val = ''
1579 ret_stmt = ''
1580 if proto.ret != "void":
1581 ret_val = "%s result = " % proto.ret
1582 ret_stmt = " return result;\n"
1583 dispatch_param = proto.params[0].name
1584 if 'CreateInstance' in proto.name:
1585 dispatch_param = '*' + proto.params[1].name
1586 if create_func:
1587 obj_type = proto.params[-1].ty.strip('*')
1588 obj_name = proto.params[-1].name
1589 if obj_type in vulkan.object_non_dispatch_list:
1590 local_name = "unique%s" % obj_type[2:]
1591 post_call_txt += '%sif (VK_SUCCESS == result) {\n' % (indent)
1592 indent += ' '
1593 if obj_name in custom_create_dict:
1594 post_call_txt += '%s\n' % (self.lineinfo.get())
1595 local_name = '%ss' % (local_name) # add 's' to end for vector of many
1596 post_call_txt += '%sstd::vector<VkUniqueObject*> %s = {};\n' % (indent, local_name)
1597 post_call_txt += '%sfor (uint32_t i=0; i<%s; ++i) {\n' % (indent, custom_create_dict[obj_name])
1598 indent += ' '
1599 post_call_txt += '%s%s.push_back(new VkUniqueObject());\n' % (indent, local_name)
1600 post_call_txt += '%s%s[i]->actualObject = (uint64_t)%s[i];\n' % (indent, local_name, obj_name)
1601 post_call_txt += '%s%s[i] = (%s)%s[i];\n' % (indent, obj_name, obj_type, local_name)
1602 indent = indent[4:]
1603 post_call_txt += '%s}\n' % (indent)
1604 else:
1605 post_call_txt += '%s\n' % (self.lineinfo.get())
1606 post_call_txt += '%sVkUniqueObject* %s = new VkUniqueObject();\n' % (indent, local_name)
1607 post_call_txt += '%s%s->actualObject = (uint64_t)*%s;\n' % (indent, local_name, obj_name)
1608 post_call_txt += '%s*%s = (%s)%s;\n' % (indent, obj_name, obj_type, local_name)
1609 indent = indent[4:]
1610 post_call_txt += '%s}\n' % (indent)
1611 elif destroy_func:
1612 del_obj = proto.params[-2].name
1613 if 'count' in del_obj.lower():
1614 post_call_txt += '%s\n' % (self.lineinfo.get())
1615 post_call_txt += '%sfor (uint32_t i=0; i<%s; ++i) {\n' % (indent, del_obj)
1616 del_obj = proto.params[-1].name
1617 indent += ' '
1618 post_call_txt += '%sdelete (VkUniqueObject*)%s[i];\n' % (indent, del_obj)
1619 indent = indent[4:]
1620 post_call_txt += '%s}\n' % (indent)
1621 else:
1622 post_call_txt += '%s\n' % (self.lineinfo.get())
1623 post_call_txt = '%sdelete (VkUniqueObject*)local_%s;\n' % (indent, proto.params[-2].name)
1624
1625 call_sig = proto.c_call()
1626 if proto_is_global(proto):
1627 table_type = "instance"
1628 else:
1629 table_type = "device"
1630 pre_call_txt += '%s\n' % (self.lineinfo.get())
1631 funcs.append('%s%s\n'
1632 '{\n'
1633 '%s'
1634 ' %sget_dispatch_table(unique_objects_%s_table_map, %s)->%s;\n'
1635 '%s'
1636 '%s'
1637 '}' % (qual, decl, pre_call_txt, ret_val, table_type, dispatch_param, call_sig, post_call_txt, ret_stmt))
1638 return "\n\n".join(funcs)
1639
1640 def generate_body(self):
1641 self.layer_name = "unique_objects"
1642 extensions=[('wsi_enabled',
1643 ['vkCreateSwapchainKHR',
1644 'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
1645 'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
1646 if sys.platform.startswith('win32'):
1647 instance_extensions=[('wsi_enabled',
1648 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1649 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1650 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1651 'vkGetPhysicalDeviceSurfacePresentModesKHR',
Jon Ashburn00dc7412016-01-07 16:13:06 -07001652 'vkCreateWin32SurfaceKHR'
1653 ])]
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07001654 elif sys.platform.startswith('linux'):
1655 instance_extensions=[('wsi_enabled',
1656 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1657 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1658 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1659 'vkGetPhysicalDeviceSurfacePresentModesKHR',
Jon Ashburn00dc7412016-01-07 16:13:06 -07001660 'vkCreateXcbSurfaceKHR'
1661 ])]
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07001662 # TODO: Add cases for Mir, Wayland and Xlib
1663 else: # android
1664 instance_extensions=[('wsi_enabled',
1665 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1666 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1667 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1668 'vkGetPhysicalDeviceSurfacePresentModesKHR'])]
1669 body = [self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
1670 self._generate_layer_gpa_function(extensions,
1671 instance_extensions)]
1672 return "\n\n".join(body)
1673
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001674class ThreadingSubcommand(Subcommand):
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001675 thread_check_dispatchable_objects = [
1676 "VkQueue",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001677 "VkCommandBuffer",
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001678 ]
1679 thread_check_nondispatchable_objects = [
1680 "VkDeviceMemory",
1681 "VkBuffer",
1682 "VkImage",
1683 "VkDescriptorSet",
1684 "VkDescriptorPool",
1685 "VkSemaphore"
1686 ]
Mike Stroyan313f7e62015-08-10 16:42:53 -06001687 thread_check_object_types = {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001688 'VkInstance' : 'VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT',
1689 'VkPhysicalDevice' : 'VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT',
1690 'VkDevice' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT',
1691 'VkQueue' : 'VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT',
1692 'VkCommandBuffer' : 'VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT',
1693 'VkFence' : 'VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT',
1694 'VkDeviceMemory' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT',
1695 'VkBuffer' : 'VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT',
1696 'VkImage' : 'VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT',
1697 'VkSemaphore' : 'VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT',
1698 'VkEvent' : 'VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT',
1699 'VkQueryPool' : 'VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT',
1700 'VkBufferView' : 'VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT',
1701 'VkImageView' : 'VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT',
1702 'VkShaderModule' : 'VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT',
1703 'VkShader' : 'VK_DEBUG_REPORT_OBJECT_TYPE_SHADER',
1704 'VkPipelineCache' : 'VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT',
1705 'VkPipelineLayout' : 'VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT',
1706 'VkRenderPass' : 'VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT',
1707 'VkPipeline' : 'VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT',
1708 'VkDescriptorSetLayout' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT',
1709 'VkSampler' : 'VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT',
1710 'VkDescriptorPool' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT',
1711 'VkDescriptorSet' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT',
1712 'VkFramebuffer' : 'VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT',
1713 'VkCommandPool' : 'VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT',
Mike Stroyan313f7e62015-08-10 16:42:53 -06001714 }
1715 def generate_useObject(self, ty):
1716 obj_type = self.thread_check_object_types[ty]
Chia-I Wue2fc5522015-10-26 20:04:44 +08001717 key = "object"
Mark Young93ecb1d2016-01-13 13:47:16 -07001718 msg_object = "(uint64_t)(object)"
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001719 header_txt = []
1720 header_txt.append('%s' % self.lineinfo.get())
Michael Lentine13803dc2015-11-04 14:35:12 -08001721 header_txt.append('static void use%s(const void* dispatchable_object, %s object)' % (ty, ty))
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001722 header_txt.append('{')
1723 header_txt.append(' loader_platform_thread_id tid = loader_platform_get_thread_id();')
1724 header_txt.append(' loader_platform_thread_lock_mutex(&threadingLock);')
1725 header_txt.append(' if (%sObjectsInUse.find(%s) == %sObjectsInUse.end()) {' % (ty, key, ty))
1726 header_txt.append(' %sObjectsInUse[%s] = tid;' % (ty, key))
1727 header_txt.append(' } else {')
1728 header_txt.append(' if (%sObjectsInUse[%s] != tid) {' % (ty, key))
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001729 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 -07001730 header_txt.append(' __LINE__, THREADING_CHECKER_MULTIPLE_THREADS, "THREADING",')
Mike Stroyan313f7e62015-08-10 16:42:53 -06001731 header_txt.append(' "THREADING ERROR : object of type %s is simultaneously used in thread %%ld and thread %%ld",' % (ty))
1732 header_txt.append(' %sObjectsInUse[%s], tid);' % (ty, key))
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001733 header_txt.append(' // Wait for thread-safe access to object')
1734 header_txt.append(' while (%sObjectsInUse.find(%s) != %sObjectsInUse.end()) {' % (ty, key, ty))
1735 header_txt.append(' loader_platform_thread_cond_wait(&threadingCond, &threadingLock);')
1736 header_txt.append(' }')
1737 header_txt.append(' %sObjectsInUse[%s] = tid;' % (ty, key))
1738 header_txt.append(' } else {')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001739 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 -07001740 header_txt.append(' __LINE__, THREADING_CHECKER_MULTIPLE_THREADS, "THREADING",')
Mike Stroyan313f7e62015-08-10 16:42:53 -06001741 header_txt.append(' "THREADING ERROR : object of type %s is recursively used in thread %%ld",' % (ty))
1742 header_txt.append(' tid);')
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001743 header_txt.append(' }')
1744 header_txt.append(' }')
1745 header_txt.append(' loader_platform_thread_unlock_mutex(&threadingLock);')
1746 header_txt.append('}')
1747 return "\n".join(header_txt)
Mike Stroyan313f7e62015-08-10 16:42:53 -06001748 def generate_finishUsingObject(self, ty):
Chia-I Wue2fc5522015-10-26 20:04:44 +08001749 key = "object"
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001750 header_txt = []
1751 header_txt.append('%s' % self.lineinfo.get())
Michael Lentine13803dc2015-11-04 14:35:12 -08001752 header_txt.append('static void finishUsing%s(%s object)' % (ty, ty))
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001753 header_txt.append('{')
1754 header_txt.append(' // Object is no longer in use')
1755 header_txt.append(' loader_platform_thread_lock_mutex(&threadingLock);')
1756 header_txt.append(' %sObjectsInUse.erase(%s);' % (ty, key))
1757 header_txt.append(' loader_platform_thread_cond_broadcast(&threadingCond);')
1758 header_txt.append(' loader_platform_thread_unlock_mutex(&threadingLock);')
1759 header_txt.append('}')
1760 return "\n".join(header_txt)
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001761 def generate_header(self):
1762 header_txt = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001763 header_txt.append('%s' % self.lineinfo.get())
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001764 header_txt.append('#include <stdio.h>')
1765 header_txt.append('#include <stdlib.h>')
1766 header_txt.append('#include <string.h>')
1767 header_txt.append('#include <unordered_map>')
Tobin Ehlisb835d1b2015-07-03 10:34:49 -06001768 header_txt.append('#include "vk_loader_platform.h"')
David Pinedo9316d3b2015-11-06 12:54:48 -07001769 header_txt.append('#include "vulkan/vk_layer.h"')
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001770 header_txt.append('#include "threading.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -06001771 header_txt.append('#include "vk_layer_config.h"')
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -06001772 header_txt.append('#include "vk_layer_extension_utils.h"')
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001773 header_txt.append('#include "vk_enum_validate_helper.h"')
1774 header_txt.append('#include "vk_struct_validate_helper.h"')
Mike Stroyan313f7e62015-08-10 16:42:53 -06001775 header_txt.append('#include "vk_layer_table.h"')
1776 header_txt.append('#include "vk_layer_logging.h"')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001777 header_txt.append('')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001778 header_txt.append('')
1779 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
1780 header_txt.append('')
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001781 header_txt.append('using namespace std;')
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001782 for ty in self.thread_check_dispatchable_objects:
1783 header_txt.append('static unordered_map<%s, loader_platform_thread_id> %sObjectsInUse;' % (ty, ty))
1784 for ty in self.thread_check_nondispatchable_objects:
Chia-I Wue2fc5522015-10-26 20:04:44 +08001785 header_txt.append('static unordered_map<%s, loader_platform_thread_id> %sObjectsInUse;' % (ty, ty))
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001786 header_txt.append('static int threadingLockInitialized = 0;')
1787 header_txt.append('static loader_platform_thread_mutex threadingLock;')
Mike Stroyaned238bb2015-05-15 08:50:57 -06001788 header_txt.append('static loader_platform_thread_cond threadingCond;')
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001789 header_txt.append('%s' % self.lineinfo.get())
Mike Stroyan313f7e62015-08-10 16:42:53 -06001790 for ty in self.thread_check_dispatchable_objects + self.thread_check_nondispatchable_objects:
1791 header_txt.append(self.generate_useObject(ty))
1792 header_txt.append(self.generate_finishUsingObject(ty))
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001793 header_txt.append('%s' % self.lineinfo.get())
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001794 return "\n".join(header_txt)
1795
1796 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001797 if proto.name in [ 'CreateDebugReportCallbackEXT' ]:
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001798 # use default version
1799 return None
1800 decl = proto.c_func(prefix="vk", attr="VKAPI")
1801 ret_val = ''
1802 stmt = ''
1803 funcs = []
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001804 table = 'device'
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001805 if proto.ret != "void":
Jon Ashburnb0fbe912015-05-06 10:15:07 -06001806 ret_val = "%s result = " % proto.ret
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001807 stmt = " return result;\n"
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001808 if proto_is_global(proto):
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001809 table = 'instance'
Jon Ashburn71836d92015-05-12 17:23:55 -06001810
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001811 # Memory range calls are special in needed thread checking within structs
1812 if proto.name in ["FlushMappedMemoryRanges","InvalidateMappedMemoryRanges"]:
Mike Stroyan313f7e62015-08-10 16:42:53 -06001813 funcs.append('%s' % self.lineinfo.get())
1814 funcs.append('%s%s\n' % (qual, decl) +
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001815 '{\n'
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001816 ' for (uint32_t i=0; i<memoryRangeCount; i++) {\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08001817 ' useVkDeviceMemory((const void *) %s, pMemoryRanges[i].memory);\n' % proto.params[0].name +
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001818 ' }\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001819 ' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_%s_table_map, %s);\n' % (table, proto.params[0].name) +
Mike Stroyan313f7e62015-08-10 16:42:53 -06001820 ' %s pDeviceTable->%s;\n' % (ret_val, proto.c_call()) +
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001821 ' for (uint32_t i=0; i<memoryRangeCount; i++) {\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08001822 ' finishUsingVkDeviceMemory(pMemoryRanges[i].memory);\n'
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001823 ' }\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06001824 '%s' % (stmt) +
1825 '}')
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001826 return "\n".join(funcs)
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001827 # All functions that do a Get are thread safe
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001828 if 'Get' in proto.name:
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001829 return None
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001830 # All WSI functions are thread safe
Ian Elliott7e40db92015-08-21 15:09:33 -06001831 if 'KHR' in proto.name:
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001832 return None
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001833 # Initialize in early calls
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06001834 if proto.name == "CreateDevice":
1835 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan313f7e62015-08-10 16:42:53 -06001836 funcs.append('%s%s\n' % (qual, decl) +
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06001837 '{\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001838 ' VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);\n'
1839 ' PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;\n'
1840 ' PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;\n'
1841 ' PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");\n'
1842 ' if (fpCreateDevice == NULL) {\n'
1843 ' return VK_ERROR_INITIALIZATION_FAILED;\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06001844 ' }\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001845 ' // Advance the link info for the next element on the chain\n'
1846 ' chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;\n'
1847 ' VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);\n'
1848 ' if (result != VK_SUCCESS) {\n'
1849 ' return result;\n'
1850 ' }\n'
1851 ' layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);\n'
1852 ' layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);\n'
1853 ' initDeviceTable(*pDevice, fpGetDeviceProcAddr, threading_device_table_map);\n'
1854 ' my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);\n'
1855 ' return result;\n'
1856 '}\n')
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06001857 return "\n".join(funcs)
1858 elif proto.params[0].ty == "VkPhysicalDevice":
Mike Stroyan313f7e62015-08-10 16:42:53 -06001859 return None
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001860 # Functions changing command buffers need thread safe use of first parameter
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001861 if proto.params[0].ty == "VkCommandBuffer":
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001862 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan313f7e62015-08-10 16:42:53 -06001863 funcs.append('%s%s\n' % (qual, decl) +
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001864 '{\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08001865 ' 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 -07001866 ' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_%s_table_map, %s);\n' % (table, proto.params[0].name) +
Mike Stroyan313f7e62015-08-10 16:42:53 -06001867 ' %spDeviceTable->%s;\n' % (ret_val, proto.c_call()) +
Michael Lentine13803dc2015-11-04 14:35:12 -08001868 ' finishUsing%s(%s);\n' % (proto.params[0].ty, proto.params[0].name) +
Mike Stroyan313f7e62015-08-10 16:42:53 -06001869 '%s' % stmt +
1870 '}')
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001871 return "\n".join(funcs)
1872 # Non-Cmd functions that do a Wait are thread safe
1873 if 'Wait' in proto.name:
1874 return None
1875 # Watch use of certain types of objects passed as any parameter
1876 checked_params = []
1877 for param in proto.params:
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06001878 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 -06001879 checked_params.append(param)
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001880 if proto.name == "DestroyDevice":
Mike Stroyan313f7e62015-08-10 16:42:53 -06001881 funcs.append('%s%s\n' % (qual, decl) +
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001882 '{\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001883 ' dispatch_key key = get_dispatch_key(device);\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001884 ' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_%s_table_map, %s);\n' % (table, proto.params[0].name) +
Mike Stroyan313f7e62015-08-10 16:42:53 -06001885 ' %spDeviceTable->%s;\n' % (ret_val, proto.c_call()) +
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001886 ' threading_device_table_map.erase(key);\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06001887 '}\n')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001888 return "\n".join(funcs);
1889 elif proto.name == "DestroyInstance":
Mike Stroyan313f7e62015-08-10 16:42:53 -06001890 funcs.append('%s%s\n' % (qual, decl) +
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001891 '{\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001892 ' dispatch_key key = get_dispatch_key(instance);\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001893 ' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(threading_instance_table_map, %s);\n' % proto.params[0].name +
Mike Stroyan313f7e62015-08-10 16:42:53 -06001894 ' %spInstanceTable->%s;\n' % (ret_val, proto.c_call()) +
Courtney Goeltzenleuchter951af522016-01-15 11:58:33 -07001895 ' destroy_dispatch_table(threading_instance_table_map, key);\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06001896 '\n'
1897 ' // Clean up logging callback, if any\n'
1898 ' layer_data *my_data = get_my_data_ptr(key, layer_data_map);\n'
1899 ' if (my_data->logging_callback) {\n'
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07001900 ' layer_destroy_msg_callback(my_data->report_data, my_data->logging_callback, pAllocator);\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06001901 ' }\n'
1902 '\n'
1903 ' layer_debug_report_destroy_instance(my_data->report_data);\n'
1904 ' layer_data_map.erase(pInstanceTable);\n'
1905 '\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001906 ' threading_instance_table_map.erase(key);\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06001907 '}\n')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001908 return "\n".join(funcs);
Courtney Goeltzenleuchterd02a9642015-06-08 14:58:39 -06001909 elif proto.name == "CreateInstance":
1910 funcs.append('%s%s\n'
1911 '{\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001912 ' VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);\n'
1913 ' PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;\n'
1914 ' PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");\n'
1915 ' if (fpCreateInstance == NULL) {\n'
1916 ' return VK_ERROR_INITIALIZATION_FAILED;\n'
Courtney Goeltzenleuchterd02a9642015-06-08 14:58:39 -06001917 ' }\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001918 ' // Advance the link info for the next element on the chain\n'
1919 ' chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;\n'
1920 ' VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);\n'
1921 ' if (result != VK_SUCCESS) {\n'
1922 ' return result;\n'
1923 ' }\n'
1924 ' VkLayerInstanceDispatchTable *pTable = initInstanceTable(*pInstance, fpGetInstanceProcAddr, threading_instance_table_map);\n'
1925 ' layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);\n'
1926 ' my_data->report_data = debug_report_create_instance(\n'
1927 ' pTable,\n'
1928 ' *pInstance,\n'
1929 ' pCreateInfo->enabledExtensionCount,\n'
1930 ' pCreateInfo->ppEnabledExtensionNames);\n'
1931 ' init_threading(my_data, pAllocator);\n'
Courtney Goeltzenleuchterd02a9642015-06-08 14:58:39 -06001932 ' return result;\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06001933 '}\n' % (qual, decl))
Courtney Goeltzenleuchterd02a9642015-06-08 14:58:39 -06001934 return "\n".join(funcs);
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001935 if len(checked_params) == 0:
1936 return None
1937 # Surround call with useObject and finishUsingObject for each checked_param
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001938 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001939 funcs.append('%s%s' % (qual, decl))
1940 funcs.append('{')
1941 for param in checked_params:
Michael Lentine13803dc2015-11-04 14:35:12 -08001942 funcs.append(' use%s((const void *) %s, %s);' % (param.ty, proto.params[0].name, param.name))
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001943 funcs.append(' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_%s_table_map, %s);' % (table, proto.params[0].name));
Mike Stroyan313f7e62015-08-10 16:42:53 -06001944 funcs.append(' %spDeviceTable->%s;' % (ret_val, proto.c_call()))
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001945 for param in checked_params:
Michael Lentine13803dc2015-11-04 14:35:12 -08001946 funcs.append(' finishUsing%s(%s);' % (param.ty, param.name))
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001947 funcs.append('%s'
1948 '}' % stmt)
1949 return "\n".join(funcs)
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001950
1951 def generate_body(self):
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001952 self.layer_name = "threading"
Mike Stroyan313f7e62015-08-10 16:42:53 -06001953 body = [self._generate_new_layer_initialization(True, lockname='threading', condname='threading'),
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001954 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Courtney Goeltzenleuchter17274172015-06-01 14:52:57 -06001955 self._generate_layer_gpa_function(extensions=[],
Jon Ashburn3dc39382015-09-17 10:00:32 -06001956 instance_extensions=[('msg_callback_get_proc_addr', [])]),
Courtney Goeltzenleuchter17274172015-06-01 14:52:57 -06001957 self._gen_create_msg_callback(),
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07001958 self._gen_destroy_msg_callback(),
1959 self._gen_debug_report_msg()]
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001960 return "\n\n".join(body)
1961
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001962def main():
1963 subcommands = {
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001964 "object_tracker" : ObjectTrackerSubcommand,
1965 "threading" : ThreadingSubcommand,
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07001966 "unique_objects" : UniqueObjectsSubcommand,
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001967 }
1968
Tobin Ehlis14ff0852014-12-17 17:44:50 -07001969 if len(sys.argv) < 3 or sys.argv[1] not in subcommands or not os.path.exists(sys.argv[2]):
1970 print("Usage: %s <subcommand> <input_header> [options]" % sys.argv[0])
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001971 print
Tobin Ehlis7e65d752015-01-15 17:51:52 -07001972 print("Available subcommands are: %s" % " ".join(subcommands))
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001973 exit(1)
1974
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001975 hfp = vk_helper.HeaderFileParser(sys.argv[2])
Tobin Ehlis14ff0852014-12-17 17:44:50 -07001976 hfp.parse()
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001977 vk_helper.enum_val_dict = hfp.get_enum_val_dict()
1978 vk_helper.enum_type_dict = hfp.get_enum_type_dict()
1979 vk_helper.struct_dict = hfp.get_struct_dict()
1980 vk_helper.typedef_fwd_dict = hfp.get_typedef_fwd_dict()
1981 vk_helper.typedef_rev_dict = hfp.get_typedef_rev_dict()
1982 vk_helper.types_dict = hfp.get_types_dict()
Tobin Ehlis14ff0852014-12-17 17:44:50 -07001983
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001984 subcmd = subcommands[sys.argv[1]](sys.argv[2:])
1985 subcmd.run()
1986
1987if __name__ == "__main__":
1988 main()