blob: bbe6e989aef90cff6467e8e86ffe6b7a622df7c5 [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#
5# Copyright (C) 2014 LunarG, Inc.
6#
7# Permission is hereby granted, free of charge, to any person obtaining a
8# copy of this software and associated documentation files (the "Software"),
9# to deal in the Software without restriction, including without limitation
10# the rights to use, copy, modify, merge, publish, distribute, sublicense,
11# and/or sell copies of the Software, and to permit persons to whom the
12# Software is furnished to do so, subject to the following conditions:
13#
14# The above copyright notice and this permission notice shall be included
15# in all copies or substantial portions of the Software.
16#
17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23# DEALINGS IN THE SOFTWARE.
24#
25# Authors:
26# Chia-I Wu <olv@lunarg.com>
27
28import sys
Tobin Ehlis14ff0852014-12-17 17:44:50 -070029import os
Mark Lobodzinski7c75b852015-05-05 15:01:37 -050030import re
Tobin Ehlis12076fc2014-10-22 09:06:33 -060031
Courtney Goeltzenleuchterf53c3cb2015-04-14 14:55:44 -060032import vulkan
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060033import vk_helper
Tobin Ehlis08fafd02015-06-12 12:49:01 -060034from source_line_info import sourcelineinfo
Tobin Ehlis12076fc2014-10-22 09:06:33 -060035
Jon Ashburn95a77ba2015-05-15 15:09:35 -060036def proto_is_global(proto):
Jon Ashburnb19ddbf2015-06-16 12:44:51 -060037 if proto.params[0].ty == "VkInstance" or proto.params[0].ty == "VkPhysicalDevice" or proto.name == "CreateInstance" or proto.name == "GetGlobalExtensionInfo" or proto.name == "GetPhysicalDeviceExtensionInfo":
Jon Ashburn95a77ba2015-05-15 15:09:35 -060038 return True
39 else:
40 return False
41
Mike Stroyan938c2532015-04-03 13:58:35 -060042def generate_get_proc_addr_check(name):
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060043 return " if (!%s || %s[0] != 'v' || %s[1] != 'k')\n" \
44 " return NULL;" % ((name,) * 3)
Mike Stroyan938c2532015-04-03 13:58:35 -060045
Mark Lobodzinski7c75b852015-05-05 15:01:37 -050046def ucc_to_U_C_C(CamelCase):
47 temp = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', CamelCase)
48 return re.sub('([a-z0-9])([A-Z])', r'\1_\2', temp).upper()
49
Tobin Ehlis12076fc2014-10-22 09:06:33 -060050class Subcommand(object):
51 def __init__(self, argv):
52 self.argv = argv
Courtney Goeltzenleuchterf53c3cb2015-04-14 14:55:44 -060053 self.headers = vulkan.headers
54 self.protos = vulkan.protos
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -060055 self.no_addr = False
56 self.layer_name = ""
Tobin Ehlis08fafd02015-06-12 12:49:01 -060057 self.lineinfo = sourcelineinfo()
Tobin Ehlis12076fc2014-10-22 09:06:33 -060058
59 def run(self):
Tobin Ehlis12076fc2014-10-22 09:06:33 -060060 print(self.generate())
61
62 def generate(self):
63 copyright = self.generate_copyright()
64 header = self.generate_header()
65 body = self.generate_body()
66 footer = self.generate_footer()
67
68 contents = []
69 if copyright:
70 contents.append(copyright)
71 if header:
72 contents.append(header)
73 if body:
74 contents.append(body)
75 if footer:
76 contents.append(footer)
77
78 return "\n\n".join(contents)
79
80 def generate_copyright(self):
81 return """/* THIS FILE IS GENERATED. DO NOT EDIT. */
82
83/*
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060084 * Vulkan
Tobin Ehlis12076fc2014-10-22 09:06:33 -060085 *
86 * Copyright (C) 2014 LunarG, Inc.
87 *
88 * Permission is hereby granted, free of charge, to any person obtaining a
89 * copy of this software and associated documentation files (the "Software"),
90 * to deal in the Software without restriction, including without limitation
91 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
92 * and/or sell copies of the Software, and to permit persons to whom the
93 * Software is furnished to do so, subject to the following conditions:
94 *
95 * The above copyright notice and this permission notice shall be included
96 * in all copies or substantial portions of the Software.
97 *
98 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
99 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
100 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
101 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
102 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
103 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
104 * DEALINGS IN THE SOFTWARE.
105 */"""
106
107 def generate_header(self):
108 return "\n".join(["#include <" + h + ">" for h in self.headers])
109
110 def generate_body(self):
111 pass
112
113 def generate_footer(self):
114 pass
115
116 # Return set of printf '%' qualifier and input to that qualifier
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600117 def _get_printf_params(self, vk_type, name, output_param, cpp=False):
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600118 # TODO : Need ENUM and STRUCT checks here
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600119 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 -0600120 return ("%s", "string_%s(%s)" % (vk_type.replace('const ', '').strip('*'), name))
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600121 if "char*" == vk_type:
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600122 return ("%s", name)
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600123 if "uint64" in vk_type:
124 if '*' in vk_type:
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600125 return ("%lu", "*%s" % name)
126 return ("%lu", name)
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600127 if "size" in vk_type:
128 if '*' in vk_type:
Chia-I Wu99ff89d2014-12-27 14:14:50 +0800129 return ("%zu", "*%s" % name)
130 return ("%zu", name)
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600131 if "float" in vk_type:
132 if '[' in vk_type: # handle array, current hard-coded to 4 (TODO: Make this dynamic)
Tobin Ehlis99f88672015-01-10 12:42:41 -0700133 if cpp:
134 return ("[%i, %i, %i, %i]", '"[" << %s[0] << "," << %s[1] << "," << %s[2] << "," << %s[3] << "]"' % (name, name, name, name))
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600135 return ("[%f, %f, %f, %f]", "%s[0], %s[1], %s[2], %s[3]" % (name, name, name, name))
136 return ("%f", name)
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600137 if "bool" in vk_type or 'xcb_randr_crtc_t' in vk_type:
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600138 return ("%u", name)
Tobin Ehlisb870cbb2015-04-15 07:46:12 -0600139 if True in [t in vk_type.lower() for t in ["int", "flags", "mask", "xcb_window_t"]]:
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600140 if '[' in vk_type: # handle array, current hard-coded to 4 (TODO: Make this dynamic)
Tobin Ehlis99f88672015-01-10 12:42:41 -0700141 if cpp:
142 return ("[%i, %i, %i, %i]", "%s[0] << %s[1] << %s[2] << %s[3]" % (name, name, name, name))
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600143 return ("[%i, %i, %i, %i]", "%s[0], %s[1], %s[2], %s[3]" % (name, name, name, name))
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600144 if '*' in vk_type:
Tobin Ehlisd2b88e82015-02-04 15:15:11 -0700145 if 'pUserData' == name:
146 return ("%i", "((pUserData == 0) ? 0 : *(pUserData))")
Tobin Ehlisc62cb892015-04-17 13:26:33 -0600147 if 'const' in vk_type.lower():
148 return ("%p", "(void*)(%s)" % name)
Jon Ashburn52f79b52014-12-12 16:10:45 -0700149 return ("%i", "*(%s)" % name)
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600150 return ("%i", name)
Tobin Ehlis3a1cc8d2014-11-11 17:28:22 -0700151 # 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 -0600152 if "VkFormat" == vk_type:
Tobin Ehlis99f88672015-01-10 12:42:41 -0700153 if cpp:
154 return ("%p", "&%s" % name)
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600155 return ("{%s.channelFormat = %%s, %s.numericFormat = %%s}" % (name, name), "string_VK_CHANNEL_FORMAT(%s.channelFormat), string_VK_NUM_FORMAT(%s.numericFormat)" % (name, name))
Tobin Ehlise7271572014-11-19 15:52:46 -0700156 if output_param:
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600157 return ("%p", "(void*)*%s" % name)
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600158 if vk_helper.is_type(vk_type, 'struct') and '*' not in vk_type:
Courtney Goeltzenleuchterd462fba2015-04-03 16:35:32 -0600159 return ("%p", "(void*)(&%s)" % name)
Jon Ashburn52f79b52014-12-12 16:10:45 -0700160 return ("%p", "(void*)(%s)" % name)
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600161
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600162 def _gen_create_msg_callback(self):
Tobin Ehlise8185062014-12-17 08:01:59 -0700163 r_body = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600164 r_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600165 r_body.append('VK_LAYER_EXPORT VkResult VKAPI vkDbgCreateMsgCallback(VkInstance instance, VkFlags msgFlags, const PFN_vkDbgMsgCallback pfnMsgCallback, void* pUserData, VkDbgMsgCallback* pMsgCallback)')
Tobin Ehlise8185062014-12-17 08:01:59 -0700166 r_body.append('{')
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600167 # Switch to this code section for the new per-instance storage and debug callbacks
168 if self.layer_name == 'ObjectTracker':
169 r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
170 r_body.append(' VkResult result = pInstanceTable->DbgCreateMsgCallback(instance, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);')
171 r_body.append(' if (VK_SUCCESS == result) {')
172 r_body.append(' layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
173 r_body.append(' result = layer_create_msg_callback(my_data->report_data, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);')
174 r_body.append(' }')
175 r_body.append(' return result;')
176 else:
177 # Old version of callbacks for compatibility
178 r_body.append(' return layer_create_msg_callback(instance, instance_dispatch_table(instance), msgFlags, pfnMsgCallback, pUserData, pMsgCallback);')
Tobin Ehlise8185062014-12-17 08:01:59 -0700179 r_body.append('}')
180 return "\n".join(r_body)
181
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600182 def _gen_destroy_msg_callback(self):
183 r_body = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600184 r_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600185 r_body.append('VK_LAYER_EXPORT VkResult VKAPI vkDbgDestroyMsgCallback(VkInstance instance, VkDbgMsgCallback msgCallback)')
186 r_body.append('{')
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600187 # Switch to this code section for the new per-instance storage and debug callbacks
188 if self.layer_name == 'ObjectTracker':
189 r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
190 r_body.append(' VkResult result = pInstanceTable->DbgDestroyMsgCallback(instance, msgCallback);')
191 r_body.append(' layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
192 r_body.append(' layer_destroy_msg_callback(my_data->report_data, msgCallback);')
193 r_body.append(' return result;')
194 else:
195 # Old version of callbacks for compatibility
196 r_body.append(' return layer_destroy_msg_callback(instance, instance_dispatch_table(instance), msgCallback);')
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600197 r_body.append('}')
198 return "\n".join(r_body)
Tobin Ehlise8185062014-12-17 08:01:59 -0700199
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600200 def _gen_layer_get_global_extension_info(self, layer="Generic"):
201 ggei_body = []
Courtney Goeltzenleuchter322a14b2015-06-07 17:24:20 -0600202 if layer == 'APIDump' or layer == 'Generic':
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600203 ggei_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600204 ggei_body.append('#define LAYER_EXT_ARRAY_SIZE 1')
205 ggei_body.append('static const VkExtensionProperties layerExts[LAYER_EXT_ARRAY_SIZE] = {')
206 ggei_body.append(' {')
207 ggei_body.append(' VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,')
208 ggei_body.append(' "%s",' % layer)
209 ggei_body.append(' 0x10,')
210 ggei_body.append(' "layer: %s",' % layer)
211 ggei_body.append(' }')
212 ggei_body.append('};')
213 else:
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600214 ggei_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600215 ggei_body.append('#define LAYER_EXT_ARRAY_SIZE 2')
216 ggei_body.append('static const VkExtensionProperties layerExts[LAYER_EXT_ARRAY_SIZE] = {')
217 ggei_body.append(' {')
218 ggei_body.append(' VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,')
219 ggei_body.append(' "%s",' % layer)
220 ggei_body.append(' 0x10,')
221 ggei_body.append(' "layer: %s",' % layer)
222 ggei_body.append(' },')
223 ggei_body.append(' {')
224 ggei_body.append(' VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,')
225 ggei_body.append(' "Validation",')
226 ggei_body.append(' 0x10,')
227 ggei_body.append(' "layer: %s",' % layer)
228 ggei_body.append(' }')
229 ggei_body.append('};')
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600230 ggei_body.append('')
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600231 ggei_body.append('%s' % self.lineinfo.get())
Mark Lobodzinskia2727c92015-04-13 16:35:52 -0500232 ggei_body.append('VK_LAYER_EXPORT VkResult VKAPI vkGetGlobalExtensionInfo(VkExtensionInfoType infoType, uint32_t extensionIndex, size_t* pDataSize, void* pData)')
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600233 ggei_body.append('{')
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600234 ggei_body.append(' uint32_t *count;')
235 ggei_body.append('')
236 ggei_body.append(' if (pDataSize == NULL)')
237 ggei_body.append(' return VK_ERROR_INVALID_POINTER;')
238 ggei_body.append('')
239 ggei_body.append(' switch (infoType) {')
240 ggei_body.append(' case VK_EXTENSION_INFO_TYPE_COUNT:')
241 ggei_body.append(' *pDataSize = sizeof(uint32_t);')
242 ggei_body.append(' if (pData == NULL)')
243 ggei_body.append(' return VK_SUCCESS;')
244 ggei_body.append(' count = (uint32_t *) pData;')
245 ggei_body.append(' *count = LAYER_EXT_ARRAY_SIZE;')
246 ggei_body.append(' break;')
247 ggei_body.append(' case VK_EXTENSION_INFO_TYPE_PROPERTIES:')
248 ggei_body.append(' *pDataSize = sizeof(VkExtensionProperties);')
249 ggei_body.append(' if (pData == NULL)')
250 ggei_body.append(' return VK_SUCCESS;')
251 ggei_body.append(' if (extensionIndex >= LAYER_EXT_ARRAY_SIZE)')
252 ggei_body.append(' return VK_ERROR_INVALID_VALUE;')
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600253 ggei_body.append(' memcpy((VkExtensionProperties *) pData, &layerExts[extensionIndex], sizeof(VkExtensionProperties));')
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600254 ggei_body.append(' break;')
255 ggei_body.append(' default:')
256 ggei_body.append(' return VK_ERROR_INVALID_VALUE;')
257 ggei_body.append(' };')
258 ggei_body.append(' return VK_SUCCESS;')
259 ggei_body.append('}')
260 return "\n".join(ggei_body)
Jon Ashburn5f3960e2015-04-02 12:06:28 -0600261
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600262 def _gen_layer_get_physical_device_extension_info(self, layer="Generic"):
263 ggei_body = []
Jon Ashburn747f2b62015-06-18 15:02:58 -0600264 if layer == 'APIDump' or layer == 'Generic':
265 ggei_body.append('#define LAYER_DEV_EXT_ARRAY_SIZE 2')
266 ggei_body.append('static const VkExtensionProperties layerDevExts[LAYER_DEV_EXT_ARRAY_SIZE] = {')
267 ggei_body.append(' {')
268 ggei_body.append(' VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,')
269 ggei_body.append(' "%s",' % layer)
270 ggei_body.append(' 0x10,')
271 ggei_body.append(' "layer: %s",' % layer)
272 ggei_body.append(' },')
273 ggei_body.append(' {')
274 ggei_body.append(' VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,')
275 ggei_body.append(' VK_WSI_LUNARG_EXTENSION_NAME,')
276 ggei_body.append(' 0x10,')
277 ggei_body.append(' "layer: %s",' % layer)
278 ggei_body.append(' }')
279 ggei_body.append('};')
280 elif layer == 'ObjectTracker':
281 ggei_body.append('#define LAYER_DEV_EXT_ARRAY_SIZE 3')
282 ggei_body.append('static const VkExtensionProperties layerDevExts[LAYER_DEV_EXT_ARRAY_SIZE] = {')
283 ggei_body.append(' {')
284 ggei_body.append(' VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,')
285 ggei_body.append(' "%s",' % layer)
286 ggei_body.append(' 0x10,')
287 ggei_body.append(' "layer: %s",' % layer)
288 ggei_body.append(' },')
289 ggei_body.append(' {')
290 ggei_body.append(' VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,')
291 ggei_body.append(' VK_WSI_LUNARG_EXTENSION_NAME,')
292 ggei_body.append(' 0x10,')
293 ggei_body.append(' "layer: %s",' % layer)
294 ggei_body.append(' },')
295 ggei_body.append(' {')
296 ggei_body.append(' VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,')
297 ggei_body.append(' "Validation",')
298 ggei_body.append(' 0x10,')
299 ggei_body.append(' "layer: %s",' % layer)
300 ggei_body.append(' }')
301 ggei_body.append('};')
302 else:
303 ggei_body.append('#define LAYER_DEV_EXT_ARRAY_SIZE 2')
304 ggei_body.append('static const VkExtensionProperties layerDevExts[LAYER_DEV_EXT_ARRAY_SIZE] = {')
305 ggei_body.append(' {')
306 ggei_body.append(' VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,')
307 ggei_body.append(' "%s",' % layer)
308 ggei_body.append(' 0x10,')
309 ggei_body.append(' "layer: %s",' % layer)
310 ggei_body.append(' },')
311 ggei_body.append(' {')
312 ggei_body.append(' VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,')
313 ggei_body.append(' "Validation",')
314 ggei_body.append(' 0x10,')
315 ggei_body.append(' "layer: %s",' % layer)
316 ggei_body.append(' }')
317 ggei_body.append('};')
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600318 ggei_body.append('')
319 ggei_body.append('VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionInfo(VkPhysicalDevice physicalDevice, VkExtensionInfoType infoType, uint32_t extensionIndex, size_t* pDataSize, void* pData)')
320 ggei_body.append('{')
321 ggei_body.append(' uint32_t *count;')
322 ggei_body.append('')
323 ggei_body.append(' if (pDataSize == NULL)')
324 ggei_body.append(' return VK_ERROR_INVALID_POINTER;')
325 ggei_body.append('')
326 ggei_body.append(' switch (infoType) {')
327 ggei_body.append(' case VK_EXTENSION_INFO_TYPE_COUNT:')
328 ggei_body.append(' *pDataSize = sizeof(uint32_t);')
329 ggei_body.append(' if (pData == NULL)')
330 ggei_body.append(' return VK_SUCCESS;')
331 ggei_body.append(' count = (uint32_t *) pData;')
Jon Ashburn747f2b62015-06-18 15:02:58 -0600332 ggei_body.append(' *count = LAYER_DEV_EXT_ARRAY_SIZE;')
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600333 ggei_body.append(' break;')
334 ggei_body.append(' case VK_EXTENSION_INFO_TYPE_PROPERTIES:')
335 ggei_body.append(' *pDataSize = sizeof(VkExtensionProperties);')
336 ggei_body.append(' if (pData == NULL)')
337 ggei_body.append(' return VK_SUCCESS;')
Jon Ashburn747f2b62015-06-18 15:02:58 -0600338 ggei_body.append(' if (extensionIndex >= LAYER_DEV_EXT_ARRAY_SIZE)')
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600339 ggei_body.append(' return VK_ERROR_INVALID_VALUE;')
Jon Ashburn747f2b62015-06-18 15:02:58 -0600340 ggei_body.append(' memcpy((VkExtensionProperties *) pData, &layerDevExts[extensionIndex], sizeof(VkExtensionProperties));')
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600341 ggei_body.append(' break;')
342 ggei_body.append(' default:')
343 ggei_body.append(' return VK_ERROR_INVALID_VALUE;')
344 ggei_body.append(' };')
345 ggei_body.append(' return VK_SUCCESS;')
346 ggei_body.append('}')
347 return "\n".join(ggei_body)
348
Mike Stroyanbf237d72015-04-03 17:45:53 -0600349 def _generate_dispatch_entrypoints(self, qual=""):
Mike Stroyan938c2532015-04-03 13:58:35 -0600350 if qual:
351 qual += " "
352
Mike Stroyan938c2532015-04-03 13:58:35 -0600353 funcs = []
354 intercepted = []
355 for proto in self.protos:
Jon Ashburn8d1b0b52015-05-18 13:20:15 -0600356 if proto.name == "GetDeviceProcAddr" or proto.name == "GetInstanceProcAddr":
Jon Ashburn8fd08252015-05-28 16:25:02 -0600357 continue
Mike Stroyan70c05e82015-04-08 10:27:43 -0600358 else:
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600359 intercept = self.generate_intercept(proto, qual)
Mike Stroyan938c2532015-04-03 13:58:35 -0600360 if intercept is None:
361 # fill in default intercept for certain entrypoints
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600362 if 'DbgCreateMsgCallback' == proto.name:
363 intercept = self._gen_layer_dbg_create_msg_callback()
364 elif 'DbgDestroyMsgCallback' == proto.name:
365 intercept = self._gen_layer_dbg_destroy_msg_callback()
366 elif 'CreateDevice' == proto.name:
367 funcs.append('/* CreateDevice HERE */')
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600368 elif 'GetGlobalExtensionInfo' == proto.name:
Mike Stroyane90a2222015-05-11 13:44:24 -0600369 intercept = self._gen_layer_get_global_extension_info(self.layer_name)
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600370 elif 'GetPhysicalDeviceExtensionInfo' == proto.name:
371 intercept = self._gen_layer_get_physical_device_extension_info(self.layer_name)
Mike Stroyan938c2532015-04-03 13:58:35 -0600372 if intercept is not None:
373 funcs.append(intercept)
Jon Ashburn747f2b62015-06-18 15:02:58 -0600374 if not "WSI" in proto.name:
375 intercepted.append(proto)
Mike Stroyan938c2532015-04-03 13:58:35 -0600376
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600377 prefix="vk"
Mike Stroyan938c2532015-04-03 13:58:35 -0600378 lookups = []
379 for proto in intercepted:
Mike Stroyan938c2532015-04-03 13:58:35 -0600380 lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
381 lookups.append(" return (void*) %s%s;" %
382 (prefix, proto.name))
Mike Stroyan938c2532015-04-03 13:58:35 -0600383
384 # add customized layer_intercept_proc
385 body = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600386 body.append('%s' % self.lineinfo.get())
Mike Stroyan938c2532015-04-03 13:58:35 -0600387 body.append("static inline void* layer_intercept_proc(const char *name)")
388 body.append("{")
389 body.append(generate_get_proc_addr_check("name"))
390 body.append("")
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600391 body.append(" name += 2;")
Mike Stroyan938c2532015-04-03 13:58:35 -0600392 body.append(" %s" % "\n ".join(lookups))
393 body.append("")
394 body.append(" return NULL;")
395 body.append("}")
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600396 # add layer_intercept_instance_proc
397 lookups = []
398 for proto in self.protos:
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600399 if not proto_is_global(proto):
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600400 continue
401
402 if not proto in intercepted:
403 continue
404 lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
405 lookups.append(" return (void*) %s%s;" % (prefix, proto.name))
406
407 body.append("static inline void* layer_intercept_instance_proc(const char *name)")
408 body.append("{")
409 body.append(generate_get_proc_addr_check("name"))
410 body.append("")
411 body.append(" name += 2;")
412 body.append(" %s" % "\n ".join(lookups))
413 body.append("")
414 body.append(" return NULL;")
415 body.append("}")
416
Mike Stroyan938c2532015-04-03 13:58:35 -0600417 funcs.append("\n".join(body))
Mike Stroyan938c2532015-04-03 13:58:35 -0600418 return "\n\n".join(funcs)
419
Tobin Ehlisca915872014-11-18 11:28:33 -0700420 def _generate_extensions(self):
421 exts = []
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600422 exts.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600423 exts.append(self._gen_create_msg_callback())
424 exts.append(self._gen_destroy_msg_callback())
Tobin Ehlisb870cbb2015-04-15 07:46:12 -0600425 return "\n".join(exts)
426
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600427 def _generate_layer_gpa_function(self, extensions=[], instance_extensions=[]):
Jon Ashburnbacb0f52015-04-06 10:58:22 -0600428 func_body = []
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600429#
430# New style fo GPA Functions for the new layer_data/layer_logging changes
431#
432 if self.layer_name == 'ObjectTracker':
433 func_body.append("VK_LAYER_EXPORT void* VKAPI vkGetDeviceProcAddr(VkDevice device, const char* funcName)\n"
434 "{\n"
435 " void* addr;\n"
436 " if (device == VK_NULL_HANDLE) {\n"
437 " return NULL;\n"
438 " }\n"
439 " /* loader uses this to force layer initialization; device object is wrapped */\n"
440 " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
441 " initDeviceTable(%s_device_table_map, (const VkBaseLayerObject *) device);\n"
442 " return (void *) vkGetDeviceProcAddr;\n"
443 " }\n\n"
444 " addr = layer_intercept_proc(funcName);\n"
445 " if (addr)\n"
446 " return addr;" % self.layer_name)
447 if 0 != len(extensions):
448 for (ext_enable, ext_list) in extensions:
449 extra_space = ""
450 if 0 != len(ext_enable):
451 func_body.append(' if (deviceExtMap.size() == 0 || deviceExtMap[get_dispatch_table(ObjectTracker_device_table_map, device)].%s)' % ext_enable)
452 func_body.append(' {')
453 extra_space = " "
454 for ext_name in ext_list:
455 func_body.append(' %sif (!strcmp("%s", funcName))\n'
456 ' %sreturn reinterpret_cast<void*>(%s);' % (extra_space, ext_name, extra_space, ext_name))
457 if 0 != len(ext_enable):
458 func_body.append(' }\n')
459 func_body.append("\n if (get_dispatch_table(%s_device_table_map, device)->GetDeviceProcAddr == NULL)\n"
460 " return NULL;\n"
461 " return get_dispatch_table(%s_device_table_map, device)->GetDeviceProcAddr(device, funcName);\n"
462 "}\n" % (self.layer_name, self.layer_name))
463 func_body.append("VK_LAYER_EXPORT void* VKAPI vkGetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
464 "{\n"
465 " void* addr;\n"
466 " if (instance == VK_NULL_HANDLE) {\n"
467 " return NULL;\n"
468 " }\n"
469 " /* loader uses this to force layer initialization; instance object is wrapped */\n"
470 " if (!strcmp(\"vkGetInstanceProcAddr\", funcName)) {\n"
471 " initInstanceTable(%s_instance_table_map, (const VkBaseLayerObject *) instance);\n"
472 " return (void *) vkGetInstanceProcAddr;\n"
473 " }\n\n"
474 " addr = layer_intercept_instance_proc(funcName);\n"
475 " if (addr) {\n"
476 " return addr;"
477 " }\n" % self.layer_name)
Jon Ashburnbacb0f52015-04-06 10:58:22 -0600478
Mark Lobodzinskifae78852015-06-23 11:35:12 -0600479 if 0 != len(instance_extensions):
480 for ext_name in instance_extensions:
481 func_body.append(" layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);\n"
482 " addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);\n"
483 " if (addr) {\n"
484 " return addr;\n"
485 " }\n"
486 " if (get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr == NULL) {\n"
487 " return NULL;\n"
488 " }\n"
489 " return get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr(instance, funcName);\n"
490 "}\n" % (self.layer_name, self.layer_name))
491 return "\n".join(func_body)
492 else:
493#
494# TODO:: Old-style GPA Functions -- no local storage, no new logging mechanism. Left for compatibility.
495#
496 func_body.append('%s' % self.lineinfo.get())
497 func_body.append("VK_LAYER_EXPORT void* VKAPI vkGetDeviceProcAddr(VkDevice device, const char* funcName)\n"
498 "{\n"
499 " void* addr;\n"
500 " if (device == VK_NULL_HANDLE) {\n"
501 " return NULL;\n"
502 " }\n"
503 " loader_platform_thread_once(&initOnce, init%s);\n\n"
504 " /* loader uses this to force layer initialization; device object is wrapped */\n"
505 " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
506 " initDeviceTable((const VkBaseLayerObject *) device);\n"
507 " return (void *) vkGetDeviceProcAddr;\n"
508 " }\n\n"
509 " addr = layer_intercept_proc(funcName);\n"
510 " if (addr)\n"
511 " return addr;" % self.layer_name)
512 func_body.append('')
513 func_body.append(' VkLayerDispatchTable *pDisp = device_dispatch_table(device);')
514 if 0 != len(extensions):
515 extra_space = ""
516 for (ext_enable, ext_list) in extensions:
517 if 0 != len(ext_enable):
518 func_body.append(' if (deviceExtMap.size() == 0 || deviceExtMap[pDisp].%s)' % ext_enable)
519 func_body.append(' {')
520 extra_space = " "
521 for ext_name in ext_list:
522 func_body.append(' %sif (!strcmp("%s", funcName))\n'
523 ' return reinterpret_cast<void*>(%s);' % (extra_space, ext_name, ext_name))
524 if 0 != len(ext_enable):
525 func_body.append(' }')
526 func_body.append('%s' % self.lineinfo.get())
527 func_body.append(" {\n"
528 " if (pDisp->GetDeviceProcAddr == NULL)\n"
529 " return NULL;\n"
530 " return pDisp->GetDeviceProcAddr(device, funcName);\n"
531 " }\n"
532 "}\n")
533 func_body.append("VK_LAYER_EXPORT void* VKAPI vkGetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
534 "{\n"
535 " void* addr;\n"
536 " if (instance == VK_NULL_HANDLE) {\n"
537 " return NULL;\n"
538 " }\n"
539 " loader_platform_thread_once(&initOnce, init%s);\n\n"
540 " /* loader uses this to force layer initialization; instance object is wrapped */\n"
541 " if (!strcmp(\"vkGetInstanceProcAddr\", funcName)) {\n"
542 " initInstanceTable((const VkBaseLayerObject *) instance);\n"
543 " return (void *) vkGetInstanceProcAddr;\n"
544 " }\n\n"
545 " addr = layer_intercept_instance_proc(funcName);\n"
546 " if (addr)\n"
547 " return addr;" % self.layer_name)
548 if 0 != len(instance_extensions):
549 for ext_name in instance_extensions:
550 func_body.append(" {\n"
551 " void *fptr;\n"
552 " fptr = %s(funcName);\n"
553 " if (fptr) return fptr;\n"
554 " }\n" % ext_name)
555 func_body.append(" VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(instance);\n"
556 " if (pTable->GetInstanceProcAddr == NULL)\n"
557 " return NULL;\n"
558 " return pTable->GetInstanceProcAddr(instance, funcName);\n"
559 "}\n")
560 return "\n".join(func_body)
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600561
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600562
Mike Stroyaned238bb2015-05-15 08:50:57 -0600563 def _generate_layer_initialization(self, init_opts=False, prefix='vk', lockname=None, condname=None):
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600564 func_body = ["#include \"vk_dispatch_table_helper.h\""]
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600565 func_body.append('%s' % self.lineinfo.get())
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700566 func_body.append('static void init%s(void)\n'
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600567 '{\n' % self.layer_name)
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700568 if init_opts:
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600569 func_body.append('%s' % self.lineinfo.get())
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700570 func_body.append(' const char *strOpt;')
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600571 func_body.append(' // initialize %s options' % self.layer_name)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600572 func_body.append(' getLayerOptionEnum("%sReportLevel", (uint32_t *) &g_reportFlags);' % self.layer_name)
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600573 func_body.append(' g_actionIsDefault = getLayerOptionEnum("%sDebugAction", (uint32_t *) &g_debugAction);' % self.layer_name)
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700574 func_body.append('')
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600575 func_body.append(' if (g_debugAction & VK_DBG_LAYER_ACTION_LOG_MSG)')
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700576 func_body.append(' {')
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600577 func_body.append(' strOpt = getLayerOption("%sLogFilename");' % self.layer_name)
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700578 func_body.append(' if (strOpt)')
579 func_body.append(' {')
580 func_body.append(' g_logFile = fopen(strOpt, "w");')
581 func_body.append(' }')
582 func_body.append(' if (g_logFile == NULL)')
583 func_body.append(' g_logFile = stdout;')
584 func_body.append(' }')
585 func_body.append('')
Tobin Ehlis36f1b462015-02-23 14:09:16 -0700586 if lockname is not None:
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600587 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlis36f1b462015-02-23 14:09:16 -0700588 func_body.append(" if (!%sLockInitialized)" % lockname)
589 func_body.append(" {")
590 func_body.append(" // TODO/TBD: Need to delete this mutex sometime. How???")
591 func_body.append(" loader_platform_thread_create_mutex(&%sLock);" % lockname)
Mike Stroyaned238bb2015-05-15 08:50:57 -0600592 if condname is not None:
593 func_body.append(" loader_platform_thread_init_cond(&%sCond);" % condname)
Tobin Ehlis36f1b462015-02-23 14:09:16 -0700594 func_body.append(" %sLockInitialized = 1;" % lockname)
595 func_body.append(" }")
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600596 func_body.append("}\n")
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -0600597 func_body.append('')
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600598 return "\n".join(func_body)
599
600class LayerFuncsSubcommand(Subcommand):
601 def generate_header(self):
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600602 return '#include <vkLayer.h>\n#include "loader.h"'
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600603
604 def generate_body(self):
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600605 return self._generate_dispatch_entrypoints("static")
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600606
607class LayerDispatchSubcommand(Subcommand):
608 def generate_header(self):
609 return '#include "layer_wrappers.h"'
610
611 def generate_body(self):
Jon Ashburnd6badbc2015-02-16 08:26:50 -0700612 return self._generate_layer_initialization()
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600613
614class GenericLayerSubcommand(Subcommand):
615 def generate_header(self):
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500616 gen_header = []
617 gen_header.append('#include <stdio.h>')
618 gen_header.append('#include <stdlib.h>')
619 gen_header.append('#include <string.h>')
620 gen_header.append('#include <unordered_map>')
621 gen_header.append('#include "loader_platform.h"')
622 gen_header.append('#include "vkLayer.h"')
623 gen_header.append('//The following is #included again to catch certain OS-specific functions being used:')
624 gen_header.append('')
625 gen_header.append('#include "loader_platform.h"')
626 gen_header.append('#include "layers_config.h"')
627 gen_header.append('#include "layers_msg.h"')
Jon Ashburn9eed2892015-06-01 10:02:09 -0600628 gen_header.append('#include "layers_table.h"')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500629 gen_header.append('')
630 gen_header.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
Jon Ashburn747f2b62015-06-18 15:02:58 -0600631 gen_header.append('struct devExts {')
632 gen_header.append(' bool wsi_lunarg_enabled;')
633 gen_header.append('};')
634 gen_header.append('static std::unordered_map<void *, struct devExts> deviceExtMap;')
635 gen_header.append('')
636 gen_header.append('static void createDeviceRegisterExtensions(const VkDeviceCreateInfo* pCreateInfo, VkDevice device)')
637 gen_header.append('{')
638 gen_header.append(' uint32_t i, ext_idx;')
639 gen_header.append(' VkLayerDispatchTable *pDisp = device_dispatch_table(device);')
640 gen_header.append(' deviceExtMap[pDisp].wsi_lunarg_enabled = false;')
641 gen_header.append(' for (i = 0; i < pCreateInfo->extensionCount; i++) {')
642 gen_header.append(' if (strcmp(pCreateInfo->pEnabledExtensions[i].name, VK_WSI_LUNARG_EXTENSION_NAME) == 0)')
643 gen_header.append(' deviceExtMap[pDisp].wsi_lunarg_enabled = true;')
644 gen_header.append('')
645 gen_header.append(' }')
646 gen_header.append('}')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500647 gen_header.append('')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500648 return "\n".join(gen_header)
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600649 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600650 if proto.name in [ 'GetGlobalExtensionInfo', 'GetPhysicalDeviceExtensionInfo' ]:
Mike Stroyan00087e62015-04-03 14:39:16 -0600651 # use default version
652 return None
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600653 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyan938c2532015-04-03 13:58:35 -0600654 ret_val = ''
655 stmt = ''
656 funcs = []
Jon Ashburn71836d92015-05-12 17:23:55 -0600657 table = ''
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600658 if proto_is_global(proto):
Jon Ashburn71836d92015-05-12 17:23:55 -0600659 table = 'Instance'
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600660 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan938c2532015-04-03 13:58:35 -0600661 if proto.ret != "void":
Jon Ashburnb0fbe912015-05-06 10:15:07 -0600662 ret_val = "%s result = " % proto.ret
Mike Stroyan938c2532015-04-03 13:58:35 -0600663 stmt = " return result;\n"
Jon Ashburn8ced4212015-05-22 12:01:50 -0600664 if proto.name == "CreateDevice":
Mike Stroyan938c2532015-04-03 13:58:35 -0600665 funcs.append('%s%s\n'
666 '{\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500667 ' char str[1024];\n'
668 ' sprintf(str, "At start of layered %s\\n");\n'
669 ' layerCbMsg(VK_DBG_REPORT_INFO_BIT,VK_OBJECT_TYPE_PHYSICAL_DEVICE, gpu, 0, 0, (char *) "GENERIC", (char *) str);\n'
670 ' %sinstance_dispatch_table(gpu)->%s;\n'
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600671 ' if (result == VK_SUCCESS) {\n'
672 ' enable_debug_report(pCreateInfo->extensionCount, pCreateInfo->pEnabledExtensions);\n'
Jon Ashburn747f2b62015-06-18 15:02:58 -0600673 ' createDeviceRegisterExtensions(pCreateInfo, *pDevice);\n'
Mike Stroyan938c2532015-04-03 13:58:35 -0600674 ' }\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500675 ' sprintf(str, "Completed layered %s\\n");\n'
676 ' layerCbMsg(VK_DBG_REPORT_INFO_BIT, VK_OBJECT_TYPE_PHYSICAL_DEVICE, gpu, 0, 0, (char *) "GENERIC", (char *) str);\n'
677 ' fflush(stdout);\n'
678 ' %s'
679 '}' % (qual, decl, proto.name, ret_val, proto.c_call(), proto.name, stmt))
680 elif proto.name == "DestroyDevice":
681 funcs.append('%s%s\n'
682 '{\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -0600683 ' dispatch_key key = get_dispatch_key(device);\n'
Jon Ashburn747f2b62015-06-18 15:02:58 -0600684 ' VkLayerDispatchTable *pDisp = device_dispatch_table(device);\n'
685 ' VkResult res = pDisp->DestroyDevice(device);\n'
686 ' deviceExtMap.erase(pDisp);\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -0600687 ' destroy_device_dispatch_table(key);\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500688 ' return res;\n'
689 '}\n' % (qual, decl))
690 elif proto.name == "DestroyInstance":
691 funcs.append('%s%s\n'
692 '{\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -0600693 ' dispatch_key key = get_dispatch_key(instance);\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500694 ' VkResult res = instance_dispatch_table(instance)->DestroyInstance(instance);\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -0600695 ' destroy_instance_dispatch_table(key);\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500696 ' return res;\n'
697 '}\n' % (qual, decl))
Jon Ashburn4d9f4652015-04-08 21:33:34 -0600698 else:
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500699 # CreateInstance needs to use the second parm instead of the first to set the correct dispatch table
700 dispatch_param = proto.params[0].name
701 # Must use 'instance' table for these APIs, 'device' table otherwise
702 table_type = ""
703 if proto_is_global(proto):
704 table_type = "instance"
705 else:
706 table_type = "device"
707 if 'CreateInstance' in proto.name:
708 dispatch_param = '*' + proto.params[1].name
Mike Stroyan938c2532015-04-03 13:58:35 -0600709 funcs.append('%s%s\n'
710 '{\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500711 ' %s%s_dispatch_table(%s)->%s;\n'
Mike Stroyan938c2532015-04-03 13:58:35 -0600712 '%s'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -0500713 '}' % (qual, decl, ret_val, table_type, dispatch_param, proto.c_call(), stmt))
Mike Stroyan938c2532015-04-03 13:58:35 -0600714 return "\n\n".join(funcs)
715
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600716 def generate_body(self):
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600717 self.layer_name = "Generic"
Jon Ashburn747f2b62015-06-18 15:02:58 -0600718 extensions=[('wsi_lunarg_enabled',
719 ['vkCreateSwapChainWSI', 'vkDestroySwapChainWSI',
720 'vkGetSwapChainInfoWSI', 'vkQueuePresentWSI'])]
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -0600721 body = [self._generate_layer_initialization(True),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600722 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600723 self._gen_create_msg_callback(),
724 self._gen_destroy_msg_callback(),
Jon Ashburn747f2b62015-06-18 15:02:58 -0600725 self._generate_layer_gpa_function(extensions)]
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600726
727 return "\n\n".join(body)
728
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600729class APIDumpSubcommand(Subcommand):
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600730 def generate_header(self):
Tobin Ehlisd009bae2014-11-24 15:46:55 -0700731 header_txt = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600732 header_txt.append('%s' % self.lineinfo.get())
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600733 header_txt.append('#include <fstream>')
734 header_txt.append('#include <iostream>')
735 header_txt.append('#include <string>')
Jon Ashburn747f2b62015-06-18 15:02:58 -0600736 header_txt.append('#include <string.h>')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600737 header_txt.append('')
738 header_txt.append('static std::ofstream fileStream;')
739 header_txt.append('static std::string fileName = "vk_apidump.txt";')
740 header_txt.append('std::ostream* outputStream = NULL;')
741 header_txt.append('void ConfigureOutputStream(bool writeToFile, bool flushAfterWrite)')
742 header_txt.append('{')
743 header_txt.append(' if(writeToFile)')
744 header_txt.append(' {')
745 header_txt.append(' fileStream.open(fileName);')
746 header_txt.append(' outputStream = &fileStream;')
747 header_txt.append(' }')
748 header_txt.append(' else')
749 header_txt.append(' {')
750 header_txt.append(' outputStream = &std::cout;')
751 header_txt.append(' }')
752 header_txt.append('')
753 header_txt.append(' if(flushAfterWrite)')
754 header_txt.append(' {')
755 header_txt.append(' outputStream->sync_with_stdio(true);')
756 header_txt.append(' }')
757 header_txt.append(' else')
758 header_txt.append(' {')
759 header_txt.append(' outputStream->sync_with_stdio(false);')
760 header_txt.append(' }')
761 header_txt.append('}')
762 header_txt.append('')
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600763 header_txt.append('%s' % self.lineinfo.get())
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700764 header_txt.append('#include "loader_platform.h"')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600765 header_txt.append('#include "vkLayer.h"')
766 header_txt.append('#include "vk_struct_string_helper_cpp.h"')
Jon Ashburn9eed2892015-06-01 10:02:09 -0600767 header_txt.append('#include "layers_table.h"')
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -0500768 header_txt.append('#include <unordered_map>')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600769 header_txt.append('')
Ian Elliott655cad72015-02-12 17:08:34 -0700770 header_txt.append('// The following is #included again to catch certain OS-specific functions being used:')
771 header_txt.append('#include "loader_platform.h"')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600772 header_txt.append('')
Jon Ashburnbacb0f52015-04-06 10:58:22 -0600773 header_txt.append('static VkBaseLayerObject *pCurObj;')
Tobin Ehlisa2b199c2015-04-27 17:30:04 -0600774 header_txt.append('static bool g_APIDumpDetailed = true;')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600775 header_txt.append('')
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -0600776 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -0500777 header_txt.append('')
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700778 header_txt.append('static int printLockInitialized = 0;')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600779 header_txt.append('static loader_platform_thread_mutex printLock;')
780 header_txt.append('')
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600781 header_txt.append('%s' % self.lineinfo.get())
Tobin Ehlisd009bae2014-11-24 15:46:55 -0700782 header_txt.append('#define MAX_TID 513')
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700783 header_txt.append('static loader_platform_thread_id tidMapping[MAX_TID] = {0};')
Tobin Ehlisd009bae2014-11-24 15:46:55 -0700784 header_txt.append('static uint32_t maxTID = 0;')
785 header_txt.append('// Map actual TID to an index value and return that index')
786 header_txt.append('// This keeps TIDs in range from 0-MAX_TID and simplifies compares between runs')
787 header_txt.append('static uint32_t getTIDIndex() {')
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700788 header_txt.append(' loader_platform_thread_id tid = loader_platform_get_thread_id();')
Tobin Ehlisd009bae2014-11-24 15:46:55 -0700789 header_txt.append(' for (uint32_t i = 0; i < maxTID; i++) {')
790 header_txt.append(' if (tid == tidMapping[i])')
791 header_txt.append(' return i;')
792 header_txt.append(' }')
793 header_txt.append(" // Don't yet have mapping, set it and return newly set index")
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700794 header_txt.append(' uint32_t retVal = (uint32_t) maxTID;')
Tobin Ehlisd009bae2014-11-24 15:46:55 -0700795 header_txt.append(' tidMapping[maxTID++] = tid;')
796 header_txt.append(' assert(maxTID < MAX_TID);')
797 header_txt.append(' return retVal;')
798 header_txt.append('}')
Jon Ashburn747f2b62015-06-18 15:02:58 -0600799 header_txt.append('struct devExts {')
800 header_txt.append(' bool wsi_lunarg_enabled;')
801 header_txt.append('};')
802 header_txt.append('')
803 header_txt.append('static std::unordered_map<void *, struct devExts> deviceExtMap;')
804 header_txt.append('')
805 header_txt.append('static void createDeviceRegisterExtensions(const VkDeviceCreateInfo* pCreateInfo, VkDevice device)')
806 header_txt.append('{')
807 header_txt.append(' uint32_t i, ext_idx;')
808 header_txt.append(' VkLayerDispatchTable *pDisp = device_dispatch_table(device);')
809 header_txt.append(' deviceExtMap[pDisp].wsi_lunarg_enabled = false;')
810 header_txt.append(' for (i = 0; i < pCreateInfo->extensionCount; i++) {')
811 header_txt.append(' if (strcmp(pCreateInfo->pEnabledExtensions[i].name, VK_WSI_LUNARG_EXTENSION_NAME) == 0)')
812 header_txt.append(' deviceExtMap[pDisp].wsi_lunarg_enabled = true;')
813 header_txt.append('')
814 header_txt.append(' }')
815 header_txt.append('}')
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -0500816 header_txt.append('')
Tobin Ehlisd009bae2014-11-24 15:46:55 -0700817 return "\n".join(header_txt)
Tobin Ehlis12076fc2014-10-22 09:06:33 -0600818
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600819 def generate_init(self):
820 func_body = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600821 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600822 func_body.append('#include "vk_dispatch_table_helper.h"')
823 func_body.append('#include "layers_config.h"')
824 func_body.append('')
825 func_body.append('static void init%s(void)' % self.layer_name)
826 func_body.append('{')
827 func_body.append(' using namespace StreamControl;')
828 func_body.append('')
Tobin Ehlisa2b199c2015-04-27 17:30:04 -0600829 func_body.append(' char const*const detailedStr = getLayerOption("APIDumpDetailed");')
830 func_body.append(' if(detailedStr != NULL)')
831 func_body.append(' {')
832 func_body.append(' if(strcmp(detailedStr, "TRUE") == 0)')
833 func_body.append(' {')
834 func_body.append(' g_APIDumpDetailed = true;')
835 func_body.append(' }')
836 func_body.append(' else if(strcmp(detailedStr, "FALSE") == 0)')
837 func_body.append(' {')
838 func_body.append(' g_APIDumpDetailed = false;')
839 func_body.append(' }')
840 func_body.append(' }')
841 func_body.append('')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600842 func_body.append(' char const*const writeToFileStr = getLayerOption("APIDumpFile");')
843 func_body.append(' bool writeToFile = false;')
844 func_body.append(' if(writeToFileStr != NULL)')
845 func_body.append(' {')
846 func_body.append(' if(strcmp(writeToFileStr, "TRUE") == 0)')
847 func_body.append(' {')
848 func_body.append(' writeToFile = true;')
849 func_body.append(' }')
850 func_body.append(' else if(strcmp(writeToFileStr, "FALSE") == 0)')
851 func_body.append(' {')
852 func_body.append(' writeToFile = false;')
853 func_body.append(' }')
854 func_body.append(' }')
855 func_body.append('')
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600856 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600857 func_body.append(' char const*const noAddrStr = getLayerOption("APIDumpNoAddr");')
858 func_body.append(' if(noAddrStr != NULL)')
859 func_body.append(' {')
860 func_body.append(' if(strcmp(noAddrStr, "FALSE") == 0)')
861 func_body.append(' {')
862 func_body.append(' StreamControl::writeAddress = true;')
863 func_body.append(' }')
864 func_body.append(' else if(strcmp(noAddrStr, "TRUE") == 0)')
865 func_body.append(' {')
866 func_body.append(' StreamControl::writeAddress = false;')
867 func_body.append(' }')
868 func_body.append(' }')
869 func_body.append('')
870 func_body.append(' char const*const flushAfterWriteStr = getLayerOption("APIDumpFlush");')
871 func_body.append(' bool flushAfterWrite = false;')
872 func_body.append(' if(flushAfterWriteStr != NULL)')
873 func_body.append(' {')
874 func_body.append(' if(strcmp(flushAfterWriteStr, "TRUE") == 0)')
875 func_body.append(' {')
876 func_body.append(' flushAfterWrite = true;')
877 func_body.append(' }')
878 func_body.append(' else if(strcmp(flushAfterWriteStr, "FALSE") == 0)')
879 func_body.append(' {')
880 func_body.append(' flushAfterWrite = false;')
881 func_body.append(' }')
882 func_body.append(' }')
883 func_body.append('')
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600884 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600885 func_body.append(' ConfigureOutputStream(writeToFile, flushAfterWrite);')
886 func_body.append('')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600887 func_body.append(' if (!printLockInitialized)')
888 func_body.append(' {')
889 func_body.append(' // TODO/TBD: Need to delete this mutex sometime. How???')
890 func_body.append(' loader_platform_thread_create_mutex(&printLock);')
891 func_body.append(' printLockInitialized = 1;')
892 func_body.append(' }')
893 func_body.append('}')
894 func_body.append('')
895 return "\n".join(func_body)
Tobin Ehlis99f88672015-01-10 12:42:41 -0700896
Mike Stroyanbf237d72015-04-03 17:45:53 -0600897 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600898 if proto.name in [ 'GetGlobalExtensionInfo', 'GetPhysicalDeviceExtensionInfo']:
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600899 return None
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600900 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyanbf237d72015-04-03 17:45:53 -0600901 ret_val = ''
902 stmt = ''
903 funcs = []
904 sp_param_dict = {} # Store 'index' for struct param to print, or an name of binding "Count" param for array to print
905 create_params = 0 # Num of params at end of function that are created and returned as output values
Chia-I Wuf8693382015-04-16 22:02:10 +0800906 if 'AllocDescriptorSets' in proto.name:
Mike Stroyanbf237d72015-04-03 17:45:53 -0600907 create_params = -2
908 elif 'Create' in proto.name or 'Alloc' in proto.name or 'MapMemory' in proto.name:
909 create_params = -1
910 if proto.ret != "void":
Jon Ashburnb0fbe912015-05-06 10:15:07 -0600911 ret_val = "%s result = " % proto.ret
Mike Stroyanbf237d72015-04-03 17:45:53 -0600912 stmt = " return result;\n"
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600913 f_open = 'loader_platform_thread_lock_mutex(&printLock);\n '
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600914 log_func = '%s\n' % self.lineinfo.get()
915 log_func += ' if (StreamControl::writeAddress == true) {'
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600916 log_func += '\n (*outputStream) << "t{" << getTIDIndex() << "} vk%s(' % proto.name
917 log_func_no_addr = '\n (*outputStream) << "t{" << getTIDIndex() << "} vk%s(' % proto.name
918 f_close = '\n loader_platform_thread_unlock_mutex(&printLock);'
Mike Stroyanbf237d72015-04-03 17:45:53 -0600919 pindex = 0
920 prev_count_name = ''
921 for p in proto.params:
922 cp = False
923 if 0 != create_params:
924 # If this is any of the N last params of the func, treat as output
925 for y in range(-1, create_params-1, -1):
926 if p.name == proto.params[y].name:
927 cp = True
928 (pft, pfi) = self._get_printf_params(p.ty, p.name, cp, cpp=True)
Mike Stroyanbf237d72015-04-03 17:45:53 -0600929 log_func += '%s = " << %s << ", ' % (p.name, pfi)
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600930 if "%p" == pft:
931 log_func_no_addr += '%s = address, ' % (p.name)
932 else:
933 log_func_no_addr += '%s = " << %s << ", ' % (p.name, pfi)
Tobin Ehlis08541742015-04-16 15:56:11 -0600934 if prev_count_name != '' and (prev_count_name.replace('Count', '')[1:] in p.name):
Mike Stroyanbf237d72015-04-03 17:45:53 -0600935 sp_param_dict[pindex] = prev_count_name
Tobin Ehlis08541742015-04-16 15:56:11 -0600936 prev_count_name = ''
Mike Stroyanbf237d72015-04-03 17:45:53 -0600937 elif 'pDescriptorSets' == p.name and proto.params[-1].name == 'pCount':
938 sp_param_dict[pindex] = '*pCount'
Chia-I Wuf8693382015-04-16 22:02:10 +0800939 elif vk_helper.is_type(p.ty.strip('*').replace('const ', ''), 'struct'):
Mike Stroyanbf237d72015-04-03 17:45:53 -0600940 sp_param_dict[pindex] = 'index'
Mike Stroyanbf237d72015-04-03 17:45:53 -0600941 if p.name.endswith('Count'):
942 if '*' in p.ty:
943 prev_count_name = "*%s" % p.name
944 else:
945 prev_count_name = p.name
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600946 pindex += 1
Mike Stroyanbf237d72015-04-03 17:45:53 -0600947 log_func = log_func.strip(', ')
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600948 log_func_no_addr = log_func_no_addr.strip(', ')
Jon Ashburnb0fbe912015-05-06 10:15:07 -0600949 if proto.ret == "VkResult":
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600950 log_func += ') = " << string_VkResult((VkResult)result) << endl'
951 log_func_no_addr += ') = " << string_VkResult((VkResult)result) << endl'
Jon Ashburnb0fbe912015-05-06 10:15:07 -0600952 elif proto.ret == "void*":
953 log_func += ') = " << result << endl'
954 log_func_no_addr += ') = " << result << endl'
Mike Stroyanbf237d72015-04-03 17:45:53 -0600955 else:
956 log_func += ')\\n"'
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600957 log_func_no_addr += ')\\n"'
Mike Stroyanbf237d72015-04-03 17:45:53 -0600958 log_func += ';'
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600959 log_func_no_addr += ';'
960 log_func += '\n }\n else {%s;\n }' % log_func_no_addr;
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600961 log_func += '\n%s' % self.lineinfo.get()
Tobin Ehlisb870cbb2015-04-15 07:46:12 -0600962 #print("Proto %s has param_dict: %s" % (proto.name, sp_param_dict))
Mike Stroyanbf237d72015-04-03 17:45:53 -0600963 if len(sp_param_dict) > 0:
Tobin Ehlisa2b199c2015-04-27 17:30:04 -0600964 indent = ' '
965 log_func += '\n%sif (g_APIDumpDetailed) {' % indent
966 indent += ' '
Mike Stroyanbf237d72015-04-03 17:45:53 -0600967 i_decl = False
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600968 log_func += '\n%s' % self.lineinfo.get()
Tobin Ehlisa2b199c2015-04-27 17:30:04 -0600969 log_func += '\n%sstring tmp_str;' % indent
Mike Stroyanbf237d72015-04-03 17:45:53 -0600970 for sp_index in sp_param_dict:
Tobin Ehlisb870cbb2015-04-15 07:46:12 -0600971 #print("sp_index: %s" % str(sp_index))
Mike Stroyanbf237d72015-04-03 17:45:53 -0600972 if 'index' == sp_param_dict[sp_index]:
Courtney Goeltzenleuchter95487bc2015-04-14 18:48:46 -0600973 cis_print_func = 'vk_print_%s' % (proto.params[sp_index].ty.replace('const ', '').strip('*').lower())
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600974 local_name = proto.params[sp_index].name
975 if '*' not in proto.params[sp_index].ty:
976 local_name = '&%s' % proto.params[sp_index].name
Tobin Ehlis08fafd02015-06-12 12:49:01 -0600977 log_func += '\n%s' % self.lineinfo.get()
Tobin Ehlisa2b199c2015-04-27 17:30:04 -0600978 log_func += '\n%sif (%s) {' % (indent, local_name)
979 indent += ' '
980 log_func += '\n%stmp_str = %s(%s, " ");' % (indent, cis_print_func, local_name)
981 log_func += '\n%s(*outputStream) << " %s (" << %s << ")" << endl << tmp_str << endl;' % (indent, local_name, local_name)
982 indent = indent[4:]
983 log_func += '\n%s}' % (indent)
Mike Stroyanbf237d72015-04-03 17:45:53 -0600984 else: # We have a count value stored to iterate over an array
985 print_cast = ''
986 print_func = ''
Courtney Goeltzenleuchter95487bc2015-04-14 18:48:46 -0600987 if vk_helper.is_type(proto.params[sp_index].ty.strip('*').replace('const ', ''), 'struct'):
Mike Stroyanbf237d72015-04-03 17:45:53 -0600988 print_cast = '&'
Courtney Goeltzenleuchter95487bc2015-04-14 18:48:46 -0600989 print_func = 'vk_print_%s' % proto.params[sp_index].ty.replace('const ', '').strip('*').lower()
Mike Stroyanbf237d72015-04-03 17:45:53 -0600990 else:
Tobin Ehlise78dbd82015-04-09 09:19:36 -0600991 print_cast = ''
Mike Stroyanbf237d72015-04-03 17:45:53 -0600992 print_func = 'string_convert_helper'
993 #cis_print_func = 'tmp_str = string_convert_helper((void*)%s[i], " ");' % proto.params[sp_index].name
994 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 -0600995 if not i_decl:
Tobin Ehlisa2b199c2015-04-27 17:30:04 -0600996 log_func += '\n%suint32_t i;' % (indent)
Mike Stroyanbf237d72015-04-03 17:45:53 -0600997 i_decl = True
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600998 log_func += '\n%sif (%s) {' % (indent, proto.params[sp_index].name)
999 indent += ' '
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001000 log_func += '\n%s' % self.lineinfo.get()
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001001 log_func += '\n%sfor (i = 0; i < %s; i++) {' % (indent, sp_param_dict[sp_index])
1002 indent += ' '
1003 log_func += '\n%s%s' % (indent, cis_print_func)
Tobin Ehlis45a23a82015-04-28 10:58:20 -06001004 log_func += '\n%sif (StreamControl::writeAddress == true) {' % (indent)
1005 indent += ' '
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001006 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)
1007 indent = indent[4:]
Tobin Ehlis45a23a82015-04-28 10:58:20 -06001008 log_func += '\n%s} else {' % (indent)
1009 indent += ' '
1010 log_func += '\n%s(*outputStream) << " %s[" << i << "] (address)" << endl << " address" << endl;' % (indent, proto.params[sp_index].name)
1011 indent = indent[4:]
1012 log_func += '\n%s}' % (indent)
1013 indent = indent[4:]
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001014 log_func += '\n%s}' % (indent)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001015 indent = indent[4:]
1016 log_func += '\n%s}' % (indent)
Tobin Ehlisa2b199c2015-04-27 17:30:04 -06001017 indent = indent[4:]
1018 log_func += '\n%s}' % (indent)
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001019 table_type = ''
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001020 if proto_is_global(proto):
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001021 table_type = 'instance'
1022 else:
1023 table_type = 'device'
Jon Ashburn71836d92015-05-12 17:23:55 -06001024
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001025 if proto.name == "CreateInstance":
1026 dispatch_param = '*' + proto.params[1].name
1027 else:
1028 dispatch_param = proto.params[0].name
1029
Jon Ashburn747f2b62015-06-18 15:02:58 -06001030 if proto.name == "CreateDevice":
1031 funcs.append('%s%s\n'
1032 '{\n'
1033 ' using namespace StreamControl;\n'
1034 ' %s%s_dispatch_table(%s)->%s;\n'
1035 ' if (result == VK_SUCCESS)\n'
1036 ' createDeviceRegisterExtensions(pCreateInfo, *pDevice);\n'
1037 ' %s%s%s\n'
1038 '%s'
1039 '}' % (qual, decl, ret_val, table_type, dispatch_param, proto.c_call(), f_open, log_func, f_close, stmt))
1040 elif proto.name == "DestroyDevice":
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001041 funcs.append('%s%s\n'
1042 '{\n'
1043 ' using namespace StreamControl;\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001044 ' dispatch_key key = get_dispatch_key(device);\n'
Jon Ashburn747f2b62015-06-18 15:02:58 -06001045 ' VkLayerDispatchTable *pDisp = %s_dispatch_table(%s);\n'
1046 ' %spDisp->%s;\n'
1047 ' deviceExtMap.erase(pDisp);\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001048 ' destroy_device_dispatch_table(key);\n'
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001049 ' %s%s%s\n'
1050 '%s'
Jon Ashburn747f2b62015-06-18 15:02:58 -06001051 '}' % (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 -05001052 elif proto.name == "DestroyInstance":
1053 funcs.append('%s%s\n'
1054 '{\n'
1055 ' using namespace StreamControl;\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001056 ' dispatch_key key = get_dispatch_key(instance);\n'
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001057 ' %s%s_dispatch_table(%s)->%s;\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001058 ' destroy_instance_dispatch_table(key);\n'
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001059 ' %s%s%s\n'
1060 '%s'
1061 '}' % (qual, decl, ret_val, table_type, dispatch_param, proto.c_call(), f_open, log_func, f_close, stmt))
1062 else:
1063 funcs.append('%s%s\n'
1064 '{\n'
1065 ' using namespace StreamControl;\n'
1066 ' %s%s_dispatch_table(%s)->%s;\n'
Jon Ashburnbacb0f52015-04-06 10:58:22 -06001067 ' %s%s%s\n'
1068 '%s'
Mark Lobodzinski4c7ac0a2015-05-26 09:29:09 -05001069 '}' % (qual, decl, ret_val, table_type, dispatch_param, proto.c_call(), f_open, log_func, f_close, stmt))
Mike Stroyanbf237d72015-04-03 17:45:53 -06001070 return "\n\n".join(funcs)
1071
Tobin Ehlis99f88672015-01-10 12:42:41 -07001072 def generate_body(self):
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001073 self.layer_name = "APIDump"
Jon Ashburn747f2b62015-06-18 15:02:58 -06001074 extensions=[('wsi_lunarg_enabled',
1075 ['vkCreateSwapChainWSI', 'vkDestroySwapChainWSI',
1076 'vkGetSwapChainInfoWSI', 'vkQueuePresentWSI'])]
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001077 body = [self.generate_init(),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001078 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Jon Ashburn747f2b62015-06-18 15:02:58 -06001079 self._generate_layer_gpa_function(extensions)]
Tobin Ehlis99f88672015-01-10 12:42:41 -07001080 return "\n\n".join(body)
1081
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001082class ObjectTrackerSubcommand(Subcommand):
1083 def generate_header(self):
1084 header_txt = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001085 header_txt.append('%s' % self.lineinfo.get())
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001086 header_txt.append('#include <stdio.h>')
1087 header_txt.append('#include <stdlib.h>')
1088 header_txt.append('#include <string.h>')
1089 header_txt.append('#include <inttypes.h>')
1090 header_txt.append('')
1091 header_txt.append('#include "vulkan.h"')
1092 header_txt.append('#include "loader_platform.h"')
1093 header_txt.append('')
Tobin Ehlis803cc492015-06-08 17:36:28 -06001094 header_txt.append('#include <unordered_map>')
1095 header_txt.append('using namespace std;')
Ian Elliott655cad72015-02-12 17:08:34 -07001096 header_txt.append('// The following is #included again to catch certain OS-specific functions being used:')
1097 header_txt.append('#include "loader_platform.h"')
Jon Ashburn9a7f9a22015-02-17 11:03:12 -07001098 header_txt.append('#include "layers_config.h"')
Jon Ashburnd6badbc2015-02-16 08:26:50 -07001099 header_txt.append('#include "layers_msg.h"')
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001100 header_txt.append('#include "vk_debug_report_lunarg.h"')
Jon Ashburn9eed2892015-06-01 10:02:09 -06001101 header_txt.append('#include "layers_table.h"')
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001102 header_txt.append('#include "layer_data.h"')
1103 header_txt.append('#include "layer_logging.h"')
1104 header_txt.append('')
1105# NOTE: The non-autoGenerated code is in the object_track.h header file
1106 header_txt.append('#include "object_track.h"')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001107 header_txt.append('')
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -06001108 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001109 header_txt.append('')
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001110 return "\n".join(header_txt)
1111
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -06001112 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001113 if proto.name in [ 'DbgCreateMsgCallback', 'GetGlobalExtensionInfo', 'GetPhysicalDeviceExtensionInfo' ]:
Mike Stroyan00087e62015-04-03 14:39:16 -06001114 # use default version
1115 return None
Mark Lobodzinski7c75b852015-05-05 15:01:37 -05001116
1117 # Create map of object names to object type enums of the form VkName : VkObjectTypeName
Tobin Ehlisb870cbb2015-04-15 07:46:12 -06001118 obj_type_mapping = {base_t : base_t.replace("Vk", "VkObjectType") for base_t in vulkan.object_type_list}
Mark Lobodzinski7c75b852015-05-05 15:01:37 -05001119 # Convert object type enum names from UpperCamelCase to UPPER_CASE_WITH_UNDERSCORES
1120 for objectName, objectTypeEnum in obj_type_mapping.items():
1121 obj_type_mapping[objectName] = ucc_to_U_C_C(objectTypeEnum);
1122 # Command Buffer Object doesn't follow the rule.
1123 obj_type_mapping['VkCmdBuffer'] = "VK_OBJECT_TYPE_COMMAND_BUFFER"
Mike Stroyan00087e62015-04-03 14:39:16 -06001124
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001125 explicit_object_tracker_functions = [
1126 "CreateInstance",
1127 "DestroyInstance",
1128 "GetPhysicalDeviceInfo",
1129 "CreateDevice",
1130 "DestroyDevice",
1131 "GetDeviceQueue",
1132 "QueueSubmit",
1133 "DestroyObject",
1134 "GetObjectInfo",
1135 "QueueBindSparseImageMemory",
1136 "QueueBindSparseBufferMemory",
1137 "GetFenceStatus",
1138 "WaitForFences",
1139 "AllocDescriptorSets",
1140 "MapMemory",
1141 "UnmapMemory",
1142 "FreeMemory",
1143 "DestroySwapChainWSI"
1144 ]
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001145 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyan00087e62015-04-03 14:39:16 -06001146 param0_name = proto.params[0].name
Mark Lobodzinski48bd16d2015-05-08 09:12:28 -05001147 using_line = ''
Mike Stroyan00087e62015-04-03 14:39:16 -06001148 create_line = ''
Tobin Ehlis803cc492015-06-08 17:36:28 -06001149 object_params = []
1150 # TODO : Should also check through struct params & add any objects embedded in struct chains
1151 # TODO : A few of the skipped types are just "hard" cases that need some more work to support
1152 # Need to handle NULL fences on queue submit, binding null memory, and WSI Image objects
1153 for p in proto.params:
1154 if p.ty in vulkan.core.objects and p.ty not in ['VkPhysicalDevice', 'VkQueue', 'VkFence', 'VkImage', 'VkDeviceMemory']:
1155 object_params.append(p.name)
Mike Stroyan00087e62015-04-03 14:39:16 -06001156 funcs = []
Tobin Ehlis803cc492015-06-08 17:36:28 -06001157 mutex_unlock = False
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001158 if proto.name in explicit_object_tracker_functions:
Jon Ashburn4d9f4652015-04-08 21:33:34 -06001159 funcs.append('%s%s\n'
1160 '{\n'
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001161 ' return explicit_%s;\n'
1162 '}' % (qual, decl, proto.c_call()))
1163 return "".join(funcs)
Jon Ashburn4d9f4652015-04-08 21:33:34 -06001164 else:
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001165 if 'Create' in proto.name or 'Alloc' in proto.name:
1166 create_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
1167 create_line += ' if (result == VK_SUCCESS) {\n'
1168 create_line += ' create_obj(%s, *%s, %s);\n' % (param0_name, proto.params[-1].name, obj_type_mapping[proto.params[-1].ty.strip('*').replace('const ', '')])
1169 create_line += ' }\n'
1170 create_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
1171 if len(object_params) > 0:
1172 if not mutex_unlock:
1173 using_line += ' loader_platform_thread_lock_mutex(&objLock);\n'
1174 mutex_unlock = True
1175 for opn in object_params:
1176 using_line += ' validate_object(%s, %s);\n' % (param0_name, opn)
1177 if mutex_unlock:
1178 using_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
1179 ret_val = ''
1180 stmt = ''
1181 table = ''
1182 if proto.ret != "void":
1183 ret_val = "%s result = " % proto.ret
1184 stmt = " return result;\n"
1185
1186 dispatch_param = proto.params[0].name
1187 if 'CreateInstance' in proto.name:
1188 dispatch_param = '*' + proto.params[1].name
1189
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001190 # Must use 'instance' table for these APIs, 'device' table otherwise
1191 table_type = ""
1192 if proto_is_global(proto):
1193 table_type = "instance"
1194 else:
1195 table_type = "device"
Mike Stroyan00087e62015-04-03 14:39:16 -06001196 funcs.append('%s%s\n'
1197 '{\n'
1198 '%s'
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001199 ' %sget_dispatch_table(ObjectTracker_%s_table_map, %s)->%s;\n'
Mike Stroyan00087e62015-04-03 14:39:16 -06001200 '%s'
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001201 '%s'
1202 '}' % (qual, decl, using_line, ret_val, table_type, dispatch_param, proto.c_call(), create_line, stmt))
Mike Stroyan00087e62015-04-03 14:39:16 -06001203 return "\n\n".join(funcs)
1204
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001205 def generate_body(self):
Mike Stroyan3e3a1eb2015-04-03 17:13:23 -06001206 self.layer_name = "ObjectTracker"
Jon Ashburn747f2b62015-06-18 15:02:58 -06001207 extensions=[('wsi_lunarg_enabled',
1208 ['vkCreateSwapChainWSI', 'vkDestroySwapChainWSI',
1209 'vkGetSwapChainInfoWSI', 'vkQueuePresentWSI']),
1210 ('',
1211 ['objTrackGetObjectsCount', 'objTrackGetObjects',
1212 'objTrackGetObjectsOfTypeCount', 'objTrackGetObjectsOfType'])]
Mark Lobodzinskifae78852015-06-23 11:35:12 -06001213 body = [self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Tobin Ehlisca915872014-11-18 11:28:33 -07001214 self._generate_extensions(),
Jon Ashburn747f2b62015-06-18 15:02:58 -06001215 self._generate_layer_gpa_function(extensions,
Courtney Goeltzenleuchter17274172015-06-01 14:52:57 -06001216 instance_extensions=['msg_callback_get_proc_addr'])]
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001217 return "\n\n".join(body)
Courtney Goeltzenleuchterb412d212014-11-18 10:40:29 -07001218
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001219class ThreadingSubcommand(Subcommand):
1220 def generate_header(self):
1221 header_txt = []
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001222 header_txt.append('%s' % self.lineinfo.get())
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001223 header_txt.append('#include <stdio.h>')
1224 header_txt.append('#include <stdlib.h>')
1225 header_txt.append('#include <string.h>')
1226 header_txt.append('#include <unordered_map>')
1227 header_txt.append('#include "loader_platform.h"')
1228 header_txt.append('#include "vkLayer.h"')
1229 header_txt.append('#include "threading.h"')
1230 header_txt.append('#include "layers_config.h"')
1231 header_txt.append('#include "vk_enum_validate_helper.h"')
1232 header_txt.append('#include "vk_struct_validate_helper.h"')
1233 header_txt.append('//The following is #included again to catch certain OS-specific functions being used:')
1234 header_txt.append('#include "loader_platform.h"\n')
1235 header_txt.append('#include "layers_msg.h"\n')
Jon Ashburn9eed2892015-06-01 10:02:09 -06001236 header_txt.append('#include "layers_table.h"\n')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001237 header_txt.append('')
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001238 header_txt.append('')
1239 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
1240 header_txt.append('')
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001241 header_txt.append('using namespace std;')
1242 header_txt.append('static unordered_map<int, void*> proxy_objectsInUse;\n')
1243 header_txt.append('static unordered_map<VkObject, loader_platform_thread_id> objectsInUse;\n')
1244 header_txt.append('static int threadingLockInitialized = 0;')
1245 header_txt.append('static loader_platform_thread_mutex threadingLock;')
Mike Stroyaned238bb2015-05-15 08:50:57 -06001246 header_txt.append('static loader_platform_thread_cond threadingCond;')
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001247 header_txt.append('static int printLockInitialized = 0;')
1248 header_txt.append('static loader_platform_thread_mutex printLock;\n')
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001249 header_txt.append('%s' % self.lineinfo.get())
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001250 header_txt.append('static void useObject(VkObject object, const char* type)')
1251 header_txt.append('{')
1252 header_txt.append(' loader_platform_thread_id tid = loader_platform_get_thread_id();')
1253 header_txt.append(' loader_platform_thread_lock_mutex(&threadingLock);')
1254 header_txt.append(' if (objectsInUse.find(object) == objectsInUse.end()) {')
1255 header_txt.append(' objectsInUse[object] = tid;')
1256 header_txt.append(' } else {')
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001257 header_txt.append(' if (objectsInUse[object] != tid) {')
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001258 header_txt.append(' char str[1024];')
1259 header_txt.append(' sprintf(str, "THREADING ERROR : object of type %s is simultaneously used in thread %ld and thread %ld", type, objectsInUse[object], tid);')
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001260 header_txt.append(' layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, 0, 0, THREADING_CHECKER_MULTIPLE_THREADS, "THREADING", str);')
Mike Stroyaned238bb2015-05-15 08:50:57 -06001261 header_txt.append(' // Wait for thread-safe access to object')
1262 header_txt.append(' while (objectsInUse.find(object) != objectsInUse.end()) {')
1263 header_txt.append(' loader_platform_thread_cond_wait(&threadingCond, &threadingLock);')
1264 header_txt.append(' }')
1265 header_txt.append(' objectsInUse[object] = tid;')
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001266 header_txt.append(' } else {')
1267 header_txt.append(' char str[1024];')
1268 header_txt.append(' sprintf(str, "THREADING ERROR : object of type %s is recursively used in thread %ld", type, tid);')
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001269 header_txt.append(' layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, 0, 0, THREADING_CHECKER_SINGLE_THREAD_REUSE, "THREADING", str);')
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001270 header_txt.append(' }')
1271 header_txt.append(' }')
1272 header_txt.append(' loader_platform_thread_unlock_mutex(&threadingLock);')
1273 header_txt.append('}')
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001274 header_txt.append('%s' % self.lineinfo.get())
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001275 header_txt.append('static void finishUsingObject(VkObject object)')
1276 header_txt.append('{')
1277 header_txt.append(' // Object is no longer in use')
1278 header_txt.append(' loader_platform_thread_lock_mutex(&threadingLock);')
1279 header_txt.append(' objectsInUse.erase(object);')
Mike Stroyaned238bb2015-05-15 08:50:57 -06001280 header_txt.append(' loader_platform_thread_cond_broadcast(&threadingCond);')
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001281 header_txt.append(' loader_platform_thread_unlock_mutex(&threadingLock);')
1282 header_txt.append('}')
1283 return "\n".join(header_txt)
1284
1285 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001286 if proto.name in [ 'DbgCreateMsgCallback' ]:
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001287 # use default version
1288 return None
1289 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001290 thread_check_objects = [
1291 "VkQueue",
1292 "VkDeviceMemory",
1293 "VkObject",
1294 "VkBuffer",
1295 "VkImage",
1296 "VkDescriptorSet",
1297 "VkDescriptorPool",
1298 "VkCmdBuffer",
1299 "VkSemaphore"
1300 ]
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001301 ret_val = ''
1302 stmt = ''
1303 funcs = []
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001304 table = 'device'
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001305 if proto.ret != "void":
Jon Ashburnb0fbe912015-05-06 10:15:07 -06001306 ret_val = "%s result = " % proto.ret
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001307 stmt = " return result;\n"
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001308 if proto_is_global(proto):
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001309 table = 'instance'
Jon Ashburn71836d92015-05-12 17:23:55 -06001310
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001311 # Memory range calls are special in needed thread checking within structs
1312 if proto.name in ["FlushMappedMemoryRanges","InvalidateMappedMemoryRanges"]:
1313 funcs.append('%s%s\n'
1314 '{\n'
1315 ' for (int i=0; i<memRangeCount; i++) {\n'
1316 ' useObject((VkObject) pMemRanges[i].mem, "VkDeviceMemory");\n'
1317 ' }\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001318 ' %s%s_dispatch_table(%s)->%s;\n'
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001319 ' for (int i=0; i<memRangeCount; i++) {\n'
1320 ' finishUsingObject((VkObject) pMemRanges[i].mem);\n'
1321 ' }\n'
1322 '%s'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001323 '}' % (qual, decl, ret_val, table, proto.params[0].name, proto.c_call(), stmt))
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001324 return "\n".join(funcs)
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001325 # All functions that do a Get are thread safe
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001326 if 'Get' in proto.name:
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001327 return None
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001328 # All WSI functions are thread safe
1329 if 'WSI' in proto.name:
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001330 return None
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001331 # Initialize in early calls
1332 if proto.params[0].ty == "VkPhysicalDevice":
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001333 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001334 funcs.append('%s%s\n'
1335 '{\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001336 ' %s%s_dispatch_table(%s)->%s;\n'
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001337 '%s'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001338 '}' % (qual, decl, ret_val, table, proto.params[0].name, proto.c_call(), stmt))
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001339 return "\n".join(funcs)
1340 # Functions changing command buffers need thread safe use of first parameter
1341 if proto.params[0].ty == "VkCmdBuffer":
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001342 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001343 funcs.append('%s%s\n'
1344 '{\n'
1345 ' useObject((VkObject) %s, "%s");\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001346 ' %s%s_dispatch_table(%s)->%s;\n'
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001347 ' finishUsingObject((VkObject) %s);\n'
1348 '%s'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001349 '}' % (qual, decl, proto.params[0].name, proto.params[0].ty, ret_val, table, proto.params[0].name, proto.c_call(), proto.params[0].name, stmt))
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001350 return "\n".join(funcs)
1351 # Non-Cmd functions that do a Wait are thread safe
1352 if 'Wait' in proto.name:
1353 return None
1354 # Watch use of certain types of objects passed as any parameter
1355 checked_params = []
1356 for param in proto.params:
1357 if param.ty in thread_check_objects:
1358 checked_params.append(param)
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001359 if proto.name == "DestroyDevice":
1360 funcs.append('%s%s\n'
1361 '{\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001362 ' dispatch_key key = get_dispatch_key(device);\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001363 ' %s%s_dispatch_table(%s)->%s;\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001364 ' destroy_device_dispatch_table(key);\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001365 ' return result;\n'
1366 '}\n' % (qual, decl, ret_val, table, proto.params[0].name, proto.c_call()))
1367 return "\n".join(funcs);
1368 elif proto.name == "DestroyInstance":
1369 funcs.append('%s%s\n'
1370 '{\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001371 ' dispatch_key key = get_dispatch_key(instance);\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001372 ' %s%s_dispatch_table(%s)->%s;\n'
Courtney Goeltzenleuchter0daf2282015-06-13 21:22:12 -06001373 ' destroy_instance_dispatch_table(key);\n'
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001374 ' return result;\n'
1375 '}\n' % (qual, decl, ret_val, table, proto.params[0].name, proto.c_call()))
1376 return "\n".join(funcs);
Courtney Goeltzenleuchterd02a9642015-06-08 14:58:39 -06001377 elif proto.name == "CreateInstance":
1378 funcs.append('%s%s\n'
1379 '{\n'
1380 ' loader_platform_thread_once(&initOnce, initThreading);\n'
1381 '\n'
1382 ' %s %s_dispatch_table(*pInstance)->CreateInstance(pCreateInfo, pInstance);\n'
1383 '\n'
1384 ' if (result == VK_SUCCESS) {\n'
1385 ' enable_debug_report(pCreateInfo->extensionCount, pCreateInfo->pEnabledExtensions);\n'
1386 ' VkLayerInstanceDispatchTable *pTable = instance_dispatch_table(*pInstance);\n'
1387 ' debug_report_init_instance_extension_dispatch_table(\n'
1388 ' pTable,\n'
1389 ' pTable->GetInstanceProcAddr,\n'
1390 ' *pInstance);\n'
1391 ' }\n'
1392 ' return result;\n'
1393 '}\n' % (qual, decl, ret_val, table))
1394 return "\n".join(funcs);
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001395 if len(checked_params) == 0:
1396 return None
1397 # Surround call with useObject and finishUsingObject for each checked_param
Tobin Ehlis08fafd02015-06-12 12:49:01 -06001398 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001399 funcs.append('%s%s' % (qual, decl))
1400 funcs.append('{')
1401 for param in checked_params:
1402 funcs.append(' useObject((VkObject) %s, "%s");' % (param.name, param.ty))
Mark Lobodzinskifb5437a2015-05-22 14:15:36 -05001403 funcs.append(' %s%s_dispatch_table(%s)->%s;' % (ret_val, table, proto.params[0].name, proto.c_call()))
Mike Stroyan6ea73e42015-05-11 17:18:14 -06001404 for param in checked_params:
1405 funcs.append(' finishUsingObject((VkObject) %s);' % param.name)
1406 funcs.append('%s'
1407 '}' % stmt)
1408 return "\n".join(funcs)
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001409
1410 def generate_body(self):
1411 self.layer_name = "Threading"
Mike Stroyaned238bb2015-05-15 08:50:57 -06001412 body = [self._generate_layer_initialization(True, lockname='threading', condname='threading'),
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001413 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Courtney Goeltzenleuchter17274172015-06-01 14:52:57 -06001414 self._generate_layer_gpa_function(extensions=[],
1415 instance_extensions=['msg_callback_get_proc_addr']),
1416 self._gen_create_msg_callback(),
1417 self._gen_destroy_msg_callback()]
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001418 return "\n\n".join(body)
1419
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001420def main():
1421 subcommands = {
1422 "layer-funcs" : LayerFuncsSubcommand,
1423 "layer-dispatch" : LayerDispatchSubcommand,
Tobin Ehlisa363cfa2014-11-25 16:59:27 -07001424 "Generic" : GenericLayerSubcommand,
Tobin Ehlise78dbd82015-04-09 09:19:36 -06001425 "APIDump" : APIDumpSubcommand,
Tobin Ehlisa363cfa2014-11-25 16:59:27 -07001426 "ObjectTracker" : ObjectTrackerSubcommand,
Mike Stroyan3712d5c2015-04-02 11:59:05 -06001427 "Threading" : ThreadingSubcommand,
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001428 }
1429
Tobin Ehlis14ff0852014-12-17 17:44:50 -07001430 if len(sys.argv) < 3 or sys.argv[1] not in subcommands or not os.path.exists(sys.argv[2]):
1431 print("Usage: %s <subcommand> <input_header> [options]" % sys.argv[0])
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001432 print
Tobin Ehlis7e65d752015-01-15 17:51:52 -07001433 print("Available subcommands are: %s" % " ".join(subcommands))
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001434 exit(1)
1435
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001436 hfp = vk_helper.HeaderFileParser(sys.argv[2])
Tobin Ehlis14ff0852014-12-17 17:44:50 -07001437 hfp.parse()
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001438 vk_helper.enum_val_dict = hfp.get_enum_val_dict()
1439 vk_helper.enum_type_dict = hfp.get_enum_type_dict()
1440 vk_helper.struct_dict = hfp.get_struct_dict()
1441 vk_helper.typedef_fwd_dict = hfp.get_typedef_fwd_dict()
1442 vk_helper.typedef_rev_dict = hfp.get_typedef_rev_dict()
1443 vk_helper.types_dict = hfp.get_types_dict()
Tobin Ehlis14ff0852014-12-17 17:44:50 -07001444
Tobin Ehlis12076fc2014-10-22 09:06:33 -06001445 subcmd = subcommands[sys.argv[1]](sys.argv[2:])
1446 subcmd.run()
1447
1448if __name__ == "__main__":
1449 main()