blob: aafa8b404a732b1d40de2be1cd3732b8aa96b635 [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 Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700476 if proto.name == "CreateInstance":
477 continue
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -0600478 if proto.name == "CreateDevice":
479 continue
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600480 lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600481 lookups.append(" return (PFN_vkVoidFunction) %s%s;" % (prefix, proto.name))
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600482
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600483 body.append("static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char *name)")
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600484 body.append("{")
485 body.append(generate_get_proc_addr_check("name"))
486 body.append("")
487 body.append(" name += 2;")
488 body.append(" %s" % "\n ".join(lookups))
489 body.append("")
490 body.append(" return NULL;")
491 body.append("}")
492
Mike Stroyan938c2532015-04-03 13:58:35 -0600493 funcs.append("\n".join(body))
Mike Stroyan938c2532015-04-03 13:58:35 -0600494 return "\n\n".join(funcs)
495
Tobin Ehlisca915872014-11-18 11:28:33 -0700496 def _generate_extensions(self):
497 exts = []
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600498 exts.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600499 exts.append(self._gen_create_msg_callback())
500 exts.append(self._gen_destroy_msg_callback())
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700501 exts.append(self._gen_debug_report_msg())
Tobin Ehlisb870cbb2015-04-15 07:46:12 -0600502 return "\n".join(exts)
503
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600504 def _generate_layer_gpa_function(self, extensions=[], instance_extensions=[]):
Jon Ashburnbacb0f52015-04-06 10:58:22 -0600505 func_body = []
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600506#
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600507# New style of GPA Functions for the new layer_data/layer_logging changes
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600508#
Tobin Ehlisd34a4c52015-12-08 10:50:10 -0700509 if self.layer_name in ['object_tracker', 'threading', 'unique_objects']:
Chia-I Wu9ab61502015-11-06 06:42:02 +0800510 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 -0600511 "{\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600512 " PFN_vkVoidFunction addr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600513 " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600514 " return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600515 " }\n\n"
516 " addr = layer_intercept_proc(funcName);\n"
517 " if (addr)\n"
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700518 " return addr;\n"
519 " if (device == VK_NULL_HANDLE) {\n"
520 " return NULL;\n"
521 " }\n")
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600522 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"
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700542 " if (!strcmp(funcName, \"vkGetInstanceProcAddr\"))\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600543 " return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700544 " if (!strcmp(funcName, \"vkCreateInstance\"))\n"
545 " return (PFN_vkVoidFunction) vkCreateInstance;\n"
546 " if (!strcmp(funcName, \"vkCreateDevice\"))\n"
547 " return (PFN_vkVoidFunction) vkCreateDevice;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600548 " addr = layer_intercept_instance_proc(funcName);\n"
549 " if (addr) {\n"
550 " return addr;"
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700551 " }\n"
552 " if (instance == VK_NULL_HANDLE) {\n"
553 " return NULL;\n"
554 " }\n"
555 )
Jon Ashburnbacb0f52015-04-06 10:58:22 -0600556
Jon Ashburn3dc39382015-09-17 10:00:32 -0600557 table_declared = False
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600558 if 0 != len(instance_extensions):
Jon Ashburn3dc39382015-09-17 10:00:32 -0600559 for (ext_enable, ext_list) in instance_extensions:
560 extra_space = ""
561 if 0 != len(ext_enable):
562 if ext_enable == 'msg_callback_get_proc_addr':
563 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 -0600564 " addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);\n"
565 " if (addr) {\n"
566 " return addr;\n"
Jon Ashburn3dc39382015-09-17 10:00:32 -0600567 " }\n")
568 else:
569 if table_declared == False:
570 func_body.append(" VkLayerInstanceDispatchTable* pTable = get_dispatch_table(%s_instance_table_map, instance);" % self.layer_name)
571 table_declared = True
572 func_body.append(' if (instanceExtMap.size() != 0 && instanceExtMap[pTable].%s)' % ext_enable)
573 func_body.append(' {')
574 extra_space = " "
575 for ext_name in ext_list:
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700576 if wsi_name(ext_name):
577 func_body.append('%s' % wsi_ifdef(ext_name))
Jon Ashburn3dc39382015-09-17 10:00:32 -0600578 func_body.append(' %sif (!strcmp("%s", funcName))\n'
579 ' return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700580 if wsi_name(ext_name):
581 func_body.append('%s' % wsi_endif(ext_name))
Jon Ashburn3dc39382015-09-17 10:00:32 -0600582 if 0 != len(ext_enable):
583 func_body.append(' }\n')
584
585 func_body.append(" if (get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr == NULL) {\n"
586 " return NULL;\n"
587 " }\n"
588 " return get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr(instance, funcName);\n"
589 "}\n" % (self.layer_name, self.layer_name))
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600590 return "\n".join(func_body)
591 else:
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600592 func_body.append('%s' % self.lineinfo.get())
Chia-I Wu9ab61502015-11-06 06:42:02 +0800593 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 -0600594 "{\n"
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700595 " PFN_vkVoidFunction addr;\n")
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700596 if self.layer_name == 'generic':
Jon Ashburn3a278b72015-10-06 17:05:21 -0600597 func_body.append("\n"
Jon Ashburn3a278b72015-10-06 17:05:21 -0600598 " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
Jon Ashburn3a278b72015-10-06 17:05:21 -0600599 " return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
600 " }\n\n"
601 " addr = layer_intercept_proc(funcName);\n"
602 " if (addr)\n"
603 " return addr;")
604 else:
605 func_body.append("\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600606 " loader_platform_thread_once(&initOnce, init%s);\n\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600607 " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600608 " return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600609 " }\n\n"
610 " addr = layer_intercept_proc(funcName);\n"
611 " if (addr)\n"
612 " return addr;" % self.layer_name)
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700613 func_body.append(" if (device == VK_NULL_HANDLE) {\n"
614 " return NULL;\n"
615 " }\n")
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600616 func_body.append('')
617 func_body.append(' VkLayerDispatchTable *pDisp = device_dispatch_table(device);')
618 if 0 != len(extensions):
619 extra_space = ""
620 for (ext_enable, ext_list) in extensions:
621 if 0 != len(ext_enable):
Jon Ashburn8acd2332015-09-16 18:08:32 -0600622 func_body.append(' if (deviceExtMap.size() != 0 && deviceExtMap[pDisp].%s)' % ext_enable)
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600623 func_body.append(' {')
624 extra_space = " "
625 for ext_name in ext_list:
626 func_body.append(' %sif (!strcmp("%s", funcName))\n'
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600627 ' return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600628 if 0 != len(ext_enable):
629 func_body.append(' }')
630 func_body.append('%s' % self.lineinfo.get())
631 func_body.append(" {\n"
632 " if (pDisp->GetDeviceProcAddr == NULL)\n"
633 " return NULL;\n"
634 " return pDisp->GetDeviceProcAddr(device, funcName);\n"
635 " }\n"
636 "}\n")
Jon Ashburn3dc39382015-09-17 10:00:32 -0600637 func_body.append('%s' % self.lineinfo.get())
Chia-I Wu9ab61502015-11-06 06:42:02 +0800638 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 -0600639 "{\n"
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600640 " PFN_vkVoidFunction addr;\n"
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700641 " if (!strcmp(funcName, \"vkGetInstanceProcAddr\"))\n"
642 " return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
643 " if (!strcmp(funcName, \"vkCreateInstance\"))\n"
644 " return (PFN_vkVoidFunction) vkCreateInstance;\n"
645 " if (!strcmp(funcName, \"vkCreateDevice\"))\n"
646 " return (PFN_vkVoidFunction) vkCreateDevice;\n"
647 )
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700648 if self.layer_name == 'generic':
Jon Ashburn3a278b72015-10-06 17:05:21 -0600649 func_body.append("\n"
Jon Ashburn3a278b72015-10-06 17:05:21 -0600650 " addr = layer_intercept_instance_proc(funcName);\n"
651 " if (addr)\n"
652 " return addr;")
653 else:
654 func_body.append(
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600655 " loader_platform_thread_once(&initOnce, init%s);\n\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600656 " addr = layer_intercept_instance_proc(funcName);\n"
657 " if (addr)\n"
658 " return addr;" % self.layer_name)
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700659 func_body.append(" if (instance == VK_NULL_HANDLE) {\n"
660 " return NULL;\n"
661 " }\n")
Jon Ashburn3dc39382015-09-17 10:00:32 -0600662 func_body.append("")
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700663 func_body.append(" VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(instance);\n")
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600664 if 0 != len(instance_extensions):
Jon Ashburn3dc39382015-09-17 10:00:32 -0600665 extra_space = ""
666 for (ext_enable, ext_list) in instance_extensions:
667 if 0 != len(ext_enable):
Jon Ashburn3a278b72015-10-06 17:05:21 -0600668 if ext_enable == 'msg_callback_get_proc_addr':
669 func_body.append(" layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);\n"
670 " addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);\n"
671 " if (addr) {\n"
672 " return addr;\n"
673 " }\n")
674 else:
675 func_body.append(' if (instanceExtMap.size() != 0 && instanceExtMap[pTable].%s)' % ext_enable)
676 func_body.append(' {')
677 extra_space = " "
678 for ext_name in ext_list:
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700679 if wsi_name(ext_name):
680 func_body.append('%s' % wsi_ifdef(ext_name))
Jon Ashburn3a278b72015-10-06 17:05:21 -0600681 func_body.append(' %sif (!strcmp("%s", funcName))\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -0600682 ' return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700683 if wsi_name(ext_name):
684 func_body.append('%s' % wsi_endif(ext_name))
Jon Ashburn3a278b72015-10-06 17:05:21 -0600685 if 0 != len(ext_enable):
686 func_body.append(' }\n')
Jon Ashburn3dc39382015-09-17 10:00:32 -0600687
688 func_body.append(" if (pTable->GetInstanceProcAddr == NULL)\n"
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600689 " return NULL;\n"
690 " return pTable->GetInstanceProcAddr(instance, funcName);\n"
691 "}\n")
692 return "\n".join(func_body)
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600693
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600694
Mike Stroyaned238bb2015-05-15 08:50:57 -0600695 def _generate_layer_initialization(self, init_opts=False, prefix='vk', lockname=None, condname=None):
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600696 func_body = ["#include \"vk_dispatch_table_helper.h\""]
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600697 func_body.append('%s' % self.lineinfo.get())
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700698 func_body.append('static void init_%s(layer_data *my_data, const VkAllocationCallbacks *pAllocator)\n'
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600699 '{\n' % self.layer_name)
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700700 if init_opts:
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600701 func_body.append('%s' % self.lineinfo.get())
Jon Ashburn3a278b72015-10-06 17:05:21 -0600702 func_body.append(' uint32_t report_flags = 0;')
703 func_body.append(' uint32_t debug_action = 0;')
704 func_body.append(' FILE *log_output = NULL;')
705 func_body.append(' const char *option_str;\n')
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600706 func_body.append(' // initialize %s options' % self.layer_name)
Jon Ashburn3a278b72015-10-06 17:05:21 -0600707 func_body.append(' report_flags = getLayerOptionFlags("%sReportFlags", 0);' % self.layer_name)
708 func_body.append(' getLayerOptionEnum("%sDebugAction", (uint32_t *) &debug_action);' % self.layer_name)
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700709 func_body.append('')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600710 func_body.append(' if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)')
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700711 func_body.append(' {')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600712 func_body.append(' option_str = getLayerOption("%sLogFilename");' % self.layer_name)
713 func_body.append(' log_output = getLayerLogOutput(option_str,"%s");' % self.layer_name)
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700714 func_body.append(' VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700715 func_body.append(' memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo));')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700716 func_body.append(' dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700717 func_body.append(' dbgCreateInfo.flags = report_flags;')
718 func_body.append(' dbgCreateInfo.pfnCallback = log_callback;')
719 func_body.append(' dbgCreateInfo.pUserData = NULL;')
720 func_body.append(' layer_create_msg_callback(my_data->report_data, &dbgCreateInfo, pAllocator,')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600721 func_body.append(' &my_data->logging_callback);')
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700722 func_body.append(' }')
723 func_body.append('')
Tobin Ehlis36f1b462015-02-23 14:09:16 -0700724 if lockname is not None:
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600725 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlis36f1b462015-02-23 14:09:16 -0700726 func_body.append(" if (!%sLockInitialized)" % lockname)
727 func_body.append(" {")
728 func_body.append(" // TODO/TBD: Need to delete this mutex sometime. How???")
729 func_body.append(" loader_platform_thread_create_mutex(&%sLock);" % lockname)
Mike Stroyaned238bb2015-05-15 08:50:57 -0600730 if condname is not None:
731 func_body.append(" loader_platform_thread_init_cond(&%sCond);" % condname)
Tobin Ehlis36f1b462015-02-23 14:09:16 -0700732 func_body.append(" %sLockInitialized = 1;" % lockname)
733 func_body.append(" }")
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600734 func_body.append("}\n")
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -0600735 func_body.append('')
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600736 return "\n".join(func_body)
737
Mike Stroyan313f7e62015-08-10 16:42:53 -0600738 def _generate_new_layer_initialization(self, init_opts=False, prefix='vk', lockname=None, condname=None):
739 func_body = ["#include \"vk_dispatch_table_helper.h\""]
740 func_body.append('%s' % self.lineinfo.get())
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700741 func_body.append('static void init_%s(layer_data *my_data, const VkAllocationCallbacks *pAllocator)\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -0600742 '{\n' % self.layer_name)
743 if init_opts:
744 func_body.append('%s' % self.lineinfo.get())
745 func_body.append(' uint32_t report_flags = 0;')
746 func_body.append(' uint32_t debug_action = 0;')
747 func_body.append(' FILE *log_output = NULL;')
748 func_body.append(' const char *strOpt;')
749 func_body.append(' // initialize %s options' % self.layer_name)
750 func_body.append(' report_flags = getLayerOptionFlags("%sReportFlags", 0);' % self.layer_name)
Jon Ashburn9ff6ae92015-10-06 17:20:01 -0600751 func_body.append(' getLayerOptionEnum("%sDebugAction", (uint32_t *) &debug_action);' % self.layer_name)
Mike Stroyan313f7e62015-08-10 16:42:53 -0600752 func_body.append('')
753 func_body.append(' if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)')
754 func_body.append(' {')
755 func_body.append(' strOpt = getLayerOption("%sLogFilename");' % self.layer_name)
Tobin Ehlisb1df55e2015-09-15 09:55:54 -0600756 func_body.append(' log_output = getLayerLogOutput(strOpt, "%s");' % self.layer_name)
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700757 func_body.append(' VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700758 func_body.append(' memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo));')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700759 func_body.append(' dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700760 func_body.append(' dbgCreateInfo.flags = report_flags;')
761 func_body.append(' dbgCreateInfo.pfnCallback = log_callback;')
762 func_body.append(' dbgCreateInfo.pUserData = log_output;')
763 func_body.append(' layer_create_msg_callback(my_data->report_data, &dbgCreateInfo, pAllocator,')
764 func_body.append(' &my_data->logging_callback);')
Mike Stroyan313f7e62015-08-10 16:42:53 -0600765 func_body.append(' }')
766 func_body.append('')
767 if lockname is not None:
768 func_body.append('%s' % self.lineinfo.get())
769 func_body.append(" if (!%sLockInitialized)" % lockname)
770 func_body.append(" {")
771 func_body.append(" // TODO/TBD: Need to delete this mutex sometime. How???")
772 func_body.append(" loader_platform_thread_create_mutex(&%sLock);" % lockname)
773 if condname is not None:
774 func_body.append(" loader_platform_thread_init_cond(&%sCond);" % condname)
775 func_body.append(" %sLockInitialized = 1;" % lockname)
776 func_body.append(" }")
777 func_body.append("}\n")
778 func_body.append('')
779 return "\n".join(func_body)
780
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600781class LayerFuncsSubcommand(Subcommand):
782 def generate_header(self):
David Pinedo9316d3b2015-11-06 12:54:48 -0700783 return '#include <vulkan/vk_layer.h>\n#include "loader.h"'
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600784
785 def generate_body(self):
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600786 return self._generate_dispatch_entrypoints("static")
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600787
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600788class GenericLayerSubcommand(Subcommand):
789 def generate_header(self):
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500790 gen_header = []
Courtney Goeltzenleuchter79a5a962015-07-07 17:51:45 -0600791 gen_header.append('%s' % self.lineinfo.get())
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500792 gen_header.append('#include <stdio.h>')
793 gen_header.append('#include <stdlib.h>')
794 gen_header.append('#include <string.h>')
795 gen_header.append('#include <unordered_map>')
Tobin Ehlisb835d1b2015-07-03 10:34:49 -0600796 gen_header.append('#include "vk_loader_platform.h"')
David Pinedo9316d3b2015-11-06 12:54:48 -0700797 gen_header.append('#include "vulkan/vk_layer.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -0600798 gen_header.append('#include "vk_layer_config.h"')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600799 gen_header.append('#include "vk_layer_logging.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -0600800 gen_header.append('#include "vk_layer_table.h"')
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -0600801 gen_header.append('#include "vk_layer_extension_utils.h"')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500802 gen_header.append('')
Courtney Goeltzenleuchter79a5a962015-07-07 17:51:45 -0600803 gen_header.append('#include "generic.h"')
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600804 gen_header.append('')
Tobin Ehlisa30e7e52015-07-06 14:02:36 -0600805 gen_header.append('%s' % self.lineinfo.get())
806 gen_header.append('#define LAYER_EXT_ARRAY_SIZE 1')
807 gen_header.append('#define LAYER_DEV_EXT_ARRAY_SIZE 1')
Jon Ashburn3a278b72015-10-06 17:05:21 -0600808 gen_header.append('//static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
809 gen_header.append('static std::unordered_map<void *, layer_data *> layer_data_map;\n')
810 gen_header.append('template layer_data *get_my_data_ptr<layer_data>(')
811 gen_header.append(' void *data_key,')
812 gen_header.append(' std::unordered_map<void *, layer_data *> &data_map);\n')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500813 gen_header.append('')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500814 return "\n".join(gen_header)
Tobin Ehlis7a314ea2015-07-07 11:02:44 -0600815
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600816 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600817 if proto.name in [ 'EnumerateInstanceLayerProperties', 'EnumerateInstanceExtensionProperties', 'EnumerateDeviceLayerProperties', 'EnumerateDeviceExtensionProperties' ]:
Mike Stroyan00087e62015-04-03 14:39:16 -0600818 # use default version
819 return None
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600820 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyan938c2532015-04-03 13:58:35 -0600821 ret_val = ''
822 stmt = ''
823 funcs = []
Jon Ashburn71836d92015-05-12 17:23:55 -0600824 table = ''
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600825 if proto_is_global(proto):
Jon Ashburn71836d92015-05-12 17:23:55 -0600826 table = 'Instance'
Mike Stroyan938c2532015-04-03 13:58:35 -0600827 if proto.ret != "void":
Courtney Goeltzenleuchter0de9e212015-06-26 15:07:53 -0600828 funcs.append('%s' % self.lineinfo.get())
Jon Ashburnb0fbe912015-05-06 10:15:07 -0600829 ret_val = "%s result = " % proto.ret
Mike Stroyan938c2532015-04-03 13:58:35 -0600830 stmt = " return result;\n"
Jon Ashburn8ced4212015-05-22 12:01:50 -0600831 if proto.name == "CreateDevice":
Courtney Goeltzenleuchter0de9e212015-06-26 15:07:53 -0600832 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan938c2532015-04-03 13:58:35 -0600833 funcs.append('%s%s\n'
834 '{\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700835 ' layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500836 ' char str[1024];\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600837 ' sprintf(str, "At start of Generic layered %s\\n");\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700838 ' log_msg(my_instance_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,'
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -0700839 ' (uint64_t)physicalDevice, __LINE__, 0, (char *) "generic", "%%s", (char *) str);\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700840 ' VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);\n'
841 ' PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;\n'
842 ' PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;\n'
843 ' PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");\n'
844 ' if (fpCreateDevice == NULL) {\n'
845 ' return VK_ERROR_INITIALIZATION_FAILED;\n'
Mike Stroyan938c2532015-04-03 13:58:35 -0600846 ' }\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700847 ' // Advance the link info for the next element on the chain\n'
848 ' chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;\n'
849 ' VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);\n'
850 ' if (result != VK_SUCCESS) {\n'
851 ' return result;\n'
852 ' }\n'
853 ' layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);\n'
854 ' initDeviceTable(*pDevice, fpGetDeviceProcAddr);\n'
855 ' my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);\n'
856 ' createDeviceRegisterExtensions(pCreateInfo, *pDevice);\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700857 ' sprintf(str, "Completed generic layered %s\\n");\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700858 ' log_msg(my_device_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 -0500859 ' %s'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700860 '}' % (qual, decl, proto.name, proto.name, stmt))
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500861 elif proto.name == "DestroyDevice":
Courtney Goeltzenleuchter0de9e212015-06-26 15:07:53 -0600862 funcs.append('%s' % self.lineinfo.get())
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500863 funcs.append('%s%s\n'
864 '{\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -0600865 ' dispatch_key key = get_dispatch_key(device);\n'
Jon Ashburn747f2b62015-06-18 15:02:58 -0600866 ' VkLayerDispatchTable *pDisp = device_dispatch_table(device);\n'
Chia-I Wuf7458c52015-10-26 21:10:41 +0800867 ' pDisp->DestroyDevice(device, pAllocator);\n'
Jon Ashburn747f2b62015-06-18 15:02:58 -0600868 ' deviceExtMap.erase(pDisp);\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -0600869 ' destroy_device_dispatch_table(key);\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500870 '}\n' % (qual, decl))
871 elif proto.name == "DestroyInstance":
Courtney Goeltzenleuchter0de9e212015-06-26 15:07:53 -0600872 funcs.append('%s' % self.lineinfo.get())
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500873 funcs.append('%s%s\n'
874 '{\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -0600875 ' dispatch_key key = get_dispatch_key(instance);\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -0600876 ' VkLayerInstanceDispatchTable *pDisp = instance_dispatch_table(instance);\n'
Chia-I Wuf7458c52015-10-26 21:10:41 +0800877 ' pDisp->DestroyInstance(instance, pAllocator);\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600878 ' // Clean up logging callback, if any\n'
879 ' layer_data *my_data = get_my_data_ptr(key, layer_data_map);\n'
880 ' if (my_data->logging_callback) {\n'
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700881 ' layer_destroy_msg_callback(my_data->report_data, my_data->logging_callback, pAllocator);\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600882 ' }\n\n'
883 ' layer_debug_report_destroy_instance(my_data->report_data);\n'
884 ' layer_data_map.erase(key);\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -0600885 ' instanceExtMap.erase(pDisp);\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -0600886 ' destroy_instance_dispatch_table(key);\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500887 '}\n' % (qual, decl))
Jon Ashburn3dc39382015-09-17 10:00:32 -0600888 elif proto.name == "CreateInstance":
Courtney Goeltzenleuchter0de9e212015-06-26 15:07:53 -0600889 funcs.append('%s' % self.lineinfo.get())
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500890 # CreateInstance needs to use the second parm instead of the first to set the correct dispatch table
Jon Ashburn3dc39382015-09-17 10:00:32 -0600891 funcs.append('%s%s\n'
892 '{\n'
Jon Ashburn3a278b72015-10-06 17:05:21 -0600893 ' char str[1024];\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700894 ' VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);\n'
895 ' PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;\n'
896 ' PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");\n'
897 ' if (fpCreateInstance == NULL) {\n'
898 ' return VK_ERROR_INITIALIZATION_FAILED;\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -0600899 ' }\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700900 ' // Advance the link info for the next element on the chain\n'
901 ' chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;\n'
902 ' VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);\n'
903 ' if (result != VK_SUCCESS) {\n'
904 ' return result;\n'
905 ' }\n'
906 ' VkLayerInstanceDispatchTable *pTable = initInstanceTable(*pInstance, fpGetInstanceProcAddr);\n'
907 ' createInstanceRegisterExtensions(pCreateInfo, *pInstance);\n'
908 ' layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);\n'
909 ' my_data->report_data = debug_report_create_instance(\n'
910 ' pTable,\n'
911 ' *pInstance,\n'
912 ' pCreateInfo->enabledExtensionCount,\n'
913 ' pCreateInfo->ppEnabledExtensionNames);\n'
914 ' init_generic(my_data, pAllocator);\n'
915 ' sprintf(str, "Completed generic layered %s\\n");\n'
916 ' 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'
Tobin Ehlis1350a362015-09-17 16:27:04 -0600917 ' return result;\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700918 '}\n' % (qual, decl, proto.name))
Jon Ashburn3dc39382015-09-17 10:00:32 -0600919 else:
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700920 if wsi_name(proto.name):
921 funcs.append('%s' % wsi_ifdef(proto.name))
Jon Ashburn3dc39382015-09-17 10:00:32 -0600922 funcs.append('%s' % self.lineinfo.get())
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500923 dispatch_param = proto.params[0].name
924 # Must use 'instance' table for these APIs, 'device' table otherwise
925 table_type = ""
926 if proto_is_global(proto):
927 table_type = "instance"
928 else:
929 table_type = "device"
Mike Stroyan938c2532015-04-03 13:58:35 -0600930 funcs.append('%s%s\n'
931 '{\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500932 ' %s%s_dispatch_table(%s)->%s;\n'
Mike Stroyan938c2532015-04-03 13:58:35 -0600933 '%s'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500934 '}' % (qual, decl, ret_val, table_type, dispatch_param, proto.c_call(), stmt))
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700935 if wsi_name(proto.name):
936 funcs.append('%s' % wsi_endif(proto.name))
Mike Stroyan938c2532015-04-03 13:58:35 -0600937 return "\n\n".join(funcs)
938
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600939 def generate_body(self):
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700940 self.layer_name = "generic"
Jon Ashburn3a278b72015-10-06 17:05:21 -0600941 instance_extensions=[('msg_callback_get_proc_addr', []),
942 ('wsi_enabled',
Ian Elliott05846062015-11-20 14:13:17 -0700943 ['vkGetPhysicalDeviceSurfaceSupportKHR',
944 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
945 'vkGetPhysicalDeviceSurfaceFormatsKHR',
946 'vkGetPhysicalDeviceSurfacePresentModesKHR'])]
Tobin Ehlisd34a4c52015-12-08 10:50:10 -0700947 extensions=[('wsi_enabled',
Ian Elliott05846062015-11-20 14:13:17 -0700948 ['vkCreateSwapchainKHR',
Jon Ashburn8acd2332015-09-16 18:08:32 -0600949 'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
950 'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600951 body = [self._generate_layer_initialization(True),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600952 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600953 self._gen_create_msg_callback(),
954 self._gen_destroy_msg_callback(),
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700955 self._gen_debug_report_msg(),
Jon Ashburn3dc39382015-09-17 10:00:32 -0600956 self._generate_layer_gpa_function(extensions, instance_extensions)]
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600957
958 return "\n\n".join(body)
959
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600960class APIDumpSubcommand(Subcommand):
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600961 def generate_header(self):
Tobin Ehlisd009bae2014-11-24 15:46:55 -0700962 header_txt = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600963 header_txt.append('%s' % self.lineinfo.get())
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600964 header_txt.append('#include <fstream>')
965 header_txt.append('#include <iostream>')
966 header_txt.append('#include <string>')
Jon Ashburn747f2b62015-06-18 15:02:58 -0600967 header_txt.append('#include <string.h>')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600968 header_txt.append('')
Tobin Ehlis80d048e2015-08-28 09:57:53 -0600969 header_txt.append('#include "vk_loader_platform.h"')
David Pinedo9316d3b2015-11-06 12:54:48 -0700970 header_txt.append('#include "vulkan/vk_layer.h"')
Tobin Ehlis80d048e2015-08-28 09:57:53 -0600971 header_txt.append('#include "vk_struct_string_helper_cpp.h"')
972 header_txt.append('#include "vk_layer_table.h"')
973 header_txt.append('#include "vk_layer_extension_utils.h"')
974 header_txt.append('#include <unordered_map>')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700975 header_txt.append('#include "api_dump.h"')
Tobin Ehlis80d048e2015-08-28 09:57:53 -0600976 header_txt.append('')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600977 header_txt.append('static std::ofstream fileStream;')
978 header_txt.append('static std::string fileName = "vk_apidump.txt";')
979 header_txt.append('std::ostream* outputStream = NULL;')
980 header_txt.append('void ConfigureOutputStream(bool writeToFile, bool flushAfterWrite)')
981 header_txt.append('{')
982 header_txt.append(' if(writeToFile)')
983 header_txt.append(' {')
Tobin Ehlis93245a92015-09-18 14:32:12 -0600984 header_txt.append(' if (fileName == "stdout")')
985 header_txt.append(' {')
Tobin Ehlis80d048e2015-08-28 09:57:53 -0600986 header_txt.append(' outputStream = &std::cout;')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700987 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 -0600988 header_txt.append(' } else {')
989 header_txt.append(' fileStream.open(fileName);')
990 header_txt.append(' if ((fileStream.rdstate() & fileStream.failbit) != 0) {')
991 header_txt.append(' outputStream = &std::cout;')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700992 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 -0600993 header_txt.append(' }')
994 header_txt.append(' else')
995 header_txt.append(' outputStream = &fileStream;')
Tobin Ehlis80d048e2015-08-28 09:57:53 -0600996 header_txt.append(' }')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600997 header_txt.append(' }')
998 header_txt.append(' else')
999 header_txt.append(' {')
1000 header_txt.append(' outputStream = &std::cout;')
1001 header_txt.append(' }')
1002 header_txt.append('')
1003 header_txt.append(' if(flushAfterWrite)')
1004 header_txt.append(' {')
1005 header_txt.append(' outputStream->sync_with_stdio(true);')
1006 header_txt.append(' }')
1007 header_txt.append(' else')
1008 header_txt.append(' {')
1009 header_txt.append(' outputStream->sync_with_stdio(false);')
1010 header_txt.append(' }')
1011 header_txt.append('}')
1012 header_txt.append('')
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001013 header_txt.append('%s' % self.lineinfo.get())
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001014 header_txt.append('static bool g_APIDumpDetailed = true;')
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001015 header_txt.append('')
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -06001016 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001017 header_txt.append('')
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001018 header_txt.append('static int printLockInitialized = 0;')
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001019 header_txt.append('static loader_platform_thread_mutex printLock;')
1020 header_txt.append('')
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001021 header_txt.append('%s' % self.lineinfo.get())
Tobin Ehlisa30e7e52015-07-06 14:02:36 -06001022 header_txt.append('#define LAYER_EXT_ARRAY_SIZE 1')
1023 header_txt.append('#define LAYER_DEV_EXT_ARRAY_SIZE 1')
Tobin Ehlisd009bae2014-11-24 15:46:55 -07001024 header_txt.append('#define MAX_TID 513')
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001025 header_txt.append('static loader_platform_thread_id tidMapping[MAX_TID] = {0};')
Tobin Ehlisd009bae2014-11-24 15:46:55 -07001026 header_txt.append('static uint32_t maxTID = 0;')
1027 header_txt.append('// Map actual TID to an index value and return that index')
1028 header_txt.append('// This keeps TIDs in range from 0-MAX_TID and simplifies compares between runs')
1029 header_txt.append('static uint32_t getTIDIndex() {')
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001030 header_txt.append(' loader_platform_thread_id tid = loader_platform_get_thread_id();')
Tobin Ehlisd009bae2014-11-24 15:46:55 -07001031 header_txt.append(' for (uint32_t i = 0; i < maxTID; i++) {')
1032 header_txt.append(' if (tid == tidMapping[i])')
1033 header_txt.append(' return i;')
1034 header_txt.append(' }')
1035 header_txt.append(" // Don't yet have mapping, set it and return newly set index")
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001036 header_txt.append(' uint32_t retVal = (uint32_t) maxTID;')
Tobin Ehlisd009bae2014-11-24 15:46:55 -07001037 header_txt.append(' tidMapping[maxTID++] = tid;')
1038 header_txt.append(' assert(maxTID < MAX_TID);')
1039 header_txt.append(' return retVal;')
1040 header_txt.append('}')
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001041 header_txt.append('')
Tobin Ehlisd009bae2014-11-24 15:46:55 -07001042 return "\n".join(header_txt)
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001043
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001044 def generate_init(self):
1045 func_body = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001046 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001047 func_body.append('#include "vk_dispatch_table_helper.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -06001048 func_body.append('#include "vk_layer_config.h"')
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001049 func_body.append('')
1050 func_body.append('static void init%s(void)' % self.layer_name)
1051 func_body.append('{')
1052 func_body.append(' using namespace StreamControl;')
1053 func_body.append('')
Tobin Ehlisa8700972015-08-26 16:18:52 -06001054 func_body.append(' char const*const logName = getLayerOption("APIDumpLogFilename");')
1055 func_body.append(' if(logName != NULL)')
1056 func_body.append(' {')
1057 func_body.append(' fileName = logName;')
1058 func_body.append(' }')
1059 func_body.append('')
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001060 func_body.append(' char const*const detailedStr = getLayerOption("APIDumpDetailed");')
1061 func_body.append(' if(detailedStr != NULL)')
1062 func_body.append(' {')
1063 func_body.append(' if(strcmp(detailedStr, "TRUE") == 0)')
1064 func_body.append(' {')
1065 func_body.append(' g_APIDumpDetailed = true;')
1066 func_body.append(' }')
1067 func_body.append(' else if(strcmp(detailedStr, "FALSE") == 0)')
1068 func_body.append(' {')
1069 func_body.append(' g_APIDumpDetailed = false;')
1070 func_body.append(' }')
1071 func_body.append(' }')
1072 func_body.append('')
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001073 func_body.append(' char const*const writeToFileStr = getLayerOption("APIDumpFile");')
1074 func_body.append(' bool writeToFile = false;')
1075 func_body.append(' if(writeToFileStr != NULL)')
1076 func_body.append(' {')
1077 func_body.append(' if(strcmp(writeToFileStr, "TRUE") == 0)')
1078 func_body.append(' {')
1079 func_body.append(' writeToFile = true;')
1080 func_body.append(' }')
1081 func_body.append(' else if(strcmp(writeToFileStr, "FALSE") == 0)')
1082 func_body.append(' {')
1083 func_body.append(' writeToFile = false;')
1084 func_body.append(' }')
1085 func_body.append(' }')
1086 func_body.append('')
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001087 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001088 func_body.append(' char const*const noAddrStr = getLayerOption("APIDumpNoAddr");')
1089 func_body.append(' if(noAddrStr != NULL)')
1090 func_body.append(' {')
1091 func_body.append(' if(strcmp(noAddrStr, "FALSE") == 0)')
1092 func_body.append(' {')
1093 func_body.append(' StreamControl::writeAddress = true;')
1094 func_body.append(' }')
1095 func_body.append(' else if(strcmp(noAddrStr, "TRUE") == 0)')
1096 func_body.append(' {')
1097 func_body.append(' StreamControl::writeAddress = false;')
1098 func_body.append(' }')
1099 func_body.append(' }')
1100 func_body.append('')
1101 func_body.append(' char const*const flushAfterWriteStr = getLayerOption("APIDumpFlush");')
1102 func_body.append(' bool flushAfterWrite = false;')
1103 func_body.append(' if(flushAfterWriteStr != NULL)')
1104 func_body.append(' {')
1105 func_body.append(' if(strcmp(flushAfterWriteStr, "TRUE") == 0)')
1106 func_body.append(' {')
1107 func_body.append(' flushAfterWrite = true;')
1108 func_body.append(' }')
1109 func_body.append(' else if(strcmp(flushAfterWriteStr, "FALSE") == 0)')
1110 func_body.append(' {')
1111 func_body.append(' flushAfterWrite = false;')
1112 func_body.append(' }')
1113 func_body.append(' }')
1114 func_body.append('')
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001115 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001116 func_body.append(' ConfigureOutputStream(writeToFile, flushAfterWrite);')
1117 func_body.append('')
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001118 func_body.append(' if (!printLockInitialized)')
1119 func_body.append(' {')
1120 func_body.append(' // TODO/TBD: Need to delete this mutex sometime. How???')
1121 func_body.append(' loader_platform_thread_create_mutex(&printLock);')
1122 func_body.append(' printLockInitialized = 1;')
1123 func_body.append(' }')
1124 func_body.append('}')
1125 func_body.append('')
1126 return "\n".join(func_body)
Tobin Ehlis99f88672015-01-10 12:42:41 -07001127
Mike Stroyanbf237d72015-04-03 17:45:53 -06001128 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001129 if proto.name in [ 'EnumerateInstanceLayerProperties','EnumerateInstanceExtensionProperties','EnumerateDeviceLayerProperties','EnumerateDeviceExtensionProperties']:
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001130 return None
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001131 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyanbf237d72015-04-03 17:45:53 -06001132 ret_val = ''
1133 stmt = ''
1134 funcs = []
1135 sp_param_dict = {} # Store 'index' for struct param to print, or an name of binding "Count" param for array to print
1136 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 +08001137 if 'AllocateDescriptorSets' in proto.name:
Cody Northrop1e4f8022015-08-03 12:47:29 -06001138 create_params = -1
Mike Stroyanbf237d72015-04-03 17:45:53 -06001139 elif 'Create' in proto.name or 'Alloc' in proto.name or 'MapMemory' in proto.name:
1140 create_params = -1
1141 if proto.ret != "void":
Jon Ashburnb0fbe912015-05-06 10:15:07 -06001142 ret_val = "%s result = " % proto.ret
Mike Stroyanbf237d72015-04-03 17:45:53 -06001143 stmt = " return result;\n"
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001144 f_open = 'loader_platform_thread_lock_mutex(&printLock);\n '
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001145 log_func = '%s\n' % self.lineinfo.get()
1146 log_func += ' if (StreamControl::writeAddress == true) {'
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001147 log_func += '\n (*outputStream) << "t{" << getTIDIndex() << "} vk%s(' % proto.name
1148 log_func_no_addr = '\n (*outputStream) << "t{" << getTIDIndex() << "} vk%s(' % proto.name
1149 f_close = '\n loader_platform_thread_unlock_mutex(&printLock);'
Mike Stroyanbf237d72015-04-03 17:45:53 -06001150 pindex = 0
1151 prev_count_name = ''
1152 for p in proto.params:
1153 cp = False
1154 if 0 != create_params:
1155 # If this is any of the N last params of the func, treat as output
1156 for y in range(-1, create_params-1, -1):
1157 if p.name == proto.params[y].name:
1158 cp = True
1159 (pft, pfi) = self._get_printf_params(p.ty, p.name, cp, cpp=True)
Jon Ashburn8acd2332015-09-16 18:08:32 -06001160 if p.name == "pSwapchain" or p.name == "pSwapchainImages":
Chia-I Wue2fc5522015-10-26 20:04:44 +08001161 log_func += '%s = " << %s << ", ' % (p.name, p.name)
Mark Lobodzinski25a2cc82015-12-02 16:12:08 -07001162 elif p.name == "swapchain" or p.name == "visual_id":
Chia-I Wue2fc5522015-10-26 20:04:44 +08001163 log_func += '%s = " << %s << ", ' % (p.name, p.name)
Ian Elliott1064fe32015-07-06 14:31:32 -06001164 else:
1165 log_func += '%s = " << %s << ", ' % (p.name, pfi)
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001166 if "%p" == pft:
1167 log_func_no_addr += '%s = address, ' % (p.name)
1168 else:
1169 log_func_no_addr += '%s = " << %s << ", ' % (p.name, pfi)
Tobin Ehlis08541742015-04-16 15:56:11 -06001170 if prev_count_name != '' and (prev_count_name.replace('Count', '')[1:] in p.name):
Mike Stroyanbf237d72015-04-03 17:45:53 -06001171 sp_param_dict[pindex] = prev_count_name
Tobin Ehlis08541742015-04-16 15:56:11 -06001172 prev_count_name = ''
Chia-I Wuf8693382015-04-16 22:02:10 +08001173 elif vk_helper.is_type(p.ty.strip('*').replace('const ', ''), 'struct'):
Mike Stroyanbf237d72015-04-03 17:45:53 -06001174 sp_param_dict[pindex] = 'index'
Mike Stroyanbf237d72015-04-03 17:45:53 -06001175 if p.name.endswith('Count'):
1176 if '*' in p.ty:
1177 prev_count_name = "*%s" % p.name
1178 else:
1179 prev_count_name = p.name
Courtney Goeltzenleuchterf260f6c2015-09-23 12:28:10 -06001180 else:
1181 prev_count_name = ''
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001182 pindex += 1
Mike Stroyanbf237d72015-04-03 17:45:53 -06001183 log_func = log_func.strip(', ')
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001184 log_func_no_addr = log_func_no_addr.strip(', ')
Jon Ashburnb0fbe912015-05-06 10:15:07 -06001185 if proto.ret == "VkResult":
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06001186 log_func += ') = " << string_VkResult((VkResult)result) << endl'
1187 log_func_no_addr += ') = " << string_VkResult((VkResult)result) << endl'
Jon Ashburnb0fbe912015-05-06 10:15:07 -06001188 elif proto.ret == "void*":
1189 log_func += ') = " << result << endl'
1190 log_func_no_addr += ') = " << result << endl'
Mike Stroyanbf237d72015-04-03 17:45:53 -06001191 else:
1192 log_func += ')\\n"'
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001193 log_func_no_addr += ')\\n"'
Mike Stroyanbf237d72015-04-03 17:45:53 -06001194 log_func += ';'
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001195 log_func_no_addr += ';'
Tobin Ehlisa30e7e52015-07-06 14:02:36 -06001196 log_func += '\n }\n else {%s\n }' % log_func_no_addr;
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001197 log_func += '\n%s' % self.lineinfo.get()
Courtney Goeltzenleuchterf260f6c2015-09-23 12:28:10 -06001198 # log_func += '\n// Proto %s has param_dict: %s' % (proto.name, sp_param_dict)
Mike Stroyanbf237d72015-04-03 17:45:53 -06001199 if len(sp_param_dict) > 0:
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001200 indent = ' '
1201 log_func += '\n%sif (g_APIDumpDetailed) {' % indent
1202 indent += ' '
Mike Stroyanbf237d72015-04-03 17:45:53 -06001203 i_decl = False
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001204 log_func += '\n%s' % self.lineinfo.get()
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001205 log_func += '\n%sstring tmp_str;' % indent
Mike Stroyanbf237d72015-04-03 17:45:53 -06001206 for sp_index in sp_param_dict:
Courtney Goeltzenleuchterf260f6c2015-09-23 12:28:10 -06001207 # log_func += '\n// sp_index: %s' % str(sp_index)
Mike Stroyanbf237d72015-04-03 17:45:53 -06001208 if 'index' == sp_param_dict[sp_index]:
Courtney Goeltzenleuchter95487bc2015-04-14 18:48:46 -06001209 cis_print_func = 'vk_print_%s' % (proto.params[sp_index].ty.replace('const ', '').strip('*').lower())
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001210 local_name = proto.params[sp_index].name
1211 if '*' not in proto.params[sp_index].ty:
1212 local_name = '&%s' % proto.params[sp_index].name
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001213 log_func += '\n%s' % self.lineinfo.get()
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001214 log_func += '\n%sif (%s) {' % (indent, local_name)
1215 indent += ' '
1216 log_func += '\n%stmp_str = %s(%s, " ");' % (indent, cis_print_func, local_name)
1217 log_func += '\n%s(*outputStream) << " %s (" << %s << ")" << endl << tmp_str << endl;' % (indent, local_name, local_name)
1218 indent = indent[4:]
1219 log_func += '\n%s}' % (indent)
Mike Stroyanbf237d72015-04-03 17:45:53 -06001220 else: # We have a count value stored to iterate over an array
1221 print_cast = ''
1222 print_func = ''
Courtney Goeltzenleuchter95487bc2015-04-14 18:48:46 -06001223 if vk_helper.is_type(proto.params[sp_index].ty.strip('*').replace('const ', ''), 'struct'):
Mike Stroyanbf237d72015-04-03 17:45:53 -06001224 print_cast = '&'
Courtney Goeltzenleuchter95487bc2015-04-14 18:48:46 -06001225 print_func = 'vk_print_%s' % proto.params[sp_index].ty.replace('const ', '').strip('*').lower()
Mike Stroyanbf237d72015-04-03 17:45:53 -06001226 else:
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001227 print_cast = ''
Mike Stroyanbf237d72015-04-03 17:45:53 -06001228 print_func = 'string_convert_helper'
1229 #cis_print_func = 'tmp_str = string_convert_helper((void*)%s[i], " ");' % proto.params[sp_index].name
Chia-I Wue2fc5522015-10-26 20:04:44 +08001230 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 -06001231 if not i_decl:
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001232 log_func += '\n%suint32_t i;' % (indent)
Mike Stroyanbf237d72015-04-03 17:45:53 -06001233 i_decl = True
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001234 log_func += '\n%sif (%s) {' % (indent, proto.params[sp_index].name)
1235 indent += ' '
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001236 log_func += '\n%s' % self.lineinfo.get()
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001237 log_func += '\n%sfor (i = 0; i < %s; i++) {' % (indent, sp_param_dict[sp_index])
1238 indent += ' '
1239 log_func += '\n%s%s' % (indent, cis_print_func)
Tobin Ehlis45a23a82015-04-28 10:58:20 -06001240 log_func += '\n%sif (StreamControl::writeAddress == true) {' % (indent)
1241 indent += ' '
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001242 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)
1243 indent = indent[4:]
Tobin Ehlis45a23a82015-04-28 10:58:20 -06001244 log_func += '\n%s} else {' % (indent)
1245 indent += ' '
1246 log_func += '\n%s(*outputStream) << " %s[" << i << "] (address)" << endl << " address" << endl;' % (indent, proto.params[sp_index].name)
1247 indent = indent[4:]
1248 log_func += '\n%s}' % (indent)
1249 indent = indent[4:]
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001250 log_func += '\n%s}' % (indent)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001251 indent = indent[4:]
1252 log_func += '\n%s}' % (indent)
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001253 indent = indent[4:]
1254 log_func += '\n%s}' % (indent)
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001255 table_type = ''
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001256 if proto_is_global(proto):
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001257 table_type = 'instance'
1258 else:
1259 table_type = 'device'
Jon Ashburn3dc39382015-09-17 10:00:32 -06001260 dispatch_param = proto.params[0].name
Jon Ashburn71836d92015-05-12 17:23:55 -06001261
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001262 if proto.name == "CreateInstance":
1263 dispatch_param = '*' + proto.params[1].name
Jon Ashburn3dc39382015-09-17 10:00:32 -06001264 funcs.append('%s%s\n'
1265 '{\n'
1266 ' using namespace StreamControl;\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001267 ' loader_platform_thread_once(&initOnce, initapi_dump);\n'
1268 ' VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);\n'
1269 ' PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;\n'
1270 ' PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");\n'
1271 ' if (fpCreateInstance == NULL) {\n'
1272 ' return VK_ERROR_INITIALIZATION_FAILED;\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -06001273 ' }\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001274 ' // Advance the link info for the next element on the chain\n'
1275 ' assert(chain_info->u.pLayerInfo);\n'
1276 ' chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;\n'
1277 ' VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);\n'
1278 ' if (result != VK_SUCCESS)\n'
1279 ' return result;\n'
1280 ' initInstanceTable(*pInstance, fpGetInstanceProcAddr);\n'
1281 ' createInstanceRegisterExtensions(pCreateInfo, *pInstance);\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -06001282 ' %s%s%s\n'
1283 '%s'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001284 '}\n' % (qual, decl, f_open, log_func, f_close, stmt))
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001285
Jon Ashburn3dc39382015-09-17 10:00:32 -06001286 elif proto.name == "CreateDevice":
Courtney Goeltzenleuchter0de9e212015-06-26 15:07:53 -06001287 funcs.append('%s\n' % self.lineinfo.get())
Jon Ashburn747f2b62015-06-18 15:02:58 -06001288 funcs.append('%s%s\n'
1289 '{\n'
1290 ' using namespace StreamControl;\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001291 ' %sexplicit_CreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);\n'
Jon Ashburn747f2b62015-06-18 15:02:58 -06001292 ' %s%s%s\n'
1293 '%s'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001294 '}' % (qual, decl, ret_val, f_open, log_func, f_close, stmt))
Jon Ashburn747f2b62015-06-18 15:02:58 -06001295 elif proto.name == "DestroyDevice":
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001296 funcs.append('%s%s\n'
1297 '{\n'
1298 ' using namespace StreamControl;\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001299 ' dispatch_key key = get_dispatch_key(device);\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -06001300 ' VkLayerDispatchTable *pDisp = %s_dispatch_table(%s);\n'
Jon Ashburn747f2b62015-06-18 15:02:58 -06001301 ' %spDisp->%s;\n'
1302 ' deviceExtMap.erase(pDisp);\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001303 ' destroy_device_dispatch_table(key);\n'
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001304 ' %s%s%s\n'
1305 '%s'
Jon Ashburn747f2b62015-06-18 15:02:58 -06001306 '}' % (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 -05001307 elif proto.name == "DestroyInstance":
1308 funcs.append('%s%s\n'
1309 '{\n'
1310 ' using namespace StreamControl;\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001311 ' dispatch_key key = get_dispatch_key(instance);\n'
Jon Ashburn3dc39382015-09-17 10:00:32 -06001312 ' VkLayerInstanceDispatchTable *pDisp = %s_dispatch_table(%s);\n'
1313 ' %spDisp->%s;\n'
1314 ' instanceExtMap.erase(pDisp);\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001315 ' destroy_instance_dispatch_table(key);\n'
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001316 ' %s%s%s\n'
1317 '%s'
Jon Ashburn3dc39382015-09-17 10:00:32 -06001318 '}' % (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 -05001319 else:
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001320 if wsi_name(decl):
1321 funcs.append('%s' % wsi_ifdef(decl))
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001322 funcs.append('%s%s\n'
1323 '{\n'
1324 ' using namespace StreamControl;\n'
1325 ' %s%s_dispatch_table(%s)->%s;\n'
Jon Ashburnbacb0f52015-04-06 10:58:22 -06001326 ' %s%s%s\n'
1327 '%s'
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001328 '}' % (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 -07001329 if wsi_name(decl):
1330 funcs.append('%s' % wsi_endif(decl))
Mike Stroyanbf237d72015-04-03 17:45:53 -06001331 return "\n\n".join(funcs)
1332
Tobin Ehlis99f88672015-01-10 12:42:41 -07001333 def generate_body(self):
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001334 self.layer_name = "api_dump"
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001335 if sys.platform.startswith('win32'):
Michael Lentine64e2ebd2015-12-03 14:33:09 -08001336 instance_extensions=[('wsi_enabled',
1337 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1338 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1339 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1340 'vkGetPhysicalDeviceSurfacePresentModesKHR',
1341 'vkCreateWin32SurfaceKHR',
1342 'vkGetPhysicalDeviceWin32PresentationSupportKHR'])]
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001343 elif sys.platform.startswith('linux'):
Michael Lentine64e2ebd2015-12-03 14:33:09 -08001344 instance_extensions=[('wsi_enabled',
1345 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1346 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1347 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1348 'vkGetPhysicalDeviceSurfacePresentModesKHR',
1349 'vkCreateXcbSurfaceKHR',
Mark Lobodzinskib49b6e52015-11-26 10:59:58 -07001350 'vkGetPhysicalDeviceXcbPresentationSupportKHR'])]
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001351 # TODO: Add cases for Mir, Xlib, Wayland
1352 else:
1353 instance_extensions=[('wsi_enabled',
1354 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1355 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1356 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1357 'vkGetPhysicalDeviceSurfacePresentModesKHR'])]
Ian Elliott1064fe32015-07-06 14:31:32 -06001358 extensions=[('wsi_enabled',
Ian Elliott05846062015-11-20 14:13:17 -07001359 ['vkCreateSwapchainKHR',
Jon Ashburn8acd2332015-09-16 18:08:32 -06001360 'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
1361 'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001362 body = [self.generate_init(),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001363 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Jon Ashburn3dc39382015-09-17 10:00:32 -06001364 self._generate_layer_gpa_function(extensions, instance_extensions)]
Tobin Ehlis99f88672015-01-10 12:42:41 -07001365 return "\n\n".join(body)
1366
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001367class ObjectTrackerSubcommand(Subcommand):
1368 def generate_header(self):
1369 header_txt = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001370 header_txt.append('%s' % self.lineinfo.get())
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001371 header_txt.append('#include <stdio.h>')
1372 header_txt.append('#include <stdlib.h>')
1373 header_txt.append('#include <string.h>')
1374 header_txt.append('#include <inttypes.h>')
1375 header_txt.append('')
David Pinedo9316d3b2015-11-06 12:54:48 -07001376 header_txt.append('#include "vulkan/vulkan.h"')
Tobin Ehlisb835d1b2015-07-03 10:34:49 -06001377 header_txt.append('#include "vk_loader_platform.h"')
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001378 header_txt.append('')
Tobin Ehlis803cc492015-06-08 17:36:28 -06001379 header_txt.append('#include <unordered_map>')
1380 header_txt.append('using namespace std;')
David Pinedo9316d3b2015-11-06 12:54:48 -07001381 header_txt.append('#include "vulkan/vk_layer.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -06001382 header_txt.append('#include "vk_layer_config.h"')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001383 header_txt.append('#include "vulkan/vk_ext_debug_report.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -06001384 header_txt.append('#include "vk_layer_table.h"')
1385 header_txt.append('#include "vk_layer_data.h"')
1386 header_txt.append('#include "vk_layer_logging.h"')
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001387 header_txt.append('')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001388# NOTE: The non-autoGenerated code is in the object_tracker.h header file
1389 header_txt.append('#include "object_tracker.h"')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001390 header_txt.append('')
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -06001391 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001392 header_txt.append('')
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001393 return "\n".join(header_txt)
1394
Tony Barboura05dbaa2015-07-09 17:31:46 -06001395 def generate_maps(self):
1396 maps_txt = []
Tobin Ehlis86684f92016-01-05 10:33:58 -07001397 for o in vulkan.object_type_list:
Michael Lentine13803dc2015-11-04 14:35:12 -08001398 maps_txt.append('unordered_map<uint64_t, OBJTRACK_NODE*> %sMap;' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001399 return "\n".join(maps_txt)
1400
Tobin Ehlis86684f92016-01-05 10:33:58 -07001401 def _gather_object_uses(self, obj_list, struct_type, obj_set):
1402 # for each member of struct_type
1403 # add objs in obj_list to obj_set
1404 # call self for structs
1405 for m in vk_helper.struct_dict[struct_type]:
1406 if vk_helper.struct_dict[struct_type][m]['type'] in obj_list:
1407 obj_set.add(vk_helper.struct_dict[struct_type][m]['type'])
1408 elif vk_helper.is_type(vk_helper.struct_dict[struct_type][m]['type'], 'struct'):
1409 obj_set = obj_set.union(self._gather_object_uses(obj_list, vk_helper.struct_dict[struct_type][m]['type'], obj_set))
1410 return obj_set
1411
Tony Barboura05dbaa2015-07-09 17:31:46 -06001412 def generate_procs(self):
1413 procs_txt = []
Tobin Ehlis86684f92016-01-05 10:33:58 -07001414 # First parse through funcs and gather dict of all objects seen by each call
1415 obj_use_dict = {}
1416 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
1417 for proto in proto_list:
1418 disp_obj = proto.params[0].ty.strip('*').replace('const ', '')
1419 if disp_obj in vulkan.object_dispatch_list:
1420 if disp_obj not in obj_use_dict:
1421 obj_use_dict[disp_obj] = set()
1422 for p in proto.params[1:]:
1423 base_type = p.ty.strip('*').replace('const ', '')
1424 if base_type in vulkan.object_type_list:
1425 obj_use_dict[disp_obj].add(base_type)
1426 if vk_helper.is_type(base_type, 'struct'):
1427 obj_use_dict[disp_obj] = self._gather_object_uses(vulkan.object_type_list, base_type, obj_use_dict[disp_obj])
1428 #for do in obj_use_dict:
1429 # print "Disp obj %s has uses for objs: %s" % (do, ', '.join(obj_use_dict[do]))
1430
1431 for o in vulkan.object_type_list:# vulkan.core.objects:
Tony Barboura05dbaa2015-07-09 17:31:46 -06001432 procs_txt.append('%s' % self.lineinfo.get())
Michael Lentine13803dc2015-11-04 14:35:12 -08001433 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o)
1434 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Tobin Ehlis154e0462015-08-26 11:22:09 -06001435 if o in vulkan.object_dispatch_list:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001436 procs_txt.append('static void create_%s(%s dispatchable_object, %s vkObj, VkDebugReportObjectTypeEXT objType)' % (name, o, o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001437 else:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001438 procs_txt.append('static void create_%s(VkDevice dispatchable_object, %s vkObj, VkDebugReportObjectTypeEXT objType)' % (name, o))
Chia-I Wue2fc5522015-10-26 20:04:44 +08001439 procs_txt.append('{')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001440 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 -07001441 procs_txt.append(' "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64 , object_track_index++, string_VkDebugReportObjectTypeEXT(objType),')
Chia-I Wue2fc5522015-10-26 20:04:44 +08001442 procs_txt.append(' reinterpret_cast<uint64_t>(vkObj));')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001443 procs_txt.append('')
1444 procs_txt.append(' OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE;')
1445 procs_txt.append(' pNewObjNode->objType = objType;')
1446 procs_txt.append(' pNewObjNode->status = OBJSTATUS_NONE;')
Chia-I Wue2fc5522015-10-26 20:04:44 +08001447 procs_txt.append(' pNewObjNode->vkObj = reinterpret_cast<uint64_t>(vkObj);')
Michael Lentine13803dc2015-11-04 14:35:12 -08001448 procs_txt.append(' %sMap[(uint64_t)vkObj] = pNewObjNode;' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001449 procs_txt.append(' uint32_t objIndex = objTypeToIndex(objType);')
1450 procs_txt.append(' numObjs[objIndex]++;')
1451 procs_txt.append(' numTotalObjs++;')
1452 procs_txt.append('}')
1453 procs_txt.append('')
1454 procs_txt.append('%s' % self.lineinfo.get())
Tobin Ehlis154e0462015-08-26 11:22:09 -06001455 if o in vulkan.object_dispatch_list:
Michael Lentine13803dc2015-11-04 14:35:12 -08001456 procs_txt.append('static void destroy_%s(%s dispatchable_object, %s object)' % (name, o, o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001457 else:
Michael Lentine13803dc2015-11-04 14:35:12 -08001458 procs_txt.append('static void destroy_%s(VkDevice dispatchable_object, %s object)' % (name, o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001459 procs_txt.append('{')
Michael Lentine13803dc2015-11-04 14:35:12 -08001460 procs_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
1461 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
1462 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[(uint64_t)object];' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001463 procs_txt.append(' uint32_t objIndex = objTypeToIndex(pNode->objType);')
1464 procs_txt.append(' assert(numTotalObjs > 0);')
1465 procs_txt.append(' numTotalObjs--;')
1466 procs_txt.append(' assert(numObjs[objIndex] > 0);')
1467 procs_txt.append(' numObjs[objIndex]--;')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001468 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 -08001469 procs_txt.append(' "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%" PRIu64 " total objs remain & %" PRIu64 " %s objs).",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001470 procs_txt.append(' string_VkDebugReportObjectTypeEXT(pNode->objType), reinterpret_cast<uint64_t>(object), numTotalObjs, numObjs[objIndex],')
1471 procs_txt.append(' string_VkDebugReportObjectTypeEXT(pNode->objType));')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001472 procs_txt.append(' delete pNode;')
Michael Lentine13803dc2015-11-04 14:35:12 -08001473 procs_txt.append(' %sMap.erase(object_handle);' % (o))
Chia-I Wue2fc5522015-10-26 20:04:44 +08001474 procs_txt.append(' } else {')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001475 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 +08001476 procs_txt.append(' "Unable to remove obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?",')
Michael Lentine13803dc2015-11-04 14:35:12 -08001477 procs_txt.append(' object_handle);')
Chia-I Wue2fc5522015-10-26 20:04:44 +08001478 procs_txt.append(' }')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001479 procs_txt.append('}')
1480 procs_txt.append('')
1481 procs_txt.append('%s' % self.lineinfo.get())
Tobin Ehlis154e0462015-08-26 11:22:09 -06001482 if o in vulkan.object_dispatch_list:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001483 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 -06001484 else:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001485 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 +08001486 procs_txt.append('{')
1487 procs_txt.append(' if (object != VK_NULL_HANDLE) {')
Michael Lentine13803dc2015-11-04 14:35:12 -08001488 procs_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
1489 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
1490 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[object_handle];' % (o))
Tobin Ehlis154e0462015-08-26 11:22:09 -06001491 procs_txt.append(' pNode->status |= status_flag;')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001492 procs_txt.append(' }')
1493 procs_txt.append(' else {')
1494 procs_txt.append(' // If we do not find it print an error')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001495 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 +08001496 procs_txt.append(' "Unable to set status for non-existent object 0x%" PRIxLEAST64 " of %s type",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001497 procs_txt.append(' object_handle, string_VkDebugReportObjectTypeEXT(objType));')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001498 procs_txt.append(' }')
1499 procs_txt.append(' }')
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -06001500 procs_txt.append(' return VK_FALSE;')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001501 procs_txt.append('}')
1502 procs_txt.append('')
1503 procs_txt.append('%s' % self.lineinfo.get())
Michael Lentine13803dc2015-11-04 14:35:12 -08001504 procs_txt.append('static VkBool32 validate_%s_status(' % (name))
Tobin Ehlis154e0462015-08-26 11:22:09 -06001505 if o in vulkan.object_dispatch_list:
Tony Barboura05dbaa2015-07-09 17:31:46 -06001506 procs_txt.append('%s dispatchable_object, %s object,' % (o, o))
1507 else:
1508 procs_txt.append('VkDevice dispatchable_object, %s object,' % (o))
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001509 procs_txt.append(' VkDebugReportObjectTypeEXT objType,')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001510 procs_txt.append(' ObjectStatusFlags status_mask,')
1511 procs_txt.append(' ObjectStatusFlags status_flag,')
1512 procs_txt.append(' VkFlags msg_flags,')
1513 procs_txt.append(' OBJECT_TRACK_ERROR error_code,')
1514 procs_txt.append(' const char *fail_msg)')
1515 procs_txt.append('{')
Michael Lentine13803dc2015-11-04 14:35:12 -08001516 procs_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
1517 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
1518 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[object_handle];' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001519 procs_txt.append(' if ((pNode->status & status_mask) != status_flag) {')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001520 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 -07001521 procs_txt.append(' "OBJECT VALIDATION WARNING: %s object 0x%" PRIxLEAST64 ": %s", string_VkDebugReportObjectTypeEXT(objType),')
Michael Lentine13803dc2015-11-04 14:35:12 -08001522 procs_txt.append(' object_handle, fail_msg);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001523 procs_txt.append(' return VK_FALSE;')
1524 procs_txt.append(' }')
1525 procs_txt.append(' return VK_TRUE;')
1526 procs_txt.append(' }')
1527 procs_txt.append(' else {')
1528 procs_txt.append(' // If we do not find it print an error')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001529 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 +08001530 procs_txt.append(' "Unable to obtain status for non-existent object 0x%" PRIxLEAST64 " of %s type",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001531 procs_txt.append(' object_handle, string_VkDebugReportObjectTypeEXT(objType));')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001532 procs_txt.append(' return VK_FALSE;')
1533 procs_txt.append(' }')
1534 procs_txt.append('}')
1535 procs_txt.append('')
1536 procs_txt.append('%s' % self.lineinfo.get())
Tobin Ehlis154e0462015-08-26 11:22:09 -06001537 if o in vulkan.object_dispatch_list:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001538 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 -06001539 else:
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001540 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 +08001541 procs_txt.append('{')
Michael Lentine13803dc2015-11-04 14:35:12 -08001542 procs_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
1543 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
1544 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[object_handle];' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001545 procs_txt.append(' pNode->status &= ~status_flag;')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001546 procs_txt.append(' }')
1547 procs_txt.append(' else {')
1548 procs_txt.append(' // If we do not find it print an error')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001549 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 +08001550 procs_txt.append(' "Unable to reset status for non-existent object 0x%" PRIxLEAST64 " of %s type",')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001551 procs_txt.append(' object_handle, string_VkDebugReportObjectTypeEXT(objType));')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001552 procs_txt.append(' }')
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -06001553 procs_txt.append(' return VK_FALSE;')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001554 procs_txt.append('}')
1555 procs_txt.append('')
Tobin Ehlis86684f92016-01-05 10:33:58 -07001556 procs_txt.append('%s' % self.lineinfo.get())
1557 # Generate the permutations of validate_* functions where for each
1558 # dispatchable object type, we have a corresponding validate_* function
1559 # for that object and all non-dispatchable objects that are used in API
1560 # calls with that dispatchable object.
1561 procs_txt.append('//%s' % str(obj_use_dict))
1562 for do in obj_use_dict:
1563 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', do)
1564 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
1565 # First create validate_* func for disp obj
1566 procs_txt.append('%s' % self.lineinfo.get())
1567 procs_txt.append('static VkBool32 validate_%s(%s dispatchable_object, %s object, VkDebugReportObjectTypeEXT objType, bool null_allowed)' % (name, do, do))
1568 procs_txt.append('{')
1569 procs_txt.append(' if (null_allowed && (object == VK_NULL_HANDLE))')
1570 procs_txt.append(' return VK_FALSE;')
1571 procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (do, do))
1572 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",')
1573 procs_txt.append(' "Invalid %s Object 0x%%" PRIx64 ,reinterpret_cast<uint64_t>(object));' % do)
1574 procs_txt.append(' }')
1575 procs_txt.append(' return VK_FALSE;')
1576 procs_txt.append('}')
1577 procs_txt.append('')
1578 for o in obj_use_dict[do]:
1579 if o == do: # We already generated this case above so skip here
1580 continue
1581 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o)
1582 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
1583 procs_txt.append('%s' % self.lineinfo.get())
1584 procs_txt.append('static VkBool32 validate_%s(%s dispatchable_object, %s object, VkDebugReportObjectTypeEXT objType, bool null_allowed)' % (name, do, o))
1585 procs_txt.append('{')
1586 procs_txt.append(' if (null_allowed && (object == VK_NULL_HANDLE))')
1587 procs_txt.append(' return VK_FALSE;')
1588 if o == "VkImage":
1589 procs_txt.append(' // We need to validate normal image objects and those from the swapchain')
1590 procs_txt.append(' if ((%sMap.find((uint64_t)object) == %sMap.end()) &&' % (o, o))
1591 procs_txt.append(' (swapchainImageMap.find((uint64_t)object) == swapchainImageMap.end())) {')
1592 else:
1593 procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (o, o))
1594 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",')
1595 procs_txt.append(' "Invalid %s Object 0x%%" PRIx64, reinterpret_cast<uint64_t>(object));' % o)
1596 procs_txt.append(' }')
1597 procs_txt.append(' return VK_FALSE;')
1598 procs_txt.append('}')
1599 procs_txt.append('')
1600 procs_txt.append('')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001601 return "\n".join(procs_txt)
1602
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001603 def generate_destroy_instance(self):
Tony Barboura05dbaa2015-07-09 17:31:46 -06001604 gedi_txt = []
1605 gedi_txt.append('%s' % self.lineinfo.get())
Mark Lobodzinski2141f652015-09-07 13:59:43 -06001606 gedi_txt.append('void vkDestroyInstance(')
Chia-I Wuf7458c52015-10-26 21:10:41 +08001607 gedi_txt.append('VkInstance instance,')
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001608 gedi_txt.append('const VkAllocationCallbacks* pAllocator)')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001609 gedi_txt.append('{')
1610 gedi_txt.append(' loader_platform_thread_lock_mutex(&objLock);')
Tobin Ehlis86684f92016-01-05 10:33:58 -07001611 gedi_txt.append(' validate_instance(instance, instance, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, false);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001612 gedi_txt.append('')
Michael Lentine13803dc2015-11-04 14:35:12 -08001613 gedi_txt.append(' destroy_instance(instance, instance);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001614 gedi_txt.append(' // Report any remaining objects in LL')
1615 for o in vulkan.core.objects:
Mike Stroyan0699a792015-08-18 14:48:34 -06001616 if o in ['VkInstance', 'VkPhysicalDevice', 'VkQueue']:
Tony Barboura05dbaa2015-07-09 17:31:46 -06001617 continue
1618 gedi_txt.append(' for (auto it = %sMap.begin(); it != %sMap.end(); ++it) {' % (o, o))
1619 gedi_txt.append(' OBJTRACK_NODE* pNode = it->second;')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001620 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 -07001621 gedi_txt.append(' "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),')
Tony Barbour343d6212015-07-10 18:32:33 -06001622 gedi_txt.append(' pNode->vkObj);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001623 gedi_txt.append(' }')
Mike Stroyan0699a792015-08-18 14:48:34 -06001624 gedi_txt.append(' %sMap.clear();' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001625 gedi_txt.append('')
1626 gedi_txt.append(' dispatch_key key = get_dispatch_key(instance);')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001627 gedi_txt.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(object_tracker_instance_table_map, instance);')
Chia-I Wuf7458c52015-10-26 21:10:41 +08001628 gedi_txt.append(' pInstanceTable->DestroyInstance(instance, pAllocator);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001629 gedi_txt.append('')
1630 gedi_txt.append(' // Clean up logging callback, if any')
1631 gedi_txt.append(' layer_data *my_data = get_my_data_ptr(key, layer_data_map);')
1632 gedi_txt.append(' if (my_data->logging_callback) {')
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07001633 gedi_txt.append(' layer_destroy_msg_callback(my_data->report_data, my_data->logging_callback, pAllocator);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001634 gedi_txt.append(' }')
1635 gedi_txt.append('')
1636 gedi_txt.append(' layer_debug_report_destroy_instance(mid(instance));')
1637 gedi_txt.append(' layer_data_map.erase(pInstanceTable);')
1638 gedi_txt.append('')
Jon Ashburn3dc39382015-09-17 10:00:32 -06001639 gedi_txt.append(' instanceExtMap.erase(pInstanceTable);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001640 gedi_txt.append(' loader_platform_thread_unlock_mutex(&objLock);')
Mike Stroyan0699a792015-08-18 14:48:34 -06001641 # The loader holds a mutex that protects this from other threads
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001642 gedi_txt.append(' object_tracker_instance_table_map.erase(key);')
1643 gedi_txt.append(' if (object_tracker_instance_table_map.empty()) {')
Mike Stroyan0699a792015-08-18 14:48:34 -06001644 gedi_txt.append(' // Release mutex when destroying last instance.')
1645 gedi_txt.append(' loader_platform_thread_delete_mutex(&objLock);')
1646 gedi_txt.append(' objLockInitialized = 0;')
1647 gedi_txt.append(' }')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001648 gedi_txt.append('}')
1649 gedi_txt.append('')
1650 return "\n".join(gedi_txt)
1651
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001652 def generate_destroy_device(self):
Tony Barboura05dbaa2015-07-09 17:31:46 -06001653 gedd_txt = []
1654 gedd_txt.append('%s' % self.lineinfo.get())
Mark Lobodzinski2141f652015-09-07 13:59:43 -06001655 gedd_txt.append('void vkDestroyDevice(')
Chia-I Wuf7458c52015-10-26 21:10:41 +08001656 gedd_txt.append('VkDevice device,')
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001657 gedd_txt.append('const VkAllocationCallbacks* pAllocator)')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001658 gedd_txt.append('{')
1659 gedd_txt.append(' loader_platform_thread_lock_mutex(&objLock);')
Tobin Ehlis86684f92016-01-05 10:33:58 -07001660 gedd_txt.append(' validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001661 gedd_txt.append('')
Michael Lentine13803dc2015-11-04 14:35:12 -08001662 gedd_txt.append(' destroy_device(device, device);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001663 gedd_txt.append(' // Report any remaining objects in LL')
1664 for o in vulkan.core.objects:
Mark Lobodzinski5f5c0e12015-11-12 16:02:35 -07001665 # DescriptorSets and Command Buffers are destroyed through their pools, not explicitly
1666 if o in ['VkInstance', 'VkPhysicalDevice', 'VkQueue', 'VkDevice', 'VkDescriptorSet', 'VkCommandBuffer']:
Tony Barboura05dbaa2015-07-09 17:31:46 -06001667 continue
Mark Lobodzinski5f5c0e12015-11-12 16:02:35 -07001668 gedd_txt.append(' for (auto it = %sMap.begin(); it != %sMap.end(); ++it) {' % (o, o))
1669 gedd_txt.append(' OBJTRACK_NODE* pNode = it->second;')
Mark Lobodzinski6085c2b2016-01-04 15:48:11 -07001670 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 -07001671 gedd_txt.append(' "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),')
Mark Lobodzinski5f5c0e12015-11-12 16:02:35 -07001672 gedd_txt.append(' pNode->vkObj);')
1673 gedd_txt.append(' }')
Mike Stroyan0699a792015-08-18 14:48:34 -06001674 gedd_txt.append(' %sMap.clear();' % (o))
Tony Barboura05dbaa2015-07-09 17:31:46 -06001675 gedd_txt.append('')
1676 gedd_txt.append(" // Clean up Queue's MemRef Linked Lists")
1677 gedd_txt.append(' destroyQueueMemRefLists();')
1678 gedd_txt.append('')
1679 gedd_txt.append(' loader_platform_thread_unlock_mutex(&objLock);')
1680 gedd_txt.append('')
1681 gedd_txt.append(' dispatch_key key = get_dispatch_key(device);')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001682 gedd_txt.append(' VkLayerDispatchTable *pDisp = get_dispatch_table(object_tracker_device_table_map, device);')
Chia-I Wuf7458c52015-10-26 21:10:41 +08001683 gedd_txt.append(' pDisp->DestroyDevice(device, pAllocator);')
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001684 gedd_txt.append(' object_tracker_device_table_map.erase(key);')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001685 gedd_txt.append('')
Tony Barboura05dbaa2015-07-09 17:31:46 -06001686 gedd_txt.append('}')
1687 gedd_txt.append('')
1688 return "\n".join(gedd_txt)
1689
Mark Lobodzinski9fde6392016-01-19 09:57:24 -07001690 # Special-case validating the array pointers in UpdateDescriptorSets. They may not be NULL but should
1691 # be ignored if the descriptorType does not specify those arrays.
1692 def _handle_descriptorType(self, indent, prefix, type_name, name):
1693 s_code = ''
1694 if type_name == 'pBufferInfo':
1695 s_code += '%sif ((%sdescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||\n' % (indent, prefix)
1696 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||\n' % (indent, prefix)
1697 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||\n' % (indent, prefix)
1698 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) ) {\n' % (indent, prefix)
1699 elif type_name == 'pImageInfo':
1700 s_code += '%sif ((%sdescriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) ||\n' % (indent, prefix)
1701 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||\n' % (indent, prefix)
1702 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) ||\n' % (indent, prefix)
1703 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||\n' % (indent, prefix)
1704 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ) {\n' % (indent, prefix)
1705 elif type_name == 'pTexelBufferView':
1706 s_code += '%sif ((%sdescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) ||\n' % (indent, prefix)
1707 s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) ) {\n' % (indent, prefix)
1708 else:
1709 s_code += '%sif (%s) {\n' % (indent, name)
1710 return s_code
1711
Tobin Ehlis86684f92016-01-05 10:33:58 -07001712 def _gen_obj_validate_code(self, struct_uses, obj_type_mapping, func_name, valid_null_dict, param0_name, indent, prefix, array_index):
1713 pre_code = ''
1714 for obj in sorted(struct_uses):
1715 name = obj
1716 array = ''
Mark Lobodzinski9fde6392016-01-19 09:57:24 -07001717 type_name = ''
Tobin Ehlis86684f92016-01-05 10:33:58 -07001718 if '[' in obj:
1719 (name, array) = obj.split('[')
Mark Lobodzinski9fde6392016-01-19 09:57:24 -07001720 type_name = name
Tobin Ehlis86684f92016-01-05 10:33:58 -07001721 array = array.strip(']')
1722 if isinstance(struct_uses[obj], dict):
1723 local_prefix = ''
1724 name = '%s%s' % (prefix, name)
1725 ptr_type = False
1726 if 'p' == obj[0]:
1727 ptr_type = True
Mark Lobodzinski9fde6392016-01-19 09:57:24 -07001728 tmp_pre = self._handle_descriptorType(indent, prefix, type_name, name)
1729 pre_code += tmp_pre
Tobin Ehlis86684f92016-01-05 10:33:58 -07001730 indent += ' '
1731 if array != '':
1732 idx = 'idx%s' % str(array_index)
1733 array_index += 1
1734 pre_code += '%s\n' % self.lineinfo.get()
1735 pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
1736 indent += ' '
1737 local_prefix = '%s[%s].' % (name, idx)
1738 elif ptr_type:
1739 local_prefix = '%s->' % (name)
1740 else:
1741 local_prefix = '%s.' % (name)
1742 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)
1743 pre_code += tmp_pre
1744 if array != '':
1745 indent = indent[4:]
1746 pre_code += '%s}\n' % (indent)
1747 if ptr_type:
1748 indent = indent[4:]
1749 pre_code += '%s}\n' % (indent)
1750 else:
1751 ptype = struct_uses[obj]
1752 dbg_obj_type = obj_type_mapping[ptype]
1753 fname = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', ptype)
1754 fname = re.sub('([a-z0-9])([A-Z])', r'\1_\2', fname).lower()[3:]
1755 full_name = '%s%s' % (prefix, name)
1756 null_obj_ok = 'false'
1757 # If a valid null param is defined for this func and we have a match, allow NULL
1758 if func_name in valid_null_dict and True in [name in pn for pn in valid_null_dict[func_name]]:
1759 null_obj_ok = 'true'
1760 if (array_index > 0) or '' != array:
Mark Lobodzinski9fde6392016-01-19 09:57:24 -07001761 tmp_pre = self._handle_descriptorType(indent, prefix, type_name, full_name)
1762 pre_code += tmp_pre
Tobin Ehlis86684f92016-01-05 10:33:58 -07001763 indent += ' '
1764 if array != '':
1765 idx = 'idx%s' % str(array_index)
1766 array_index += 1
1767 pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
1768 indent += ' '
1769 full_name = '%s[%s]' % (full_name, idx)
1770 pre_code += '%s\n' % self.lineinfo.get()
1771 pre_code += '%sskipCall |= validate_%s(%s, %s, %s, %s);\n' %(indent, fname, param0_name, full_name, dbg_obj_type, null_obj_ok)
1772 if array != '':
1773 indent = indent[4:]
1774 pre_code += '%s}\n' % (indent)
1775 indent = indent[4:]
1776 pre_code += '%s}\n' % (indent)
1777 else:
1778 pre_code += '%s\n' % self.lineinfo.get()
1779 pre_code += '%sskipCall |= validate_%s(%s, %s, %s, %s);\n' %(indent, fname, param0_name, full_name, dbg_obj_type, null_obj_ok)
1780 return pre_code
Tony Barboura05dbaa2015-07-09 17:31:46 -06001781
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -06001782 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001783 if proto.name in [ 'CreateDebugReportCallbackEXT', 'EnumerateInstanceLayerProperties', 'EnumerateInstanceExtensionProperties','EnumerateDeviceLayerProperties', 'EnumerateDeviceExtensionProperties' ]:
Mike Stroyan00087e62015-04-03 14:39:16 -06001784 # use default version
1785 return None
Mark Lobodzinski7c75b852015-05-05 15:01:37 -05001786
Tony Barboura05dbaa2015-07-09 17:31:46 -06001787 # Create map of object names to object type enums of the form VkName : VkObjectTypeName
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001788 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 -05001789 # Convert object type enum names from UpperCamelCase to UPPER_CASE_WITH_UNDERSCORES
1790 for objectName, objectTypeEnum in obj_type_mapping.items():
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001791 obj_type_mapping[objectName] = ucc_to_U_C_C(objectTypeEnum) + '_EXT';
Mark Lobodzinski7c75b852015-05-05 15:01:37 -05001792 # Command Buffer Object doesn't follow the rule.
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001793 obj_type_mapping['VkCommandBuffer'] = "VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT"
1794 obj_type_mapping['VkShaderModule'] = "VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT"
Mike Stroyan00087e62015-04-03 14:39:16 -06001795
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001796 explicit_object_tracker_functions = [
1797 "CreateInstance",
Tobin Ehlisec598302015-09-15 15:02:17 -06001798 "EnumeratePhysicalDevices",
Cody Northropd0802882015-08-03 17:04:53 -06001799 "GetPhysicalDeviceQueueFamilyProperties",
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001800 "CreateDevice",
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001801 "GetDeviceQueue",
Chia-I Wu1ff4c3d2015-10-26 16:55:27 +08001802 "QueueBindSparse",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001803 "AllocateDescriptorSets",
Tony Barbour770f80d2015-07-20 10:52:13 -06001804 "FreeDescriptorSets",
Mark Lobodzinski5f5c0e12015-11-12 16:02:35 -07001805 "AllocateCommandBuffers",
1806 "FreeCommandBuffers",
1807 "DestroyDescriptorPool",
1808 "DestroyCommandPool",
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001809 "MapMemory",
1810 "UnmapMemory",
1811 "FreeMemory",
Mark Lobodzinskie6d3f2c2015-10-14 13:16:33 -06001812 "DestroySwapchainKHR",
1813 "GetSwapchainImagesKHR"
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001814 ]
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001815 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyan00087e62015-04-03 14:39:16 -06001816 param0_name = proto.params[0].name
Mark Lobodzinski48bd16d2015-05-08 09:12:28 -05001817 using_line = ''
Mike Stroyan00087e62015-04-03 14:39:16 -06001818 create_line = ''
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001819 destroy_line = ''
Tobin Ehlis154e0462015-08-26 11:22:09 -06001820 # 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 -07001821 # TODO : Should integrate slightly better code for this purpose from unique_objects layer
Tobin Ehlis154e0462015-08-26 11:22:09 -06001822 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 -08001823 loop_types = defaultdict(list)
Tobin Ehlis2717d132015-07-10 18:25:07 -06001824 # 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 -06001825 # or better yet, these should be encoded into an API json definition and we generate checks from there
1826 # 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)
1827 # param names may be directly passed to the function, or may be a field in a struct param
1828 valid_null_object_names = {'CreateGraphicsPipelines' : ['basePipelineHandle'],
1829 'CreateComputePipelines' : ['basePipelineHandle'],
1830 'BeginCommandBuffer' : ['renderPass', 'framebuffer'],
Tobin Ehlisec598302015-09-15 15:02:17 -06001831 'QueueSubmit' : ['fence'],
Jon Ashburn9216ae42016-01-14 15:11:55 -07001832 'AcquireNextImageKHR' : ['fence', 'semaphore' ],
Tobin Ehlisba31cab2015-11-02 15:24:32 -07001833 'UpdateDescriptorSets' : ['pTexelBufferView'],
Tobin Ehlis86684f92016-01-05 10:33:58 -07001834 'CreateSwapchainKHR' : ['oldSwapchain'],
Tobin Ehlis154e0462015-08-26 11:22:09 -06001835 }
Tobin Ehlis154e0462015-08-26 11:22:09 -06001836 param_count = 'NONE' # keep track of arrays passed directly into API functions
Tobin Ehlis803cc492015-06-08 17:36:28 -06001837 for p in proto.params:
Tobin Ehlisec598302015-09-15 15:02:17 -06001838 base_type = p.ty.replace('const ', '').strip('*')
Tobin Ehlis154e0462015-08-26 11:22:09 -06001839 if 'count' in p.name.lower():
1840 param_count = p.name
Tobin Ehlisec598302015-09-15 15:02:17 -06001841 if base_type in vulkan.core.objects:
1842 # This is an object to potentially check for validity. First see if it's an array
1843 if '*' in p.ty and 'const' in p.ty and param_count != 'NONE':
1844 loop_params[param_count].append(p.name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001845 loop_types[param_count].append(str(p.ty[6:-1]))
Tobin Ehlisec598302015-09-15 15:02:17 -06001846 # Not an array, check for just a base Object that's not in exceptions
1847 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 -06001848 loop_params[0].append(p.name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001849 loop_types[0].append(str(p.ty))
Tobin Ehlisec598302015-09-15 15:02:17 -06001850 elif vk_helper.is_type(base_type, 'struct'):
1851 struct_type = base_type
Tobin Ehlis9d675942015-06-30 14:32:16 -06001852 if vk_helper.typedef_rev_dict[struct_type] in vk_helper.struct_dict:
1853 struct_type = vk_helper.typedef_rev_dict[struct_type]
Tobin Ehlis82b3db52015-10-23 17:52:53 -06001854 # Parse elements of this struct param to identify objects and/or arrays of objects
Tobin Ehlis9d675942015-06-30 14:32:16 -06001855 for m in sorted(vk_helper.struct_dict[struct_type]):
1856 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 -06001857 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 -06001858 # This is not great, but gets the job done for now, but If we have a count and this param is a ptr w/
1859 # last letter 's' OR non-'count' string of count is in the param name, then this is a dynamically sized array param
1860 param_array = False
1861 if param_count != 'NONE':
1862 if '*' in p.ty:
1863 if 's' == p.name[-1] or param_count.lower().replace('count', '') in p.name.lower():
1864 param_array = True
1865 if param_array:
Tobin Ehlis154e0462015-08-26 11:22:09 -06001866 param_name = '%s[i].%s' % (p.name, vk_helper.struct_dict[struct_type][m]['name'])
Tobin Ehlis46d53622015-07-10 11:10:21 -06001867 else:
Tobin Ehlis154e0462015-08-26 11:22:09 -06001868 param_name = '%s->%s' % (p.name, vk_helper.struct_dict[struct_type][m]['name'])
1869 if vk_helper.struct_dict[struct_type][m]['dyn_array']:
Tobin Ehlis82b3db52015-10-23 17:52:53 -06001870 if param_count != 'NONE': # this will be a double-embedded loop, use comma delineated 'count,name' for param_name
1871 loop_count = '%s[i].%s' % (p.name, vk_helper.struct_dict[struct_type][m]['array_size'])
1872 loop_params[param_count].append('%s,%s' % (loop_count, param_name))
Michael Lentine13803dc2015-11-04 14:35:12 -08001873 loop_types[param_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Tobin Ehlis82b3db52015-10-23 17:52:53 -06001874 else:
1875 loop_count = '%s->%s' % (p.name, vk_helper.struct_dict[struct_type][m]['array_size'])
1876 loop_params[loop_count].append(param_name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001877 loop_types[loop_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Tobin Ehlis154e0462015-08-26 11:22:09 -06001878 else:
1879 if '[' in param_name: # dynamic array param, set size
1880 loop_params[param_count].append(param_name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001881 loop_types[param_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Tobin Ehlis154e0462015-08-26 11:22:09 -06001882 else:
1883 loop_params[0].append(param_name)
Michael Lentine13803dc2015-11-04 14:35:12 -08001884 loop_types[0].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Tobin Ehlis86684f92016-01-05 10:33:58 -07001885 last_param_index = None
1886 create_func = False
1887 if True in [create_txt in proto.name for create_txt in ['Create', 'Allocate']]:
1888 create_func = True
1889 last_param_index = -1 # For create funcs don't validate last object
1890 struct_uses = get_object_uses(vulkan.object_type_list, proto.params[:last_param_index])
Mike Stroyan00087e62015-04-03 14:39:16 -06001891 funcs = []
Tobin Ehlis803cc492015-06-08 17:36:28 -06001892 mutex_unlock = False
Tobin Ehlis154e0462015-08-26 11:22:09 -06001893 funcs.append('%s\n' % self.lineinfo.get())
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001894 if proto.name in explicit_object_tracker_functions:
Jon Ashburn4d9f4652015-04-08 21:33:34 -06001895 funcs.append('%s%s\n'
1896 '{\n'
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001897 ' return explicit_%s;\n'
1898 '}' % (qual, decl, proto.c_call()))
1899 return "".join(funcs)
Mark Lobodzinski308d7792015-11-24 10:28:31 -07001900 # Temporarily prevent DestroySurface call from being generated until WSI layer support is fleshed out
Mark Lobodzinski882655d2016-01-05 11:32:53 -07001901 elif 'DestroyInstance' in proto.name or 'DestroyDevice' in proto.name:
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001902 return ""
Jon Ashburn4d9f4652015-04-08 21:33:34 -06001903 else:
Tobin Ehlis86684f92016-01-05 10:33:58 -07001904 if create_func:
Michael Lentine13803dc2015-11-04 14:35:12 -08001905 typ = proto.params[-1].ty.strip('*').replace('const ', '');
1906 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1907 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001908 create_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
1909 create_line += ' if (result == VK_SUCCESS) {\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08001910 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 -06001911 create_line += ' }\n'
1912 create_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06001913 if 'FreeCommandBuffers' in proto.name:
Michael Lentine13803dc2015-11-04 14:35:12 -08001914 typ = proto.params[-1].ty.strip('*').replace('const ', '');
1915 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1916 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06001917 funcs.append('%s\n' % self.lineinfo.get())
1918 destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Chia-I Wud50a7d72015-10-26 20:48:51 +08001919 destroy_line += ' for (uint32_t i = 0; i < commandBufferCount; i++) {\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08001920 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 -06001921 destroy_line += ' }\n'
1922 destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001923 if 'Destroy' in proto.name:
Michael Lentine13803dc2015-11-04 14:35:12 -08001924 typ = proto.params[-2].ty.strip('*').replace('const ', '');
1925 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1926 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06001927 funcs.append('%s\n' % self.lineinfo.get())
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001928 destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08001929 destroy_line += ' destroy_%s(%s, %s);\n' % (name, param0_name, proto.params[-2].name)
Mark Lobodzinski64d57752015-07-17 11:51:24 -06001930 destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Tobin Ehlis86684f92016-01-05 10:33:58 -07001931 indent = ' '
1932 if len(struct_uses) > 0:
1933 using_line += '%sVkBool32 skipCall = VK_FALSE;\n' % (indent)
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001934 if not mutex_unlock:
Tobin Ehlis86684f92016-01-05 10:33:58 -07001935 using_line += '%sloader_platform_thread_lock_mutex(&objLock);\n' % (indent)
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001936 mutex_unlock = True
Tobin Ehlis86684f92016-01-05 10:33:58 -07001937 using_line += '// objects to validate: %s\n' % str(struct_uses)
1938 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 -06001939 if mutex_unlock:
Tobin Ehlis86684f92016-01-05 10:33:58 -07001940 using_line += '%sloader_platform_thread_unlock_mutex(&objLock);\n' % (indent)
1941 if len(struct_uses) > 0:
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -06001942 using_line += ' if (skipCall)\n'
1943 if proto.ret != "void":
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07001944 using_line += ' return VK_ERROR_VALIDATION_FAILED_EXT;\n'
Tobin Ehlisc9ac2b62015-09-11 12:57:55 -06001945 else:
1946 using_line += ' return;\n'
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001947 ret_val = ''
1948 stmt = ''
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001949 if proto.ret != "void":
1950 ret_val = "%s result = " % proto.ret
1951 stmt = " return result;\n"
1952
1953 dispatch_param = proto.params[0].name
1954 if 'CreateInstance' in proto.name:
1955 dispatch_param = '*' + proto.params[1].name
1956
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001957 # Must use 'instance' table for these APIs, 'device' table otherwise
1958 table_type = ""
1959 if proto_is_global(proto):
1960 table_type = "instance"
1961 else:
1962 table_type = "device"
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001963 if wsi_name(proto.name):
1964 funcs.append('%s' % wsi_ifdef(proto.name))
Mike Stroyan00087e62015-04-03 14:39:16 -06001965 funcs.append('%s%s\n'
1966 '{\n'
1967 '%s'
Mike Stroyan00087e62015-04-03 14:39:16 -06001968 '%s'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001969 ' %sget_dispatch_table(object_tracker_%s_table_map, %s)->%s;\n'
Mike Stroyan38820b32015-09-28 13:47:29 -06001970 '%s'
1971 '%s'
1972 '}' % (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 -07001973 if wsi_name(proto.name):
1974 funcs.append('%s' % wsi_endif(proto.name))
Mike Stroyan00087e62015-04-03 14:39:16 -06001975 return "\n\n".join(funcs)
1976
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001977 def generate_body(self):
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07001978 self.layer_name = "object_tracker"
Ian Elliott1064fe32015-07-06 14:31:32 -06001979 extensions=[('wsi_enabled',
Ian Elliott05846062015-11-20 14:13:17 -07001980 ['vkCreateSwapchainKHR',
Jon Ashburn8acd2332015-09-16 18:08:32 -06001981 'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
1982 'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001983 if sys.platform.startswith('win32'):
Michael Lentine64e2ebd2015-12-03 14:33:09 -08001984 instance_extensions=[('msg_callback_get_proc_addr', []),
1985 ('wsi_enabled',
1986 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1987 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1988 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1989 'vkGetPhysicalDeviceSurfacePresentModesKHR',
1990 'vkCreateWin32SurfaceKHR',
1991 'vkGetPhysicalDeviceWin32PresentationSupportKHR'])]
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07001992 elif sys.platform.startswith('linux'):
Michael Lentine64e2ebd2015-12-03 14:33:09 -08001993 instance_extensions=[('msg_callback_get_proc_addr', []),
1994 ('wsi_enabled',
1995 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1996 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1997 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1998 'vkGetPhysicalDeviceSurfacePresentModesKHR',
1999 'vkCreateXcbSurfaceKHR',
Mark Lobodzinskib49b6e52015-11-26 10:59:58 -07002000 'vkGetPhysicalDeviceXcbPresentationSupportKHR'])]
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -07002001 # TODO: Add cases for Mir, Wayland and Xlib
2002 else: # android
2003 instance_extensions=[('msg_callback_get_proc_addr', []),
2004 ('wsi_enabled',
2005 ['vkGetPhysicalDeviceSurfaceSupportKHR',
2006 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
2007 'vkGetPhysicalDeviceSurfaceFormatsKHR',
2008 'vkGetPhysicalDeviceSurfacePresentModesKHR'])]
Tony Barboura05dbaa2015-07-09 17:31:46 -06002009 body = [self.generate_maps(),
2010 self.generate_procs(),
Mark Lobodzinski64d57752015-07-17 11:51:24 -06002011 self.generate_destroy_instance(),
2012 self.generate_destroy_device(),
Tony Barboura05dbaa2015-07-09 17:31:46 -06002013 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Tobin Ehlisca915872014-11-18 11:28:33 -07002014 self._generate_extensions(),
Jon Ashburn747f2b62015-06-18 15:02:58 -06002015 self._generate_layer_gpa_function(extensions,
Jon Ashburn3dc39382015-09-17 10:00:32 -06002016 instance_extensions)]
Tobin Ehlis12076fc2014-10-22 09:06:33 -06002017 return "\n\n".join(body)
Courtney Goeltzenleuchterb412d212014-11-18 10:40:29 -07002018
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07002019class UniqueObjectsSubcommand(Subcommand):
2020 def generate_header(self):
2021 header_txt = []
2022 header_txt.append('%s' % self.lineinfo.get())
2023 header_txt.append('#include "unique_objects.h"')
2024 header_txt.append('')
2025 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
2026 return "\n".join(header_txt)
2027
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002028 # Generate UniqueObjects code for given struct_uses dict of objects that need to be unwrapped
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002029 # vector_name_set is used to make sure we don't replicate vector names
2030 # 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 -07002031 # TODO : Comment this code
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002032 def _gen_obj_code(self, struct_uses, indent, prefix, array_index, vector_name_set, first_level_param):
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002033 decls = ''
2034 pre_code = ''
2035 post_code = ''
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002036 for obj in sorted(struct_uses):
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002037 name = obj
2038 array = ''
2039 if '[' in obj:
2040 (name, array) = obj.split('[')
2041 array = array.strip(']')
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002042 ptr_type = False
Tobin Ehlis991d45a2016-01-06 08:48:41 -07002043 if 'p' == obj[0] and obj[1] != obj[1].lower(): # TODO : Not idea way to determine ptr
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002044 ptr_type = True
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002045 if isinstance(struct_uses[obj], dict):
2046 local_prefix = ''
2047 name = '%s%s' % (prefix, name)
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002048 if ptr_type:
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002049 pre_code += '%sif (%s) {\n' % (indent, name)
2050 post_code += '%sif (%s) {\n' % (indent, name)
2051 indent += ' '
2052 if array != '':
2053 idx = 'idx%s' % str(array_index)
2054 array_index += 1
2055 pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
2056 post_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
2057 indent += ' '
2058 local_prefix = '%s[%s].' % (name, idx)
2059 elif ptr_type:
2060 local_prefix = '%s->' % (name)
2061 else:
2062 local_prefix = '%s.' % (name)
2063 assert isinstance(decls, object)
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002064 (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 -07002065 decls += tmp_decl
2066 pre_code += tmp_pre
2067 post_code += tmp_post
2068 if array != '':
2069 indent = indent[4:]
2070 pre_code += '%s}\n' % (indent)
2071 post_code += '%s}\n' % (indent)
2072 if ptr_type:
2073 indent = indent[4:]
2074 pre_code += '%s}\n' % (indent)
2075 post_code += '%s}\n' % (indent)
2076 else:
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002077 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 -07002078 pre_code += '%sif (%s%s) {\n' %(indent, prefix, name)
2079 post_code += '%sif (%s%s) {\n' %(indent, prefix, name)
2080 indent += ' '
2081 # Append unique_count to make sure name is unique (some aliasing for "buffer" and "image" names
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002082 vec_name = 'original_%s' % (name)
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002083 if array != '':
2084 idx = 'idx%s' % str(array_index)
2085 array_index += 1
2086 pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
2087 post_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
2088 indent += ' '
2089 name = '%s[%s]' % (name, idx)
2090 pName = 'p%s' % (struct_uses[obj][2:])
2091 pre_code += '%s%s* %s = (%s*)&(%s%s);\n' % (indent, struct_uses[obj], pName, struct_uses[obj], prefix, name)
2092 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 -07002093 if name not in vector_name_set:
2094 vector_name_set.add(name)
2095 decls += ' std::vector<%s> %s = {};\n' % (struct_uses[obj], vec_name)
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002096 pre_code += '%s%s.push_back(%s%s);\n' % (indent, vec_name, prefix, name)
2097 pre_code += '%s*(%s) = (%s)((VkUniqueObject*)%s%s)->actualObject;\n' % (indent, pName, struct_uses[obj], prefix, name)
2098 post_code += '%s*(%s) = %s.front();\n' % (indent, pName, vec_name)
2099 post_code += '%s%s.erase(%s.begin());\n' % (indent, vec_name, vec_name)
2100 if array != '':
2101 indent = indent[4:]
2102 pre_code += '%s}\n' % (indent)
2103 post_code += '%s}\n' % (indent)
2104 indent = indent[4:]
2105 pre_code += '%s}\n' % (indent)
2106 post_code += '%s}\n' % (indent)
2107 else:
2108 pre_code += '%sif (%s%s) {\n' %(indent, prefix, name)
2109 indent += ' '
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002110 deref_txt = '&'
2111 if ptr_type:
2112 deref_txt = ''
2113 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 -07002114 pre_code += '%s*p%s = (%s)((VkUniqueObject*)%s%s)->actualObject;\n' % (indent, name, struct_uses[obj], prefix, name)
2115 indent = indent[4:]
2116 pre_code += '%s}\n' % (indent)
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002117 if not first_level_param: # embedded in a ptr/struct so need to undo the update
2118 decls += ' %s local_%s = %s%s;\n' % (struct_uses[obj], name, prefix, name)
2119 post_code += '%sif (%s%s) {\n' %(indent, prefix, name)
2120 post_code += '%s %s* p%s = (%s*)%s%s%s;\n' % (indent, struct_uses[obj], name, struct_uses[obj], deref_txt, prefix, name)
2121 post_code += '%s *p%s = local_%s;\n' % (indent, name, name)
2122 post_code += '%s}\n' % (indent)
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002123 return decls, pre_code, post_code
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07002124
2125 def generate_intercept(self, proto, qual):
2126 create_func = False
2127 destroy_func = False
2128 last_param_index = None #typcially we look at all params for ndos
2129 pre_call_txt = '' # code prior to calling down chain such as unwrap uses of ndos
2130 post_call_txt = '' # code following call down chain such to wrap newly created ndos, or destroy local wrap struct
2131 funcs = []
2132 indent = ' ' # indent level for generated code
2133 decl = proto.c_func(prefix="vk", attr="VKAPI")
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002134 # A few API cases that are manual code
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002135 # TODO : Special case Create*Pipelines funcs to handle creating multiple unique objects
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002136 explicit_object_tracker_functions = ['GetSwapchainImagesKHR',
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07002137 'CreateInstance',
Tobin Ehlisa39c26a2016-01-05 16:34:59 -07002138 'CreateDevice',
2139 'CreateComputePipelines',
2140 'CreateGraphicsPipelines']
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07002141 # Give special treatment to create functions that return multiple new objects
2142 # This dict stores array name and size of array
Jon Ashburnf19916e2016-01-11 13:12:43 -07002143 custom_create_dict = {'pDescriptorSets' : 'pAllocateInfo->descriptorSetCount'}
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07002144 if proto.name in explicit_object_tracker_functions:
2145 funcs.append('%s%s\n'
2146 '{\n'
2147 ' return explicit_%s;\n'
2148 '}' % (qual, decl, proto.c_call()))
2149 return "".join(funcs)
2150 if True in [create_txt in proto.name for create_txt in ['Create', 'Allocate']]:
2151 create_func = True
2152 last_param_index = -1 # For create funcs don't care if last param is ndo
2153 if True in [destroy_txt in proto.name for destroy_txt in ['Destroy', 'Free']]:
2154 destroy_obj_type = proto.params[-2].ty
2155 if destroy_obj_type in vulkan.object_non_dispatch_list:
2156 destroy_func = True
2157
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002158 # First thing we need to do is gather uses of non-dispatchable-objects (ndos)
2159 struct_uses = get_object_uses(vulkan.object_non_dispatch_list, proto.params[1:last_param_index])
2160
2161 if len(struct_uses) > 0:
2162 pre_call_txt += '// STRUCT USES:%s\n' % struct_uses
2163 if destroy_func: # only one object
2164 for del_obj in struct_uses:
2165 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 -07002166 (pre_decl, pre_code, post_code) = self._gen_obj_code(struct_uses, ' ', '', 0, set(), True)
Tobin Ehlis65f44e42016-01-05 09:46:03 -07002167 pre_call_txt += '%s%s' % (pre_decl, pre_code)
2168 post_call_txt += post_code
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07002169 elif create_func:
2170 base_type = proto.params[-1].ty.replace('const ', '').strip('*')
2171 if base_type not in vulkan.object_non_dispatch_list:
2172 return None
2173 else:
2174 return None
2175
2176 ret_val = ''
2177 ret_stmt = ''
2178 if proto.ret != "void":
2179 ret_val = "%s result = " % proto.ret
2180 ret_stmt = " return result;\n"
2181 dispatch_param = proto.params[0].name
2182 if 'CreateInstance' in proto.name:
2183 dispatch_param = '*' + proto.params[1].name
2184 if create_func:
2185 obj_type = proto.params[-1].ty.strip('*')
2186 obj_name = proto.params[-1].name
2187 if obj_type in vulkan.object_non_dispatch_list:
2188 local_name = "unique%s" % obj_type[2:]
2189 post_call_txt += '%sif (VK_SUCCESS == result) {\n' % (indent)
2190 indent += ' '
2191 if obj_name in custom_create_dict:
2192 post_call_txt += '%s\n' % (self.lineinfo.get())
2193 local_name = '%ss' % (local_name) # add 's' to end for vector of many
2194 post_call_txt += '%sstd::vector<VkUniqueObject*> %s = {};\n' % (indent, local_name)
2195 post_call_txt += '%sfor (uint32_t i=0; i<%s; ++i) {\n' % (indent, custom_create_dict[obj_name])
2196 indent += ' '
2197 post_call_txt += '%s%s.push_back(new VkUniqueObject());\n' % (indent, local_name)
2198 post_call_txt += '%s%s[i]->actualObject = (uint64_t)%s[i];\n' % (indent, local_name, obj_name)
2199 post_call_txt += '%s%s[i] = (%s)%s[i];\n' % (indent, obj_name, obj_type, local_name)
2200 indent = indent[4:]
2201 post_call_txt += '%s}\n' % (indent)
2202 else:
2203 post_call_txt += '%s\n' % (self.lineinfo.get())
2204 post_call_txt += '%sVkUniqueObject* %s = new VkUniqueObject();\n' % (indent, local_name)
2205 post_call_txt += '%s%s->actualObject = (uint64_t)*%s;\n' % (indent, local_name, obj_name)
2206 post_call_txt += '%s*%s = (%s)%s;\n' % (indent, obj_name, obj_type, local_name)
2207 indent = indent[4:]
2208 post_call_txt += '%s}\n' % (indent)
2209 elif destroy_func:
2210 del_obj = proto.params[-2].name
2211 if 'count' in del_obj.lower():
2212 post_call_txt += '%s\n' % (self.lineinfo.get())
2213 post_call_txt += '%sfor (uint32_t i=0; i<%s; ++i) {\n' % (indent, del_obj)
2214 del_obj = proto.params[-1].name
2215 indent += ' '
2216 post_call_txt += '%sdelete (VkUniqueObject*)%s[i];\n' % (indent, del_obj)
2217 indent = indent[4:]
2218 post_call_txt += '%s}\n' % (indent)
2219 else:
2220 post_call_txt += '%s\n' % (self.lineinfo.get())
2221 post_call_txt = '%sdelete (VkUniqueObject*)local_%s;\n' % (indent, proto.params[-2].name)
2222
2223 call_sig = proto.c_call()
2224 if proto_is_global(proto):
2225 table_type = "instance"
2226 else:
2227 table_type = "device"
2228 pre_call_txt += '%s\n' % (self.lineinfo.get())
2229 funcs.append('%s%s\n'
2230 '{\n'
2231 '%s'
2232 ' %sget_dispatch_table(unique_objects_%s_table_map, %s)->%s;\n'
2233 '%s'
2234 '%s'
2235 '}' % (qual, decl, pre_call_txt, ret_val, table_type, dispatch_param, call_sig, post_call_txt, ret_stmt))
2236 return "\n\n".join(funcs)
2237
2238 def generate_body(self):
2239 self.layer_name = "unique_objects"
2240 extensions=[('wsi_enabled',
2241 ['vkCreateSwapchainKHR',
2242 'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
2243 'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
2244 if sys.platform.startswith('win32'):
2245 instance_extensions=[('wsi_enabled',
2246 ['vkGetPhysicalDeviceSurfaceSupportKHR',
2247 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
2248 'vkGetPhysicalDeviceSurfaceFormatsKHR',
2249 'vkGetPhysicalDeviceSurfacePresentModesKHR',
Jon Ashburn00dc7412016-01-07 16:13:06 -07002250 'vkCreateWin32SurfaceKHR'
2251 ])]
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07002252 elif sys.platform.startswith('linux'):
2253 instance_extensions=[('wsi_enabled',
2254 ['vkGetPhysicalDeviceSurfaceSupportKHR',
2255 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
2256 'vkGetPhysicalDeviceSurfaceFormatsKHR',
2257 'vkGetPhysicalDeviceSurfacePresentModesKHR',
Jon Ashburn00dc7412016-01-07 16:13:06 -07002258 'vkCreateXcbSurfaceKHR'
2259 ])]
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07002260 # TODO: Add cases for Mir, Wayland and Xlib
2261 else: # android
2262 instance_extensions=[('wsi_enabled',
2263 ['vkGetPhysicalDeviceSurfaceSupportKHR',
2264 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
2265 'vkGetPhysicalDeviceSurfaceFormatsKHR',
2266 'vkGetPhysicalDeviceSurfacePresentModesKHR'])]
2267 body = [self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
2268 self._generate_layer_gpa_function(extensions,
2269 instance_extensions)]
2270 return "\n\n".join(body)
2271
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002272class ThreadingSubcommand(Subcommand):
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002273 thread_check_dispatchable_objects = [
2274 "VkQueue",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002275 "VkCommandBuffer",
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002276 ]
2277 thread_check_nondispatchable_objects = [
2278 "VkDeviceMemory",
2279 "VkBuffer",
2280 "VkImage",
2281 "VkDescriptorSet",
2282 "VkDescriptorPool",
2283 "VkSemaphore"
2284 ]
Mike Stroyan313f7e62015-08-10 16:42:53 -06002285 thread_check_object_types = {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002286 'VkInstance' : 'VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT',
2287 'VkPhysicalDevice' : 'VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT',
2288 'VkDevice' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT',
2289 'VkQueue' : 'VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT',
2290 'VkCommandBuffer' : 'VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT',
2291 'VkFence' : 'VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT',
2292 'VkDeviceMemory' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT',
2293 'VkBuffer' : 'VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT',
2294 'VkImage' : 'VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT',
2295 'VkSemaphore' : 'VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT',
2296 'VkEvent' : 'VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT',
2297 'VkQueryPool' : 'VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT',
2298 'VkBufferView' : 'VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT',
2299 'VkImageView' : 'VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT',
2300 'VkShaderModule' : 'VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT',
2301 'VkShader' : 'VK_DEBUG_REPORT_OBJECT_TYPE_SHADER',
2302 'VkPipelineCache' : 'VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT',
2303 'VkPipelineLayout' : 'VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT',
2304 'VkRenderPass' : 'VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT',
2305 'VkPipeline' : 'VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT',
2306 'VkDescriptorSetLayout' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT',
2307 'VkSampler' : 'VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT',
2308 'VkDescriptorPool' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT',
2309 'VkDescriptorSet' : 'VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT',
2310 'VkFramebuffer' : 'VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT',
2311 'VkCommandPool' : 'VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT',
Mike Stroyan313f7e62015-08-10 16:42:53 -06002312 }
2313 def generate_useObject(self, ty):
2314 obj_type = self.thread_check_object_types[ty]
Chia-I Wue2fc5522015-10-26 20:04:44 +08002315 key = "object"
2316 msg_object = "reinterpret_cast<uint64_t>(object)"
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002317 header_txt = []
2318 header_txt.append('%s' % self.lineinfo.get())
Michael Lentine13803dc2015-11-04 14:35:12 -08002319 header_txt.append('static void use%s(const void* dispatchable_object, %s object)' % (ty, ty))
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002320 header_txt.append('{')
2321 header_txt.append(' loader_platform_thread_id tid = loader_platform_get_thread_id();')
2322 header_txt.append(' loader_platform_thread_lock_mutex(&threadingLock);')
2323 header_txt.append(' if (%sObjectsInUse.find(%s) == %sObjectsInUse.end()) {' % (ty, key, ty))
2324 header_txt.append(' %sObjectsInUse[%s] = tid;' % (ty, key))
2325 header_txt.append(' } else {')
2326 header_txt.append(' if (%sObjectsInUse[%s] != tid) {' % (ty, key))
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002327 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 -07002328 header_txt.append(' __LINE__, THREADING_CHECKER_MULTIPLE_THREADS, "THREADING",')
Mike Stroyan313f7e62015-08-10 16:42:53 -06002329 header_txt.append(' "THREADING ERROR : object of type %s is simultaneously used in thread %%ld and thread %%ld",' % (ty))
2330 header_txt.append(' %sObjectsInUse[%s], tid);' % (ty, key))
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002331 header_txt.append(' // Wait for thread-safe access to object')
2332 header_txt.append(' while (%sObjectsInUse.find(%s) != %sObjectsInUse.end()) {' % (ty, key, ty))
2333 header_txt.append(' loader_platform_thread_cond_wait(&threadingCond, &threadingLock);')
2334 header_txt.append(' }')
2335 header_txt.append(' %sObjectsInUse[%s] = tid;' % (ty, key))
2336 header_txt.append(' } else {')
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002337 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 -07002338 header_txt.append(' __LINE__, THREADING_CHECKER_MULTIPLE_THREADS, "THREADING",')
Mike Stroyan313f7e62015-08-10 16:42:53 -06002339 header_txt.append(' "THREADING ERROR : object of type %s is recursively used in thread %%ld",' % (ty))
2340 header_txt.append(' tid);')
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002341 header_txt.append(' }')
2342 header_txt.append(' }')
2343 header_txt.append(' loader_platform_thread_unlock_mutex(&threadingLock);')
2344 header_txt.append('}')
2345 return "\n".join(header_txt)
Mike Stroyan313f7e62015-08-10 16:42:53 -06002346 def generate_finishUsingObject(self, ty):
Chia-I Wue2fc5522015-10-26 20:04:44 +08002347 key = "object"
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002348 header_txt = []
2349 header_txt.append('%s' % self.lineinfo.get())
Michael Lentine13803dc2015-11-04 14:35:12 -08002350 header_txt.append('static void finishUsing%s(%s object)' % (ty, ty))
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002351 header_txt.append('{')
2352 header_txt.append(' // Object is no longer in use')
2353 header_txt.append(' loader_platform_thread_lock_mutex(&threadingLock);')
2354 header_txt.append(' %sObjectsInUse.erase(%s);' % (ty, key))
2355 header_txt.append(' loader_platform_thread_cond_broadcast(&threadingCond);')
2356 header_txt.append(' loader_platform_thread_unlock_mutex(&threadingLock);')
2357 header_txt.append('}')
2358 return "\n".join(header_txt)
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002359 def generate_header(self):
2360 header_txt = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -06002361 header_txt.append('%s' % self.lineinfo.get())
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002362 header_txt.append('#include <stdio.h>')
2363 header_txt.append('#include <stdlib.h>')
2364 header_txt.append('#include <string.h>')
2365 header_txt.append('#include <unordered_map>')
Tobin Ehlisb835d1b2015-07-03 10:34:49 -06002366 header_txt.append('#include "vk_loader_platform.h"')
David Pinedo9316d3b2015-11-06 12:54:48 -07002367 header_txt.append('#include "vulkan/vk_layer.h"')
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002368 header_txt.append('#include "threading.h"')
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -06002369 header_txt.append('#include "vk_layer_config.h"')
Courtney Goeltzenleuchter3f9f7c42015-07-06 09:11:12 -06002370 header_txt.append('#include "vk_layer_extension_utils.h"')
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002371 header_txt.append('#include "vk_enum_validate_helper.h"')
2372 header_txt.append('#include "vk_struct_validate_helper.h"')
Mike Stroyan313f7e62015-08-10 16:42:53 -06002373 header_txt.append('#include "vk_layer_table.h"')
2374 header_txt.append('#include "vk_layer_logging.h"')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002375 header_txt.append('')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002376 header_txt.append('')
2377 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
2378 header_txt.append('')
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002379 header_txt.append('using namespace std;')
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002380 for ty in self.thread_check_dispatchable_objects:
2381 header_txt.append('static unordered_map<%s, loader_platform_thread_id> %sObjectsInUse;' % (ty, ty))
2382 for ty in self.thread_check_nondispatchable_objects:
Chia-I Wue2fc5522015-10-26 20:04:44 +08002383 header_txt.append('static unordered_map<%s, loader_platform_thread_id> %sObjectsInUse;' % (ty, ty))
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002384 header_txt.append('static int threadingLockInitialized = 0;')
2385 header_txt.append('static loader_platform_thread_mutex threadingLock;')
Mike Stroyaned238bb2015-05-15 08:50:57 -06002386 header_txt.append('static loader_platform_thread_cond threadingCond;')
Tobin Ehlis08fafd02015-06-12 12:49:01 -06002387 header_txt.append('%s' % self.lineinfo.get())
Mike Stroyan313f7e62015-08-10 16:42:53 -06002388 for ty in self.thread_check_dispatchable_objects + self.thread_check_nondispatchable_objects:
2389 header_txt.append(self.generate_useObject(ty))
2390 header_txt.append(self.generate_finishUsingObject(ty))
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002391 header_txt.append('%s' % self.lineinfo.get())
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002392 return "\n".join(header_txt)
2393
2394 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002395 if proto.name in [ 'CreateDebugReportCallbackEXT' ]:
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002396 # use default version
2397 return None
2398 decl = proto.c_func(prefix="vk", attr="VKAPI")
2399 ret_val = ''
2400 stmt = ''
2401 funcs = []
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002402 table = 'device'
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002403 if proto.ret != "void":
Jon Ashburnb0fbe912015-05-06 10:15:07 -06002404 ret_val = "%s result = " % proto.ret
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002405 stmt = " return result;\n"
Jon Ashburn95a77ba2015-05-15 15:09:35 -06002406 if proto_is_global(proto):
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002407 table = 'instance'
Jon Ashburn71836d92015-05-12 17:23:55 -06002408
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002409 # Memory range calls are special in needed thread checking within structs
2410 if proto.name in ["FlushMappedMemoryRanges","InvalidateMappedMemoryRanges"]:
Mike Stroyan313f7e62015-08-10 16:42:53 -06002411 funcs.append('%s' % self.lineinfo.get())
2412 funcs.append('%s%s\n' % (qual, decl) +
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002413 '{\n'
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002414 ' for (uint32_t i=0; i<memoryRangeCount; i++) {\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08002415 ' useVkDeviceMemory((const void *) %s, pMemoryRanges[i].memory);\n' % proto.params[0].name +
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002416 ' }\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002417 ' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_%s_table_map, %s);\n' % (table, proto.params[0].name) +
Mike Stroyan313f7e62015-08-10 16:42:53 -06002418 ' %s pDeviceTable->%s;\n' % (ret_val, proto.c_call()) +
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002419 ' for (uint32_t i=0; i<memoryRangeCount; i++) {\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08002420 ' finishUsingVkDeviceMemory(pMemoryRanges[i].memory);\n'
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002421 ' }\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002422 '%s' % (stmt) +
2423 '}')
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002424 return "\n".join(funcs)
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002425 # All functions that do a Get are thread safe
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002426 if 'Get' in proto.name:
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002427 return None
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002428 # All WSI functions are thread safe
Ian Elliott7e40db92015-08-21 15:09:33 -06002429 if 'KHR' in proto.name:
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002430 return None
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002431 # Initialize in early calls
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002432 if proto.name == "CreateDevice":
2433 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan313f7e62015-08-10 16:42:53 -06002434 funcs.append('%s%s\n' % (qual, decl) +
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002435 '{\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002436 ' VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);\n'
2437 ' PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;\n'
2438 ' PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;\n'
2439 ' PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");\n'
2440 ' if (fpCreateDevice == NULL) {\n'
2441 ' return VK_ERROR_INITIALIZATION_FAILED;\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002442 ' }\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002443 ' // Advance the link info for the next element on the chain\n'
2444 ' chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;\n'
2445 ' VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);\n'
2446 ' if (result != VK_SUCCESS) {\n'
2447 ' return result;\n'
2448 ' }\n'
2449 ' layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);\n'
2450 ' layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);\n'
2451 ' initDeviceTable(*pDevice, fpGetDeviceProcAddr, threading_device_table_map);\n'
2452 ' my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);\n'
2453 ' return result;\n'
2454 '}\n')
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002455 return "\n".join(funcs)
2456 elif proto.params[0].ty == "VkPhysicalDevice":
Mike Stroyan313f7e62015-08-10 16:42:53 -06002457 return None
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002458 # Functions changing command buffers need thread safe use of first parameter
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002459 if proto.params[0].ty == "VkCommandBuffer":
Tobin Ehlis08fafd02015-06-12 12:49:01 -06002460 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan313f7e62015-08-10 16:42:53 -06002461 funcs.append('%s%s\n' % (qual, decl) +
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002462 '{\n'
Michael Lentine13803dc2015-11-04 14:35:12 -08002463 ' 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 -07002464 ' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_%s_table_map, %s);\n' % (table, proto.params[0].name) +
Mike Stroyan313f7e62015-08-10 16:42:53 -06002465 ' %spDeviceTable->%s;\n' % (ret_val, proto.c_call()) +
Michael Lentine13803dc2015-11-04 14:35:12 -08002466 ' finishUsing%s(%s);\n' % (proto.params[0].ty, proto.params[0].name) +
Mike Stroyan313f7e62015-08-10 16:42:53 -06002467 '%s' % stmt +
2468 '}')
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002469 return "\n".join(funcs)
2470 # Non-Cmd functions that do a Wait are thread safe
2471 if 'Wait' in proto.name:
2472 return None
2473 # Watch use of certain types of objects passed as any parameter
2474 checked_params = []
2475 for param in proto.params:
Mike Stroyanbe2b5d82015-07-09 11:01:07 -06002476 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 -06002477 checked_params.append(param)
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002478 if proto.name == "DestroyDevice":
Mike Stroyan313f7e62015-08-10 16:42:53 -06002479 funcs.append('%s%s\n' % (qual, decl) +
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002480 '{\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06002481 ' dispatch_key key = get_dispatch_key(device);\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002482 ' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_%s_table_map, %s);\n' % (table, proto.params[0].name) +
Mike Stroyan313f7e62015-08-10 16:42:53 -06002483 ' %spDeviceTable->%s;\n' % (ret_val, proto.c_call()) +
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002484 ' threading_device_table_map.erase(key);\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002485 '}\n')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002486 return "\n".join(funcs);
2487 elif proto.name == "DestroyInstance":
Mike Stroyan313f7e62015-08-10 16:42:53 -06002488 funcs.append('%s%s\n' % (qual, decl) +
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002489 '{\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06002490 ' dispatch_key key = get_dispatch_key(instance);\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002491 ' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(threading_instance_table_map, %s);\n' % proto.params[0].name +
Mike Stroyan313f7e62015-08-10 16:42:53 -06002492 ' %spInstanceTable->%s;\n' % (ret_val, proto.c_call()) +
Courtney Goeltzenleuchter951af522016-01-15 11:58:33 -07002493 ' destroy_dispatch_table(threading_instance_table_map, key);\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002494 '\n'
2495 ' // Clean up logging callback, if any\n'
2496 ' layer_data *my_data = get_my_data_ptr(key, layer_data_map);\n'
2497 ' if (my_data->logging_callback) {\n'
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07002498 ' layer_destroy_msg_callback(my_data->report_data, my_data->logging_callback, pAllocator);\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002499 ' }\n'
2500 '\n'
2501 ' layer_debug_report_destroy_instance(my_data->report_data);\n'
2502 ' layer_data_map.erase(pInstanceTable);\n'
2503 '\n'
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002504 ' threading_instance_table_map.erase(key);\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002505 '}\n')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05002506 return "\n".join(funcs);
Courtney Goeltzenleuchterd02a9642015-06-08 14:58:39 -06002507 elif proto.name == "CreateInstance":
2508 funcs.append('%s%s\n'
2509 '{\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002510 ' VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);\n'
2511 ' PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;\n'
2512 ' PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");\n'
2513 ' if (fpCreateInstance == NULL) {\n'
2514 ' return VK_ERROR_INITIALIZATION_FAILED;\n'
Courtney Goeltzenleuchterd02a9642015-06-08 14:58:39 -06002515 ' }\n'
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002516 ' // Advance the link info for the next element on the chain\n'
2517 ' chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;\n'
2518 ' VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);\n'
2519 ' if (result != VK_SUCCESS) {\n'
2520 ' return result;\n'
2521 ' }\n'
2522 ' VkLayerInstanceDispatchTable *pTable = initInstanceTable(*pInstance, fpGetInstanceProcAddr, threading_instance_table_map);\n'
2523 ' layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);\n'
2524 ' my_data->report_data = debug_report_create_instance(\n'
2525 ' pTable,\n'
2526 ' *pInstance,\n'
2527 ' pCreateInfo->enabledExtensionCount,\n'
2528 ' pCreateInfo->ppEnabledExtensionNames);\n'
2529 ' init_threading(my_data, pAllocator);\n'
Courtney Goeltzenleuchterd02a9642015-06-08 14:58:39 -06002530 ' return result;\n'
Mike Stroyan313f7e62015-08-10 16:42:53 -06002531 '}\n' % (qual, decl))
Courtney Goeltzenleuchterd02a9642015-06-08 14:58:39 -06002532 return "\n".join(funcs);
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002533 if len(checked_params) == 0:
2534 return None
2535 # Surround call with useObject and finishUsingObject for each checked_param
Tobin Ehlis08fafd02015-06-12 12:49:01 -06002536 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002537 funcs.append('%s%s' % (qual, decl))
2538 funcs.append('{')
2539 for param in checked_params:
Michael Lentine13803dc2015-11-04 14:35:12 -08002540 funcs.append(' use%s((const void *) %s, %s);' % (param.ty, proto.params[0].name, param.name))
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002541 funcs.append(' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_%s_table_map, %s);' % (table, proto.params[0].name));
Mike Stroyan313f7e62015-08-10 16:42:53 -06002542 funcs.append(' %spDeviceTable->%s;' % (ret_val, proto.c_call()))
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002543 for param in checked_params:
Michael Lentine13803dc2015-11-04 14:35:12 -08002544 funcs.append(' finishUsing%s(%s);' % (param.ty, param.name))
Mike Stroyan6ea73e42015-05-11 17:18:14 -06002545 funcs.append('%s'
2546 '}' % stmt)
2547 return "\n".join(funcs)
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002548
2549 def generate_body(self):
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002550 self.layer_name = "threading"
Mike Stroyan313f7e62015-08-10 16:42:53 -06002551 body = [self._generate_new_layer_initialization(True, lockname='threading', condname='threading'),
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002552 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Courtney Goeltzenleuchter17274172015-06-01 14:52:57 -06002553 self._generate_layer_gpa_function(extensions=[],
Jon Ashburn3dc39382015-09-17 10:00:32 -06002554 instance_extensions=[('msg_callback_get_proc_addr', [])]),
Courtney Goeltzenleuchter17274172015-06-01 14:52:57 -06002555 self._gen_create_msg_callback(),
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07002556 self._gen_destroy_msg_callback(),
2557 self._gen_debug_report_msg()]
Mike Stroyan3712d5c2015-04-02 11:59:05 -06002558 return "\n\n".join(body)
2559
Tobin Ehlis12076fc2014-10-22 09:06:33 -06002560def main():
2561 subcommands = {
2562 "layer-funcs" : LayerFuncsSubcommand,
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002563 "generic" : GenericLayerSubcommand,
2564 "api_dump" : APIDumpSubcommand,
2565 "object_tracker" : ObjectTrackerSubcommand,
2566 "threading" : ThreadingSubcommand,
Tobin Ehlisd34a4c52015-12-08 10:50:10 -07002567 "unique_objects" : UniqueObjectsSubcommand,
Tobin Ehlis12076fc2014-10-22 09:06:33 -06002568 }
2569
Tobin Ehlis14ff0852014-12-17 17:44:50 -07002570 if len(sys.argv) < 3 or sys.argv[1] not in subcommands or not os.path.exists(sys.argv[2]):
2571 print("Usage: %s <subcommand> <input_header> [options]" % sys.argv[0])
Tobin Ehlis12076fc2014-10-22 09:06:33 -06002572 print
Tobin Ehlis7e65d752015-01-15 17:51:52 -07002573 print("Available subcommands are: %s" % " ".join(subcommands))
Tobin Ehlis12076fc2014-10-22 09:06:33 -06002574 exit(1)
2575
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06002576 hfp = vk_helper.HeaderFileParser(sys.argv[2])
Tobin Ehlis14ff0852014-12-17 17:44:50 -07002577 hfp.parse()
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06002578 vk_helper.enum_val_dict = hfp.get_enum_val_dict()
2579 vk_helper.enum_type_dict = hfp.get_enum_type_dict()
2580 vk_helper.struct_dict = hfp.get_struct_dict()
2581 vk_helper.typedef_fwd_dict = hfp.get_typedef_fwd_dict()
2582 vk_helper.typedef_rev_dict = hfp.get_typedef_rev_dict()
2583 vk_helper.types_dict = hfp.get_types_dict()
Tobin Ehlis14ff0852014-12-17 17:44:50 -07002584
Tobin Ehlis12076fc2014-10-22 09:06:33 -06002585 subcmd = subcommands[sys.argv[1]](sys.argv[2:])
2586 subcmd.run()
2587
2588if __name__ == "__main__":
2589 main()