blob: 6c8a2c89a46485a65be18e08ba70b25b321bf757 [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
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700346 def _gen_layer_get_global_extension_props(self, layer="generic"):
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,')
356 ggep_body.append(' VK_EXT_DEBUG_REPORT_REVISION')
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
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700368 def _gen_layer_get_global_layer_props(self, layer="generic"):
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600369 ggep_body = []
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700370 if layer == 'generic':
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600371 # Do nothing, extension definition part of generic.h
Tony Barbour59a47322015-06-24 16:06:58 -0600372 ggep_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600373 else:
Michael Lentine03107b42015-12-11 10:49:51 -0800374 layer_name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', layer)
375 layer_name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', layer_name).lower()
Tony Barbour59a47322015-06-24 16:06:58 -0600376 ggep_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter79a5a962015-07-07 17:51:45 -0600377 ggep_body.append('static const VkLayerProperties globalLayerProps[] = {')
Tony Barbour59a47322015-06-24 16:06:58 -0600378 ggep_body.append(' {')
Michael Lentine03107b42015-12-11 10:49:51 -0800379 ggep_body.append(' "VK_LAYER_LUNARG_%s",' % layer_name)
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600380 ggep_body.append(' VK_API_VERSION, // specVersion')
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800381 ggep_body.append(' VK_MAKE_VERSION(0, 1, 0), // implementationVersion')
Tony Barbour59a47322015-06-24 16:06:58 -0600382 ggep_body.append(' "layer: %s",' % layer)
383 ggep_body.append(' }')
384 ggep_body.append('};')
385 ggep_body.append('')
386 ggep_body.append('%s' % self.lineinfo.get())
Tony Barbour59a47322015-06-24 16:06:58 -0600387 ggep_body.append('')
Chia-I Wu9ab61502015-11-06 06:42:02 +0800388 ggep_body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties* pProperties)')
Tony Barbour59a47322015-06-24 16:06:58 -0600389 ggep_body.append('{')
Courtney Goeltzenleuchter79a5a962015-07-07 17:51:45 -0600390 ggep_body.append(' return util_GetLayerProperties(ARRAY_SIZE(globalLayerProps), globalLayerProps, pCount, pProperties);')
Tony Barbour59a47322015-06-24 16:06:58 -0600391 ggep_body.append('}')
392 return "\n".join(ggep_body)
393
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700394 def _gen_layer_get_physical_device_layer_props(self, layer="generic"):
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600395 gpdlp_body = []
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700396 if layer == 'generic':
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600397 # Do nothing, extension definition part of generic.h
398 gpdlp_body.append('%s' % self.lineinfo.get())
399 else:
400 gpdlp_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter79a5a962015-07-07 17:51:45 -0600401 gpdlp_body.append('static const VkLayerProperties deviceLayerProps[] = {')
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600402 gpdlp_body.append(' {')
Michael Lentine1f8d4412016-01-19 14:19:38 -0600403 gpdlp_body.append(' "VK_LAYER_LUNARG_%s",' % layer)
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600404 gpdlp_body.append(' VK_API_VERSION,')
405 gpdlp_body.append(' VK_MAKE_VERSION(0, 1, 0),')
406 gpdlp_body.append(' "layer: %s",' % layer)
407 gpdlp_body.append(' }')
408 gpdlp_body.append('};')
Chia-I Wu9ab61502015-11-06 06:42:02 +0800409 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 -0600410 gpdlp_body.append('{')
Courtney Goeltzenleuchter79a5a962015-07-07 17:51:45 -0600411 gpdlp_body.append(' return util_GetLayerProperties(ARRAY_SIZE(deviceLayerProps), deviceLayerProps, pCount, pProperties);')
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600412 gpdlp_body.append('}')
413 gpdlp_body.append('')
414 return "\n".join(gpdlp_body)
415
Mike Stroyanbf237d72015-04-03 17:45:53 -0600416 def _generate_dispatch_entrypoints(self, qual=""):
Mike Stroyan938c2532015-04-03 13:58:35 -0600417 if qual:
418 qual += " "
419
Mike Stroyan938c2532015-04-03 13:58:35 -0600420 funcs = []
421 intercepted = []
422 for proto in self.protos:
Jon Ashburn8d1b0b52015-05-18 13:20:15 -0600423 if proto.name == "GetDeviceProcAddr" or proto.name == "GetInstanceProcAddr":
Jon Ashburn8fd08252015-05-28 16:25:02 -0600424 continue
Mike Stroyan70c05e82015-04-08 10:27:43 -0600425 else:
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600426 intercept = self.generate_intercept(proto, qual)
Mike Stroyan938c2532015-04-03 13:58:35 -0600427 if intercept is None:
428 # fill in default intercept for certain entrypoints
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700429 if 'CreateDebugReportCallbackEXT' == proto.name:
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600430 intercept = self._gen_layer_dbg_create_msg_callback()
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700431 elif 'DestroyDebugReportCallbackEXT' == proto.name:
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600432 intercept = self._gen_layer_dbg_destroy_msg_callback()
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700433 elif 'DebugReportMessageEXT' == proto.name:
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700434 intercept = self._gen_debug_report_msg()
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600435 elif 'CreateDevice' == proto.name:
436 funcs.append('/* CreateDevice HERE */')
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600437 elif 'EnumerateInstanceExtensionProperties' == proto.name:
Tony Barbour59a47322015-06-24 16:06:58 -0600438 intercept = self._gen_layer_get_global_extension_props(self.layer_name)
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600439 elif 'EnumerateInstanceLayerProperties' == proto.name:
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600440 intercept = self._gen_layer_get_global_layer_props(self.layer_name)
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600441 elif 'EnumerateDeviceLayerProperties' == proto.name:
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600442 intercept = self._gen_layer_get_physical_device_layer_props(self.layer_name)
Tony Barbour59a47322015-06-24 16:06:58 -0600443
Mike Stroyan938c2532015-04-03 13:58:35 -0600444 if intercept is not None:
445 funcs.append(intercept)
Ian Elliott7e40db92015-08-21 15:09:33 -0600446 if not "KHR" in proto.name:
Jon Ashburn747f2b62015-06-18 15:02:58 -0600447 intercepted.append(proto)
Mike Stroyan938c2532015-04-03 13:58:35 -0600448
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600449 prefix="vk"
Mike Stroyan938c2532015-04-03 13:58:35 -0600450 lookups = []
451 for proto in intercepted:
Mike Stroyan938c2532015-04-03 13:58:35 -0600452 lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600453 lookups.append(" return (PFN_vkVoidFunction) %s%s;" %
Mike Stroyan938c2532015-04-03 13:58:35 -0600454 (prefix, proto.name))
Mike Stroyan938c2532015-04-03 13:58:35 -0600455
456 # add customized layer_intercept_proc
457 body = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600458 body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600459 body.append("static inline PFN_vkVoidFunction layer_intercept_proc(const char *name)")
Mike Stroyan938c2532015-04-03 13:58:35 -0600460 body.append("{")
461 body.append(generate_get_proc_addr_check("name"))
462 body.append("")
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600463 body.append(" name += 2;")
Mike Stroyan938c2532015-04-03 13:58:35 -0600464 body.append(" %s" % "\n ".join(lookups))
465 body.append("")
466 body.append(" return NULL;")
467 body.append("}")
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600468 # add layer_intercept_instance_proc
469 lookups = []
470 for proto in self.protos:
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600471 if not proto_is_global(proto):
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600472 continue
473
474 if not proto in intercepted:
475 continue
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -0600476 if proto.name == "CreateDevice":
477 continue
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600478 lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600479 lookups.append(" return (PFN_vkVoidFunction) %s%s;" % (prefix, proto.name))
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600480
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600481 body.append("static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char *name)")
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600482 body.append("{")
483 body.append(generate_get_proc_addr_check("name"))
484 body.append("")
485 body.append(" name += 2;")
486 body.append(" %s" % "\n ".join(lookups))
487 body.append("")
488 body.append(" return NULL;")
489 body.append("}")
490
Mike Stroyan938c2532015-04-03 13:58:35 -0600491 funcs.append("\n".join(body))
Mike Stroyan938c2532015-04-03 13:58:35 -0600492 return "\n\n".join(funcs)
493
Tobin Ehlisca915872014-11-18 11:28:33 -0700494 def _generate_extensions(self):
495 exts = []
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600496 exts.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600497 exts.append(self._gen_create_msg_callback())
498 exts.append(self._gen_destroy_msg_callback())
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700499 exts.append(self._gen_debug_report_msg())
Tobin Ehlisb870cbb2015-04-15 07:46:12 -0600500 return "\n".join(exts)
501
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600502 def _generate_layer_gpa_function(self, extensions=[], instance_extensions=[]):
Jon Ashburnbacb0f52015-04-06 10:58:22 -0600503 func_body = []
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600504#
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600505# New style of GPA Functions for the new layer_data/layer_logging changes
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600506#
Tobin Ehlisd34a4c52015-12-08 10:50:10 -0700507 if self.layer_name in ['object_tracker', 'threading', 'unique_objects']:
Chia-I Wu9ab61502015-11-06 06:42:02 +0800508 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 -0600509 "{\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600510 " PFN_vkVoidFunction addr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600511 " if (device == VK_NULL_HANDLE) {\n"
512 " return NULL;\n"
513 " }\n"
514 " /* loader uses this to force layer initialization; device object is wrapped */\n"
515 " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
516 " initDeviceTable(%s_device_table_map, (const VkBaseLayerObject *) device);\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600517 " return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600518 " }\n\n"
519 " addr = layer_intercept_proc(funcName);\n"
520 " if (addr)\n"
521 " return addr;" % self.layer_name)
522 if 0 != len(extensions):
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600523 func_body.append('%s' % self.lineinfo.get())
524 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 -0600525 for (ext_enable, ext_list) in extensions:
526 extra_space = ""
527 if 0 != len(ext_enable):
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600528 func_body.append(' if (my_device_data->%s) {' % ext_enable)
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600529 extra_space = " "
530 for ext_name in ext_list:
531 func_body.append(' %sif (!strcmp("%s", funcName))\n'
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600532 ' %sreturn reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, extra_space, ext_name))
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600533 if 0 != len(ext_enable):
534 func_body.append(' }\n')
535 func_body.append("\n if (get_dispatch_table(%s_device_table_map, device)->GetDeviceProcAddr == NULL)\n"
536 " return NULL;\n"
537 " return get_dispatch_table(%s_device_table_map, device)->GetDeviceProcAddr(device, funcName);\n"
538 "}\n" % (self.layer_name, self.layer_name))
Chia-I Wu9ab61502015-11-06 06:42:02 +0800539 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 -0600540 "{\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600541 " PFN_vkVoidFunction addr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600542 " if (instance == VK_NULL_HANDLE) {\n"
543 " return NULL;\n"
544 " }\n"
545 " /* loader uses this to force layer initialization; instance object is wrapped */\n"
546 " if (!strcmp(\"vkGetInstanceProcAddr\", funcName)) {\n"
547 " initInstanceTable(%s_instance_table_map, (const VkBaseLayerObject *) instance);\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600548 " return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600549 " }\n\n"
550 " addr = layer_intercept_instance_proc(funcName);\n"
551 " if (addr) {\n"
552 " return addr;"
553 " }\n" % self.layer_name)
Jon Ashburnbacb0f52015-04-06 10:58:22 -0600554
Jon Ashburn3dc39382015-09-17 10:00:32 -0600555 table_declared = False
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600556 if 0 != len(instance_extensions):
Jon Ashburn3dc39382015-09-17 10:00:32 -0600557 for (ext_enable, ext_list) in instance_extensions:
558 extra_space = ""
559 if 0 != len(ext_enable):
560 if ext_enable == 'msg_callback_get_proc_addr':
561 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 -0600562 " addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);\n"
563 " if (addr) {\n"
564 " return addr;\n"
Jon Ashburn3dc39382015-09-17 10:00:32 -0600565 " }\n")
566 else:
567 if table_declared == False:
568 func_body.append(" VkLayerInstanceDispatchTable* pTable = get_dispatch_table(%s_instance_table_map, instance);" % self.layer_name)
569 table_declared = True
570 func_body.append(' if (instanceExtMap.size() != 0 && instanceExtMap[pTable].%s)' % ext_enable)
571 func_body.append(' {')
572 extra_space = " "
573 for ext_name in ext_list:
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700574 if wsi_name(ext_name):
575 func_body.append('%s' % wsi_ifdef(ext_name))
Jon Ashburn3dc39382015-09-17 10:00:32 -0600576 func_body.append(' %sif (!strcmp("%s", funcName))\n'
577 ' return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700578 if wsi_name(ext_name):
579 func_body.append('%s' % wsi_endif(ext_name))
Jon Ashburn3dc39382015-09-17 10:00:32 -0600580 if 0 != len(ext_enable):
581 func_body.append(' }\n')
582
583 func_body.append(" if (get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr == NULL) {\n"
584 " return NULL;\n"
585 " }\n"
586 " return get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr(instance, funcName);\n"
587 "}\n" % (self.layer_name, self.layer_name))
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600588 return "\n".join(func_body)
589 else:
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600590 func_body.append('%s' % self.lineinfo.get())
Chia-I Wu9ab61502015-11-06 06:42:02 +0800591 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 -0600592 "{\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600593 " PFN_vkVoidFunction addr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600594 " if (device == VK_NULL_HANDLE) {\n"
595 " return NULL;\n"
Jon Ashburn3a278b72015-10-06 17:05:21 -0600596 " }\n")
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700597 if self.layer_name == 'generic':
Jon Ashburn3a278b72015-10-06 17:05:21 -0600598 func_body.append("\n"
599 " /* loader uses this to force layer initialization; device object is wrapped */\n"
600 " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
601 " initDeviceTable((const VkBaseLayerObject *) device);\n"
602 " return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
603 " }\n\n"
604 " addr = layer_intercept_proc(funcName);\n"
605 " if (addr)\n"
606 " return addr;")
607 else:
608 func_body.append("\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600609 " loader_platform_thread_once(&initOnce, init%s);\n\n"
610 " /* loader uses this to force layer initialization; device object is wrapped */\n"
611 " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
612 " initDeviceTable((const VkBaseLayerObject *) device);\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600613 " return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600614 " }\n\n"
615 " addr = layer_intercept_proc(funcName);\n"
616 " if (addr)\n"
617 " return addr;" % self.layer_name)
618 func_body.append('')
619 func_body.append(' VkLayerDispatchTable *pDisp = device_dispatch_table(device);')
620 if 0 != len(extensions):
621 extra_space = ""
622 for (ext_enable, ext_list) in extensions:
623 if 0 != len(ext_enable):
Jon Ashburn8acd2332015-09-16 18:08:32 -0600624 func_body.append(' if (deviceExtMap.size() != 0 && deviceExtMap[pDisp].%s)' % ext_enable)
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600625 func_body.append(' {')
626 extra_space = " "
627 for ext_name in ext_list:
628 func_body.append(' %sif (!strcmp("%s", funcName))\n'
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600629 ' return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600630 if 0 != len(ext_enable):
631 func_body.append(' }')
632 func_body.append('%s' % self.lineinfo.get())
633 func_body.append(" {\n"
634 " if (pDisp->GetDeviceProcAddr == NULL)\n"
635 " return NULL;\n"
636 " return pDisp->GetDeviceProcAddr(device, funcName);\n"
637 " }\n"
638 "}\n")
Jon Ashburn3dc39382015-09-17 10:00:32 -0600639 func_body.append('%s' % self.lineinfo.get())
Chia-I Wu9ab61502015-11-06 06:42:02 +0800640 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 -0600641 "{\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600642 " PFN_vkVoidFunction addr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600643 " if (instance == VK_NULL_HANDLE) {\n"
644 " return NULL;\n"
Jon Ashburn3a278b72015-10-06 17:05:21 -0600645 " }\n")
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700646 if self.layer_name == 'generic':
Jon Ashburn3a278b72015-10-06 17:05:21 -0600647 func_body.append("\n"
648 " /* loader uses this to force layer initialization; instance object is wrapped */\n"
649 " if (!strcmp(\"vkGetInstanceProcAddr\", funcName)) {\n"
650 " initInstanceTable((const VkBaseLayerObject *) instance);\n"
651 " return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
652 " }\n\n"
653 " addr = layer_intercept_instance_proc(funcName);\n"
654 " if (addr)\n"
655 " return addr;")
656 else:
657 func_body.append(
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600658 " loader_platform_thread_once(&initOnce, init%s);\n\n"
659 " /* loader uses this to force layer initialization; instance object is wrapped */\n"
660 " if (!strcmp(\"vkGetInstanceProcAddr\", funcName)) {\n"
661 " initInstanceTable((const VkBaseLayerObject *) instance);\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600662 " return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600663 " }\n\n"
664 " addr = layer_intercept_instance_proc(funcName);\n"
665 " if (addr)\n"
666 " return addr;" % self.layer_name)
Jon Ashburn3dc39382015-09-17 10:00:32 -0600667 func_body.append("")
668 func_body.append(" VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(instance);")
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600669 if 0 != len(instance_extensions):
Jon Ashburn3dc39382015-09-17 10:00:32 -0600670 extra_space = ""
671 for (ext_enable, ext_list) in instance_extensions:
672 if 0 != len(ext_enable):
Jon Ashburn3a278b72015-10-06 17:05:21 -0600673 if ext_enable == 'msg_callback_get_proc_addr':
674 func_body.append(" layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);\n"
675 " addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);\n"
676 " if (addr) {\n"
677 " return addr;\n"
678 " }\n")
679 else:
680 func_body.append(' if (instanceExtMap.size() != 0 && instanceExtMap[pTable].%s)' % ext_enable)
681 func_body.append(' {')
682 extra_space = " "
683 for ext_name in ext_list:
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700684 if wsi_name(ext_name):
685 func_body.append('%s' % wsi_ifdef(ext_name))
Jon Ashburn3a278b72015-10-06 17:05:21 -0600686 func_body.append(' %sif (!strcmp("%s", funcName))\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -0600687 ' return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700688 if wsi_name(ext_name):
689 func_body.append('%s' % wsi_endif(ext_name))
Jon Ashburn3a278b72015-10-06 17:05:21 -0600690 if 0 != len(ext_enable):
691 func_body.append(' }\n')
Jon Ashburn3dc39382015-09-17 10:00:32 -0600692
693 func_body.append(" if (pTable->GetInstanceProcAddr == NULL)\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600694 " return NULL;\n"
695 " return pTable->GetInstanceProcAddr(instance, funcName);\n"
696 "}\n")
697 return "\n".join(func_body)
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600698
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600699
Mike Stroyaned238bb2015-05-15 08:50:57 -0600700 def _generate_layer_initialization(self, init_opts=False, prefix='vk', lockname=None, condname=None):
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600701 func_body = ["#include \"vk_dispatch_table_helper.h\""]
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600702 func_body.append('%s' % self.lineinfo.get())
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700703 func_body.append('static void init_%s(layer_data *my_data, const VkAllocationCallbacks *pAllocator)\n'
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600704 '{\n' % self.layer_name)
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700705 if init_opts:
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600706 func_body.append('%s' % self.lineinfo.get())
Jon Ashburn3a278b72015-10-06 17:05:21 -0600707 func_body.append(' uint32_t report_flags = 0;')
708 func_body.append(' uint32_t debug_action = 0;')
709 func_body.append(' FILE *log_output = NULL;')
710 func_body.append(' const char *option_str;\n')
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600711 func_body.append(' // initialize %s options' % self.layer_name)
Jon Ashburn3a278b72015-10-06 17:05:21 -0600712 func_body.append(' report_flags = getLayerOptionFlags("%sReportFlags", 0);' % self.layer_name)
713 func_body.append(' getLayerOptionEnum("%sDebugAction", (uint32_t *) &debug_action);' % self.layer_name)
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700714 func_body.append('')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600715 func_body.append(' if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)')
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700716 func_body.append(' {')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600717 func_body.append(' option_str = getLayerOption("%sLogFilename");' % self.layer_name)
718 func_body.append(' log_output = getLayerLogOutput(option_str,"%s");' % self.layer_name)
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700719 func_body.append(' VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700720 func_body.append(' memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo));')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700721 func_body.append(' dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700722 func_body.append(' dbgCreateInfo.flags = report_flags;')
723 func_body.append(' dbgCreateInfo.pfnCallback = log_callback;')
724 func_body.append(' dbgCreateInfo.pUserData = NULL;')
725 func_body.append(' layer_create_msg_callback(my_data->report_data, &dbgCreateInfo, pAllocator,')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600726 func_body.append(' &my_data->logging_callback);')
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700727 func_body.append(' }')
728 func_body.append('')
Tobin Ehlis36f1b462015-02-23 14:09:16 -0700729 if lockname is not None:
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600730 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlis36f1b462015-02-23 14:09:16 -0700731 func_body.append(" if (!%sLockInitialized)" % lockname)
732 func_body.append(" {")
733 func_body.append(" // TODO/TBD: Need to delete this mutex sometime. How???")
734 func_body.append(" loader_platform_thread_create_mutex(&%sLock);" % lockname)
Mike Stroyaned238bb2015-05-15 08:50:57 -0600735 if condname is not None:
736 func_body.append(" loader_platform_thread_init_cond(&%sCond);" % condname)
Tobin Ehlis36f1b462015-02-23 14:09:16 -0700737 func_body.append(" %sLockInitialized = 1;" % lockname)
738 func_body.append(" }")
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600739 func_body.append("}\n")
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -0600740 func_body.append('')
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600741 return "\n".join(func_body)
742
Mike Stroyan313f7e62015-08-10 16:42:53 -0600743 def _generate_new_layer_initialization(self, init_opts=False, prefix='vk', lockname=None, condname=None):
744 func_body = ["#include \"vk_dispatch_table_helper.h\""]
745 func_body.append('%s' % self.lineinfo.get())
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700746 func_body.append('static void init_%s(layer_data *my_data, const VkAllocationCallbacks *pAllocator)\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -0600747 '{\n' % self.layer_name)
748 if init_opts:
749 func_body.append('%s' % self.lineinfo.get())
750 func_body.append(' uint32_t report_flags = 0;')
751 func_body.append(' uint32_t debug_action = 0;')
752 func_body.append(' FILE *log_output = NULL;')
753 func_body.append(' const char *strOpt;')
754 func_body.append(' // initialize %s options' % self.layer_name)
755 func_body.append(' report_flags = getLayerOptionFlags("%sReportFlags", 0);' % self.layer_name)
Jon Ashburn9ff6ae92015-10-06 17:20:01 -0600756 func_body.append(' getLayerOptionEnum("%sDebugAction", (uint32_t *) &debug_action);' % self.layer_name)
Mike Stroyan313f7e62015-08-10 16:42:53 -0600757 func_body.append('')
758 func_body.append(' if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)')
759 func_body.append(' {')
760 func_body.append(' strOpt = getLayerOption("%sLogFilename");' % self.layer_name)
Tobin Ehlisb1df55e2015-09-15 09:55:54 -0600761 func_body.append(' log_output = getLayerLogOutput(strOpt, "%s");' % self.layer_name)
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700762 func_body.append(' VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700763 func_body.append(' memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo));')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700764 func_body.append(' dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700765 func_body.append(' dbgCreateInfo.flags = report_flags;')
766 func_body.append(' dbgCreateInfo.pfnCallback = log_callback;')
767 func_body.append(' dbgCreateInfo.pUserData = log_output;')
768 func_body.append(' layer_create_msg_callback(my_data->report_data, &dbgCreateInfo, pAllocator,')
769 func_body.append(' &my_data->logging_callback);')
Mike Stroyan313f7e62015-08-10 16:42:53 -0600770 func_body.append(' }')
771 func_body.append('')
772 if lockname is not None:
773 func_body.append('%s' % self.lineinfo.get())
774 func_body.append(" if (!%sLockInitialized)" % lockname)
775 func_body.append(" {")
776 func_body.append(" // TODO/TBD: Need to delete this mutex sometime. How???")
777 func_body.append(" loader_platform_thread_create_mutex(&%sLock);" % lockname)
778 if condname is not None:
779 func_body.append(" loader_platform_thread_init_cond(&%sCond);" % condname)
780 func_body.append(" %sLockInitialized = 1;" % lockname)
781 func_body.append(" }")
782 func_body.append("}\n")
783 func_body.append('')
784 return "\n".join(func_body)
785
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600786class LayerFuncsSubcommand(Subcommand):
787 def generate_header(self):
David Pinedo9316d3b2015-11-06 12:54:48 -0700788 return '#include <vulkan/vk_layer.h>\n#include "loader.h"'
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600789
790 def generate_body(self):
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600791 return self._generate_dispatch_entrypoints("static")
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600792
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600793class GenericLayerSubcommand(Subcommand):
794 def generate_header(self):
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500795 gen_header = []
Courtney Goeltzenleuchter79a5a962015-07-07 17:51:45 -0600796 gen_header.append('%s' % self.lineinfo.get())
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500797 gen_header.append('#include <stdio.h>')
798 gen_header.append('#include <stdlib.h>')
799 gen_header.append('#include <string.h>')
800 gen_header.append('#include <unordered_map>')
Tobin Ehlisb835d1b2015-07-03 10:34:49 -0600801 gen_header.append('#include "vk_loader_platform.h"')
David Pinedo9316d3b2015-11-06 12:54:48 -0700802 gen_header.append('#include "vulkan/vk_layer.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -0600803 gen_header.append('#include "vk_layer_config.h"')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600804 gen_header.append('#include "vk_layer_logging.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -0600805 gen_header.append('#include "vk_layer_table.h"')
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600806 gen_header.append('#include "vk_layer_extension_utils.h"')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500807 gen_header.append('')
Courtney Goeltzenleuchter79a5a962015-07-07 17:51:45 -0600808 gen_header.append('#include "generic.h"')
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600809 gen_header.append('')
Tobin Ehlisa30e7e52015-07-06 14:02:36 -0600810 gen_header.append('%s' % self.lineinfo.get())
811 gen_header.append('#define LAYER_EXT_ARRAY_SIZE 1')
812 gen_header.append('#define LAYER_DEV_EXT_ARRAY_SIZE 1')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600813 gen_header.append('//static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
814 gen_header.append('static std::unordered_map<void *, layer_data *> layer_data_map;\n')
815 gen_header.append('template layer_data *get_my_data_ptr<layer_data>(')
816 gen_header.append(' void *data_key,')
817 gen_header.append(' std::unordered_map<void *, layer_data *> &data_map);\n')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500818 gen_header.append('')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500819 return "\n".join(gen_header)
Tobin Ehlis7a314ea2015-07-07 11:02:44 -0600820
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600821 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600822 if proto.name in [ 'EnumerateInstanceLayerProperties', 'EnumerateInstanceExtensionProperties', 'EnumerateDeviceLayerProperties', 'EnumerateDeviceExtensionProperties' ]:
Mike Stroyan00087e62015-04-03 14:39:16 -0600823 # use default version
824 return None
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600825 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyan938c2532015-04-03 13:58:35 -0600826 ret_val = ''
827 stmt = ''
828 funcs = []
Jon Ashburn71836d92015-05-12 17:23:55 -0600829 table = ''
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600830 if proto_is_global(proto):
Jon Ashburn71836d92015-05-12 17:23:55 -0600831 table = 'Instance'
Mike Stroyan938c2532015-04-03 13:58:35 -0600832 if proto.ret != "void":
Courtney Goeltzenleuchter0de9e212015-06-26 15:07:53 -0600833 funcs.append('%s' % self.lineinfo.get())
Jon Ashburnb0fbe912015-05-06 10:15:07 -0600834 ret_val = "%s result = " % proto.ret
Mike Stroyan938c2532015-04-03 13:58:35 -0600835 stmt = " return result;\n"
Jon Ashburn8ced4212015-05-22 12:01:50 -0600836 if proto.name == "CreateDevice":
Courtney Goeltzenleuchter0de9e212015-06-26 15:07:53 -0600837 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan938c2532015-04-03 13:58:35 -0600838 funcs.append('%s%s\n'
839 '{\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500840 ' char str[1024];\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600841 ' layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);\n'
842 ' sprintf(str, "At start of Generic layered %s\\n");\n'
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700843 ' log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,'
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -0700844 ' (uint64_t)physicalDevice, __LINE__, 0, (char *) "generic", "%%s", (char *) str);\n'
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -0600845 ' %sdevice_dispatch_table(*pDevice)->%s;\n'
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600846 ' if (result == VK_SUCCESS) {\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600847 ' my_data->report_data = layer_debug_report_create_device(my_data->report_data, *pDevice);\n'
Jon Ashburn747f2b62015-06-18 15:02:58 -0600848 ' createDeviceRegisterExtensions(pCreateInfo, *pDevice);\n'
Mike Stroyan938c2532015-04-03 13:58:35 -0600849 ' }\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700850 ' sprintf(str, "Completed generic layered %s\\n");\n'
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -0700851 ' log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, (uint64_t)physicalDevice, __LINE__, 0, (char *) "generic", "%%s", (char *) str);\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500852 ' %s'
853 '}' % (qual, decl, proto.name, ret_val, proto.c_call(), proto.name, stmt))
854 elif proto.name == "DestroyDevice":
Courtney Goeltzenleuchter0de9e212015-06-26 15:07:53 -0600855 funcs.append('%s' % self.lineinfo.get())
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500856 funcs.append('%s%s\n'
857 '{\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -0600858 ' dispatch_key key = get_dispatch_key(device);\n'
Jon Ashburn747f2b62015-06-18 15:02:58 -0600859 ' VkLayerDispatchTable *pDisp = device_dispatch_table(device);\n'
Chia-I Wuf7458c52015-10-26 21:10:41 +0800860 ' pDisp->DestroyDevice(device, pAllocator);\n'
Jon Ashburn747f2b62015-06-18 15:02:58 -0600861 ' deviceExtMap.erase(pDisp);\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -0600862 ' destroy_device_dispatch_table(key);\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500863 '}\n' % (qual, decl))
864 elif proto.name == "DestroyInstance":
Courtney Goeltzenleuchter0de9e212015-06-26 15:07:53 -0600865 funcs.append('%s' % self.lineinfo.get())
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500866 funcs.append('%s%s\n'
867 '{\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -0600868 ' dispatch_key key = get_dispatch_key(instance);\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -0600869 ' VkLayerInstanceDispatchTable *pDisp = instance_dispatch_table(instance);\n'
Chia-I Wuf7458c52015-10-26 21:10:41 +0800870 ' pDisp->DestroyInstance(instance, pAllocator);\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600871 ' // Clean up logging callback, if any\n'
872 ' layer_data *my_data = get_my_data_ptr(key, layer_data_map);\n'
873 ' if (my_data->logging_callback) {\n'
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700874 ' layer_destroy_msg_callback(my_data->report_data, my_data->logging_callback, pAllocator);\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600875 ' }\n\n'
876 ' layer_debug_report_destroy_instance(my_data->report_data);\n'
877 ' layer_data_map.erase(key);\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -0600878 ' instanceExtMap.erase(pDisp);\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -0600879 ' destroy_instance_dispatch_table(key);\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500880 '}\n' % (qual, decl))
Jon Ashburn3dc39382015-09-17 10:00:32 -0600881 elif proto.name == "CreateInstance":
Courtney Goeltzenleuchter0de9e212015-06-26 15:07:53 -0600882 funcs.append('%s' % self.lineinfo.get())
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500883 # CreateInstance needs to use the second parm instead of the first to set the correct dispatch table
Jon Ashburn3dc39382015-09-17 10:00:32 -0600884 funcs.append('%s%s\n'
885 '{\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600886 ' char str[1024];\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -0600887 ' %sinstance_dispatch_table(*pInstance)->%s;\n'
888 ' if (result == VK_SUCCESS) {\n'
889 ' createInstanceRegisterExtensions(pCreateInfo, *pInstance);\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600890 ' layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);\n'
891 ' my_data->report_data = debug_report_create_instance(\n'
892 ' instance_dispatch_table(*pInstance),\n'
893 ' *pInstance,\n'
Jon Ashburnf19916e2016-01-11 13:12:43 -0700894 ' pCreateInfo->enabledExtensionCount,\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600895 ' pCreateInfo->ppEnabledExtensionNames);\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700896 ' init_generic(my_data, pAllocator);\n'
897 ' sprintf(str, "Completed generic layered %s\\n");\n'
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -0700898 ' log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, (uint64_t)*pInstance, __LINE__, 0, (char *) "generic", "%%s", (char *) str);\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -0600899 ' }\n'
Tobin Ehlis1350a362015-09-17 16:27:04 -0600900 ' return result;\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600901 '}\n' % (qual, decl, ret_val, proto.c_call(), proto.name))
Jon Ashburn3dc39382015-09-17 10:00:32 -0600902 else:
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700903 if wsi_name(proto.name):
904 funcs.append('%s' % wsi_ifdef(proto.name))
Jon Ashburn3dc39382015-09-17 10:00:32 -0600905 funcs.append('%s' % self.lineinfo.get())
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500906 dispatch_param = proto.params[0].name
907 # Must use 'instance' table for these APIs, 'device' table otherwise
908 table_type = ""
909 if proto_is_global(proto):
910 table_type = "instance"
911 else:
912 table_type = "device"
Mike Stroyan938c2532015-04-03 13:58:35 -0600913 funcs.append('%s%s\n'
914 '{\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500915 ' %s%s_dispatch_table(%s)->%s;\n'
Mike Stroyan938c2532015-04-03 13:58:35 -0600916 '%s'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500917 '}' % (qual, decl, ret_val, table_type, dispatch_param, proto.c_call(), stmt))
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700918 if wsi_name(proto.name):
919 funcs.append('%s' % wsi_endif(proto.name))
Mike Stroyan938c2532015-04-03 13:58:35 -0600920 return "\n\n".join(funcs)
921
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600922 def generate_body(self):
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700923 self.layer_name = "generic"
Jon Ashburn3a278b72015-10-06 17:05:21 -0600924 instance_extensions=[('msg_callback_get_proc_addr', []),
925 ('wsi_enabled',
Ian Elliott05846062015-11-20 14:13:17 -0700926 ['vkGetPhysicalDeviceSurfaceSupportKHR',
927 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
928 'vkGetPhysicalDeviceSurfaceFormatsKHR',
929 'vkGetPhysicalDeviceSurfacePresentModesKHR'])]
Tobin Ehlisd34a4c52015-12-08 10:50:10 -0700930 extensions=[('wsi_enabled',
Ian Elliott05846062015-11-20 14:13:17 -0700931 ['vkCreateSwapchainKHR',
Jon Ashburn8acd2332015-09-16 18:08:32 -0600932 'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
933 'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600934 body = [self._generate_layer_initialization(True),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600935 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600936 self._gen_create_msg_callback(),
937 self._gen_destroy_msg_callback(),
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700938 self._gen_debug_report_msg(),
Jon Ashburn3dc39382015-09-17 10:00:32 -0600939 self._generate_layer_gpa_function(extensions, instance_extensions)]
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600940
941 return "\n\n".join(body)
942
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600943class APIDumpSubcommand(Subcommand):
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600944 def generate_header(self):
Tobin Ehlisd009bae2014-11-24 15:46:55 -0700945 header_txt = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600946 header_txt.append('%s' % self.lineinfo.get())
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600947 header_txt.append('#include <fstream>')
948 header_txt.append('#include <iostream>')
949 header_txt.append('#include <string>')
Jon Ashburn747f2b62015-06-18 15:02:58 -0600950 header_txt.append('#include <string.h>')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600951 header_txt.append('')
Tobin Ehlis80d048e2015-08-28 09:57:53 -0600952 header_txt.append('#include "vk_loader_platform.h"')
David Pinedo9316d3b2015-11-06 12:54:48 -0700953 header_txt.append('#include "vulkan/vk_layer.h"')
Tobin Ehlis80d048e2015-08-28 09:57:53 -0600954 header_txt.append('#include "vk_struct_string_helper_cpp.h"')
955 header_txt.append('#include "vk_layer_table.h"')
956 header_txt.append('#include "vk_layer_extension_utils.h"')
957 header_txt.append('#include <unordered_map>')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700958 header_txt.append('#include "api_dump.h"')
Tobin Ehlis80d048e2015-08-28 09:57:53 -0600959 header_txt.append('')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600960 header_txt.append('static std::ofstream fileStream;')
961 header_txt.append('static std::string fileName = "vk_apidump.txt";')
962 header_txt.append('std::ostream* outputStream = NULL;')
963 header_txt.append('void ConfigureOutputStream(bool writeToFile, bool flushAfterWrite)')
964 header_txt.append('{')
965 header_txt.append(' if(writeToFile)')
966 header_txt.append(' {')
Tobin Ehlis93245a92015-09-18 14:32:12 -0600967 header_txt.append(' if (fileName == "stdout")')
968 header_txt.append(' {')
Tobin Ehlis80d048e2015-08-28 09:57:53 -0600969 header_txt.append(' outputStream = &std::cout;')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700970 header_txt.append(' (*outputStream) << endl << "api_dump output filename \'stdout\' specified. Writing to STDOUT instead of a file." << endl << endl;')
Tobin Ehlis93245a92015-09-18 14:32:12 -0600971 header_txt.append(' } else {')
972 header_txt.append(' fileStream.open(fileName);')
973 header_txt.append(' if ((fileStream.rdstate() & fileStream.failbit) != 0) {')
974 header_txt.append(' outputStream = &std::cout;')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700975 header_txt.append(' (*outputStream) << endl << "api_dump ERROR: Bad output filename specified: " << fileName << ". Writing to STDOUT instead" << endl << endl;')
Tobin Ehlis93245a92015-09-18 14:32:12 -0600976 header_txt.append(' }')
977 header_txt.append(' else')
978 header_txt.append(' outputStream = &fileStream;')
Tobin Ehlis80d048e2015-08-28 09:57:53 -0600979 header_txt.append(' }')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600980 header_txt.append(' }')
981 header_txt.append(' else')
982 header_txt.append(' {')
983 header_txt.append(' outputStream = &std::cout;')
984 header_txt.append(' }')
985 header_txt.append('')
986 header_txt.append(' if(flushAfterWrite)')
987 header_txt.append(' {')
988 header_txt.append(' outputStream->sync_with_stdio(true);')
989 header_txt.append(' }')
990 header_txt.append(' else')
991 header_txt.append(' {')
992 header_txt.append(' outputStream->sync_with_stdio(false);')
993 header_txt.append(' }')
994 header_txt.append('}')
995 header_txt.append('')
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600996 header_txt.append('%s' % self.lineinfo.get())
Jon Ashburnbacb0f52015-04-06 10:58:22 -0600997 header_txt.append('static VkBaseLayerObject *pCurObj;')
Tobin Ehlisa2b199c2015-04-27 17:30:04 -0600998 header_txt.append('static bool g_APIDumpDetailed = true;')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600999 header_txt.append('')
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -06001000 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001001 header_txt.append('')
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001002 header_txt.append('static int printLockInitialized = 0;')
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001003 header_txt.append('static loader_platform_thread_mutex printLock;')
1004 header_txt.append('')
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001005 header_txt.append('%s' % self.lineinfo.get())
Tobin Ehlisa30e7e52015-07-06 14:02:36 -06001006 header_txt.append('#define LAYER_EXT_ARRAY_SIZE 1')
1007 header_txt.append('#define LAYER_DEV_EXT_ARRAY_SIZE 1')
Tobin Ehlisd009bae2014-11-24 15:46:55 -07001008 header_txt.append('#define MAX_TID 513')
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001009 header_txt.append('static loader_platform_thread_id tidMapping[MAX_TID] = {0};')
Tobin Ehlisd009bae2014-11-24 15:46:55 -07001010 header_txt.append('static uint32_t maxTID = 0;')
1011 header_txt.append('// Map actual TID to an index value and return that index')
1012 header_txt.append('// This keeps TIDs in range from 0-MAX_TID and simplifies compares between runs')
1013 header_txt.append('static uint32_t getTIDIndex() {')
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001014 header_txt.append(' loader_platform_thread_id tid = loader_platform_get_thread_id();')
Tobin Ehlisd009bae2014-11-24 15:46:55 -07001015 header_txt.append(' for (uint32_t i = 0; i < maxTID; i++) {')
1016 header_txt.append(' if (tid == tidMapping[i])')
1017 header_txt.append(' return i;')
1018 header_txt.append(' }')
1019 header_txt.append(" // Don't yet have mapping, set it and return newly set index")
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001020 header_txt.append(' uint32_t retVal = (uint32_t) maxTID;')
Tobin Ehlisd009bae2014-11-24 15:46:55 -07001021 header_txt.append(' tidMapping[maxTID++] = tid;')
1022 header_txt.append(' assert(maxTID < MAX_TID);')
1023 header_txt.append(' return retVal;')
1024 header_txt.append('}')
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001025 header_txt.append('')
Tobin Ehlisd009bae2014-11-24 15:46:55 -07001026 return "\n".join(header_txt)
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001027
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001028 def generate_init(self):
1029 func_body = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001030 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001031 func_body.append('#include "vk_dispatch_table_helper.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -06001032 func_body.append('#include "vk_layer_config.h"')
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001033 func_body.append('')
1034 func_body.append('static void init%s(void)' % self.layer_name)
1035 func_body.append('{')
1036 func_body.append(' using namespace StreamControl;')
1037 func_body.append('')
Tobin Ehlisa8700972015-08-26 16:18:52 -06001038 func_body.append(' char const*const logName = getLayerOption("APIDumpLogFilename");')
1039 func_body.append(' if(logName != NULL)')
1040 func_body.append(' {')
1041 func_body.append(' fileName = logName;')
1042 func_body.append(' }')
1043 func_body.append('')
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001044 func_body.append(' char const*const detailedStr = getLayerOption("APIDumpDetailed");')
1045 func_body.append(' if(detailedStr != NULL)')
1046 func_body.append(' {')
1047 func_body.append(' if(strcmp(detailedStr, "TRUE") == 0)')
1048 func_body.append(' {')
1049 func_body.append(' g_APIDumpDetailed = true;')
1050 func_body.append(' }')
1051 func_body.append(' else if(strcmp(detailedStr, "FALSE") == 0)')
1052 func_body.append(' {')
1053 func_body.append(' g_APIDumpDetailed = false;')
1054 func_body.append(' }')
1055 func_body.append(' }')
1056 func_body.append('')
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001057 func_body.append(' char const*const writeToFileStr = getLayerOption("APIDumpFile");')
1058 func_body.append(' bool writeToFile = false;')
1059 func_body.append(' if(writeToFileStr != NULL)')
1060 func_body.append(' {')
1061 func_body.append(' if(strcmp(writeToFileStr, "TRUE") == 0)')
1062 func_body.append(' {')
1063 func_body.append(' writeToFile = true;')
1064 func_body.append(' }')
1065 func_body.append(' else if(strcmp(writeToFileStr, "FALSE") == 0)')
1066 func_body.append(' {')
1067 func_body.append(' writeToFile = false;')
1068 func_body.append(' }')
1069 func_body.append(' }')
1070 func_body.append('')
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001071 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001072 func_body.append(' char const*const noAddrStr = getLayerOption("APIDumpNoAddr");')
1073 func_body.append(' if(noAddrStr != NULL)')
1074 func_body.append(' {')
1075 func_body.append(' if(strcmp(noAddrStr, "FALSE") == 0)')
1076 func_body.append(' {')
1077 func_body.append(' StreamControl::writeAddress = true;')
1078 func_body.append(' }')
1079 func_body.append(' else if(strcmp(noAddrStr, "TRUE") == 0)')
1080 func_body.append(' {')
1081 func_body.append(' StreamControl::writeAddress = false;')
1082 func_body.append(' }')
1083 func_body.append(' }')
1084 func_body.append('')
1085 func_body.append(' char const*const flushAfterWriteStr = getLayerOption("APIDumpFlush");')
1086 func_body.append(' bool flushAfterWrite = false;')
1087 func_body.append(' if(flushAfterWriteStr != NULL)')
1088 func_body.append(' {')
1089 func_body.append(' if(strcmp(flushAfterWriteStr, "TRUE") == 0)')
1090 func_body.append(' {')
1091 func_body.append(' flushAfterWrite = true;')
1092 func_body.append(' }')
1093 func_body.append(' else if(strcmp(flushAfterWriteStr, "FALSE") == 0)')
1094 func_body.append(' {')
1095 func_body.append(' flushAfterWrite = false;')
1096 func_body.append(' }')
1097 func_body.append(' }')
1098 func_body.append('')
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001099 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001100 func_body.append(' ConfigureOutputStream(writeToFile, flushAfterWrite);')
1101 func_body.append('')
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001102 func_body.append(' if (!printLockInitialized)')
1103 func_body.append(' {')
1104 func_body.append(' // TODO/TBD: Need to delete this mutex sometime. How???')
1105 func_body.append(' loader_platform_thread_create_mutex(&printLock);')
1106 func_body.append(' printLockInitialized = 1;')
1107 func_body.append(' }')
1108 func_body.append('}')
1109 func_body.append('')
1110 return "\n".join(func_body)
Tobin Ehlis99f88672015-01-10 12:42:41 -07001111
Mike Stroyanbf237d72015-04-03 17:45:53 -06001112 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001113 if proto.name in [ 'EnumerateInstanceLayerProperties','EnumerateInstanceExtensionProperties','EnumerateDeviceLayerProperties','EnumerateDeviceExtensionProperties']:
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001114 return None
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001115 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyanbf237d72015-04-03 17:45:53 -06001116 ret_val = ''
1117 stmt = ''
1118 funcs = []
1119 sp_param_dict = {} # Store 'index' for struct param to print, or an name of binding "Count" param for array to print
1120 create_params = 0 # Num of params at end of function that are created and returned as output values
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001121 if 'AllocateDescriptorSets' in proto.name:
Cody Northrop1e4f8022015-08-03 12:47:29 -06001122 create_params = -1
Mike Stroyanbf237d72015-04-03 17:45:53 -06001123 elif 'Create' in proto.name or 'Alloc' in proto.name or 'MapMemory' in proto.name:
1124 create_params = -1
1125 if proto.ret != "void":
Jon Ashburnb0fbe912015-05-06 10:15:07 -06001126 ret_val = "%s result = " % proto.ret
Mike Stroyanbf237d72015-04-03 17:45:53 -06001127 stmt = " return result;\n"
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001128 f_open = 'loader_platform_thread_lock_mutex(&printLock);\n '
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001129 log_func = '%s\n' % self.lineinfo.get()
1130 log_func += ' if (StreamControl::writeAddress == true) {'
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001131 log_func += '\n (*outputStream) << "t{" << getTIDIndex() << "} vk%s(' % proto.name
1132 log_func_no_addr = '\n (*outputStream) << "t{" << getTIDIndex() << "} vk%s(' % proto.name
1133 f_close = '\n loader_platform_thread_unlock_mutex(&printLock);'
Mike Stroyanbf237d72015-04-03 17:45:53 -06001134 pindex = 0
1135 prev_count_name = ''
1136 for p in proto.params:
1137 cp = False
1138 if 0 != create_params:
1139 # If this is any of the N last params of the func, treat as output
1140 for y in range(-1, create_params-1, -1):
1141 if p.name == proto.params[y].name:
1142 cp = True
1143 (pft, pfi) = self._get_printf_params(p.ty, p.name, cp, cpp=True)
Jon Ashburn8acd2332015-09-16 18:08:32 -06001144 if p.name == "pSwapchain" or p.name == "pSwapchainImages":
Chia-I Wue2fc5522015-10-26 20:04:44 +08001145 log_func += '%s = " << %s << ", ' % (p.name, p.name)
Mark Lobodzinski25a2cc82015-12-02 16:12:08 -07001146 elif p.name == "swapchain" or p.name == "visual_id":
Chia-I Wue2fc5522015-10-26 20:04:44 +08001147 log_func += '%s = " << %s << ", ' % (p.name, p.name)
Ian Elliott1064fe32015-07-06 14:31:32 -06001148 else:
1149 log_func += '%s = " << %s << ", ' % (p.name, pfi)
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001150 if "%p" == pft:
1151 log_func_no_addr += '%s = address, ' % (p.name)
1152 else:
1153 log_func_no_addr += '%s = " << %s << ", ' % (p.name, pfi)
Tobin Ehlis08541742015-04-16 15:56:11 -06001154 if prev_count_name != '' and (prev_count_name.replace('Count', '')[1:] in p.name):
Mike Stroyanbf237d72015-04-03 17:45:53 -06001155 sp_param_dict[pindex] = prev_count_name
Tobin Ehlis08541742015-04-16 15:56:11 -06001156 prev_count_name = ''
Chia-I Wuf8693382015-04-16 22:02:10 +08001157 elif vk_helper.is_type(p.ty.strip('*').replace('const ', ''), 'struct'):
Mike Stroyanbf237d72015-04-03 17:45:53 -06001158 sp_param_dict[pindex] = 'index'
Mike Stroyanbf237d72015-04-03 17:45:53 -06001159 if p.name.endswith('Count'):
1160 if '*' in p.ty:
1161 prev_count_name = "*%s" % p.name
1162 else:
1163 prev_count_name = p.name
Courtney Goeltzenleuchterf260f6c2015-09-23 12:28:10 -06001164 else:
1165 prev_count_name = ''
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001166 pindex += 1
Mike Stroyanbf237d72015-04-03 17:45:53 -06001167 log_func = log_func.strip(', ')
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001168 log_func_no_addr = log_func_no_addr.strip(', ')
Jon Ashburnb0fbe912015-05-06 10:15:07 -06001169 if proto.ret == "VkResult":
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06001170 log_func += ') = " << string_VkResult((VkResult)result) << endl'
1171 log_func_no_addr += ') = " << string_VkResult((VkResult)result) << endl'
Jon Ashburnb0fbe912015-05-06 10:15:07 -06001172 elif proto.ret == "void*":
1173 log_func += ') = " << result << endl'
1174 log_func_no_addr += ') = " << result << endl'
Mike Stroyanbf237d72015-04-03 17:45:53 -06001175 else:
1176 log_func += ')\\n"'
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001177 log_func_no_addr += ')\\n"'
Mike Stroyanbf237d72015-04-03 17:45:53 -06001178 log_func += ';'
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001179 log_func_no_addr += ';'
Tobin Ehlisa30e7e52015-07-06 14:02:36 -06001180 log_func += '\n }\n else {%s\n }' % log_func_no_addr;
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001181 log_func += '\n%s' % self.lineinfo.get()
Courtney Goeltzenleuchterf260f6c2015-09-23 12:28:10 -06001182 # log_func += '\n// Proto %s has param_dict: %s' % (proto.name, sp_param_dict)
Mike Stroyanbf237d72015-04-03 17:45:53 -06001183 if len(sp_param_dict) > 0:
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001184 indent = ' '
1185 log_func += '\n%sif (g_APIDumpDetailed) {' % indent
1186 indent += ' '
Mike Stroyanbf237d72015-04-03 17:45:53 -06001187 i_decl = False
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001188 log_func += '\n%s' % self.lineinfo.get()
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001189 log_func += '\n%sstring tmp_str;' % indent
Mike Stroyanbf237d72015-04-03 17:45:53 -06001190 for sp_index in sp_param_dict:
Courtney Goeltzenleuchterf260f6c2015-09-23 12:28:10 -06001191 # log_func += '\n// sp_index: %s' % str(sp_index)
Mike Stroyanbf237d72015-04-03 17:45:53 -06001192 if 'index' == sp_param_dict[sp_index]:
Courtney Goeltzenleuchter95487bc2015-04-14 18:48:46 -06001193 cis_print_func = 'vk_print_%s' % (proto.params[sp_index].ty.replace('const ', '').strip('*').lower())
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001194 local_name = proto.params[sp_index].name
1195 if '*' not in proto.params[sp_index].ty:
1196 local_name = '&%s' % proto.params[sp_index].name
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001197 log_func += '\n%s' % self.lineinfo.get()
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001198 log_func += '\n%sif (%s) {' % (indent, local_name)
1199 indent += ' '
1200 log_func += '\n%stmp_str = %s(%s, " ");' % (indent, cis_print_func, local_name)
1201 log_func += '\n%s(*outputStream) << " %s (" << %s << ")" << endl << tmp_str << endl;' % (indent, local_name, local_name)
1202 indent = indent[4:]
1203 log_func += '\n%s}' % (indent)
Mike Stroyanbf237d72015-04-03 17:45:53 -06001204 else: # We have a count value stored to iterate over an array
1205 print_cast = ''
1206 print_func = ''
Courtney Goeltzenleuchter95487bc2015-04-14 18:48:46 -06001207 if vk_helper.is_type(proto.params[sp_index].ty.strip('*').replace('const ', ''), 'struct'):
Mike Stroyanbf237d72015-04-03 17:45:53 -06001208 print_cast = '&'
Courtney Goeltzenleuchter95487bc2015-04-14 18:48:46 -06001209 print_func = 'vk_print_%s' % proto.params[sp_index].ty.replace('const ', '').strip('*').lower()
Mike Stroyanbf237d72015-04-03 17:45:53 -06001210 else:
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001211 print_cast = ''
Mike Stroyanbf237d72015-04-03 17:45:53 -06001212 print_func = 'string_convert_helper'
1213 #cis_print_func = 'tmp_str = string_convert_helper((void*)%s[i], " ");' % proto.params[sp_index].name
Chia-I Wue2fc5522015-10-26 20:04:44 +08001214 cis_print_func = 'tmp_str = %s(%s%s[i], " ");' % (print_func, print_cast, proto.params[sp_index].name)
Mike Stroyanbf237d72015-04-03 17:45:53 -06001215 if not i_decl:
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001216 log_func += '\n%suint32_t i;' % (indent)
Mike Stroyanbf237d72015-04-03 17:45:53 -06001217 i_decl = True
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001218 log_func += '\n%sif (%s) {' % (indent, proto.params[sp_index].name)
1219 indent += ' '
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001220 log_func += '\n%s' % self.lineinfo.get()
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001221 log_func += '\n%sfor (i = 0; i < %s; i++) {' % (indent, sp_param_dict[sp_index])
1222 indent += ' '
1223 log_func += '\n%s%s' % (indent, cis_print_func)
Tobin Ehlis45a23a82015-04-28 10:58:20 -06001224 log_func += '\n%sif (StreamControl::writeAddress == true) {' % (indent)
1225 indent += ' '
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001226 log_func += '\n%s(*outputStream) << " %s[" << i << "] (" << %s%s[i] << ")" << endl << tmp_str << endl;' % (indent, proto.params[sp_index].name, '&', proto.params[sp_index].name)
1227 indent = indent[4:]
Tobin Ehlis45a23a82015-04-28 10:58:20 -06001228 log_func += '\n%s} else {' % (indent)
1229 indent += ' '
1230 log_func += '\n%s(*outputStream) << " %s[" << i << "] (address)" << endl << " address" << endl;' % (indent, proto.params[sp_index].name)
1231 indent = indent[4:]
1232 log_func += '\n%s}' % (indent)
1233 indent = indent[4:]
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001234 log_func += '\n%s}' % (indent)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001235 indent = indent[4:]
1236 log_func += '\n%s}' % (indent)
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001237 indent = indent[4:]
1238 log_func += '\n%s}' % (indent)
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001239 table_type = ''
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001240 if proto_is_global(proto):
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001241 table_type = 'instance'
1242 else:
1243 table_type = 'device'
Jon Ashburn3dc39382015-09-17 10:00:32 -06001244 dispatch_param = proto.params[0].name
Jon Ashburn71836d92015-05-12 17:23:55 -06001245
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001246 if proto.name == "CreateInstance":
1247 dispatch_param = '*' + proto.params[1].name
Jon Ashburn3dc39382015-09-17 10:00:32 -06001248 funcs.append('%s%s\n'
1249 '{\n'
1250 ' using namespace StreamControl;\n'
1251 ' %sinstance_dispatch_table(*pInstance)->%s;\n'
1252 ' if (result == VK_SUCCESS) {\n'
1253 ' createInstanceRegisterExtensions(pCreateInfo, *pInstance);\n'
1254 ' }\n'
1255 ' %s%s%s\n'
1256 '%s'
1257 '}\n' % (qual, decl, ret_val, proto.c_call(), f_open, log_func, f_close, stmt))
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001258
Jon Ashburn3dc39382015-09-17 10:00:32 -06001259 elif proto.name == "CreateDevice":
Courtney Goeltzenleuchter0de9e212015-06-26 15:07:53 -06001260 funcs.append('%s\n' % self.lineinfo.get())
Jon Ashburn747f2b62015-06-18 15:02:58 -06001261 funcs.append('%s%s\n'
1262 '{\n'
1263 ' using namespace StreamControl;\n'
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06001264 ' %sdevice_dispatch_table(*pDevice)->%s;\n'
Jon Ashburn747f2b62015-06-18 15:02:58 -06001265 ' if (result == VK_SUCCESS)\n'
1266 ' createDeviceRegisterExtensions(pCreateInfo, *pDevice);\n'
1267 ' %s%s%s\n'
1268 '%s'
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06001269 '}' % (qual, decl, ret_val, proto.c_call(), f_open, log_func, f_close, stmt))
Jon Ashburn747f2b62015-06-18 15:02:58 -06001270 elif proto.name == "DestroyDevice":
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001271 funcs.append('%s%s\n'
1272 '{\n'
1273 ' using namespace StreamControl;\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001274 ' dispatch_key key = get_dispatch_key(device);\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -06001275 ' VkLayerDispatchTable *pDisp = %s_dispatch_table(%s);\n'
Jon Ashburn747f2b62015-06-18 15:02:58 -06001276 ' %spDisp->%s;\n'
1277 ' deviceExtMap.erase(pDisp);\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001278 ' destroy_device_dispatch_table(key);\n'
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001279 ' %s%s%s\n'
1280 '%s'
Jon Ashburn747f2b62015-06-18 15:02:58 -06001281 '}' % (qual, decl, table_type, dispatch_param, ret_val, proto.c_call(), f_open, log_func, f_close, stmt))
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001282 elif proto.name == "DestroyInstance":
1283 funcs.append('%s%s\n'
1284 '{\n'
1285 ' using namespace StreamControl;\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001286 ' dispatch_key key = get_dispatch_key(instance);\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -06001287 ' VkLayerInstanceDispatchTable *pDisp = %s_dispatch_table(%s);\n'
1288 ' %spDisp->%s;\n'
1289 ' instanceExtMap.erase(pDisp);\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001290 ' destroy_instance_dispatch_table(key);\n'
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001291 ' %s%s%s\n'
1292 '%s'
Jon Ashburn3dc39382015-09-17 10:00:32 -06001293 '}' % (qual, decl, table_type, dispatch_param, ret_val, proto.c_call(), f_open, log_func, f_close, stmt))
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001294 else:
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001295 if wsi_name(decl):
1296 funcs.append('%s' % wsi_ifdef(decl))
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001297 funcs.append('%s%s\n'
1298 '{\n'
1299 ' using namespace StreamControl;\n'
1300 ' %s%s_dispatch_table(%s)->%s;\n'
Jon Ashburnbacb0f52015-04-06 10:58:22 -06001301 ' %s%s%s\n'
1302 '%s'
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001303 '}' % (qual, decl, ret_val, table_type, dispatch_param, proto.c_call(), f_open, log_func, f_close, stmt))
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001304 if wsi_name(decl):
1305 funcs.append('%s' % wsi_endif(decl))
Mike Stroyanbf237d72015-04-03 17:45:53 -06001306 return "\n\n".join(funcs)
1307
Tobin Ehlis99f88672015-01-10 12:42:41 -07001308 def generate_body(self):
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001309 self.layer_name = "api_dump"
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001310 if sys.platform.startswith('win32'):
Michael Lentine64e2ebd2015-12-03 14:33:09 -08001311 instance_extensions=[('wsi_enabled',
1312 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1313 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1314 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1315 'vkGetPhysicalDeviceSurfacePresentModesKHR',
1316 'vkCreateWin32SurfaceKHR',
1317 'vkGetPhysicalDeviceWin32PresentationSupportKHR'])]
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001318 elif sys.platform.startswith('linux'):
Michael Lentine64e2ebd2015-12-03 14:33:09 -08001319 instance_extensions=[('wsi_enabled',
1320 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1321 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1322 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1323 'vkGetPhysicalDeviceSurfacePresentModesKHR',
1324 'vkCreateXcbSurfaceKHR',
Mark Lobodzinskib49b6e52015-11-26 10:59:58 -07001325 'vkGetPhysicalDeviceXcbPresentationSupportKHR'])]
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001326 # TODO: Add cases for Mir, Xlib, Wayland
1327 else:
1328 instance_extensions=[('wsi_enabled',
1329 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1330 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1331 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1332 'vkGetPhysicalDeviceSurfacePresentModesKHR'])]
Ian Elliott1064fe32015-07-06 14:31:32 -06001333 extensions=[('wsi_enabled',
Ian Elliott05846062015-11-20 14:13:17 -07001334 ['vkCreateSwapchainKHR',
Jon Ashburn8acd2332015-09-16 18:08:32 -06001335 'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
1336 'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001337 body = [self.generate_init(),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001338 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Jon Ashburn3dc39382015-09-17 10:00:32 -06001339 self._generate_layer_gpa_function(extensions, instance_extensions)]
Tobin Ehlis99f88672015-01-10 12:42:41 -07001340 return "\n\n".join(body)
1341
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001342class ObjectTrackerSubcommand(Subcommand):
1343 def generate_header(self):
1344 header_txt = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001345 header_txt.append('%s' % self.lineinfo.get())
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001346 header_txt.append('#include <stdio.h>')
1347 header_txt.append('#include <stdlib.h>')
1348 header_txt.append('#include <string.h>')
1349 header_txt.append('#include <inttypes.h>')
1350 header_txt.append('')
David Pinedo9316d3b2015-11-06 12:54:48 -07001351 header_txt.append('#include "vulkan/vulkan.h"')
Tobin Ehlisb835d1b2015-07-03 10:34:49 -06001352 header_txt.append('#include "vk_loader_platform.h"')
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001353 header_txt.append('')
Tobin Ehlis803cc492015-06-08 17:36:28 -06001354 header_txt.append('#include <unordered_map>')
1355 header_txt.append('using namespace std;')
David Pinedo9316d3b2015-11-06 12:54:48 -07001356 header_txt.append('#include "vulkan/vk_layer.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -06001357 header_txt.append('#include "vk_layer_config.h"')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001358 header_txt.append('#include "vulkan/vk_ext_debug_report.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -06001359 header_txt.append('#include "vk_layer_table.h"')
1360 header_txt.append('#include "vk_layer_data.h"')
1361 header_txt.append('#include "vk_layer_logging.h"')
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001362 header_txt.append('')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001363# NOTE: The non-autoGenerated code is in the object_tracker.h header file
1364 header_txt.append('#include "object_tracker.h"')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001365 header_txt.append('')
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -06001366 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001367 header_txt.append('')
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001368 return "\n".join(header_txt)
1369
Tony Barboura05dbaa2015-07-09 17:31:46 -06001370 def generate_maps(self):
1371 maps_txt = []
Tobin Ehlis86684f92016-01-05 10:33:58 -07001372 for o in vulkan.object_type_list:
Michael Lentine13803dc2015-11-04 14:35:12 -08001373 maps_txt.append('unordered_map<uint64_t, OBJTRACK_NODE*> %sMap;' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001374 return "\n".join(maps_txt)
1375
Tobin Ehlis86684f92016-01-05 10:33:58 -07001376 def _gather_object_uses(self, obj_list, struct_type, obj_set):
1377 # for each member of struct_type
1378 # add objs in obj_list to obj_set
1379 # call self for structs
1380 for m in vk_helper.struct_dict[struct_type]:
1381 if vk_helper.struct_dict[struct_type][m]['type'] in obj_list:
1382 obj_set.add(vk_helper.struct_dict[struct_type][m]['type'])
1383 elif vk_helper.is_type(vk_helper.struct_dict[struct_type][m]['type'], 'struct'):
1384 obj_set = obj_set.union(self._gather_object_uses(obj_list, vk_helper.struct_dict[struct_type][m]['type'], obj_set))
1385 return obj_set
1386
Tony Barboura05dbaa2015-07-09 17:31:46 -06001387 def generate_procs(self):
1388 procs_txt = []
Tobin Ehlis86684f92016-01-05 10:33:58 -07001389 # First parse through funcs and gather dict of all objects seen by each call
1390 obj_use_dict = {}
1391 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
1392 for proto in proto_list:
1393 disp_obj = proto.params[0].ty.strip('*').replace('const ', '')
1394 if disp_obj in vulkan.object_dispatch_list:
1395 if disp_obj not in obj_use_dict:
1396 obj_use_dict[disp_obj] = set()
1397 for p in proto.params[1:]:
1398 base_type = p.ty.strip('*').replace('const ', '')
1399 if base_type in vulkan.object_type_list:
1400 obj_use_dict[disp_obj].add(base_type)
1401 if vk_helper.is_type(base_type, 'struct'):
1402 obj_use_dict[disp_obj] = self._gather_object_uses(vulkan.object_type_list, base_type, obj_use_dict[disp_obj])
1403 #for do in obj_use_dict:
1404 # print "Disp obj %s has uses for objs: %s" % (do, ', '.join(obj_use_dict[do]))
1405
1406 for o in vulkan.object_type_list:# vulkan.core.objects:
Tony Barboura05dbaa2015-07-09 17:31:46 -06001407 procs_txt.append('%s' % self.lineinfo.get())
Michael Lentine13803dc2015-11-04 14:35:12 -08001408 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o)
1409 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Tobin Ehlis154e0462015-08-26 11:22:09 -06001410 if o in vulkan.object_dispatch_list:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001411 procs_txt.append('static void create_%s(%s dispatchable_object, %s vkObj, VkDebugReportObjectTypeEXT objType)' % (name, o, o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001412 else:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001413 procs_txt.append('static void create_%s(VkDevice dispatchable_object, %s vkObj, VkDebugReportObjectTypeEXT objType)' % (name, o))
Chia-I Wue2fc5522015-10-26 20:04:44 +08001414 procs_txt.append('{')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001415 procs_txt.append(' log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFO_BIT_EXT, objType, reinterpret_cast<uint64_t>(vkObj), __LINE__, OBJTRACK_NONE, "OBJTRACK",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001416 procs_txt.append(' "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64 , object_track_index++, string_VkDebugReportObjectTypeEXT(objType),')
Chia-I Wue2fc5522015-10-26 20:04:44 +08001417 procs_txt.append(' reinterpret_cast<uint64_t>(vkObj));')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001418 procs_txt.append('')
1419 procs_txt.append(' OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE;')
1420 procs_txt.append(' pNewObjNode->objType = objType;')
1421 procs_txt.append(' pNewObjNode->status = OBJSTATUS_NONE;')
Chia-I Wue2fc5522015-10-26 20:04:44 +08001422 procs_txt.append(' pNewObjNode->vkObj = reinterpret_cast<uint64_t>(vkObj);')
Michael Lentine13803dc2015-11-04 14:35:12 -08001423 procs_txt.append(' %sMap[(uint64_t)vkObj] = pNewObjNode;' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001424 procs_txt.append(' uint32_t objIndex = objTypeToIndex(objType);')
1425 procs_txt.append(' numObjs[objIndex]++;')
1426 procs_txt.append(' numTotalObjs++;')
1427 procs_txt.append('}')
1428 procs_txt.append('')
1429 procs_txt.append('%s' % self.lineinfo.get())
Tobin Ehlis154e0462015-08-26 11:22:09 -06001430 if o in vulkan.object_dispatch_list:
Michael Lentine13803dc2015-11-04 14:35:12 -08001431 procs_txt.append('static void destroy_%s(%s dispatchable_object, %s object)' % (name, o, o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001432 else:
Michael Lentine13803dc2015-11-04 14:35:12 -08001433 procs_txt.append('static void destroy_%s(VkDevice dispatchable_object, %s object)' % (name, o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001434 procs_txt.append('{')
Michael Lentine13803dc2015-11-04 14:35:12 -08001435 procs_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
1436 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
1437 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[(uint64_t)object];' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001438 procs_txt.append(' uint32_t objIndex = objTypeToIndex(pNode->objType);')
1439 procs_txt.append(' assert(numTotalObjs > 0);')
1440 procs_txt.append(' numTotalObjs--;')
1441 procs_txt.append(' assert(numObjs[objIndex] > 0);')
1442 procs_txt.append(' numObjs[objIndex]--;')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001443 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 -08001444 procs_txt.append(' "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%" PRIu64 " total objs remain & %" PRIu64 " %s objs).",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001445 procs_txt.append(' string_VkDebugReportObjectTypeEXT(pNode->objType), reinterpret_cast<uint64_t>(object), numTotalObjs, numObjs[objIndex],')
1446 procs_txt.append(' string_VkDebugReportObjectTypeEXT(pNode->objType));')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001447 procs_txt.append(' delete pNode;')
Michael Lentine13803dc2015-11-04 14:35:12 -08001448 procs_txt.append(' %sMap.erase(object_handle);' % (o))
Chia-I Wue2fc5522015-10-26 20:04:44 +08001449 procs_txt.append(' } else {')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001450 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 +08001451 procs_txt.append(' "Unable to remove obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?",')
Michael Lentine13803dc2015-11-04 14:35:12 -08001452 procs_txt.append(' object_handle);')
Chia-I Wue2fc5522015-10-26 20:04:44 +08001453 procs_txt.append(' }')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001454 procs_txt.append('}')
1455 procs_txt.append('')
1456 procs_txt.append('%s' % self.lineinfo.get())
Tobin Ehlis154e0462015-08-26 11:22:09 -06001457 if o in vulkan.object_dispatch_list:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001458 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 -06001459 else:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001460 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 +08001461 procs_txt.append('{')
1462 procs_txt.append(' if (object != VK_NULL_HANDLE) {')
Michael Lentine13803dc2015-11-04 14:35:12 -08001463 procs_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
1464 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
1465 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[object_handle];' % (o))
Tobin Ehlis154e0462015-08-26 11:22:09 -06001466 procs_txt.append(' pNode->status |= status_flag;')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001467 procs_txt.append(' }')
1468 procs_txt.append(' else {')
1469 procs_txt.append(' // If we do not find it print an error')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001470 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 +08001471 procs_txt.append(' "Unable to set status for non-existent object 0x%" PRIxLEAST64 " of %s type",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001472 procs_txt.append(' object_handle, string_VkDebugReportObjectTypeEXT(objType));')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001473 procs_txt.append(' }')
1474 procs_txt.append(' }')
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -06001475 procs_txt.append(' return VK_FALSE;')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001476 procs_txt.append('}')
1477 procs_txt.append('')
1478 procs_txt.append('%s' % self.lineinfo.get())
Michael Lentine13803dc2015-11-04 14:35:12 -08001479 procs_txt.append('static VkBool32 validate_%s_status(' % (name))
Tobin Ehlis154e0462015-08-26 11:22:09 -06001480 if o in vulkan.object_dispatch_list:
Tony Barboura05dbaa2015-07-09 17:31:46 -06001481 procs_txt.append('%s dispatchable_object, %s object,' % (o, o))
1482 else:
1483 procs_txt.append('VkDevice dispatchable_object, %s object,' % (o))
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001484 procs_txt.append(' VkDebugReportObjectTypeEXT objType,')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001485 procs_txt.append(' ObjectStatusFlags status_mask,')
1486 procs_txt.append(' ObjectStatusFlags status_flag,')
1487 procs_txt.append(' VkFlags msg_flags,')
1488 procs_txt.append(' OBJECT_TRACK_ERROR error_code,')
1489 procs_txt.append(' const char *fail_msg)')
1490 procs_txt.append('{')
Michael Lentine13803dc2015-11-04 14:35:12 -08001491 procs_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
1492 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
1493 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[object_handle];' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001494 procs_txt.append(' if ((pNode->status & status_mask) != status_flag) {')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001495 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 -07001496 procs_txt.append(' "OBJECT VALIDATION WARNING: %s object 0x%" PRIxLEAST64 ": %s", string_VkDebugReportObjectTypeEXT(objType),')
Michael Lentine13803dc2015-11-04 14:35:12 -08001497 procs_txt.append(' object_handle, fail_msg);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001498 procs_txt.append(' return VK_FALSE;')
1499 procs_txt.append(' }')
1500 procs_txt.append(' return VK_TRUE;')
1501 procs_txt.append(' }')
1502 procs_txt.append(' else {')
1503 procs_txt.append(' // If we do not find it print an error')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001504 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 +08001505 procs_txt.append(' "Unable to obtain status for non-existent object 0x%" PRIxLEAST64 " of %s type",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001506 procs_txt.append(' object_handle, string_VkDebugReportObjectTypeEXT(objType));')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001507 procs_txt.append(' return VK_FALSE;')
1508 procs_txt.append(' }')
1509 procs_txt.append('}')
1510 procs_txt.append('')
1511 procs_txt.append('%s' % self.lineinfo.get())
Tobin Ehlis154e0462015-08-26 11:22:09 -06001512 if o in vulkan.object_dispatch_list:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001513 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 -06001514 else:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001515 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 +08001516 procs_txt.append('{')
Michael Lentine13803dc2015-11-04 14:35:12 -08001517 procs_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
1518 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
1519 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[object_handle];' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001520 procs_txt.append(' pNode->status &= ~status_flag;')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001521 procs_txt.append(' }')
1522 procs_txt.append(' else {')
1523 procs_txt.append(' // If we do not find it print an error')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001524 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 +08001525 procs_txt.append(' "Unable to reset status for non-existent object 0x%" PRIxLEAST64 " of %s type",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001526 procs_txt.append(' object_handle, string_VkDebugReportObjectTypeEXT(objType));')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001527 procs_txt.append(' }')
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -06001528 procs_txt.append(' return VK_FALSE;')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001529 procs_txt.append('}')
1530 procs_txt.append('')
Tobin Ehlis86684f92016-01-05 10:33:58 -07001531 procs_txt.append('%s' % self.lineinfo.get())
1532 # Generate the permutations of validate_* functions where for each
1533 # dispatchable object type, we have a corresponding validate_* function
1534 # for that object and all non-dispatchable objects that are used in API
1535 # calls with that dispatchable object.
1536 procs_txt.append('//%s' % str(obj_use_dict))
1537 for do in obj_use_dict:
1538 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', do)
1539 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
1540 # First create validate_* func for disp obj
1541 procs_txt.append('%s' % self.lineinfo.get())
1542 procs_txt.append('static VkBool32 validate_%s(%s dispatchable_object, %s object, VkDebugReportObjectTypeEXT objType, bool null_allowed)' % (name, do, do))
1543 procs_txt.append('{')
1544 procs_txt.append(' if (null_allowed && (object == VK_NULL_HANDLE))')
1545 procs_txt.append(' return VK_FALSE;')
1546 procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (do, do))
1547 procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, objType, reinterpret_cast<uint64_t>(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
1548 procs_txt.append(' "Invalid %s Object 0x%%" PRIx64 ,reinterpret_cast<uint64_t>(object));' % do)
1549 procs_txt.append(' }')
1550 procs_txt.append(' return VK_FALSE;')
1551 procs_txt.append('}')
1552 procs_txt.append('')
1553 for o in obj_use_dict[do]:
1554 if o == do: # We already generated this case above so skip here
1555 continue
1556 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o)
1557 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
1558 procs_txt.append('%s' % self.lineinfo.get())
1559 procs_txt.append('static VkBool32 validate_%s(%s dispatchable_object, %s object, VkDebugReportObjectTypeEXT objType, bool null_allowed)' % (name, do, o))
1560 procs_txt.append('{')
1561 procs_txt.append(' if (null_allowed && (object == VK_NULL_HANDLE))')
1562 procs_txt.append(' return VK_FALSE;')
1563 if o == "VkImage":
1564 procs_txt.append(' // We need to validate normal image objects and those from the swapchain')
1565 procs_txt.append(' if ((%sMap.find((uint64_t)object) == %sMap.end()) &&' % (o, o))
1566 procs_txt.append(' (swapchainImageMap.find((uint64_t)object) == swapchainImageMap.end())) {')
1567 else:
1568 procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (o, o))
1569 procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, objType, reinterpret_cast<uint64_t>(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
1570 procs_txt.append(' "Invalid %s Object 0x%%" PRIx64, reinterpret_cast<uint64_t>(object));' % o)
1571 procs_txt.append(' }')
1572 procs_txt.append(' return VK_FALSE;')
1573 procs_txt.append('}')
1574 procs_txt.append('')
1575 procs_txt.append('')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001576 return "\n".join(procs_txt)
1577
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001578 def generate_destroy_instance(self):
Tony Barboura05dbaa2015-07-09 17:31:46 -06001579 gedi_txt = []
1580 gedi_txt.append('%s' % self.lineinfo.get())
Mark Lobodzinski2141f652015-09-07 13:59:43 -06001581 gedi_txt.append('void vkDestroyInstance(')
Chia-I Wuf7458c52015-10-26 21:10:41 +08001582 gedi_txt.append('VkInstance instance,')
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001583 gedi_txt.append('const VkAllocationCallbacks* pAllocator)')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001584 gedi_txt.append('{')
1585 gedi_txt.append(' loader_platform_thread_lock_mutex(&objLock);')
Tobin Ehlis86684f92016-01-05 10:33:58 -07001586 gedi_txt.append(' validate_instance(instance, instance, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, false);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001587 gedi_txt.append('')
Michael Lentine13803dc2015-11-04 14:35:12 -08001588 gedi_txt.append(' destroy_instance(instance, instance);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001589 gedi_txt.append(' // Report any remaining objects in LL')
1590 for o in vulkan.core.objects:
Mike Stroyan0699a792015-08-18 14:48:34 -06001591 if o in ['VkInstance', 'VkPhysicalDevice', 'VkQueue']:
Tony Barboura05dbaa2015-07-09 17:31:46 -06001592 continue
1593 gedi_txt.append(' for (auto it = %sMap.begin(); it != %sMap.end(); ++it) {' % (o, o))
1594 gedi_txt.append(' OBJTRACK_NODE* pNode = it->second;')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001595 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 -07001596 gedi_txt.append(' "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),')
Tony Barbour343d6212015-07-10 18:32:33 -06001597 gedi_txt.append(' pNode->vkObj);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001598 gedi_txt.append(' }')
Mike Stroyan0699a792015-08-18 14:48:34 -06001599 gedi_txt.append(' %sMap.clear();' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001600 gedi_txt.append('')
1601 gedi_txt.append(' dispatch_key key = get_dispatch_key(instance);')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001602 gedi_txt.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(object_tracker_instance_table_map, instance);')
Chia-I Wuf7458c52015-10-26 21:10:41 +08001603 gedi_txt.append(' pInstanceTable->DestroyInstance(instance, pAllocator);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001604 gedi_txt.append('')
1605 gedi_txt.append(' // Clean up logging callback, if any')
1606 gedi_txt.append(' layer_data *my_data = get_my_data_ptr(key, layer_data_map);')
1607 gedi_txt.append(' if (my_data->logging_callback) {')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07001608 gedi_txt.append(' layer_destroy_msg_callback(my_data->report_data, my_data->logging_callback, pAllocator);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001609 gedi_txt.append(' }')
1610 gedi_txt.append('')
1611 gedi_txt.append(' layer_debug_report_destroy_instance(mid(instance));')
1612 gedi_txt.append(' layer_data_map.erase(pInstanceTable);')
1613 gedi_txt.append('')
Jon Ashburn3dc39382015-09-17 10:00:32 -06001614 gedi_txt.append(' instanceExtMap.erase(pInstanceTable);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001615 gedi_txt.append(' loader_platform_thread_unlock_mutex(&objLock);')
Mike Stroyan0699a792015-08-18 14:48:34 -06001616 # The loader holds a mutex that protects this from other threads
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001617 gedi_txt.append(' object_tracker_instance_table_map.erase(key);')
1618 gedi_txt.append(' if (object_tracker_instance_table_map.empty()) {')
Mike Stroyan0699a792015-08-18 14:48:34 -06001619 gedi_txt.append(' // Release mutex when destroying last instance.')
1620 gedi_txt.append(' loader_platform_thread_delete_mutex(&objLock);')
1621 gedi_txt.append(' objLockInitialized = 0;')
1622 gedi_txt.append(' }')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001623 gedi_txt.append('}')
1624 gedi_txt.append('')
1625 return "\n".join(gedi_txt)
1626
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001627 def generate_destroy_device(self):
Tony Barboura05dbaa2015-07-09 17:31:46 -06001628 gedd_txt = []
1629 gedd_txt.append('%s' % self.lineinfo.get())
Mark Lobodzinski2141f652015-09-07 13:59:43 -06001630 gedd_txt.append('void vkDestroyDevice(')
Chia-I Wuf7458c52015-10-26 21:10:41 +08001631 gedd_txt.append('VkDevice device,')
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001632 gedd_txt.append('const VkAllocationCallbacks* pAllocator)')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001633 gedd_txt.append('{')
1634 gedd_txt.append(' loader_platform_thread_lock_mutex(&objLock);')
Tobin Ehlis86684f92016-01-05 10:33:58 -07001635 gedd_txt.append(' validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001636 gedd_txt.append('')
Michael Lentine13803dc2015-11-04 14:35:12 -08001637 gedd_txt.append(' destroy_device(device, device);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001638 gedd_txt.append(' // Report any remaining objects in LL')
1639 for o in vulkan.core.objects:
Mark Lobodzinski5f5c0e12015-11-12 16:02:35 -07001640 # DescriptorSets and Command Buffers are destroyed through their pools, not explicitly
1641 if o in ['VkInstance', 'VkPhysicalDevice', 'VkQueue', 'VkDevice', 'VkDescriptorSet', 'VkCommandBuffer']:
Tony Barboura05dbaa2015-07-09 17:31:46 -06001642 continue
Mark Lobodzinski5f5c0e12015-11-12 16:02:35 -07001643 gedd_txt.append(' for (auto it = %sMap.begin(); it != %sMap.end(); ++it) {' % (o, o))
1644 gedd_txt.append(' OBJTRACK_NODE* pNode = it->second;')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001645 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 -07001646 gedd_txt.append(' "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),')
Mark Lobodzinski5f5c0e12015-11-12 16:02:35 -07001647 gedd_txt.append(' pNode->vkObj);')
1648 gedd_txt.append(' }')
Mike Stroyan0699a792015-08-18 14:48:34 -06001649 gedd_txt.append(' %sMap.clear();' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001650 gedd_txt.append('')
1651 gedd_txt.append(" // Clean up Queue's MemRef Linked Lists")
1652 gedd_txt.append(' destroyQueueMemRefLists();')
1653 gedd_txt.append('')
1654 gedd_txt.append(' loader_platform_thread_unlock_mutex(&objLock);')
1655 gedd_txt.append('')
1656 gedd_txt.append(' dispatch_key key = get_dispatch_key(device);')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001657 gedd_txt.append(' VkLayerDispatchTable *pDisp = get_dispatch_table(object_tracker_device_table_map, device);')
Chia-I Wuf7458c52015-10-26 21:10:41 +08001658 gedd_txt.append(' pDisp->DestroyDevice(device, pAllocator);')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001659 gedd_txt.append(' object_tracker_device_table_map.erase(key);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001660 gedd_txt.append('')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001661 gedd_txt.append('}')
1662 gedd_txt.append('')
1663 return "\n".join(gedd_txt)
1664
Mark Lobodzinski9fde6392016-01-19 09:57:24 -07001665 # Special-case validating the array pointers in UpdateDescriptorSets. They may not be NULL but should
1666 # be ignored if the descriptorType does not specify those arrays.
1667 def _handle_descriptorType(self, indent, prefix, type_name, name):
1668 s_code = ''
1669 if type_name == 'pBufferInfo':
1670 s_code += '%sif ((%sdescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||\n' % (indent, prefix)
1671 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||\n' % (indent, prefix)
1672 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||\n' % (indent, prefix)
1673 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) ) {\n' % (indent, prefix)
1674 elif type_name == 'pImageInfo':
1675 s_code += '%sif ((%sdescriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) ||\n' % (indent, prefix)
1676 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||\n' % (indent, prefix)
1677 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) ||\n' % (indent, prefix)
1678 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||\n' % (indent, prefix)
1679 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ) {\n' % (indent, prefix)
1680 elif type_name == 'pTexelBufferView':
1681 s_code += '%sif ((%sdescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) ||\n' % (indent, prefix)
1682 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) ) {\n' % (indent, prefix)
1683 else:
1684 s_code += '%sif (%s) {\n' % (indent, name)
1685 return s_code
1686
Tobin Ehlis86684f92016-01-05 10:33:58 -07001687 def _gen_obj_validate_code(self, struct_uses, obj_type_mapping, func_name, valid_null_dict, param0_name, indent, prefix, array_index):
1688 pre_code = ''
1689 for obj in sorted(struct_uses):
1690 name = obj
1691 array = ''
Mark Lobodzinski9fde6392016-01-19 09:57:24 -07001692 type_name = ''
Tobin Ehlis86684f92016-01-05 10:33:58 -07001693 if '[' in obj:
1694 (name, array) = obj.split('[')
Mark Lobodzinski9fde6392016-01-19 09:57:24 -07001695 type_name = name
Tobin Ehlis86684f92016-01-05 10:33:58 -07001696 array = array.strip(']')
1697 if isinstance(struct_uses[obj], dict):
1698 local_prefix = ''
1699 name = '%s%s' % (prefix, name)
1700 ptr_type = False
1701 if 'p' == obj[0]:
1702 ptr_type = True
Mark Lobodzinski9fde6392016-01-19 09:57:24 -07001703 tmp_pre = self._handle_descriptorType(indent, prefix, type_name, name)
1704 pre_code += tmp_pre
Tobin Ehlis86684f92016-01-05 10:33:58 -07001705 indent += ' '
1706 if array != '':
1707 idx = 'idx%s' % str(array_index)
1708 array_index += 1
1709 pre_code += '%s\n' % self.lineinfo.get()
1710 pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
1711 indent += ' '
1712 local_prefix = '%s[%s].' % (name, idx)
1713 elif ptr_type:
1714 local_prefix = '%s->' % (name)
1715 else:
1716 local_prefix = '%s.' % (name)
1717 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)
1718 pre_code += tmp_pre
1719 if array != '':
1720 indent = indent[4:]
1721 pre_code += '%s}\n' % (indent)
1722 if ptr_type:
1723 indent = indent[4:]
1724 pre_code += '%s}\n' % (indent)
1725 else:
1726 ptype = struct_uses[obj]
1727 dbg_obj_type = obj_type_mapping[ptype]
1728 fname = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', ptype)
1729 fname = re.sub('([a-z0-9])([A-Z])', r'\1_\2', fname).lower()[3:]
1730 full_name = '%s%s' % (prefix, name)
1731 null_obj_ok = 'false'
1732 # If a valid null param is defined for this func and we have a match, allow NULL
1733 if func_name in valid_null_dict and True in [name in pn for pn in valid_null_dict[func_name]]:
1734 null_obj_ok = 'true'
1735 if (array_index > 0) or '' != array:
Mark Lobodzinski9fde6392016-01-19 09:57:24 -07001736 tmp_pre = self._handle_descriptorType(indent, prefix, type_name, full_name)
1737 pre_code += tmp_pre
Tobin Ehlis86684f92016-01-05 10:33:58 -07001738 indent += ' '
1739 if array != '':
1740 idx = 'idx%s' % str(array_index)
1741 array_index += 1
1742 pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
1743 indent += ' '
1744 full_name = '%s[%s]' % (full_name, idx)
1745 pre_code += '%s\n' % self.lineinfo.get()
1746 pre_code += '%sskipCall |= validate_%s(%s, %s, %s, %s);\n' %(indent, fname, param0_name, full_name, dbg_obj_type, null_obj_ok)
1747 if array != '':
1748 indent = indent[4:]
1749 pre_code += '%s}\n' % (indent)
1750 indent = indent[4:]
1751 pre_code += '%s}\n' % (indent)
1752 else:
1753 pre_code += '%s\n' % self.lineinfo.get()
1754 pre_code += '%sskipCall |= validate_%s(%s, %s, %s, %s);\n' %(indent, fname, param0_name, full_name, dbg_obj_type, null_obj_ok)
1755 return pre_code
Tony Barboura05dbaa2015-07-09 17:31:46 -06001756
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -06001757 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001758 if proto.name in [ 'CreateDebugReportCallbackEXT', 'EnumerateInstanceLayerProperties', 'EnumerateInstanceExtensionProperties','EnumerateDeviceLayerProperties', 'EnumerateDeviceExtensionProperties' ]:
Mike Stroyan00087e62015-04-03 14:39:16 -06001759 # use default version
1760 return None
Mark Lobodzinski7c75b852015-05-05 15:01:37 -05001761
Tony Barboura05dbaa2015-07-09 17:31:46 -06001762 # Create map of object names to object type enums of the form VkName : VkObjectTypeName
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001763 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 -05001764 # Convert object type enum names from UpperCamelCase to UPPER_CASE_WITH_UNDERSCORES
1765 for objectName, objectTypeEnum in obj_type_mapping.items():
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001766 obj_type_mapping[objectName] = ucc_to_U_C_C(objectTypeEnum) + '_EXT';
Mark Lobodzinski7c75b852015-05-05 15:01:37 -05001767 # Command Buffer Object doesn't follow the rule.
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001768 obj_type_mapping['VkCommandBuffer'] = "VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT"
1769 obj_type_mapping['VkShaderModule'] = "VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT"
Mike Stroyan00087e62015-04-03 14:39:16 -06001770
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001771 explicit_object_tracker_functions = [
1772 "CreateInstance",
Tobin Ehlisec598302015-09-15 15:02:17 -06001773 "EnumeratePhysicalDevices",
Cody Northropd0802882015-08-03 17:04:53 -06001774 "GetPhysicalDeviceQueueFamilyProperties",
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001775 "CreateDevice",
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001776 "GetDeviceQueue",
Chia-I Wu1ff4c3d2015-10-26 16:55:27 +08001777 "QueueBindSparse",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001778 "AllocateDescriptorSets",
Tony Barbour770f80d2015-07-20 10:52:13 -06001779 "FreeDescriptorSets",
Mark Lobodzinski5f5c0e12015-11-12 16:02:35 -07001780 "AllocateCommandBuffers",
1781 "FreeCommandBuffers",
1782 "DestroyDescriptorPool",
1783 "DestroyCommandPool",
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001784 "MapMemory",
1785 "UnmapMemory",
1786 "FreeMemory",
Mark Lobodzinskie6d3f2c2015-10-14 13:16:33 -06001787 "DestroySwapchainKHR",
1788 "GetSwapchainImagesKHR"
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001789 ]
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001790 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyan00087e62015-04-03 14:39:16 -06001791 param0_name = proto.params[0].name
Mark Lobodzinski48bd16d2015-05-08 09:12:28 -05001792 using_line = ''
Mike Stroyan00087e62015-04-03 14:39:16 -06001793 create_line = ''
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001794 destroy_line = ''
Tobin Ehlis154e0462015-08-26 11:22:09 -06001795 # 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 -07001796 # TODO : Should integrate slightly better code for this purpose from unique_objects layer
Tobin Ehlis154e0462015-08-26 11:22:09 -06001797 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 -08001798 loop_types = defaultdict(list)
Tobin Ehlis2717d132015-07-10 18:25:07 -06001799 # 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 -06001800 # or better yet, these should be encoded into an API json definition and we generate checks from there
1801 # 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)
1802 # param names may be directly passed to the function, or may be a field in a struct param
1803 valid_null_object_names = {'CreateGraphicsPipelines' : ['basePipelineHandle'],
1804 'CreateComputePipelines' : ['basePipelineHandle'],
1805 'BeginCommandBuffer' : ['renderPass', 'framebuffer'],
Tobin Ehlisec598302015-09-15 15:02:17 -06001806 'QueueSubmit' : ['fence'],
Jon Ashburn9216ae42016-01-14 15:11:55 -07001807 'AcquireNextImageKHR' : ['fence', 'semaphore' ],
Tobin Ehlisba31cab2015-11-02 15:24:32 -07001808 'UpdateDescriptorSets' : ['pTexelBufferView'],
Tobin Ehlis86684f92016-01-05 10:33:58 -07001809 'CreateSwapchainKHR' : ['oldSwapchain'],
Tobin Ehlis154e0462015-08-26 11:22:09 -06001810 }
Tobin Ehlis154e0462015-08-26 11:22:09 -06001811 param_count = 'NONE' # keep track of arrays passed directly into API functions
Tobin Ehlis803cc492015-06-08 17:36:28 -06001812 for p in proto.params:
Tobin Ehlisec598302015-09-15 15:02:17 -06001813 base_type = p.ty.replace('const ', '').strip('*')
Tobin Ehlis154e0462015-08-26 11:22:09 -06001814 if 'count' in p.name.lower():
1815 param_count = p.name
Tobin Ehlisec598302015-09-15 15:02:17 -06001816 if base_type in vulkan.core.objects:
1817 # This is an object to potentially check for validity. First see if it's an array
1818 if '*' in p.ty and 'const' in p.ty and param_count != 'NONE':
1819 loop_params[param_count].append(p.name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001820 loop_types[param_count].append(str(p.ty[6:-1]))
Tobin Ehlisec598302015-09-15 15:02:17 -06001821 # Not an array, check for just a base Object that's not in exceptions
1822 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 -06001823 loop_params[0].append(p.name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001824 loop_types[0].append(str(p.ty))
Tobin Ehlisec598302015-09-15 15:02:17 -06001825 elif vk_helper.is_type(base_type, 'struct'):
1826 struct_type = base_type
Tobin Ehlis9d675942015-06-30 14:32:16 -06001827 if vk_helper.typedef_rev_dict[struct_type] in vk_helper.struct_dict:
1828 struct_type = vk_helper.typedef_rev_dict[struct_type]
Tobin Ehlis82b3db52015-10-23 17:52:53 -06001829 # Parse elements of this struct param to identify objects and/or arrays of objects
Tobin Ehlis9d675942015-06-30 14:32:16 -06001830 for m in sorted(vk_helper.struct_dict[struct_type]):
1831 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 -06001832 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 -06001833 # This is not great, but gets the job done for now, but If we have a count and this param is a ptr w/
1834 # last letter 's' OR non-'count' string of count is in the param name, then this is a dynamically sized array param
1835 param_array = False
1836 if param_count != 'NONE':
1837 if '*' in p.ty:
1838 if 's' == p.name[-1] or param_count.lower().replace('count', '') in p.name.lower():
1839 param_array = True
1840 if param_array:
Tobin Ehlis154e0462015-08-26 11:22:09 -06001841 param_name = '%s[i].%s' % (p.name, vk_helper.struct_dict[struct_type][m]['name'])
Tobin Ehlis46d53622015-07-10 11:10:21 -06001842 else:
Tobin Ehlis154e0462015-08-26 11:22:09 -06001843 param_name = '%s->%s' % (p.name, vk_helper.struct_dict[struct_type][m]['name'])
1844 if vk_helper.struct_dict[struct_type][m]['dyn_array']:
Tobin Ehlis82b3db52015-10-23 17:52:53 -06001845 if param_count != 'NONE': # this will be a double-embedded loop, use comma delineated 'count,name' for param_name
1846 loop_count = '%s[i].%s' % (p.name, vk_helper.struct_dict[struct_type][m]['array_size'])
1847 loop_params[param_count].append('%s,%s' % (loop_count, param_name))
Michael Lentine13803dc2015-11-04 14:35:12 -08001848 loop_types[param_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Tobin Ehlis82b3db52015-10-23 17:52:53 -06001849 else:
1850 loop_count = '%s->%s' % (p.name, vk_helper.struct_dict[struct_type][m]['array_size'])
1851 loop_params[loop_count].append(param_name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001852 loop_types[loop_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Tobin Ehlis154e0462015-08-26 11:22:09 -06001853 else:
1854 if '[' in param_name: # dynamic array param, set size
1855 loop_params[param_count].append(param_name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001856 loop_types[param_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Tobin Ehlis154e0462015-08-26 11:22:09 -06001857 else:
1858 loop_params[0].append(param_name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001859 loop_types[0].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Tobin Ehlis86684f92016-01-05 10:33:58 -07001860 last_param_index = None
1861 create_func = False
1862 if True in [create_txt in proto.name for create_txt in ['Create', 'Allocate']]:
1863 create_func = True
1864 last_param_index = -1 # For create funcs don't validate last object
1865 struct_uses = get_object_uses(vulkan.object_type_list, proto.params[:last_param_index])
Mike Stroyan00087e62015-04-03 14:39:16 -06001866 funcs = []
Tobin Ehlis803cc492015-06-08 17:36:28 -06001867 mutex_unlock = False
Tobin Ehlis154e0462015-08-26 11:22:09 -06001868 funcs.append('%s\n' % self.lineinfo.get())
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001869 if proto.name in explicit_object_tracker_functions:
Jon Ashburn4d9f4652015-04-08 21:33:34 -06001870 funcs.append('%s%s\n'
1871 '{\n'
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001872 ' return explicit_%s;\n'
1873 '}' % (qual, decl, proto.c_call()))
1874 return "".join(funcs)
Mark Lobodzinski308d7792015-11-24 10:28:31 -07001875 # Temporarily prevent DestroySurface call from being generated until WSI layer support is fleshed out
Mark Lobodzinski882655d2016-01-05 11:32:53 -07001876 elif 'DestroyInstance' in proto.name or 'DestroyDevice' in proto.name:
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001877 return ""
Jon Ashburn4d9f4652015-04-08 21:33:34 -06001878 else:
Tobin Ehlis86684f92016-01-05 10:33:58 -07001879 if create_func:
Michael Lentine13803dc2015-11-04 14:35:12 -08001880 typ = proto.params[-1].ty.strip('*').replace('const ', '');
1881 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1882 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001883 create_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
1884 create_line += ' if (result == VK_SUCCESS) {\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08001885 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 -06001886 create_line += ' }\n'
1887 create_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06001888 if 'FreeCommandBuffers' in proto.name:
Michael Lentine13803dc2015-11-04 14:35:12 -08001889 typ = proto.params[-1].ty.strip('*').replace('const ', '');
1890 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1891 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06001892 funcs.append('%s\n' % self.lineinfo.get())
1893 destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Chia-I Wud50a7d72015-10-26 20:48:51 +08001894 destroy_line += ' for (uint32_t i = 0; i < commandBufferCount; i++) {\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08001895 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 -06001896 destroy_line += ' }\n'
1897 destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001898 if 'Destroy' in proto.name:
Michael Lentine13803dc2015-11-04 14:35:12 -08001899 typ = proto.params[-2].ty.strip('*').replace('const ', '');
1900 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1901 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06001902 funcs.append('%s\n' % self.lineinfo.get())
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001903 destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08001904 destroy_line += ' destroy_%s(%s, %s);\n' % (name, param0_name, proto.params[-2].name)
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001905 destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Tobin Ehlis86684f92016-01-05 10:33:58 -07001906 indent = ' '
1907 if len(struct_uses) > 0:
1908 using_line += '%sVkBool32 skipCall = VK_FALSE;\n' % (indent)
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001909 if not mutex_unlock:
Tobin Ehlis86684f92016-01-05 10:33:58 -07001910 using_line += '%sloader_platform_thread_lock_mutex(&objLock);\n' % (indent)
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001911 mutex_unlock = True
Tobin Ehlis86684f92016-01-05 10:33:58 -07001912 using_line += '// objects to validate: %s\n' % str(struct_uses)
1913 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 -06001914 if mutex_unlock:
Tobin Ehlis86684f92016-01-05 10:33:58 -07001915 using_line += '%sloader_platform_thread_unlock_mutex(&objLock);\n' % (indent)
1916 if len(struct_uses) > 0:
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -06001917 using_line += ' if (skipCall)\n'
1918 if proto.ret != "void":
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07001919 using_line += ' return VK_ERROR_VALIDATION_FAILED_EXT;\n'
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -06001920 else:
1921 using_line += ' return;\n'
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001922 ret_val = ''
1923 stmt = ''
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001924 if proto.ret != "void":
1925 ret_val = "%s result = " % proto.ret
1926 stmt = " return result;\n"
1927
1928 dispatch_param = proto.params[0].name
1929 if 'CreateInstance' in proto.name:
1930 dispatch_param = '*' + proto.params[1].name
1931
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001932 # Must use 'instance' table for these APIs, 'device' table otherwise
1933 table_type = ""
1934 if proto_is_global(proto):
1935 table_type = "instance"
1936 else:
1937 table_type = "device"
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001938 if wsi_name(proto.name):
1939 funcs.append('%s' % wsi_ifdef(proto.name))
Mike Stroyan00087e62015-04-03 14:39:16 -06001940 funcs.append('%s%s\n'
1941 '{\n'
1942 '%s'
Mike Stroyan00087e62015-04-03 14:39:16 -06001943 '%s'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001944 ' %sget_dispatch_table(object_tracker_%s_table_map, %s)->%s;\n'
Mike Stroyan38820b32015-09-28 13:47:29 -06001945 '%s'
1946 '%s'
1947 '}' % (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 -07001948 if wsi_name(proto.name):
1949 funcs.append('%s' % wsi_endif(proto.name))
Mike Stroyan00087e62015-04-03 14:39:16 -06001950 return "\n\n".join(funcs)
1951
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001952 def generate_body(self):
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001953 self.layer_name = "object_tracker"
Ian Elliott1064fe32015-07-06 14:31:32 -06001954 extensions=[('wsi_enabled',
Ian Elliott05846062015-11-20 14:13:17 -07001955 ['vkCreateSwapchainKHR',
Jon Ashburn8acd2332015-09-16 18:08:32 -06001956 'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
1957 'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001958 if sys.platform.startswith('win32'):
Michael Lentine64e2ebd2015-12-03 14:33:09 -08001959 instance_extensions=[('msg_callback_get_proc_addr', []),
1960 ('wsi_enabled',
1961 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1962 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1963 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1964 'vkGetPhysicalDeviceSurfacePresentModesKHR',
1965 'vkCreateWin32SurfaceKHR',
1966 'vkGetPhysicalDeviceWin32PresentationSupportKHR'])]
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001967 elif sys.platform.startswith('linux'):
Michael Lentine64e2ebd2015-12-03 14:33:09 -08001968 instance_extensions=[('msg_callback_get_proc_addr', []),
1969 ('wsi_enabled',
1970 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1971 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1972 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1973 'vkGetPhysicalDeviceSurfacePresentModesKHR',
1974 'vkCreateXcbSurfaceKHR',
Mark Lobodzinskib49b6e52015-11-26 10:59:58 -07001975 'vkGetPhysicalDeviceXcbPresentationSupportKHR'])]
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001976 # TODO: Add cases for Mir, Wayland and Xlib
1977 else: # android
1978 instance_extensions=[('msg_callback_get_proc_addr', []),
1979 ('wsi_enabled',
1980 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1981 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1982 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1983 'vkGetPhysicalDeviceSurfacePresentModesKHR'])]
Tony Barboura05dbaa2015-07-09 17:31:46 -06001984 body = [self.generate_maps(),
1985 self.generate_procs(),
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001986 self.generate_destroy_instance(),
1987 self.generate_destroy_device(),
Tony Barboura05dbaa2015-07-09 17:31:46 -06001988 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Tobin Ehlisca915872014-11-18 11:28:33 -07001989 self._generate_extensions(),
Jon Ashburn747f2b62015-06-18 15:02:58 -06001990 self._generate_layer_gpa_function(extensions,
Jon Ashburn3dc39382015-09-17 10:00:32 -06001991 instance_extensions)]
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001992 return "\n\n".join(body)
Courtney Goeltzenleuchterb412d212014-11-18 10:40:29 -07001993
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07001994class UniqueObjectsSubcommand(Subcommand):
1995 def generate_header(self):
1996 header_txt = []
1997 header_txt.append('%s' % self.lineinfo.get())
1998 header_txt.append('#include "unique_objects.h"')
1999 header_txt.append('')
2000 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
2001 return "\n".join(header_txt)
2002
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002003 # Generate UniqueObjects code for given struct_uses dict of objects that need to be unwrapped
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002004 # vector_name_set is used to make sure we don't replicate vector names
2005 # 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 -07002006 # TODO : Comment this code
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002007 def _gen_obj_code(self, struct_uses, indent, prefix, array_index, vector_name_set, first_level_param):
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002008 decls = ''
2009 pre_code = ''
2010 post_code = ''
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002011 for obj in sorted(struct_uses):
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002012 name = obj
2013 array = ''
2014 if '[' in obj:
2015 (name, array) = obj.split('[')
2016 array = array.strip(']')
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002017 ptr_type = False
Tobin Ehlis991d45a2016-01-06 08:48:41 -07002018 if 'p' == obj[0] and obj[1] != obj[1].lower(): # TODO : Not idea way to determine ptr
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002019 ptr_type = True
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002020 if isinstance(struct_uses[obj], dict):
2021 local_prefix = ''
2022 name = '%s%s' % (prefix, name)
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002023 if ptr_type:
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002024 pre_code += '%sif (%s) {\n' % (indent, name)
2025 post_code += '%sif (%s) {\n' % (indent, name)
2026 indent += ' '
2027 if array != '':
2028 idx = 'idx%s' % str(array_index)
2029 array_index += 1
2030 pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
2031 post_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
2032 indent += ' '
2033 local_prefix = '%s[%s].' % (name, idx)
2034 elif ptr_type:
2035 local_prefix = '%s->' % (name)
2036 else:
2037 local_prefix = '%s.' % (name)
2038 assert isinstance(decls, object)
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002039 (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 -07002040 decls += tmp_decl
2041 pre_code += tmp_pre
2042 post_code += tmp_post
2043 if array != '':
2044 indent = indent[4:]
2045 pre_code += '%s}\n' % (indent)
2046 post_code += '%s}\n' % (indent)
2047 if ptr_type:
2048 indent = indent[4:]
2049 pre_code += '%s}\n' % (indent)
2050 post_code += '%s}\n' % (indent)
2051 else:
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002052 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 -07002053 pre_code += '%sif (%s%s) {\n' %(indent, prefix, name)
2054 post_code += '%sif (%s%s) {\n' %(indent, prefix, name)
2055 indent += ' '
2056 # Append unique_count to make sure name is unique (some aliasing for "buffer" and "image" names
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002057 vec_name = 'original_%s' % (name)
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002058 if array != '':
2059 idx = 'idx%s' % str(array_index)
2060 array_index += 1
2061 pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
2062 post_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
2063 indent += ' '
2064 name = '%s[%s]' % (name, idx)
2065 pName = 'p%s' % (struct_uses[obj][2:])
2066 pre_code += '%s%s* %s = (%s*)&(%s%s);\n' % (indent, struct_uses[obj], pName, struct_uses[obj], prefix, name)
2067 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 -07002068 if name not in vector_name_set:
2069 vector_name_set.add(name)
2070 decls += ' std::vector<%s> %s = {};\n' % (struct_uses[obj], vec_name)
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002071 pre_code += '%s%s.push_back(%s%s);\n' % (indent, vec_name, prefix, name)
2072 pre_code += '%s*(%s) = (%s)((VkUniqueObject*)%s%s)->actualObject;\n' % (indent, pName, struct_uses[obj], prefix, name)
2073 post_code += '%s*(%s) = %s.front();\n' % (indent, pName, vec_name)
2074 post_code += '%s%s.erase(%s.begin());\n' % (indent, vec_name, vec_name)
2075 if array != '':
2076 indent = indent[4:]
2077 pre_code += '%s}\n' % (indent)
2078 post_code += '%s}\n' % (indent)
2079 indent = indent[4:]
2080 pre_code += '%s}\n' % (indent)
2081 post_code += '%s}\n' % (indent)
2082 else:
2083 pre_code += '%sif (%s%s) {\n' %(indent, prefix, name)
2084 indent += ' '
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002085 deref_txt = '&'
2086 if ptr_type:
2087 deref_txt = ''
2088 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 -07002089 pre_code += '%s*p%s = (%s)((VkUniqueObject*)%s%s)->actualObject;\n' % (indent, name, struct_uses[obj], prefix, name)
2090 indent = indent[4:]
2091 pre_code += '%s}\n' % (indent)
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002092 if not first_level_param: # embedded in a ptr/struct so need to undo the update
2093 decls += ' %s local_%s = %s%s;\n' % (struct_uses[obj], name, prefix, name)
2094 post_code += '%sif (%s%s) {\n' %(indent, prefix, name)
2095 post_code += '%s %s* p%s = (%s*)%s%s%s;\n' % (indent, struct_uses[obj], name, struct_uses[obj], deref_txt, prefix, name)
2096 post_code += '%s *p%s = local_%s;\n' % (indent, name, name)
2097 post_code += '%s}\n' % (indent)
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002098 return decls, pre_code, post_code
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07002099
2100 def generate_intercept(self, proto, qual):
2101 create_func = False
2102 destroy_func = False
2103 last_param_index = None #typcially we look at all params for ndos
2104 pre_call_txt = '' # code prior to calling down chain such as unwrap uses of ndos
2105 post_call_txt = '' # code following call down chain such to wrap newly created ndos, or destroy local wrap struct
2106 funcs = []
2107 indent = ' ' # indent level for generated code
2108 decl = proto.c_func(prefix="vk", attr="VKAPI")
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002109 # A few API cases that are manual code
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002110 # TODO : Special case Create*Pipelines funcs to handle creating multiple unique objects
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002111 explicit_object_tracker_functions = ['GetSwapchainImagesKHR',
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07002112 'CreateInstance',
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002113 'CreateDevice',
2114 'CreateComputePipelines',
2115 'CreateGraphicsPipelines']
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07002116 # Give special treatment to create functions that return multiple new objects
2117 # This dict stores array name and size of array
Jon Ashburnf19916e2016-01-11 13:12:43 -07002118 custom_create_dict = {'pDescriptorSets' : 'pAllocateInfo->descriptorSetCount'}
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07002119 if proto.name in explicit_object_tracker_functions:
2120 funcs.append('%s%s\n'
2121 '{\n'
2122 ' return explicit_%s;\n'
2123 '}' % (qual, decl, proto.c_call()))
2124 return "".join(funcs)
2125 if True in [create_txt in proto.name for create_txt in ['Create', 'Allocate']]:
2126 create_func = True
2127 last_param_index = -1 # For create funcs don't care if last param is ndo
2128 if True in [destroy_txt in proto.name for destroy_txt in ['Destroy', 'Free']]:
2129 destroy_obj_type = proto.params[-2].ty
2130 if destroy_obj_type in vulkan.object_non_dispatch_list:
2131 destroy_func = True
2132
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002133 # First thing we need to do is gather uses of non-dispatchable-objects (ndos)
2134 struct_uses = get_object_uses(vulkan.object_non_dispatch_list, proto.params[1:last_param_index])
2135
2136 if len(struct_uses) > 0:
2137 pre_call_txt += '// STRUCT USES:%s\n' % struct_uses
2138 if destroy_func: # only one object
2139 for del_obj in struct_uses:
2140 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 -07002141 (pre_decl, pre_code, post_code) = self._gen_obj_code(struct_uses, ' ', '', 0, set(), True)
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002142 pre_call_txt += '%s%s' % (pre_decl, pre_code)
2143 post_call_txt += post_code
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07002144 elif create_func:
2145 base_type = proto.params[-1].ty.replace('const ', '').strip('*')
2146 if base_type not in vulkan.object_non_dispatch_list:
2147 return None
2148 else:
2149 return None
2150
2151 ret_val = ''
2152 ret_stmt = ''
2153 if proto.ret != "void":
2154 ret_val = "%s result = " % proto.ret
2155 ret_stmt = " return result;\n"
2156 dispatch_param = proto.params[0].name
2157 if 'CreateInstance' in proto.name:
2158 dispatch_param = '*' + proto.params[1].name
2159 if create_func:
2160 obj_type = proto.params[-1].ty.strip('*')
2161 obj_name = proto.params[-1].name
2162 if obj_type in vulkan.object_non_dispatch_list:
2163 local_name = "unique%s" % obj_type[2:]
2164 post_call_txt += '%sif (VK_SUCCESS == result) {\n' % (indent)
2165 indent += ' '
2166 if obj_name in custom_create_dict:
2167 post_call_txt += '%s\n' % (self.lineinfo.get())
2168 local_name = '%ss' % (local_name) # add 's' to end for vector of many
2169 post_call_txt += '%sstd::vector<VkUniqueObject*> %s = {};\n' % (indent, local_name)
2170 post_call_txt += '%sfor (uint32_t i=0; i<%s; ++i) {\n' % (indent, custom_create_dict[obj_name])
2171 indent += ' '
2172 post_call_txt += '%s%s.push_back(new VkUniqueObject());\n' % (indent, local_name)
2173 post_call_txt += '%s%s[i]->actualObject = (uint64_t)%s[i];\n' % (indent, local_name, obj_name)
2174 post_call_txt += '%s%s[i] = (%s)%s[i];\n' % (indent, obj_name, obj_type, local_name)
2175 indent = indent[4:]
2176 post_call_txt += '%s}\n' % (indent)
2177 else:
2178 post_call_txt += '%s\n' % (self.lineinfo.get())
2179 post_call_txt += '%sVkUniqueObject* %s = new VkUniqueObject();\n' % (indent, local_name)
2180 post_call_txt += '%s%s->actualObject = (uint64_t)*%s;\n' % (indent, local_name, obj_name)
2181 post_call_txt += '%s*%s = (%s)%s;\n' % (indent, obj_name, obj_type, local_name)
2182 indent = indent[4:]
2183 post_call_txt += '%s}\n' % (indent)
2184 elif destroy_func:
2185 del_obj = proto.params[-2].name
2186 if 'count' in del_obj.lower():
2187 post_call_txt += '%s\n' % (self.lineinfo.get())
2188 post_call_txt += '%sfor (uint32_t i=0; i<%s; ++i) {\n' % (indent, del_obj)
2189 del_obj = proto.params[-1].name
2190 indent += ' '
2191 post_call_txt += '%sdelete (VkUniqueObject*)%s[i];\n' % (indent, del_obj)
2192 indent = indent[4:]
2193 post_call_txt += '%s}\n' % (indent)
2194 else:
2195 post_call_txt += '%s\n' % (self.lineinfo.get())
2196 post_call_txt = '%sdelete (VkUniqueObject*)local_%s;\n' % (indent, proto.params[-2].name)
2197
2198 call_sig = proto.c_call()
2199 if proto_is_global(proto):
2200 table_type = "instance"
2201 else:
2202 table_type = "device"
2203 pre_call_txt += '%s\n' % (self.lineinfo.get())
2204 funcs.append('%s%s\n'
2205 '{\n'
2206 '%s'
2207 ' %sget_dispatch_table(unique_objects_%s_table_map, %s)->%s;\n'
2208 '%s'
2209 '%s'
2210 '}' % (qual, decl, pre_call_txt, ret_val, table_type, dispatch_param, call_sig, post_call_txt, ret_stmt))
2211 return "\n\n".join(funcs)
2212
2213 def generate_body(self):
2214 self.layer_name = "unique_objects"
2215 extensions=[('wsi_enabled',
2216 ['vkCreateSwapchainKHR',
2217 'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
2218 'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
2219 if sys.platform.startswith('win32'):
2220 instance_extensions=[('wsi_enabled',
2221 ['vkGetPhysicalDeviceSurfaceSupportKHR',
2222 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
2223 'vkGetPhysicalDeviceSurfaceFormatsKHR',
2224 'vkGetPhysicalDeviceSurfacePresentModesKHR',
Jon Ashburn00dc7412016-01-07 16:13:06 -07002225 'vkCreateWin32SurfaceKHR'
2226 ])]
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07002227 elif sys.platform.startswith('linux'):
2228 instance_extensions=[('wsi_enabled',
2229 ['vkGetPhysicalDeviceSurfaceSupportKHR',
2230 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
2231 'vkGetPhysicalDeviceSurfaceFormatsKHR',
2232 'vkGetPhysicalDeviceSurfacePresentModesKHR',
Jon Ashburn00dc7412016-01-07 16:13:06 -07002233 'vkCreateXcbSurfaceKHR'
2234 ])]
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07002235 # TODO: Add cases for Mir, Wayland and Xlib
2236 else: # android
2237 instance_extensions=[('wsi_enabled',
2238 ['vkGetPhysicalDeviceSurfaceSupportKHR',
2239 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
2240 'vkGetPhysicalDeviceSurfaceFormatsKHR',
2241 'vkGetPhysicalDeviceSurfacePresentModesKHR'])]
2242 body = [self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
2243 self._generate_layer_gpa_function(extensions,
2244 instance_extensions)]
2245 return "\n\n".join(body)
2246
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002247class ThreadingSubcommand(Subcommand):
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002248 thread_check_dispatchable_objects = [
2249 "VkQueue",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002250 "VkCommandBuffer",
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002251 ]
2252 thread_check_nondispatchable_objects = [
2253 "VkDeviceMemory",
2254 "VkBuffer",
2255 "VkImage",
2256 "VkDescriptorSet",
2257 "VkDescriptorPool",
2258 "VkSemaphore"
2259 ]
Mike Stroyan313f7e62015-08-10 16:42:53 -06002260 thread_check_object_types = {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002261 'VkInstance' : 'VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT',
2262 'VkPhysicalDevice' : 'VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT',
2263 'VkDevice' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT',
2264 'VkQueue' : 'VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT',
2265 'VkCommandBuffer' : 'VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT',
2266 'VkFence' : 'VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT',
2267 'VkDeviceMemory' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT',
2268 'VkBuffer' : 'VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT',
2269 'VkImage' : 'VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT',
2270 'VkSemaphore' : 'VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT',
2271 'VkEvent' : 'VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT',
2272 'VkQueryPool' : 'VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT',
2273 'VkBufferView' : 'VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT',
2274 'VkImageView' : 'VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT',
2275 'VkShaderModule' : 'VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT',
2276 'VkShader' : 'VK_DEBUG_REPORT_OBJECT_TYPE_SHADER',
2277 'VkPipelineCache' : 'VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT',
2278 'VkPipelineLayout' : 'VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT',
2279 'VkRenderPass' : 'VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT',
2280 'VkPipeline' : 'VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT',
2281 'VkDescriptorSetLayout' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT',
2282 'VkSampler' : 'VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT',
2283 'VkDescriptorPool' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT',
2284 'VkDescriptorSet' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT',
2285 'VkFramebuffer' : 'VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT',
2286 'VkCommandPool' : 'VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT',
Mike Stroyan313f7e62015-08-10 16:42:53 -06002287 }
2288 def generate_useObject(self, ty):
2289 obj_type = self.thread_check_object_types[ty]
Chia-I Wue2fc5522015-10-26 20:04:44 +08002290 key = "object"
2291 msg_object = "reinterpret_cast<uint64_t>(object)"
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002292 header_txt = []
2293 header_txt.append('%s' % self.lineinfo.get())
Michael Lentine13803dc2015-11-04 14:35:12 -08002294 header_txt.append('static void use%s(const void* dispatchable_object, %s object)' % (ty, ty))
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002295 header_txt.append('{')
2296 header_txt.append(' loader_platform_thread_id tid = loader_platform_get_thread_id();')
2297 header_txt.append(' loader_platform_thread_lock_mutex(&threadingLock);')
2298 header_txt.append(' if (%sObjectsInUse.find(%s) == %sObjectsInUse.end()) {' % (ty, key, ty))
2299 header_txt.append(' %sObjectsInUse[%s] = tid;' % (ty, key))
2300 header_txt.append(' } else {')
2301 header_txt.append(' if (%sObjectsInUse[%s] != tid) {' % (ty, key))
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002302 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 -07002303 header_txt.append(' __LINE__, THREADING_CHECKER_MULTIPLE_THREADS, "THREADING",')
Mike Stroyan313f7e62015-08-10 16:42:53 -06002304 header_txt.append(' "THREADING ERROR : object of type %s is simultaneously used in thread %%ld and thread %%ld",' % (ty))
2305 header_txt.append(' %sObjectsInUse[%s], tid);' % (ty, key))
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002306 header_txt.append(' // Wait for thread-safe access to object')
2307 header_txt.append(' while (%sObjectsInUse.find(%s) != %sObjectsInUse.end()) {' % (ty, key, ty))
2308 header_txt.append(' loader_platform_thread_cond_wait(&threadingCond, &threadingLock);')
2309 header_txt.append(' }')
2310 header_txt.append(' %sObjectsInUse[%s] = tid;' % (ty, key))
2311 header_txt.append(' } else {')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002312 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 -07002313 header_txt.append(' __LINE__, THREADING_CHECKER_MULTIPLE_THREADS, "THREADING",')
Mike Stroyan313f7e62015-08-10 16:42:53 -06002314 header_txt.append(' "THREADING ERROR : object of type %s is recursively used in thread %%ld",' % (ty))
2315 header_txt.append(' tid);')
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002316 header_txt.append(' }')
2317 header_txt.append(' }')
2318 header_txt.append(' loader_platform_thread_unlock_mutex(&threadingLock);')
2319 header_txt.append('}')
2320 return "\n".join(header_txt)
Mike Stroyan313f7e62015-08-10 16:42:53 -06002321 def generate_finishUsingObject(self, ty):
Chia-I Wue2fc5522015-10-26 20:04:44 +08002322 key = "object"
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002323 header_txt = []
2324 header_txt.append('%s' % self.lineinfo.get())
Michael Lentine13803dc2015-11-04 14:35:12 -08002325 header_txt.append('static void finishUsing%s(%s object)' % (ty, ty))
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002326 header_txt.append('{')
2327 header_txt.append(' // Object is no longer in use')
2328 header_txt.append(' loader_platform_thread_lock_mutex(&threadingLock);')
2329 header_txt.append(' %sObjectsInUse.erase(%s);' % (ty, key))
2330 header_txt.append(' loader_platform_thread_cond_broadcast(&threadingCond);')
2331 header_txt.append(' loader_platform_thread_unlock_mutex(&threadingLock);')
2332 header_txt.append('}')
2333 return "\n".join(header_txt)
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002334 def generate_header(self):
2335 header_txt = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -06002336 header_txt.append('%s' % self.lineinfo.get())
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002337 header_txt.append('#include <stdio.h>')
2338 header_txt.append('#include <stdlib.h>')
2339 header_txt.append('#include <string.h>')
2340 header_txt.append('#include <unordered_map>')
Tobin Ehlisb835d1b2015-07-03 10:34:49 -06002341 header_txt.append('#include "vk_loader_platform.h"')
David Pinedo9316d3b2015-11-06 12:54:48 -07002342 header_txt.append('#include "vulkan/vk_layer.h"')
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002343 header_txt.append('#include "threading.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -06002344 header_txt.append('#include "vk_layer_config.h"')
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -06002345 header_txt.append('#include "vk_layer_extension_utils.h"')
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002346 header_txt.append('#include "vk_enum_validate_helper.h"')
2347 header_txt.append('#include "vk_struct_validate_helper.h"')
Mike Stroyan313f7e62015-08-10 16:42:53 -06002348 header_txt.append('#include "vk_layer_table.h"')
2349 header_txt.append('#include "vk_layer_logging.h"')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002350 header_txt.append('')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002351 header_txt.append('')
2352 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
2353 header_txt.append('')
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002354 header_txt.append('using namespace std;')
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002355 for ty in self.thread_check_dispatchable_objects:
2356 header_txt.append('static unordered_map<%s, loader_platform_thread_id> %sObjectsInUse;' % (ty, ty))
2357 for ty in self.thread_check_nondispatchable_objects:
Chia-I Wue2fc5522015-10-26 20:04:44 +08002358 header_txt.append('static unordered_map<%s, loader_platform_thread_id> %sObjectsInUse;' % (ty, ty))
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002359 header_txt.append('static int threadingLockInitialized = 0;')
2360 header_txt.append('static loader_platform_thread_mutex threadingLock;')
Mike Stroyaned238bb2015-05-15 08:50:57 -06002361 header_txt.append('static loader_platform_thread_cond threadingCond;')
Tobin Ehlis08fafd02015-06-12 12:49:01 -06002362 header_txt.append('%s' % self.lineinfo.get())
Mike Stroyan313f7e62015-08-10 16:42:53 -06002363 for ty in self.thread_check_dispatchable_objects + self.thread_check_nondispatchable_objects:
2364 header_txt.append(self.generate_useObject(ty))
2365 header_txt.append(self.generate_finishUsingObject(ty))
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002366 header_txt.append('%s' % self.lineinfo.get())
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002367 return "\n".join(header_txt)
2368
2369 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002370 if proto.name in [ 'CreateDebugReportCallbackEXT' ]:
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002371 # use default version
2372 return None
2373 decl = proto.c_func(prefix="vk", attr="VKAPI")
2374 ret_val = ''
2375 stmt = ''
2376 funcs = []
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002377 table = 'device'
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002378 if proto.ret != "void":
Jon Ashburnb0fbe912015-05-06 10:15:07 -06002379 ret_val = "%s result = " % proto.ret
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002380 stmt = " return result;\n"
Jon Ashburn95a77ba2015-05-15 15:09:35 -06002381 if proto_is_global(proto):
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002382 table = 'instance'
Jon Ashburn71836d92015-05-12 17:23:55 -06002383
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002384 # Memory range calls are special in needed thread checking within structs
2385 if proto.name in ["FlushMappedMemoryRanges","InvalidateMappedMemoryRanges"]:
Mike Stroyan313f7e62015-08-10 16:42:53 -06002386 funcs.append('%s' % self.lineinfo.get())
2387 funcs.append('%s%s\n' % (qual, decl) +
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002388 '{\n'
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002389 ' for (uint32_t i=0; i<memoryRangeCount; i++) {\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08002390 ' useVkDeviceMemory((const void *) %s, pMemoryRanges[i].memory);\n' % proto.params[0].name +
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002391 ' }\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002392 ' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_%s_table_map, %s);\n' % (table, proto.params[0].name) +
Mike Stroyan313f7e62015-08-10 16:42:53 -06002393 ' %s pDeviceTable->%s;\n' % (ret_val, proto.c_call()) +
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002394 ' for (uint32_t i=0; i<memoryRangeCount; i++) {\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08002395 ' finishUsingVkDeviceMemory(pMemoryRanges[i].memory);\n'
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002396 ' }\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002397 '%s' % (stmt) +
2398 '}')
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002399 return "\n".join(funcs)
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002400 # All functions that do a Get are thread safe
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002401 if 'Get' in proto.name:
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002402 return None
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002403 # All WSI functions are thread safe
Ian Elliott7e40db92015-08-21 15:09:33 -06002404 if 'KHR' in proto.name:
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002405 return None
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002406 # Initialize in early calls
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002407 if proto.name == "CreateDevice":
2408 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan313f7e62015-08-10 16:42:53 -06002409 funcs.append('%s%s\n' % (qual, decl) +
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002410 '{\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002411 ' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_device_table_map, (void *) *pDevice);\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002412 ' VkResult result = pDeviceTable->%s;\n' % (proto.c_call()) +
2413 ' if (result == VK_SUCCESS) {\n'
2414 ' layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(%s), layer_data_map);\n' % proto.params[0].name +
2415 ' layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);\n'
2416 ' my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);\n'
2417 ' }\n'
2418 '\n'
2419 ' return result;'
2420 '}')
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002421 return "\n".join(funcs)
2422 elif proto.params[0].ty == "VkPhysicalDevice":
Mike Stroyan313f7e62015-08-10 16:42:53 -06002423 return None
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002424 # Functions changing command buffers need thread safe use of first parameter
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002425 if proto.params[0].ty == "VkCommandBuffer":
Tobin Ehlis08fafd02015-06-12 12:49:01 -06002426 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan313f7e62015-08-10 16:42:53 -06002427 funcs.append('%s%s\n' % (qual, decl) +
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002428 '{\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08002429 ' 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 -07002430 ' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_%s_table_map, %s);\n' % (table, proto.params[0].name) +
Mike Stroyan313f7e62015-08-10 16:42:53 -06002431 ' %spDeviceTable->%s;\n' % (ret_val, proto.c_call()) +
Michael Lentine13803dc2015-11-04 14:35:12 -08002432 ' finishUsing%s(%s);\n' % (proto.params[0].ty, proto.params[0].name) +
Mike Stroyan313f7e62015-08-10 16:42:53 -06002433 '%s' % stmt +
2434 '}')
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002435 return "\n".join(funcs)
2436 # Non-Cmd functions that do a Wait are thread safe
2437 if 'Wait' in proto.name:
2438 return None
2439 # Watch use of certain types of objects passed as any parameter
2440 checked_params = []
2441 for param in proto.params:
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002442 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 -06002443 checked_params.append(param)
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002444 if proto.name == "DestroyDevice":
Mike Stroyan313f7e62015-08-10 16:42:53 -06002445 funcs.append('%s%s\n' % (qual, decl) +
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002446 '{\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06002447 ' dispatch_key key = get_dispatch_key(device);\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002448 ' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_%s_table_map, %s);\n' % (table, proto.params[0].name) +
Mike Stroyan313f7e62015-08-10 16:42:53 -06002449 ' %spDeviceTable->%s;\n' % (ret_val, proto.c_call()) +
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002450 ' threading_device_table_map.erase(key);\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002451 '}\n')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002452 return "\n".join(funcs);
2453 elif proto.name == "DestroyInstance":
Mike Stroyan313f7e62015-08-10 16:42:53 -06002454 funcs.append('%s%s\n' % (qual, decl) +
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002455 '{\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06002456 ' dispatch_key key = get_dispatch_key(instance);\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002457 ' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(threading_instance_table_map, %s);\n' % proto.params[0].name +
Mike Stroyan313f7e62015-08-10 16:42:53 -06002458 ' %spInstanceTable->%s;\n' % (ret_val, proto.c_call()) +
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06002459 ' destroy_instance_dispatch_table(key);\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002460 '\n'
2461 ' // Clean up logging callback, if any\n'
2462 ' layer_data *my_data = get_my_data_ptr(key, layer_data_map);\n'
2463 ' if (my_data->logging_callback) {\n'
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07002464 ' layer_destroy_msg_callback(my_data->report_data, my_data->logging_callback, pAllocator);\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002465 ' }\n'
2466 '\n'
2467 ' layer_debug_report_destroy_instance(my_data->report_data);\n'
2468 ' layer_data_map.erase(pInstanceTable);\n'
2469 '\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002470 ' threading_instance_table_map.erase(key);\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002471 '}\n')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002472 return "\n".join(funcs);
Courtney Goeltzenleuchterd02a9642015-06-08 14:58:39 -06002473 elif proto.name == "CreateInstance":
2474 funcs.append('%s%s\n'
2475 '{\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002476 ' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(threading_instance_table_map, *pInstance);\n'
Chia-I Wuf7458c52015-10-26 21:10:41 +08002477 ' VkResult result = pInstanceTable->CreateInstance(pCreateInfo, pAllocator, pInstance);\n'
Courtney Goeltzenleuchterd02a9642015-06-08 14:58:39 -06002478 '\n'
2479 ' if (result == VK_SUCCESS) {\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002480 ' layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);\n'
2481 ' my_data->report_data = debug_report_create_instance(\n'
2482 ' pInstanceTable,\n'
2483 ' *pInstance,\n'
Jon Ashburnf19916e2016-01-11 13:12:43 -07002484 ' pCreateInfo->enabledExtensionCount,\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002485 ' pCreateInfo->ppEnabledExtensionNames);\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002486 ' init_threading(my_data, pAllocator);\n'
Courtney Goeltzenleuchterd02a9642015-06-08 14:58:39 -06002487 ' }\n'
2488 ' return result;\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002489 '}\n' % (qual, decl))
Courtney Goeltzenleuchterd02a9642015-06-08 14:58:39 -06002490 return "\n".join(funcs);
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002491 if len(checked_params) == 0:
2492 return None
2493 # Surround call with useObject and finishUsingObject for each checked_param
Tobin Ehlis08fafd02015-06-12 12:49:01 -06002494 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002495 funcs.append('%s%s' % (qual, decl))
2496 funcs.append('{')
2497 for param in checked_params:
Michael Lentine13803dc2015-11-04 14:35:12 -08002498 funcs.append(' use%s((const void *) %s, %s);' % (param.ty, proto.params[0].name, param.name))
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002499 funcs.append(' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_%s_table_map, %s);' % (table, proto.params[0].name));
Mike Stroyan313f7e62015-08-10 16:42:53 -06002500 funcs.append(' %spDeviceTable->%s;' % (ret_val, proto.c_call()))
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002501 for param in checked_params:
Michael Lentine13803dc2015-11-04 14:35:12 -08002502 funcs.append(' finishUsing%s(%s);' % (param.ty, param.name))
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002503 funcs.append('%s'
2504 '}' % stmt)
2505 return "\n".join(funcs)
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002506
2507 def generate_body(self):
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002508 self.layer_name = "threading"
Mike Stroyan313f7e62015-08-10 16:42:53 -06002509 body = [self._generate_new_layer_initialization(True, lockname='threading', condname='threading'),
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002510 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Courtney Goeltzenleuchter17274172015-06-01 14:52:57 -06002511 self._generate_layer_gpa_function(extensions=[],
Jon Ashburn3dc39382015-09-17 10:00:32 -06002512 instance_extensions=[('msg_callback_get_proc_addr', [])]),
Courtney Goeltzenleuchter17274172015-06-01 14:52:57 -06002513 self._gen_create_msg_callback(),
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07002514 self._gen_destroy_msg_callback(),
2515 self._gen_debug_report_msg()]
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002516 return "\n\n".join(body)
2517
Tobin Ehlis12076fc2014-10-22 09:06:33 -06002518def main():
2519 subcommands = {
2520 "layer-funcs" : LayerFuncsSubcommand,
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002521 "generic" : GenericLayerSubcommand,
2522 "api_dump" : APIDumpSubcommand,
2523 "object_tracker" : ObjectTrackerSubcommand,
2524 "threading" : ThreadingSubcommand,
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07002525 "unique_objects" : UniqueObjectsSubcommand,
Tobin Ehlis12076fc2014-10-22 09:06:33 -06002526 }
2527
Tobin Ehlis14ff0852014-12-17 17:44:50 -07002528 if len(sys.argv) < 3 or sys.argv[1] not in subcommands or not os.path.exists(sys.argv[2]):
2529 print("Usage: %s <subcommand> <input_header> [options]" % sys.argv[0])
Tobin Ehlis12076fc2014-10-22 09:06:33 -06002530 print
Tobin Ehlis7e65d752015-01-15 17:51:52 -07002531 print("Available subcommands are: %s" % " ".join(subcommands))
Tobin Ehlis12076fc2014-10-22 09:06:33 -06002532 exit(1)
2533
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06002534 hfp = vk_helper.HeaderFileParser(sys.argv[2])
Tobin Ehlis14ff0852014-12-17 17:44:50 -07002535 hfp.parse()
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06002536 vk_helper.enum_val_dict = hfp.get_enum_val_dict()
2537 vk_helper.enum_type_dict = hfp.get_enum_type_dict()
2538 vk_helper.struct_dict = hfp.get_struct_dict()
2539 vk_helper.typedef_fwd_dict = hfp.get_typedef_fwd_dict()
2540 vk_helper.typedef_rev_dict = hfp.get_typedef_rev_dict()
2541 vk_helper.types_dict = hfp.get_types_dict()
Tobin Ehlis14ff0852014-12-17 17:44:50 -07002542
Tobin Ehlis12076fc2014-10-22 09:06:33 -06002543 subcmd = subcommands[sys.argv[1]](sys.argv[2:])
2544 subcmd.run()
2545
2546if __name__ == "__main__":
2547 main()