blob: 7937266d13192af85e0dd530e792576c6aaff175 [file] [log] [blame]
Tobin Ehlis92dbf802014-10-22 09:06:33 -06001#!/usr/bin/env python3
2#
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06003# VK
Tobin Ehlis92dbf802014-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 Ehlis6cd06372014-12-17 17:44:50 -070029import os
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -050030import re
Tobin Ehlis92dbf802014-10-22 09:06:33 -060031
Courtney Goeltzenleuchtera8c06282015-04-14 14:55:44 -060032import vulkan
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060033import vk_helper
Tobin Ehlis92dbf802014-10-22 09:06:33 -060034
Mike Stroyan7c2efaa2015-04-03 13:58:35 -060035def generate_get_proc_addr_check(name):
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060036 return " if (!%s || %s[0] != 'v' || %s[1] != 'k')\n" \
37 " return NULL;" % ((name,) * 3)
Mike Stroyan7c2efaa2015-04-03 13:58:35 -060038
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -050039def ucc_to_U_C_C(CamelCase):
40 temp = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', CamelCase)
41 return re.sub('([a-z0-9])([A-Z])', r'\1_\2', temp).upper()
42
Tobin Ehlis92dbf802014-10-22 09:06:33 -060043class Subcommand(object):
44 def __init__(self, argv):
45 self.argv = argv
Courtney Goeltzenleuchtera8c06282015-04-14 14:55:44 -060046 self.headers = vulkan.headers
47 self.protos = vulkan.protos
Mike Stroyan3aecdb42015-04-03 17:13:23 -060048 self.no_addr = False
49 self.layer_name = ""
Tobin Ehlis92dbf802014-10-22 09:06:33 -060050
51 def run(self):
Tobin Ehlis92dbf802014-10-22 09:06:33 -060052 print(self.generate())
53
54 def generate(self):
55 copyright = self.generate_copyright()
56 header = self.generate_header()
57 body = self.generate_body()
58 footer = self.generate_footer()
59
60 contents = []
61 if copyright:
62 contents.append(copyright)
63 if header:
64 contents.append(header)
65 if body:
66 contents.append(body)
67 if footer:
68 contents.append(footer)
69
70 return "\n\n".join(contents)
71
72 def generate_copyright(self):
73 return """/* THIS FILE IS GENERATED. DO NOT EDIT. */
74
75/*
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060076 * Vulkan
Tobin Ehlis92dbf802014-10-22 09:06:33 -060077 *
78 * Copyright (C) 2014 LunarG, Inc.
79 *
80 * Permission is hereby granted, free of charge, to any person obtaining a
81 * copy of this software and associated documentation files (the "Software"),
82 * to deal in the Software without restriction, including without limitation
83 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
84 * and/or sell copies of the Software, and to permit persons to whom the
85 * Software is furnished to do so, subject to the following conditions:
86 *
87 * The above copyright notice and this permission notice shall be included
88 * in all copies or substantial portions of the Software.
89 *
90 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
91 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
92 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
93 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
94 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
95 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
96 * DEALINGS IN THE SOFTWARE.
97 */"""
98
99 def generate_header(self):
100 return "\n".join(["#include <" + h + ">" for h in self.headers])
101
102 def generate_body(self):
103 pass
104
105 def generate_footer(self):
106 pass
107
108 # Return set of printf '%' qualifier and input to that qualifier
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600109 def _get_printf_params(self, vk_type, name, output_param, cpp=False):
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600110 # TODO : Need ENUM and STRUCT checks here
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600111 if vk_helper.is_type(vk_type, 'enum'):#"_TYPE" in vk_type: # TODO : This should be generic ENUM check
Courtney Goeltzenleuchterddcb6192015-04-14 18:48:46 -0600112 return ("%s", "string_%s(%s)" % (vk_type.replace('const ', '').strip('*'), name))
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600113 if "char*" == vk_type:
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600114 return ("%s", name)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600115 if "uint64" in vk_type:
116 if '*' in vk_type:
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600117 return ("%lu", "*%s" % name)
118 return ("%lu", name)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600119 if "size" in vk_type:
120 if '*' in vk_type:
Chia-I Wu54ed0792014-12-27 14:14:50 +0800121 return ("%zu", "*%s" % name)
122 return ("%zu", name)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600123 if "float" in vk_type:
124 if '[' in vk_type: # handle array, current hard-coded to 4 (TODO: Make this dynamic)
Tobin Ehlis434db7c2015-01-10 12:42:41 -0700125 if cpp:
126 return ("[%i, %i, %i, %i]", '"[" << %s[0] << "," << %s[1] << "," << %s[2] << "," << %s[3] << "]"' % (name, name, name, name))
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600127 return ("[%f, %f, %f, %f]", "%s[0], %s[1], %s[2], %s[3]" % (name, name, name, name))
128 return ("%f", name)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600129 if "bool" in vk_type or 'xcb_randr_crtc_t' in vk_type:
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600130 return ("%u", name)
Tobin Ehlisf29da382015-04-15 07:46:12 -0600131 if True in [t in vk_type.lower() for t in ["int", "flags", "mask", "xcb_window_t"]]:
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600132 if '[' in vk_type: # handle array, current hard-coded to 4 (TODO: Make this dynamic)
Tobin Ehlis434db7c2015-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 Ehlis92dbf802014-10-22 09:06:33 -0600135 return ("[%i, %i, %i, %i]", "%s[0], %s[1], %s[2], %s[3]" % (name, name, name, name))
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600136 if '*' in vk_type:
Tobin Ehlis1336c8d2015-02-04 15:15:11 -0700137 if 'pUserData' == name:
138 return ("%i", "((pUserData == 0) ? 0 : *(pUserData))")
Tobin Ehlisa74d53a2015-04-17 13:26:33 -0600139 if 'const' in vk_type.lower():
140 return ("%p", "(void*)(%s)" % name)
Jon Ashburn1f7e2d72014-12-12 16:10:45 -0700141 return ("%i", "*(%s)" % name)
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600142 return ("%i", name)
Tobin Ehlis0a1e06d2014-11-11 17:28:22 -0700143 # TODO : This is special-cased as there's only one "format" param currently and it's nice to expand it
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600144 if "VkFormat" == vk_type:
Tobin Ehlis434db7c2015-01-10 12:42:41 -0700145 if cpp:
146 return ("%p", "&%s" % name)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600147 return ("{%s.channelFormat = %%s, %s.numericFormat = %%s}" % (name, name), "string_VK_CHANNEL_FORMAT(%s.channelFormat), string_VK_NUM_FORMAT(%s.numericFormat)" % (name, name))
Tobin Ehlisa554dc32014-11-19 15:52:46 -0700148 if output_param:
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600149 return ("%p", "(void*)*%s" % name)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600150 if vk_helper.is_type(vk_type, 'struct') and '*' not in vk_type:
Courtney Goeltzenleuchter9a1ded82015-04-03 16:35:32 -0600151 return ("%p", "(void*)(&%s)" % name)
Jon Ashburn1f7e2d72014-12-12 16:10:45 -0700152 return ("%p", "(void*)(%s)" % name)
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600153
Tobin Ehlisc54139f2014-12-17 08:01:59 -0700154 def _gen_layer_dbg_callback_register(self):
155 r_body = []
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600156 r_body.append('VK_LAYER_EXPORT VkResult VKAPI vkDbgRegisterMsgCallback(VkInstance instance, VK_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback, void* pUserData)')
Tobin Ehlisc54139f2014-12-17 08:01:59 -0700157 r_body.append('{')
158 r_body.append(' // This layer intercepts callbacks')
Mark Lobodzinski7d2d5ac2015-05-20 17:33:47 -0500159 if self.layer_name == "ObjectTracker" or self.layer_name == "Threading":
160 r_body.append(' VK_LAYER_DBG_FUNCTION_NODE *pNewDbgFuncNode = new VK_LAYER_DBG_FUNCTION_NODE;')
161 else:
162 r_body.append(' VK_LAYER_DBG_FUNCTION_NODE *pNewDbgFuncNode = (VK_LAYER_DBG_FUNCTION_NODE*)malloc(sizeof(VK_LAYER_DBG_FUNCTION_NODE));')
Tobin Ehlisc54139f2014-12-17 08:01:59 -0700163 r_body.append(' if (!pNewDbgFuncNode)')
Tony Barbour8205d902015-04-16 15:59:00 -0600164 r_body.append(' return VK_ERROR_OUT_OF_HOST_MEMORY;')
Tobin Ehlisc54139f2014-12-17 08:01:59 -0700165 r_body.append(' pNewDbgFuncNode->pfnMsgCallback = pfnMsgCallback;')
166 r_body.append(' pNewDbgFuncNode->pUserData = pUserData;')
Jon Ashburn21001f62015-02-16 08:26:50 -0700167 r_body.append(' pNewDbgFuncNode->pNext = g_pDbgFunctionHead;')
168 r_body.append(' g_pDbgFunctionHead = pNewDbgFuncNode;')
Jon Ashburne4722392015-03-03 15:07:15 -0700169 r_body.append(' // force callbacks if DebugAction hasn\'t been set already other than initial value')
Ian Elliottc9473d92015-03-05 12:28:53 -0700170 r_body.append(' if (g_actionIsDefault) {')
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600171 r_body.append(' g_debugAction = VK_DBG_LAYER_ACTION_CALLBACK;')
Ian Elliottc9473d92015-03-05 12:28:53 -0700172 r_body.append(' }')
Jon Ashburn52c1d732015-05-12 17:23:55 -0600173 r_body.append(' VkResult result = nextInstanceTable.DbgRegisterMsgCallback(instance, pfnMsgCallback, pUserData);')
Tobin Ehlisc54139f2014-12-17 08:01:59 -0700174 r_body.append(' return result;')
175 r_body.append('}')
176 return "\n".join(r_body)
177
178 def _gen_layer_dbg_callback_unregister(self):
179 ur_body = []
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600180 ur_body.append('VK_LAYER_EXPORT VkResult VKAPI vkDbgUnregisterMsgCallback(VkInstance instance, VK_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback)')
Tobin Ehlisc54139f2014-12-17 08:01:59 -0700181 ur_body.append('{')
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600182 ur_body.append(' VK_LAYER_DBG_FUNCTION_NODE *pTrav = g_pDbgFunctionHead;')
183 ur_body.append(' VK_LAYER_DBG_FUNCTION_NODE *pPrev = pTrav;')
Tobin Ehlisc54139f2014-12-17 08:01:59 -0700184 ur_body.append(' while (pTrav) {')
185 ur_body.append(' if (pTrav->pfnMsgCallback == pfnMsgCallback) {')
186 ur_body.append(' pPrev->pNext = pTrav->pNext;')
Jon Ashburn21001f62015-02-16 08:26:50 -0700187 ur_body.append(' if (g_pDbgFunctionHead == pTrav)')
188 ur_body.append(' g_pDbgFunctionHead = pTrav->pNext;')
Mark Lobodzinski7d2d5ac2015-05-20 17:33:47 -0500189 if self.layer_name == "ObjectTracker" or self.layer_name == "Threading":
190 ur_body.append(' delete pTrav;')
191 else:
192 ur_body.append(' free(pTrav);')
Tobin Ehlisc54139f2014-12-17 08:01:59 -0700193 ur_body.append(' break;')
194 ur_body.append(' }')
195 ur_body.append(' pPrev = pTrav;')
196 ur_body.append(' pTrav = pTrav->pNext;')
197 ur_body.append(' }')
Jon Ashburne4722392015-03-03 15:07:15 -0700198 ur_body.append(' if (g_pDbgFunctionHead == NULL)')
199 ur_body.append(' {')
200 ur_body.append(' if (g_actionIsDefault)')
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600201 ur_body.append(' g_debugAction = VK_DBG_LAYER_ACTION_LOG_MSG;')
Jon Ashburne4722392015-03-03 15:07:15 -0700202 ur_body.append(' else')
Mike Stroyanb326d2c2015-04-02 11:59:05 -0600203 ur_body.append(' g_debugAction = (VK_LAYER_DBG_ACTION)(g_debugAction & ~((uint32_t)VK_DBG_LAYER_ACTION_CALLBACK));')
Jon Ashburne4722392015-03-03 15:07:15 -0700204 ur_body.append(' }')
Jon Ashburn52c1d732015-05-12 17:23:55 -0600205 ur_body.append(' VkResult result = nextInstanceTable.DbgUnregisterMsgCallback(instance, pfnMsgCallback);')
Tobin Ehlisc54139f2014-12-17 08:01:59 -0700206 ur_body.append(' return result;')
207 ur_body.append('}')
208 return "\n".join(ur_body)
209
Jon Ashburneb2728b2015-04-10 14:33:07 -0600210 def _gen_layer_get_global_extension_info(self, layer="Generic"):
211 ggei_body = []
212 ggei_body.append('struct extProps {')
213 ggei_body.append(' uint32_t version;')
214 ggei_body.append(' const char * const name;')
215 ggei_body.append('};')
Jon Ashburnbdcd7562015-04-14 14:12:59 -0600216 if layer == 'ObjectTracker':
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -0500217 ggei_body.append('#define LAYER_EXT_ARRAY_SIZE 6')
Jon Ashburnbdcd7562015-04-14 14:12:59 -0600218 ggei_body.append('static const struct extProps layerExts[LAYER_EXT_ARRAY_SIZE] = {')
219 ggei_body.append(' // TODO what is the version?')
220 ggei_body.append(' {0x10, "%s"},' % layer)
221 ggei_body.append(' {0x10, "Validation"},')
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -0500222 ggei_body.append(' {0x10, "objTrackGetObjectsCount"},')
223 ggei_body.append(' {0x10, "objTrackGetObjects"},')
224 ggei_body.append(' {0x10, "objTrackGetObjectsOfTypeCount"},')
225 ggei_body.append(' {0x10, "objTrackGetObjectsOfType"}')
Jon Ashburnbdcd7562015-04-14 14:12:59 -0600226 ggei_body.append('};')
Tobin Ehlisa53add02015-04-15 17:19:18 -0600227 elif layer == 'Threading':
228 ggei_body.append('#define LAYER_EXT_ARRAY_SIZE 2')
229 ggei_body.append('static const struct extProps layerExts[LAYER_EXT_ARRAY_SIZE] = {')
230 ggei_body.append(' // TODO what is the version?')
231 ggei_body.append(' {0x10, "%s"},' % layer)
232 ggei_body.append(' {0x10, "Validation"},')
233 ggei_body.append('};')
Jon Ashburnbdcd7562015-04-14 14:12:59 -0600234 else:
235 ggei_body.append('#define LAYER_EXT_ARRAY_SIZE 1')
236 ggei_body.append('static const struct extProps layerExts[LAYER_EXT_ARRAY_SIZE] = {')
237 ggei_body.append(' // TODO what is the version?')
238 ggei_body.append(' {0x10, "%s"}' % layer)
239 ggei_body.append('};')
Jon Ashburneb2728b2015-04-10 14:33:07 -0600240 ggei_body.append('')
Mark Lobodzinski8bae7d42015-04-13 16:35:52 -0500241 ggei_body.append('VK_LAYER_EXPORT VkResult VKAPI vkGetGlobalExtensionInfo(VkExtensionInfoType infoType, uint32_t extensionIndex, size_t* pDataSize, void* pData)')
Jon Ashburneb2728b2015-04-10 14:33:07 -0600242 ggei_body.append('{')
243 ggei_body.append(' VkExtensionProperties *ext_props;')
244 ggei_body.append(' uint32_t *count;')
245 ggei_body.append('')
246 ggei_body.append(' if (pDataSize == NULL)')
247 ggei_body.append(' return VK_ERROR_INVALID_POINTER;')
248 ggei_body.append('')
249 ggei_body.append(' switch (infoType) {')
250 ggei_body.append(' case VK_EXTENSION_INFO_TYPE_COUNT:')
251 ggei_body.append(' *pDataSize = sizeof(uint32_t);')
252 ggei_body.append(' if (pData == NULL)')
253 ggei_body.append(' return VK_SUCCESS;')
254 ggei_body.append(' count = (uint32_t *) pData;')
255 ggei_body.append(' *count = LAYER_EXT_ARRAY_SIZE;')
256 ggei_body.append(' break;')
257 ggei_body.append(' case VK_EXTENSION_INFO_TYPE_PROPERTIES:')
258 ggei_body.append(' *pDataSize = sizeof(VkExtensionProperties);')
259 ggei_body.append(' if (pData == NULL)')
260 ggei_body.append(' return VK_SUCCESS;')
261 ggei_body.append(' if (extensionIndex >= LAYER_EXT_ARRAY_SIZE)')
262 ggei_body.append(' return VK_ERROR_INVALID_VALUE;')
263 ggei_body.append(' ext_props = (VkExtensionProperties *) pData;')
264 ggei_body.append(' ext_props->version = layerExts[extensionIndex].version;')
265 ggei_body.append(' strncpy(ext_props->extName, layerExts[extensionIndex].name,')
266 ggei_body.append(' VK_MAX_EXTENSION_NAME);')
267 ggei_body.append(" ext_props->extName[VK_MAX_EXTENSION_NAME - 1] = '\\0';")
268 ggei_body.append(' break;')
269 ggei_body.append(' default:')
270 ggei_body.append(' return VK_ERROR_INVALID_VALUE;')
271 ggei_body.append(' };')
272 ggei_body.append(' return VK_SUCCESS;')
273 ggei_body.append('}')
274 return "\n".join(ggei_body)
Jon Ashburn25566352015-04-02 12:06:28 -0600275
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600276 def _generate_dispatch_entrypoints(self, qual=""):
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600277 if qual:
278 qual += " "
279
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600280 funcs = []
281 intercepted = []
282 for proto in self.protos:
Jon Ashburn79b78ac2015-05-05 14:22:52 -0600283 if proto.name == "GetProcAddr" or proto.name == "GetInstanceProcAddr":
Mike Stroyan88f0ecf2015-04-08 10:27:43 -0600284 intercepted.append(proto)
285 else:
Mike Stroyan3aecdb42015-04-03 17:13:23 -0600286 intercept = self.generate_intercept(proto, qual)
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600287 if intercept is None:
288 # fill in default intercept for certain entrypoints
289 if 'DbgRegisterMsgCallback' == proto.name:
290 intercept = self._gen_layer_dbg_callback_register()
Jon Ashburn25566352015-04-02 12:06:28 -0600291 elif 'DbgUnregisterMsgCallback' == proto.name:
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600292 intercept = self._gen_layer_dbg_callback_unregister()
Jon Ashburneb2728b2015-04-10 14:33:07 -0600293 elif 'GetGlobalExtensionInfo' == proto.name:
Mike Stroyanc1490942015-05-11 13:44:24 -0600294 intercept = self._gen_layer_get_global_extension_info(self.layer_name)
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600295 if intercept is not None:
296 funcs.append(intercept)
297 intercepted.append(proto)
298
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600299 prefix="vk"
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600300 lookups = []
301 for proto in intercepted:
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600302 lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
303 lookups.append(" return (void*) %s%s;" %
304 (prefix, proto.name))
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600305
306 # add customized layer_intercept_proc
307 body = []
308 body.append("static inline void* layer_intercept_proc(const char *name)")
309 body.append("{")
310 body.append(generate_get_proc_addr_check("name"))
311 body.append("")
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600312 body.append(" name += 2;")
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600313 body.append(" %s" % "\n ".join(lookups))
314 body.append("")
315 body.append(" return NULL;")
316 body.append("}")
Jon Ashburn79b78ac2015-05-05 14:22:52 -0600317 # add layer_intercept_instance_proc
318 lookups = []
319 for proto in self.protos:
320 if proto.params[0].ty != "VkInstance" and proto.params[0].ty != "VkPhysicalDevice" and proto.name != "CreateInstance" and proto.name != "GetGlobalExtensionInfo":
321 continue
322
323 if not proto in intercepted:
324 continue
325 lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
326 lookups.append(" return (void*) %s%s;" % (prefix, proto.name))
327
328 body.append("static inline void* layer_intercept_instance_proc(const char *name)")
329 body.append("{")
330 body.append(generate_get_proc_addr_check("name"))
331 body.append("")
332 body.append(" name += 2;")
333 body.append(" %s" % "\n ".join(lookups))
334 body.append("")
335 body.append(" return NULL;")
336 body.append("}")
337
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600338 funcs.append("\n".join(body))
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600339 return "\n\n".join(funcs)
340
341
Tobin Ehlis3c26a542014-11-18 11:28:33 -0700342 def _generate_extensions(self):
343 exts = []
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -0500344 exts.append('uint64_t objTrackGetObjectsCount(void)')
Tobin Ehlis3c26a542014-11-18 11:28:33 -0700345 exts.append('{')
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -0500346 exts.append(' return numTotalObjs;')
Tobin Ehlis3c26a542014-11-18 11:28:33 -0700347 exts.append('}')
348 exts.append('')
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -0500349 exts.append('VkResult objTrackGetObjects(uint64_t objCount, OBJTRACK_NODE* pObjNodeArray)')
Tobin Ehlis3c26a542014-11-18 11:28:33 -0700350 exts.append('{')
351 exts.append(" // This bool flags if we're pulling all objs or just a single class of objs")
Tobin Ehlis3c26a542014-11-18 11:28:33 -0700352 exts.append(' // Check the count first thing')
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -0500353 exts.append(' uint64_t maxObjCount = numTotalObjs;')
Tobin Ehlis3c26a542014-11-18 11:28:33 -0700354 exts.append(' if (objCount > maxObjCount) {')
355 exts.append(' char str[1024];')
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -0500356 exts.append(' sprintf(str, "OBJ ERROR : Received objTrackGetObjects() request for %lu objs, but there are only %lu total objs", objCount, maxObjCount);')
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600357 exts.append(' layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, 0, 0, OBJTRACK_OBJCOUNT_MAX_EXCEEDED, "OBJTRACK", str);')
358 exts.append(' return VK_ERROR_INVALID_VALUE;')
Tobin Ehlis3c26a542014-11-18 11:28:33 -0700359 exts.append(' }')
Tobin Ehlis586aa012015-06-08 17:36:28 -0600360 exts.append(' auto it = objMap.begin();')
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -0600361 exts.append(' for (uint64_t i = 0; i < objCount; i++) {')
Tobin Ehlis586aa012015-06-08 17:36:28 -0600362 exts.append(' if (objMap.end() == it) {')
Tobin Ehlis3c26a542014-11-18 11:28:33 -0700363 exts.append(' char str[1024];')
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -0500364 exts.append(' sprintf(str, "OBJ INTERNAL ERROR : Ran out of objs! Should have %lu, but only copied %lu and not the requested %lu.", maxObjCount, i, objCount);')
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600365 exts.append(' layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, 0, 0, OBJTRACK_INTERNAL_ERROR, "OBJTRACK", str);')
366 exts.append(' return VK_ERROR_UNKNOWN;')
Tobin Ehlis3c26a542014-11-18 11:28:33 -0700367 exts.append(' }')
Tobin Ehlis586aa012015-06-08 17:36:28 -0600368 exts.append(' memcpy(&pObjNodeArray[i], it->second, sizeof(OBJTRACK_NODE));')
369 exts.append(' ++it;')
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -0500370 exts.append(' }')
371 exts.append(' return VK_SUCCESS;')
372 exts.append('}')
373 exts.append('uint64_t objTrackGetObjectsOfTypeCount(VkObjectType type)')
374 exts.append('{')
375 exts.append(' return numObjs[type];')
376 exts.append('}')
377 exts.append('')
378 exts.append('VkResult objTrackGetObjectsOfType(VkObjectType type, uint64_t objCount, OBJTRACK_NODE* pObjNodeArray)')
379 exts.append('{')
380 exts.append(' // Check the count first thing')
381 exts.append(' uint64_t maxObjCount = numObjs[type];')
382 exts.append(' if (objCount > maxObjCount) {')
383 exts.append(' char str[1024];')
384 exts.append(' sprintf(str, "OBJ ERROR : Received objTrackGetObjects() request for %lu objs, but there are only %lu objs of type %s", objCount, maxObjCount, string_from_vulkan_object_type(type));')
385 exts.append(' layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, 0, 0, OBJTRACK_OBJCOUNT_MAX_EXCEEDED, "OBJTRACK", str);')
386 exts.append(' return VK_ERROR_INVALID_VALUE;')
387 exts.append(' }')
Tobin Ehlis586aa012015-06-08 17:36:28 -0600388 exts.append(' auto it = objMap.begin();')
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -0500389 exts.append(' for (uint64_t i = 0; i < objCount; i++) {')
Tobin Ehlis586aa012015-06-08 17:36:28 -0600390 exts.append(' // Get next object of correct type')
391 exts.append(' while ((objMap.end() != it) && (it->second->objType != type))')
392 exts.append(' ++it;')
393 exts.append(' if (objMap.end() == it) {')
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -0500394 exts.append(' char str[1024];')
395 exts.append(' sprintf(str, "OBJ INTERNAL ERROR : Ran out of %s objs! Should have %lu, but only copied %lu and not the requested %lu.", string_from_vulkan_object_type(type), maxObjCount, i, objCount);')
396 exts.append(' layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, 0, 0, OBJTRACK_INTERNAL_ERROR, "OBJTRACK", str);')
397 exts.append(' return VK_ERROR_UNKNOWN;')
398 exts.append(' }')
Tobin Ehlis586aa012015-06-08 17:36:28 -0600399 exts.append(' memcpy(&pObjNodeArray[i], it->second, sizeof(OBJTRACK_NODE));')
Tobin Ehlis3c26a542014-11-18 11:28:33 -0700400 exts.append(' }')
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600401 exts.append(' return VK_SUCCESS;')
Tobin Ehlis3c26a542014-11-18 11:28:33 -0700402 exts.append('}')
Tobin Ehlisf29da382015-04-15 07:46:12 -0600403 return "\n".join(exts)
404
Jon Ashburn79b78ac2015-05-05 14:22:52 -0600405 def _generate_layer_gpa_function(self, extensions=[], instance_extensions=[]):
Jon Ashburn301c5f02015-04-06 10:58:22 -0600406 func_body = []
Tony Barbour8205d902015-04-16 15:59:00 -0600407 func_body.append("VK_LAYER_EXPORT void* VKAPI vkGetProcAddr(VkPhysicalDevice gpu, const char* funcName)\n"
Jon Ashburn301c5f02015-04-06 10:58:22 -0600408 "{\n"
409 " VkBaseLayerObject* gpuw = (VkBaseLayerObject *) gpu;\n"
410 " void* addr;\n"
Mike Stroyan230e6252015-04-17 12:36:38 -0600411 " if (gpu == VK_NULL_HANDLE)\n"
Jon Ashburn301c5f02015-04-06 10:58:22 -0600412 " return NULL;\n"
413 " pCurObj = gpuw;\n"
Jon Ashburnd9564002015-05-07 10:27:37 -0600414 " loader_platform_thread_once(&initOnce, init%s);\n\n"
415 " loader_platform_thread_once(&tabDeviceOnce, initDeviceTable);\n\n"
Jon Ashburn301c5f02015-04-06 10:58:22 -0600416 " addr = layer_intercept_proc(funcName);\n"
417 " if (addr)\n"
418 " return addr;" % self.layer_name)
419
Tobin Ehlis3c26a542014-11-18 11:28:33 -0700420 if 0 != len(extensions):
Mark Lobodzinski7d2d5ac2015-05-20 17:33:47 -0500421 cpp_prefix = ''
422 cpp_postfix = ''
423 if self.layer_name == 'ObjectTracker':
424 cpp_prefix = "reinterpret_cast<void*>("
425 cpp_postfix = ")"
Tobin Ehlis3c26a542014-11-18 11:28:33 -0700426 for ext_name in extensions:
Chia-I Wu7461fcf2014-12-27 15:16:07 +0800427 func_body.append(' else if (!strncmp("%s", funcName, sizeof("%s")))\n'
Mark Lobodzinski7d2d5ac2015-05-20 17:33:47 -0500428 ' return %s%s%s;' % (ext_name, ext_name, cpp_prefix, ext_name, cpp_postfix))
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600429 func_body.append(" else {\n"
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600430 " if (gpuw->pGPA == NULL)\n"
431 " return NULL;\n"
Jon Ashburn79b78ac2015-05-05 14:22:52 -0600432 " return gpuw->pGPA((VkObject)gpuw->nextObject, funcName);\n"
433 " }\n"
434 "}\n")
435 func_body.append("VK_LAYER_EXPORT void* VKAPI vkGetInstanceProcAddr(VkInstance inst, const char* funcName)\n"
436 "{\n"
437 " VkBaseLayerObject* instw = (VkBaseLayerObject *) inst;\n"
438 " void* addr;\n"
439 " if (inst == VK_NULL_HANDLE)\n"
440 " return NULL;\n"
Jon Ashburnd9564002015-05-07 10:27:37 -0600441 " pCurObj = instw;\n"
442 " loader_platform_thread_once(&initOnce, init%s);\n\n"
443 " loader_platform_thread_once(&tabInstanceOnce, initInstanceTable);\n\n"
Jon Ashburn79b78ac2015-05-05 14:22:52 -0600444 " addr = layer_intercept_instance_proc(funcName);\n"
445 " if (addr)\n"
446 " return addr;" % self.layer_name)
447
448 if 0 != len(instance_extensions):
449 for ext_name in instance_extensions:
450 func_body.append(' else if (!strcmp("%s", funcName))\n'
451 ' return %s;' % (ext_name, ext_name))
452 func_body.append(" else {\n"
453 " if (instw->pGPA == NULL)\n"
454 " return NULL;\n"
455 " return instw->pGPA((VkObject)instw->nextObject, funcName);\n"
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600456 " }\n"
457 "}\n")
458 return "\n".join(func_body)
459
Mike Stroyan354ed672015-05-15 08:50:57 -0600460 def _generate_layer_initialization(self, init_opts=False, prefix='vk', lockname=None, condname=None):
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600461 func_body = ["#include \"vk_dispatch_table_helper.h\""]
Jon Ashburn21001f62015-02-16 08:26:50 -0700462 func_body.append('static void init%s(void)\n'
Mike Stroyan3aecdb42015-04-03 17:13:23 -0600463 '{\n' % self.layer_name)
Jon Ashburn21001f62015-02-16 08:26:50 -0700464 if init_opts:
465 func_body.append(' const char *strOpt;')
Mike Stroyan3aecdb42015-04-03 17:13:23 -0600466 func_body.append(' // initialize %s options' % self.layer_name)
467 func_body.append(' getLayerOptionEnum("%sReportLevel", (uint32_t *) &g_reportingLevel);' % self.layer_name)
468 func_body.append(' g_actionIsDefault = getLayerOptionEnum("%sDebugAction", (uint32_t *) &g_debugAction);' % self.layer_name)
Jon Ashburn21001f62015-02-16 08:26:50 -0700469 func_body.append('')
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600470 func_body.append(' if (g_debugAction & VK_DBG_LAYER_ACTION_LOG_MSG)')
Jon Ashburn21001f62015-02-16 08:26:50 -0700471 func_body.append(' {')
Mike Stroyan3aecdb42015-04-03 17:13:23 -0600472 func_body.append(' strOpt = getLayerOption("%sLogFilename");' % self.layer_name)
Jon Ashburn21001f62015-02-16 08:26:50 -0700473 func_body.append(' if (strOpt)')
474 func_body.append(' {')
475 func_body.append(' g_logFile = fopen(strOpt, "w");')
476 func_body.append(' }')
477 func_body.append(' if (g_logFile == NULL)')
478 func_body.append(' g_logFile = stdout;')
479 func_body.append(' }')
480 func_body.append('')
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600481
Tobin Ehlis84a8a9b2015-02-23 14:09:16 -0700482 if lockname is not None:
483 func_body.append(" if (!%sLockInitialized)" % lockname)
484 func_body.append(" {")
485 func_body.append(" // TODO/TBD: Need to delete this mutex sometime. How???")
486 func_body.append(" loader_platform_thread_create_mutex(&%sLock);" % lockname)
Mike Stroyan354ed672015-05-15 08:50:57 -0600487 if condname is not None:
488 func_body.append(" loader_platform_thread_init_cond(&%sCond);" % condname)
Tobin Ehlis84a8a9b2015-02-23 14:09:16 -0700489 func_body.append(" %sLockInitialized = 1;" % lockname)
490 func_body.append(" }")
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600491 func_body.append("}\n")
Jon Ashburnd9564002015-05-07 10:27:37 -0600492 func_body.append('')
493 func_body.append('static void initDeviceTable(void)')
494 func_body.append('{')
495 func_body.append(' PFN_vkGetProcAddr fpNextGPA;')
496 func_body.append(' fpNextGPA = (PFN_vkGetProcAddr) pCurObj->pGPA;')
497 func_body.append(' assert(fpNextGPA);')
498 func_body.append(' layer_initialize_dispatch_table(&nextTable, fpNextGPA, (VkPhysicalDevice) pCurObj->nextObject);')
499 func_body.append('}')
500 func_body.append('')
501 func_body.append('static void initInstanceTable(void)')
502 func_body.append('{')
503 func_body.append(' PFN_vkGetInstanceProcAddr fpNextGPA;')
504 func_body.append(' fpNextGPA = (PFN_vkGetInstanceProcAddr) pCurObj->pGPA;')
505 func_body.append(' assert(fpNextGPA);')
506 func_body.append(' layer_init_instance_dispatch_table(&nextInstanceTable, fpNextGPA, (VkInstance) pCurObj->nextObject);')
507 func_body.append('}')
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600508 return "\n".join(func_body)
509
510class LayerFuncsSubcommand(Subcommand):
511 def generate_header(self):
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600512 return '#include <vkLayer.h>\n#include "loader.h"'
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600513
514 def generate_body(self):
Mike Stroyan3aecdb42015-04-03 17:13:23 -0600515 return self._generate_dispatch_entrypoints("static")
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600516
517class LayerDispatchSubcommand(Subcommand):
518 def generate_header(self):
519 return '#include "layer_wrappers.h"'
520
521 def generate_body(self):
Jon Ashburn21001f62015-02-16 08:26:50 -0700522 return self._generate_layer_initialization()
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600523
524class GenericLayerSubcommand(Subcommand):
525 def generate_header(self):
Jon Ashburnd9564002015-05-07 10:27:37 -0600526 return '#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include "loader_platform.h"\n#include "vkLayer.h"\n//The following is #included again to catch certain OS-specific functions being used:\n#include "loader_platform.h"\n\n#include "layers_config.h"\n#include "layers_msg.h"\n\nstatic VkLayerDispatchTable nextTable;\nstatic VkLayerInstanceDispatchTable nextInstanceTable;\nstatic VkBaseLayerObject *pCurObj;\n\nstatic LOADER_PLATFORM_THREAD_ONCE_DECLARATION(tabDeviceOnce);\nstatic LOADER_PLATFORM_THREAD_ONCE_DECLARATION(tabInstanceOnce);\nstatic LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);'
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600527
Mike Stroyan3aecdb42015-04-03 17:13:23 -0600528 def generate_intercept(self, proto, qual):
Tobin Ehlis46c96652015-04-16 11:17:12 -0600529 if proto.name in [ 'DbgRegisterMsgCallback', 'DbgUnregisterMsgCallback' , 'GetGlobalExtensionInfo']:
Mike Stroyan723913e2015-04-03 14:39:16 -0600530 # use default version
531 return None
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600532 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600533 ret_val = ''
534 stmt = ''
535 funcs = []
Jon Ashburn52c1d732015-05-12 17:23:55 -0600536 table = ''
537 if proto.params[0].ty == "VkInstance" or proto.name == "CreateInstance":
538 table = 'Instance'
539
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600540 if proto.ret != "void":
Jon Ashburn53c16772015-05-06 10:15:07 -0600541 ret_val = "%s result = " % proto.ret
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600542 stmt = " return result;\n"
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600543 if proto.name == "EnumerateLayers":
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600544 funcs.append('%s%s\n'
545 '{\n'
546 ' char str[1024];\n'
Mike Stroyan230e6252015-04-17 12:36:38 -0600547 ' if (gpu != VK_NULL_HANDLE) {\n'
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600548 ' sprintf(str, "At start of layered %s\\n");\n'
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600549 ' layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, gpu, 0, 0, (char *) "GENERIC", (char *) str);\n'
Jon Ashburn630e44f2015-04-08 21:33:34 -0600550 ' pCurObj = (VkBaseLayerObject *) gpu;\n'
Jon Ashburnd9564002015-05-07 10:27:37 -0600551 ' loader_platform_thread_once(&initOnce, init%s);\n'
552 ' loader_platform_thread_once(&tabDeviceOnce, initDeviceTable);\n'
Jon Ashburn52c1d732015-05-12 17:23:55 -0600553 ' %snext%sTable.%s;\n'
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600554 ' sprintf(str, "Completed layered %s\\n");\n'
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600555 ' layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, gpu, 0, 0, (char *) "GENERIC", (char *) str);\n'
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600556 ' fflush(stdout);\n'
557 ' %s'
558 ' } else {\n'
Courtney Goeltzenleuchterbb1f3602015-04-20 11:04:54 -0600559 ' if (pLayerCount == NULL || pOutLayers == NULL || pOutLayers[0] == NULL)\n'
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600560 ' return VK_ERROR_INVALID_POINTER;\n'
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600561 ' // This layer compatible with all GPUs\n'
Courtney Goeltzenleuchterbb1f3602015-04-20 11:04:54 -0600562 ' *pLayerCount = 1;\n'
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600563 ' strncpy((char *) pOutLayers[0], "%s", maxStringSize);\n'
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600564 ' return VK_SUCCESS;\n'
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600565 ' }\n'
Jon Ashburn52c1d732015-05-12 17:23:55 -0600566 '}' % (qual, decl, proto.name, self.layer_name, ret_val, table, proto.c_call(), proto.name, stmt, self.layer_name))
Jon Ashburn630e44f2015-04-08 21:33:34 -0600567 else:
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600568 funcs.append('%s%s\n'
569 '{\n'
Jon Ashburn52c1d732015-05-12 17:23:55 -0600570 ' %snext%sTable.%s;\n'
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600571 '%s'
Jon Ashburn52c1d732015-05-12 17:23:55 -0600572 '}' % (qual, decl, ret_val, table, proto.c_call(), stmt))
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600573 return "\n\n".join(funcs)
574
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600575 def generate_body(self):
Mike Stroyan3aecdb42015-04-03 17:13:23 -0600576 self.layer_name = "Generic"
577 body = [self._generate_layer_initialization(True),
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600578 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600579 self._generate_layer_gpa_function()]
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600580
581 return "\n\n".join(body)
582
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600583class APIDumpSubcommand(Subcommand):
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600584 def generate_header(self):
Tobin Ehlis0c68c9c2014-11-24 15:46:55 -0700585 header_txt = []
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600586 header_txt.append('#include <fstream>')
587 header_txt.append('#include <iostream>')
588 header_txt.append('#include <string>')
589 header_txt.append('')
590 header_txt.append('static std::ofstream fileStream;')
591 header_txt.append('static std::string fileName = "vk_apidump.txt";')
592 header_txt.append('std::ostream* outputStream = NULL;')
593 header_txt.append('void ConfigureOutputStream(bool writeToFile, bool flushAfterWrite)')
594 header_txt.append('{')
595 header_txt.append(' if(writeToFile)')
596 header_txt.append(' {')
597 header_txt.append(' fileStream.open(fileName);')
598 header_txt.append(' outputStream = &fileStream;')
599 header_txt.append(' }')
600 header_txt.append(' else')
601 header_txt.append(' {')
602 header_txt.append(' outputStream = &std::cout;')
603 header_txt.append(' }')
604 header_txt.append('')
605 header_txt.append(' if(flushAfterWrite)')
606 header_txt.append(' {')
607 header_txt.append(' outputStream->sync_with_stdio(true);')
608 header_txt.append(' }')
609 header_txt.append(' else')
610 header_txt.append(' {')
611 header_txt.append(' outputStream->sync_with_stdio(false);')
612 header_txt.append(' }')
613 header_txt.append('}')
614 header_txt.append('')
Ian Elliott81ac44c2015-01-13 17:52:38 -0700615 header_txt.append('#include "loader_platform.h"')
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600616 header_txt.append('#include "vkLayer.h"')
617 header_txt.append('#include "vk_struct_string_helper_cpp.h"')
618 header_txt.append('')
Ian Elliott20f06872015-02-12 17:08:34 -0700619 header_txt.append('// The following is #included again to catch certain OS-specific functions being used:')
620 header_txt.append('#include "loader_platform.h"')
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600621 header_txt.append('')
Jon Ashburn301c5f02015-04-06 10:58:22 -0600622 header_txt.append('static VkLayerDispatchTable nextTable;')
Jon Ashburnd9564002015-05-07 10:27:37 -0600623 header_txt.append('static VkLayerInstanceDispatchTable nextInstanceTable;')
Jon Ashburn301c5f02015-04-06 10:58:22 -0600624 header_txt.append('static VkBaseLayerObject *pCurObj;')
Tobin Ehlis55c40412015-04-27 17:30:04 -0600625 header_txt.append('static bool g_APIDumpDetailed = true;')
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600626 header_txt.append('')
Jon Ashburnd9564002015-05-07 10:27:37 -0600627 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(tabInstanceOnce);')
628 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(tabDeviceOnce);')
629 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
Ian Elliott81ac44c2015-01-13 17:52:38 -0700630 header_txt.append('static int printLockInitialized = 0;')
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600631 header_txt.append('static loader_platform_thread_mutex printLock;')
632 header_txt.append('')
Tobin Ehlis0c68c9c2014-11-24 15:46:55 -0700633 header_txt.append('#define MAX_TID 513')
Ian Elliott81ac44c2015-01-13 17:52:38 -0700634 header_txt.append('static loader_platform_thread_id tidMapping[MAX_TID] = {0};')
Tobin Ehlis0c68c9c2014-11-24 15:46:55 -0700635 header_txt.append('static uint32_t maxTID = 0;')
636 header_txt.append('// Map actual TID to an index value and return that index')
637 header_txt.append('// This keeps TIDs in range from 0-MAX_TID and simplifies compares between runs')
638 header_txt.append('static uint32_t getTIDIndex() {')
Ian Elliott81ac44c2015-01-13 17:52:38 -0700639 header_txt.append(' loader_platform_thread_id tid = loader_platform_get_thread_id();')
Tobin Ehlis0c68c9c2014-11-24 15:46:55 -0700640 header_txt.append(' for (uint32_t i = 0; i < maxTID; i++) {')
641 header_txt.append(' if (tid == tidMapping[i])')
642 header_txt.append(' return i;')
643 header_txt.append(' }')
644 header_txt.append(" // Don't yet have mapping, set it and return newly set index")
Ian Elliott81ac44c2015-01-13 17:52:38 -0700645 header_txt.append(' uint32_t retVal = (uint32_t) maxTID;')
Tobin Ehlis0c68c9c2014-11-24 15:46:55 -0700646 header_txt.append(' tidMapping[maxTID++] = tid;')
647 header_txt.append(' assert(maxTID < MAX_TID);')
648 header_txt.append(' return retVal;')
649 header_txt.append('}')
650 return "\n".join(header_txt)
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600651
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600652 def generate_init(self):
653 func_body = []
654 func_body.append('#include "vk_dispatch_table_helper.h"')
655 func_body.append('#include "layers_config.h"')
656 func_body.append('')
657 func_body.append('static void init%s(void)' % self.layer_name)
658 func_body.append('{')
659 func_body.append(' using namespace StreamControl;')
660 func_body.append('')
Tobin Ehlis55c40412015-04-27 17:30:04 -0600661 func_body.append(' char const*const detailedStr = getLayerOption("APIDumpDetailed");')
662 func_body.append(' if(detailedStr != NULL)')
663 func_body.append(' {')
664 func_body.append(' if(strcmp(detailedStr, "TRUE") == 0)')
665 func_body.append(' {')
666 func_body.append(' g_APIDumpDetailed = true;')
667 func_body.append(' }')
668 func_body.append(' else if(strcmp(detailedStr, "FALSE") == 0)')
669 func_body.append(' {')
670 func_body.append(' g_APIDumpDetailed = false;')
671 func_body.append(' }')
672 func_body.append(' }')
673 func_body.append('')
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600674 func_body.append(' char const*const writeToFileStr = getLayerOption("APIDumpFile");')
675 func_body.append(' bool writeToFile = false;')
676 func_body.append(' if(writeToFileStr != NULL)')
677 func_body.append(' {')
678 func_body.append(' if(strcmp(writeToFileStr, "TRUE") == 0)')
679 func_body.append(' {')
680 func_body.append(' writeToFile = true;')
681 func_body.append(' }')
682 func_body.append(' else if(strcmp(writeToFileStr, "FALSE") == 0)')
683 func_body.append(' {')
684 func_body.append(' writeToFile = false;')
685 func_body.append(' }')
686 func_body.append(' }')
687 func_body.append('')
688 func_body.append(' char const*const noAddrStr = getLayerOption("APIDumpNoAddr");')
689 func_body.append(' if(noAddrStr != NULL)')
690 func_body.append(' {')
691 func_body.append(' if(strcmp(noAddrStr, "FALSE") == 0)')
692 func_body.append(' {')
693 func_body.append(' StreamControl::writeAddress = true;')
694 func_body.append(' }')
695 func_body.append(' else if(strcmp(noAddrStr, "TRUE") == 0)')
696 func_body.append(' {')
697 func_body.append(' StreamControl::writeAddress = false;')
698 func_body.append(' }')
699 func_body.append(' }')
700 func_body.append('')
701 func_body.append(' char const*const flushAfterWriteStr = getLayerOption("APIDumpFlush");')
702 func_body.append(' bool flushAfterWrite = false;')
703 func_body.append(' if(flushAfterWriteStr != NULL)')
704 func_body.append(' {')
705 func_body.append(' if(strcmp(flushAfterWriteStr, "TRUE") == 0)')
706 func_body.append(' {')
707 func_body.append(' flushAfterWrite = true;')
708 func_body.append(' }')
709 func_body.append(' else if(strcmp(flushAfterWriteStr, "FALSE") == 0)')
710 func_body.append(' {')
711 func_body.append(' flushAfterWrite = false;')
712 func_body.append(' }')
713 func_body.append(' }')
714 func_body.append('')
715 func_body.append(' ConfigureOutputStream(writeToFile, flushAfterWrite);')
716 func_body.append('')
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600717 func_body.append(' if (!printLockInitialized)')
718 func_body.append(' {')
719 func_body.append(' // TODO/TBD: Need to delete this mutex sometime. How???')
720 func_body.append(' loader_platform_thread_create_mutex(&printLock);')
721 func_body.append(' printLockInitialized = 1;')
722 func_body.append(' }')
723 func_body.append('}')
724 func_body.append('')
Jon Ashburnd9564002015-05-07 10:27:37 -0600725 func_body.append('static void initDeviceTable(void)')
726 func_body.append('{')
727 func_body.append(' PFN_vkGetProcAddr fpNextGPA;')
728 func_body.append(' fpNextGPA = (PFN_vkGetProcAddr) pCurObj->pGPA;')
729 func_body.append(' assert(fpNextGPA);')
730 func_body.append(' layer_initialize_dispatch_table(&nextTable, fpNextGPA, (VkPhysicalDevice) pCurObj->nextObject);')
731 func_body.append('}')
732 func_body.append('')
733 func_body.append('static void initInstanceTable(void)')
734 func_body.append('{')
735 func_body.append(' PFN_vkGetInstanceProcAddr fpNextGPA;')
736 func_body.append(' fpNextGPA = (PFN_vkGetInstanceProcAddr) pCurObj->pGPA;')
737 func_body.append(' assert(fpNextGPA);')
738 func_body.append(' layer_init_instance_dispatch_table(&nextInstanceTable, fpNextGPA, (VkInstance) pCurObj->nextObject);')
739 func_body.append('}')
740 func_body.append('')
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600741 return "\n".join(func_body)
Tobin Ehlis434db7c2015-01-10 12:42:41 -0700742
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600743 def generate_intercept(self, proto, qual):
Jon Ashburneb2728b2015-04-10 14:33:07 -0600744 if proto.name in [ 'GetGlobalExtensionInfo']:
745 return None
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600746 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600747 ret_val = ''
748 stmt = ''
749 funcs = []
750 sp_param_dict = {} # Store 'index' for struct param to print, or an name of binding "Count" param for array to print
751 create_params = 0 # Num of params at end of function that are created and returned as output values
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800752 if 'AllocDescriptorSets' in proto.name:
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600753 create_params = -2
754 elif 'Create' in proto.name or 'Alloc' in proto.name or 'MapMemory' in proto.name:
755 create_params = -1
756 if proto.ret != "void":
Jon Ashburn53c16772015-05-06 10:15:07 -0600757 ret_val = "%s result = " % proto.ret
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600758 stmt = " return result;\n"
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600759 f_open = 'loader_platform_thread_lock_mutex(&printLock);\n '
760 log_func = ' if (StreamControl::writeAddress == true) {'
761 log_func += '\n (*outputStream) << "t{" << getTIDIndex() << "} vk%s(' % proto.name
762 log_func_no_addr = '\n (*outputStream) << "t{" << getTIDIndex() << "} vk%s(' % proto.name
763 f_close = '\n loader_platform_thread_unlock_mutex(&printLock);'
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600764 pindex = 0
765 prev_count_name = ''
766 for p in proto.params:
767 cp = False
768 if 0 != create_params:
769 # If this is any of the N last params of the func, treat as output
770 for y in range(-1, create_params-1, -1):
771 if p.name == proto.params[y].name:
772 cp = True
773 (pft, pfi) = self._get_printf_params(p.ty, p.name, cp, cpp=True)
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600774 log_func += '%s = " << %s << ", ' % (p.name, pfi)
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600775 if "%p" == pft:
776 log_func_no_addr += '%s = address, ' % (p.name)
777 else:
778 log_func_no_addr += '%s = " << %s << ", ' % (p.name, pfi)
Tobin Ehlisc99cb0d2015-04-16 15:56:11 -0600779 if prev_count_name != '' and (prev_count_name.replace('Count', '')[1:] in p.name):
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600780 sp_param_dict[pindex] = prev_count_name
Tobin Ehlisc99cb0d2015-04-16 15:56:11 -0600781 prev_count_name = ''
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600782 elif 'pDescriptorSets' == p.name and proto.params[-1].name == 'pCount':
783 sp_param_dict[pindex] = '*pCount'
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800784 elif vk_helper.is_type(p.ty.strip('*').replace('const ', ''), 'struct'):
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600785 sp_param_dict[pindex] = 'index'
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600786 if p.name.endswith('Count'):
787 if '*' in p.ty:
788 prev_count_name = "*%s" % p.name
789 else:
790 prev_count_name = p.name
Jon Ashburneb2728b2015-04-10 14:33:07 -0600791 pindex += 1
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600792 log_func = log_func.strip(', ')
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600793 log_func_no_addr = log_func_no_addr.strip(', ')
Jon Ashburn53c16772015-05-06 10:15:07 -0600794 if proto.ret == "VkResult":
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600795 log_func += ') = " << string_VkResult((VkResult)result) << endl'
796 log_func_no_addr += ') = " << string_VkResult((VkResult)result) << endl'
Jon Ashburn53c16772015-05-06 10:15:07 -0600797 elif proto.ret == "void*":
798 log_func += ') = " << result << endl'
799 log_func_no_addr += ') = " << result << endl'
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600800 else:
801 log_func += ')\\n"'
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600802 log_func_no_addr += ')\\n"'
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600803 log_func += ';'
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600804 log_func_no_addr += ';'
805 log_func += '\n }\n else {%s;\n }' % log_func_no_addr;
Tobin Ehlisf29da382015-04-15 07:46:12 -0600806 #print("Proto %s has param_dict: %s" % (proto.name, sp_param_dict))
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600807 if len(sp_param_dict) > 0:
Tobin Ehlis55c40412015-04-27 17:30:04 -0600808 indent = ' '
809 log_func += '\n%sif (g_APIDumpDetailed) {' % indent
810 indent += ' '
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600811 i_decl = False
Tobin Ehlis55c40412015-04-27 17:30:04 -0600812 log_func += '\n%sstring tmp_str;' % indent
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600813 for sp_index in sp_param_dict:
Tobin Ehlisf29da382015-04-15 07:46:12 -0600814 #print("sp_index: %s" % str(sp_index))
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600815 if 'index' == sp_param_dict[sp_index]:
Courtney Goeltzenleuchterddcb6192015-04-14 18:48:46 -0600816 cis_print_func = 'vk_print_%s' % (proto.params[sp_index].ty.replace('const ', '').strip('*').lower())
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600817 local_name = proto.params[sp_index].name
818 if '*' not in proto.params[sp_index].ty:
819 local_name = '&%s' % proto.params[sp_index].name
Tobin Ehlis55c40412015-04-27 17:30:04 -0600820 log_func += '\n%sif (%s) {' % (indent, local_name)
821 indent += ' '
822 log_func += '\n%stmp_str = %s(%s, " ");' % (indent, cis_print_func, local_name)
823 log_func += '\n%s(*outputStream) << " %s (" << %s << ")" << endl << tmp_str << endl;' % (indent, local_name, local_name)
824 indent = indent[4:]
825 log_func += '\n%s}' % (indent)
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600826 else: # We have a count value stored to iterate over an array
827 print_cast = ''
828 print_func = ''
Courtney Goeltzenleuchterddcb6192015-04-14 18:48:46 -0600829 if vk_helper.is_type(proto.params[sp_index].ty.strip('*').replace('const ', ''), 'struct'):
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600830 print_cast = '&'
Courtney Goeltzenleuchterddcb6192015-04-14 18:48:46 -0600831 print_func = 'vk_print_%s' % proto.params[sp_index].ty.replace('const ', '').strip('*').lower()
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600832 else:
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600833 print_cast = ''
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600834 print_func = 'string_convert_helper'
835 #cis_print_func = 'tmp_str = string_convert_helper((void*)%s[i], " ");' % proto.params[sp_index].name
836 cis_print_func = 'tmp_str = %s(%s%s[i], " ");' % (print_func, print_cast, proto.params[sp_index].name)
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600837 if not i_decl:
Tobin Ehlis55c40412015-04-27 17:30:04 -0600838 log_func += '\n%suint32_t i;' % (indent)
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600839 i_decl = True
Tobin Ehlis55c40412015-04-27 17:30:04 -0600840 log_func += '\n%sfor (i = 0; i < %s; i++) {' % (indent, sp_param_dict[sp_index])
841 indent += ' '
842 log_func += '\n%s%s' % (indent, cis_print_func)
Tobin Ehlis8ad15742015-04-28 10:58:20 -0600843 log_func += '\n%sif (StreamControl::writeAddress == true) {' % (indent)
844 indent += ' '
Tobin Ehlis55c40412015-04-27 17:30:04 -0600845 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)
846 indent = indent[4:]
Tobin Ehlis8ad15742015-04-28 10:58:20 -0600847 log_func += '\n%s} else {' % (indent)
848 indent += ' '
849 log_func += '\n%s(*outputStream) << " %s[" << i << "] (address)" << endl << " address" << endl;' % (indent, proto.params[sp_index].name)
850 indent = indent[4:]
851 log_func += '\n%s}' % (indent)
852 indent = indent[4:]
Tobin Ehlis55c40412015-04-27 17:30:04 -0600853 log_func += '\n%s}' % (indent)
854 indent = indent[4:]
855 log_func += '\n%s}' % (indent)
Jon Ashburn52c1d732015-05-12 17:23:55 -0600856 table = ''
857 if proto.params[0].ty == "VkInstance" or proto.name == "CreateInstance":
858 table = 'Instance'
859
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600860 if proto.name == "EnumerateLayers":
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600861 funcs.append('%s%s\n'
862 '{\n'
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600863 ' using namespace StreamControl;\n'
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600864 ' if (gpu != NULL) {\n'
Jon Ashburn630e44f2015-04-08 21:33:34 -0600865 ' pCurObj = (VkBaseLayerObject *) gpu;\n'
Jon Ashburnd9564002015-05-07 10:27:37 -0600866 ' loader_platform_thread_once(&initOnce, init%s);\n'
867 ' loader_platform_thread_once(&tabDeviceOnce, initDeviceTable);\n'
Jon Ashburn52c1d732015-05-12 17:23:55 -0600868 ' %snext%sTable.%s;\n'
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600869 ' %s %s %s\n'
870 ' %s'
871 ' } else {\n'
Courtney Goeltzenleuchterbb1f3602015-04-20 11:04:54 -0600872 ' if (pLayerCount == NULL || pOutLayers == NULL || pOutLayers[0] == NULL)\n'
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600873 ' return VK_ERROR_INVALID_POINTER;\n'
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600874 ' // This layer compatible with all GPUs\n'
Courtney Goeltzenleuchterbb1f3602015-04-20 11:04:54 -0600875 ' *pLayerCount = 1;\n'
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600876 ' strncpy((char *) pOutLayers[0], "%s", maxStringSize);\n'
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600877 ' return VK_SUCCESS;\n'
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600878 ' }\n'
Jon Ashburn52c1d732015-05-12 17:23:55 -0600879 '}' % (qual, decl, self.layer_name, ret_val, table, proto.c_call(),f_open, log_func, f_close, stmt, self.layer_name))
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600880 else:
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600881 funcs.append('%s%s\n'
882 '{\n'
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600883 ' using namespace StreamControl;\n'
Jon Ashburn52c1d732015-05-12 17:23:55 -0600884 ' %snext%sTable.%s;\n'
Jon Ashburn301c5f02015-04-06 10:58:22 -0600885 ' %s%s%s\n'
886 '%s'
Jon Ashburn52c1d732015-05-12 17:23:55 -0600887 '}' % (qual, decl, ret_val, table, proto.c_call(), f_open, log_func, f_close, stmt))
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600888 return "\n\n".join(funcs)
889
Tobin Ehlis434db7c2015-01-10 12:42:41 -0700890 def generate_body(self):
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600891 self.layer_name = "APIDump"
892 body = [self.generate_init(),
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600893 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Mike Stroyan3aecdb42015-04-03 17:13:23 -0600894 self._generate_layer_gpa_function()]
Tobin Ehlis434db7c2015-01-10 12:42:41 -0700895 return "\n\n".join(body)
896
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600897class ObjectTrackerSubcommand(Subcommand):
898 def generate_header(self):
899 header_txt = []
Tony Barbour11e76ac2015-04-20 16:28:46 -0600900 header_txt.append('#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <inttypes.h>\n#include "loader_platform.h"')
Jon Ashburnd9564002015-05-07 10:27:37 -0600901 header_txt.append('#include "object_track.h"\n\n')
Tobin Ehlis586aa012015-06-08 17:36:28 -0600902 header_txt.append('#include <unordered_map>')
903 header_txt.append('using namespace std;')
Ian Elliott20f06872015-02-12 17:08:34 -0700904 header_txt.append('// The following is #included again to catch certain OS-specific functions being used:')
905 header_txt.append('#include "loader_platform.h"')
Jon Ashburn7a2da4f2015-02-17 11:03:12 -0700906 header_txt.append('#include "layers_config.h"')
Jon Ashburn21001f62015-02-16 08:26:50 -0700907 header_txt.append('#include "layers_msg.h"')
Jon Ashburnd9564002015-05-07 10:27:37 -0600908 header_txt.append('static VkLayerDispatchTable nextTable;\nstatic VkLayerInstanceDispatchTable nextInstanceTable;\n')
909 header_txt.append('static VkBaseLayerObject *pCurObj;')
910 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
911 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(tabDeviceOnce);')
912 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(tabInstanceOnce);')
Ian Elliott81ac44c2015-01-13 17:52:38 -0700913 header_txt.append('static long long unsigned int object_track_index = 0;')
Tobin Ehlis84a8a9b2015-02-23 14:09:16 -0700914 header_txt.append('static int objLockInitialized = 0;')
915 header_txt.append('static loader_platform_thread_mutex objLock;')
Tobin Ehlis586aa012015-06-08 17:36:28 -0600916 header_txt.append('// Objects stored in a global map w/ struct containing basic info')
917 header_txt.append('unordered_map<VkObject, OBJTRACK_NODE*> objMap;')
Mark Lobodzinski93fdbd22015-04-09 12:09:45 -0500918 header_txt.append('')
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -0500919 header_txt.append('#define NUM_OBJECT_TYPES (VK_NUM_OBJECT_TYPE + (VK_OBJECT_TYPE_SWAP_CHAIN_WSI - VK_OBJECT_TYPE_DISPLAY_WSI))')
920 header_txt.append('')
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -0500921 header_txt.append('static uint64_t numObjs[NUM_OBJECT_TYPES] = {0};')
922 header_txt.append('static uint64_t numTotalObjs = 0;')
923 header_txt.append('static VkPhysicalDeviceQueueProperties *queueInfo = NULL;')
924 header_txt.append('static uint32_t queueCount = 0;')
Mark Lobodzinski93fdbd22015-04-09 12:09:45 -0500925 header_txt.append('')
926 header_txt.append('// For each Queue\'s doubly linked-list of mem refs')
927 header_txt.append('typedef struct _OT_MEM_INFO {')
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -0500928 header_txt.append(' VkDeviceMemory mem;')
Mark Lobodzinski93fdbd22015-04-09 12:09:45 -0500929 header_txt.append(' struct _OT_MEM_INFO *pNextMI;')
930 header_txt.append(' struct _OT_MEM_INFO *pPrevMI;')
931 header_txt.append('')
932 header_txt.append('} OT_MEM_INFO;')
933 header_txt.append('')
934 header_txt.append('// Track Queue information')
935 header_txt.append('typedef struct _OT_QUEUE_INFO {')
Mark Lobodzinskifaa29822015-04-30 17:04:27 -0500936 header_txt.append(' OT_MEM_INFO *pMemRefList;')
937 header_txt.append(' struct _OT_QUEUE_INFO *pNextQI;')
Mike Stroyanabf7c362015-05-05 16:33:08 -0600938 header_txt.append(' uint32_t queueNodeIndex;')
Mark Lobodzinskifaa29822015-04-30 17:04:27 -0500939 header_txt.append(' VkQueue queue;')
940 header_txt.append(' uint32_t refCount;')
Mark Lobodzinski93fdbd22015-04-09 12:09:45 -0500941 header_txt.append('} OT_QUEUE_INFO;')
942 header_txt.append('')
943 header_txt.append('// Global list of QueueInfo structures, one per queue')
Mike Stroyanabf7c362015-05-05 16:33:08 -0600944 header_txt.append('static OT_QUEUE_INFO *g_pQueueInfo = NULL;')
Mark Lobodzinski93fdbd22015-04-09 12:09:45 -0500945 header_txt.append('')
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -0500946 header_txt.append('// Convert an object type enum to an object type array index')
947 header_txt.append('static uint32_t objTypeToIndex(uint32_t objType)')
948 header_txt.append('{')
949 header_txt.append(' uint32_t index = objType;')
950 header_txt.append(' if (objType > VK_OBJECT_TYPE_END_RANGE) {')
951 header_txt.append(' // These come from vk_wsi_lunarg.h, rebase')
952 header_txt.append(' index = (index -(VK_WSI_LUNARG_EXTENSION_NUMBER * -1000)) + VK_OBJECT_TYPE_END_RANGE;')
953 header_txt.append(' }')
954 header_txt.append(' return index;')
955 header_txt.append('}')
956 header_txt.append('')
Tobin Ehlis586aa012015-06-08 17:36:28 -0600957 header_txt.append('// Validate that object is in the object map')
Mark Lobodzinskif5d3dec2015-06-11 13:51:41 -0500958 header_txt.append('static void validate_object(const VkObject object)')
Tobin Ehlis586aa012015-06-08 17:36:28 -0600959 header_txt.append('{')
960 header_txt.append(' if (objMap.find(object) == objMap.end()) {')
961 header_txt.append(' char str[1024];')
962 header_txt.append(' sprintf(str, "Invalid Object %p", (void*)object);')
963 header_txt.append(' layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, object, 0, OBJTRACK_INVALID_OBJECT, "OBJTRACK", str);')
964 header_txt.append(' }')
965 header_txt.append('}')
966 header_txt.append('')
Mark Lobodzinski7a3d5ff2015-05-05 18:24:45 -0500967 header_txt.append('// Validate that object parameter matches designated object type')
968 header_txt.append('static void validateObjectType(')
969 header_txt.append(' const char *apiName,')
970 header_txt.append(' VkObjectType objType,')
971 header_txt.append(' VkObject object)')
972 header_txt.append('{')
Tobin Ehlis586aa012015-06-08 17:36:28 -0600973 header_txt.append(' if (objMap.find(object) != objMap.end()) {')
974 header_txt.append(' OBJTRACK_NODE* pNode = objMap[object];')
Mark Lobodzinski7a3d5ff2015-05-05 18:24:45 -0500975 header_txt.append(' // Found our object, check type')
Tobin Ehlis586aa012015-06-08 17:36:28 -0600976 header_txt.append(' if (strcmp(string_VkObjectType(pNode->objType), string_VkObjectType(objType)) != 0) {')
Mark Lobodzinski7a3d5ff2015-05-05 18:24:45 -0500977 header_txt.append(' char str[1024];')
978 header_txt.append(' sprintf(str, "ERROR: Object Parameter Type %s does not match designated type %s",')
Tobin Ehlis586aa012015-06-08 17:36:28 -0600979 header_txt.append(' string_VkObjectType(pNode->objType), string_VkObjectType(objType));')
Mark Lobodzinski7a3d5ff2015-05-05 18:24:45 -0500980 header_txt.append(' layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, object, 0, OBJTRACK_OBJECT_TYPE_MISMATCH, "OBJTRACK", str);')
981 header_txt.append(' }')
982 header_txt.append(' }')
983 header_txt.append('}')
984 header_txt.append('')
Mark Lobodzinski93fdbd22015-04-09 12:09:45 -0500985 header_txt.append('// Add new queue to head of global queue list')
Mark Lobodzinskifaa29822015-04-30 17:04:27 -0500986 header_txt.append('static void addQueueInfo(uint32_t queueNodeIndex, VkQueue queue)')
Mark Lobodzinski93fdbd22015-04-09 12:09:45 -0500987 header_txt.append('{')
Mark Lobodzinski7d2d5ac2015-05-20 17:33:47 -0500988 header_txt.append(' OT_QUEUE_INFO *pQueueInfo = new OT_QUEUE_INFO;')
Mark Lobodzinski93fdbd22015-04-09 12:09:45 -0500989 header_txt.append('')
990 header_txt.append(' if (pQueueInfo != NULL) {')
Mike Stroyanabf7c362015-05-05 16:33:08 -0600991 header_txt.append(' memset(pQueueInfo, 0, sizeof(OT_QUEUE_INFO));')
992 header_txt.append(' pQueueInfo->queue = queue;')
993 header_txt.append(' pQueueInfo->queueNodeIndex = queueNodeIndex;')
Mark Lobodzinski93fdbd22015-04-09 12:09:45 -0500994 header_txt.append(' pQueueInfo->pNextQI = g_pQueueInfo;')
995 header_txt.append(' g_pQueueInfo = pQueueInfo;')
996 header_txt.append(' }')
997 header_txt.append(' else {')
998 header_txt.append(' char str[1024];')
Tony Barbour8205d902015-04-16 15:59:00 -0600999 header_txt.append(' sprintf(str, "ERROR: VK_ERROR_OUT_OF_HOST_MEMORY -- could not allocate memory for Queue Information");')
Mark Lobodzinski93fdbd22015-04-09 12:09:45 -05001000 header_txt.append(' layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, queue, 0, OBJTRACK_INTERNAL_ERROR, "OBJTRACK", str);')
1001 header_txt.append(' }')
1002 header_txt.append('}')
1003 header_txt.append('')
Mark Lobodzinski93fdbd22015-04-09 12:09:45 -05001004 header_txt.append('// Destroy memRef lists and free all memory')
1005 header_txt.append('static void destroyQueueMemRefLists()')
1006 header_txt.append('{')
1007 header_txt.append(' OT_QUEUE_INFO *pQueueInfo = g_pQueueInfo;')
1008 header_txt.append(' OT_QUEUE_INFO *pDelQueueInfo = NULL;')
1009 header_txt.append(' while (pQueueInfo != NULL) {')
1010 header_txt.append(' OT_MEM_INFO *pMemInfo = pQueueInfo->pMemRefList;')
1011 header_txt.append(' while (pMemInfo != NULL) {')
1012 header_txt.append(' OT_MEM_INFO *pDelMemInfo = pMemInfo;')
1013 header_txt.append(' pMemInfo = pMemInfo->pNextMI;')
Mark Lobodzinski7d2d5ac2015-05-20 17:33:47 -05001014 header_txt.append(' delete pDelMemInfo;')
Mark Lobodzinski93fdbd22015-04-09 12:09:45 -05001015 header_txt.append(' }')
1016 header_txt.append(' pDelQueueInfo = pQueueInfo;')
1017 header_txt.append(' pQueueInfo = pQueueInfo->pNextQI;')
Mark Lobodzinski7d2d5ac2015-05-20 17:33:47 -05001018 header_txt.append(' delete pDelQueueInfo;')
Mark Lobodzinski93fdbd22015-04-09 12:09:45 -05001019 header_txt.append(' }')
1020 header_txt.append('}')
1021 header_txt.append('')
Tobin Ehlis586aa012015-06-08 17:36:28 -06001022 header_txt.append('static void create_obj(VkObject vkObj, VkObjectType objType) {')
Tobin Ehlis3c26a542014-11-18 11:28:33 -07001023 header_txt.append(' char str[1024];')
Mark Lobodzinski7d2d5ac2015-05-20 17:33:47 -05001024 header_txt.append(' sprintf(str, "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64 , object_track_index++, string_from_vulkan_object_type(objType), reinterpret_cast<VkUintPtrLeast64>(vkObj));')
Tony Barbour83e67712015-04-21 09:18:02 -06001025 header_txt.append(' layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, vkObj, 0, OBJTRACK_NONE, "OBJTRACK", str);')
Tobin Ehlis586aa012015-06-08 17:36:28 -06001026 header_txt.append(' OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE;')
1027 header_txt.append(' pNewObjNode->vkObj = vkObj;')
1028 header_txt.append(' pNewObjNode->objType = objType;')
1029 header_txt.append(' pNewObjNode->status = OBJSTATUS_NONE;')
1030 header_txt.append(' objMap[vkObj] = pNewObjNode;')
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -05001031 header_txt.append(' uint32_t objIndex = objTypeToIndex(objType);')
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -05001032 header_txt.append(' numObjs[objIndex]++;')
Tobin Ehlis3c26a542014-11-18 11:28:33 -07001033 header_txt.append(' numTotalObjs++;')
Tobin Ehlis3c26a542014-11-18 11:28:33 -07001034 header_txt.append('}')
1035 header_txt.append('// Parse global list to find obj type, then remove obj from obj type list, finally')
1036 header_txt.append('// remove obj from global list')
Tobin Ehlis586aa012015-06-08 17:36:28 -06001037 header_txt.append('static void destroy_obj(VkObject vkObj) {')
1038 header_txt.append(' if (objMap.find(vkObj) != objMap.end()) {')
1039 header_txt.append(' OBJTRACK_NODE* pNode = objMap[vkObj];')
1040 header_txt.append(' uint32_t objIndex = objTypeToIndex(pNode->objType);')
1041 header_txt.append(' assert(numTotalObjs > 0);')
1042 header_txt.append(' numTotalObjs--;')
1043 header_txt.append(' assert(numObjs[objIndex] > 0);')
1044 header_txt.append(' numObjs[objIndex]--;')
1045 header_txt.append(' char str[1024];')
1046 header_txt.append(' sprintf(str, "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%lu total objs remain & %lu %s objs).", string_from_vulkan_object_type(pNode->objType), reinterpret_cast<VkUintPtrLeast64>(pNode->vkObj), numTotalObjs, numObjs[objIndex], string_from_vulkan_object_type(pNode->objType));')
1047 header_txt.append(' layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, vkObj, 0, OBJTRACK_NONE, "OBJTRACK", str);')
1048 header_txt.append(' delete pNode;')
1049 header_txt.append(' objMap.erase(vkObj);')
Tobin Ehlis3c26a542014-11-18 11:28:33 -07001050 header_txt.append(' }')
Tobin Ehlis586aa012015-06-08 17:36:28 -06001051 header_txt.append(' else {')
1052 header_txt.append(' char str[1024];')
1053 header_txt.append(' sprintf(str, "Unable to remove obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?", reinterpret_cast<VkUintPtrLeast64>(vkObj));')
1054 header_txt.append(' layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, vkObj, 0, OBJTRACK_DESTROY_OBJECT_FAILED, "OBJTRACK", str);')
1055 header_txt.append(' }')
Tobin Ehlis92dbf802014-10-22 09:06:33 -06001056 header_txt.append('}')
Tobin Ehlis235c20e2015-01-16 08:56:30 -07001057 header_txt.append('// Set selected flag state for an object node')
Mark Lobodzinski7d2d5ac2015-05-20 17:33:47 -05001058 header_txt.append('static void set_status(VkObject vkObj, VkObjectType objType, ObjectStatusFlags status_flag) {')
Tony Barbour83e67712015-04-21 09:18:02 -06001059 header_txt.append(' if (vkObj != VK_NULL_HANDLE) {')
Tobin Ehlis586aa012015-06-08 17:36:28 -06001060 header_txt.append(' if (objMap.find(vkObj) != objMap.end()) {')
1061 header_txt.append(' OBJTRACK_NODE* pNode = objMap[vkObj];')
1062 header_txt.append(' pNode->status |= status_flag;')
1063 header_txt.append(' return;')
Tobin Ehlis235c20e2015-01-16 08:56:30 -07001064 header_txt.append(' }')
Tobin Ehlis586aa012015-06-08 17:36:28 -06001065 header_txt.append(' else {')
1066 header_txt.append(' // If we do not find it print an error')
1067 header_txt.append(' char str[1024];')
1068 header_txt.append(' sprintf(str, "Unable to set status for non-existent object 0x%" PRIxLEAST64 " of %s type", reinterpret_cast<VkUintPtrLeast64>(vkObj), string_from_vulkan_object_type(objType));')
1069 header_txt.append(' layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, vkObj, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK", str);')
1070 header_txt.append(' }')
1071 header_txt.append(' }')
Tobin Ehlis235c20e2015-01-16 08:56:30 -07001072 header_txt.append('}')
1073 header_txt.append('')
Mark Lobodzinski01552702015-02-03 10:06:31 -06001074 header_txt.append('// Reset selected flag state for an object node')
Mark Lobodzinski7d2d5ac2015-05-20 17:33:47 -05001075 header_txt.append('static void reset_status(VkObject vkObj, VkObjectType objType, ObjectStatusFlags status_flag) {')
Tobin Ehlis586aa012015-06-08 17:36:28 -06001076 header_txt.append(' if (objMap.find(vkObj) != objMap.end()) {')
1077 header_txt.append(' OBJTRACK_NODE* pNode = objMap[vkObj];')
1078 header_txt.append(' pNode->status &= ~status_flag;')
1079 header_txt.append(' return;')
Mark Lobodzinski01552702015-02-03 10:06:31 -06001080 header_txt.append(' }')
Tobin Ehlis586aa012015-06-08 17:36:28 -06001081 header_txt.append(' else {')
1082 header_txt.append(' // If we do not find it print an error')
1083 header_txt.append(' char str[1024];')
1084 header_txt.append(' sprintf(str, "Unable to reset status for non-existent object 0x%" PRIxLEAST64 " of %s type", reinterpret_cast<VkUintPtrLeast64>(vkObj), string_from_vulkan_object_type(objType));')
1085 header_txt.append(' layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, vkObj, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK", str);')
1086 header_txt.append(' }')
Mark Lobodzinski01552702015-02-03 10:06:31 -06001087 header_txt.append('}')
1088 header_txt.append('')
Mark Lobodzinskifaa29822015-04-30 17:04:27 -05001089 header_txt.append('static void setGpuQueueInfoState(size_t* pDataSize, void *pData) {')
1090 header_txt.append(' queueCount = ((uint32_t)*pDataSize / sizeof(VkPhysicalDeviceQueueProperties));')
Mike Stroyanabf7c362015-05-05 16:33:08 -06001091 header_txt.append(' queueInfo = (VkPhysicalDeviceQueueProperties*)realloc((void*)queueInfo, *pDataSize);')
1092 header_txt.append(' if (queueInfo != NULL) {')
1093 header_txt.append(' memcpy(queueInfo, pData, *pDataSize);')
1094 header_txt.append(' }')
Mark Lobodzinskifaa29822015-04-30 17:04:27 -05001095 header_txt.append('}')
1096 header_txt.append('')
Mark Lobodzinski7d2d5ac2015-05-20 17:33:47 -05001097 header_txt.append('// Check Queue type flags for selected queue operations')
Mike Stroyanabf7c362015-05-05 16:33:08 -06001098 header_txt.append('static void validateQueueFlags(VkQueue queue, const char *function) {')
Mark Lobodzinskifaa29822015-04-30 17:04:27 -05001099 header_txt.append(' OT_QUEUE_INFO *pQueueInfo = g_pQueueInfo;')
Mike Stroyanabf7c362015-05-05 16:33:08 -06001100 header_txt.append(' while ((pQueueInfo != NULL) && (pQueueInfo->queue != queue)) {')
Mark Lobodzinskifaa29822015-04-30 17:04:27 -05001101 header_txt.append(' pQueueInfo = pQueueInfo->pNextQI;')
1102 header_txt.append(' }')
1103 header_txt.append(' if (pQueueInfo != NULL) {')
Mike Stroyanabf7c362015-05-05 16:33:08 -06001104 header_txt.append(' char str[1024];\n')
Mark Lobodzinskifb9f5642015-05-11 17:21:15 -05001105 header_txt.append(' if ((queueInfo != NULL) && (queueInfo[pQueueInfo->queueNodeIndex].queueFlags & VK_QUEUE_SPARSE_MEMMGR_BIT) == 0) {')
1106 header_txt.append(' sprintf(str, "Attempting %s on a non-memory-management capable queue -- VK_QUEUE_SPARSE_MEMMGR_BIT not set", function);')
Mike Stroyanabf7c362015-05-05 16:33:08 -06001107 header_txt.append(' layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, queue, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK", str);')
1108 header_txt.append(' } else {')
Mark Lobodzinskifb9f5642015-05-11 17:21:15 -05001109 header_txt.append(' sprintf(str, "Attempting %s on a possibly non-memory-management capable queue -- VK_QUEUE_SPARSE_MEMMGR_BIT not known", function);')
Mike Stroyanabf7c362015-05-05 16:33:08 -06001110 header_txt.append(' layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, queue, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK", str);')
Mark Lobodzinskifaa29822015-04-30 17:04:27 -05001111 header_txt.append(' }')
1112 header_txt.append(' }')
Mark Lobodzinskifaa29822015-04-30 17:04:27 -05001113 header_txt.append('}')
1114 header_txt.append('')
Mark Lobodzinski01552702015-02-03 10:06:31 -06001115 header_txt.append('// Check object status for selected flag state')
Mark Lobodzinski7d2d5ac2015-05-20 17:33:47 -05001116 header_txt.append('static bool32_t validate_status(VkObject vkObj, VkObjectType objType, ObjectStatusFlags status_mask, ObjectStatusFlags status_flag, VK_DBG_MSG_TYPE error_level, OBJECT_TRACK_ERROR error_code, const char* fail_msg) {')
Tobin Ehlis586aa012015-06-08 17:36:28 -06001117 header_txt.append(' if (objMap.find(vkObj) != objMap.end()) {')
1118 header_txt.append(' OBJTRACK_NODE* pNode = objMap[vkObj];')
1119 header_txt.append(' if ((pNode->status & status_mask) != status_flag) {')
1120 header_txt.append(' char str[1024];')
1121 header_txt.append(' sprintf(str, "OBJECT VALIDATION WARNING: %s object 0x%" PRIxLEAST64 ": %s", string_from_vulkan_object_type(objType), reinterpret_cast<VkUintPtrLeast64>(vkObj), fail_msg);')
1122 header_txt.append(' layerCbMsg(error_level, VK_VALIDATION_LEVEL_0, vkObj, 0, error_code, "OBJTRACK", str);')
1123 header_txt.append(' return VK_FALSE;')
Tobin Ehlis235c20e2015-01-16 08:56:30 -07001124 header_txt.append(' }')
Tobin Ehlis586aa012015-06-08 17:36:28 -06001125 header_txt.append(' return VK_TRUE;')
Tobin Ehlis235c20e2015-01-16 08:56:30 -07001126 header_txt.append(' }')
Tobin Ehlis586aa012015-06-08 17:36:28 -06001127 header_txt.append(' else {')
1128 header_txt.append(' // If we do not find it print an error')
1129 header_txt.append(' char str[1024];')
1130 header_txt.append(' sprintf(str, "Unable to obtain status for non-existent object 0x%" PRIxLEAST64 " of %s type", reinterpret_cast<VkUintPtrLeast64>(vkObj), string_from_vulkan_object_type(objType));')
1131 header_txt.append(' layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, vkObj, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK", str);')
1132 header_txt.append(' return VK_FALSE;')
1133 header_txt.append(' }')
Tobin Ehlis235c20e2015-01-16 08:56:30 -07001134 header_txt.append('}')
Mark Lobodzinski01552702015-02-03 10:06:31 -06001135 header_txt.append('')
Tobin Ehlis92dbf802014-10-22 09:06:33 -06001136 return "\n".join(header_txt)
1137
Mike Stroyan3aecdb42015-04-03 17:13:23 -06001138 def generate_intercept(self, proto, qual):
Jon Ashburneb2728b2015-04-10 14:33:07 -06001139 if proto.name in [ 'DbgRegisterMsgCallback', 'DbgUnregisterMsgCallback', 'GetGlobalExtensionInfo' ]:
Mike Stroyan723913e2015-04-03 14:39:16 -06001140 # use default version
1141 return None
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -05001142
1143 # Create map of object names to object type enums of the form VkName : VkObjectTypeName
Tobin Ehlisf29da382015-04-15 07:46:12 -06001144 obj_type_mapping = {base_t : base_t.replace("Vk", "VkObjectType") for base_t in vulkan.object_type_list}
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -05001145 # Convert object type enum names from UpperCamelCase to UPPER_CASE_WITH_UNDERSCORES
1146 for objectName, objectTypeEnum in obj_type_mapping.items():
1147 obj_type_mapping[objectName] = ucc_to_U_C_C(objectTypeEnum);
1148 # Command Buffer Object doesn't follow the rule.
1149 obj_type_mapping['VkCmdBuffer'] = "VK_OBJECT_TYPE_COMMAND_BUFFER"
Mike Stroyan723913e2015-04-03 14:39:16 -06001150
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001151 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyan723913e2015-04-03 14:39:16 -06001152 param0_name = proto.params[0].name
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001153 using_line = ''
Mike Stroyan723913e2015-04-03 14:39:16 -06001154 create_line = ''
1155 destroy_line = ''
Tobin Ehlis586aa012015-06-08 17:36:28 -06001156 object_params = []
1157 # TODO : Should also check through struct params & add any objects embedded in struct chains
1158 # TODO : A few of the skipped types are just "hard" cases that need some more work to support
1159 # Need to handle NULL fences on queue submit, binding null memory, and WSI Image objects
1160 for p in proto.params:
1161 if p.ty in vulkan.core.objects and p.ty not in ['VkPhysicalDevice', 'VkQueue', 'VkFence', 'VkImage', 'VkDeviceMemory']:
1162 object_params.append(p.name)
Mike Stroyan723913e2015-04-03 14:39:16 -06001163 funcs = []
Tobin Ehlis586aa012015-06-08 17:36:28 -06001164 mutex_unlock = False
Mike Stroyan723913e2015-04-03 14:39:16 -06001165 if 'QueueSubmit' in proto.name:
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001166 using_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -05001167 using_line += ' set_status(fence, VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED);\n'
Courtney Goeltzenleuchter8d49dbd2015-04-07 17:13:38 -06001168 using_line += ' // TODO: Fix for updated memory reference mechanism\n'
1169 using_line += ' // validate_memory_mapping_status(pMemRefs, memRefCount);\n'
1170 using_line += ' // validate_mem_ref_count(memRefCount);\n'
Tobin Ehlis586aa012015-06-08 17:36:28 -06001171 mutex_unlock = True
Mark Lobodzinskifb9f5642015-05-11 17:21:15 -05001172 elif 'QueueBindSparse' in proto.name:
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001173 using_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Mike Stroyanabf7c362015-05-05 16:33:08 -06001174 using_line += ' validateQueueFlags(queue, "%s");\n' % (proto.name)
Tobin Ehlis586aa012015-06-08 17:36:28 -06001175 mutex_unlock = True
Mark Lobodzinski7a3d5ff2015-05-05 18:24:45 -05001176 elif 'QueueBindObject' in proto.name:
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001177 using_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Mark Lobodzinski7a3d5ff2015-05-05 18:24:45 -05001178 using_line += ' validateObjectType("vk%s", objType, object);\n' % (proto.name)
Tobin Ehlis586aa012015-06-08 17:36:28 -06001179 mutex_unlock = True
Mark Lobodzinski7a3d5ff2015-05-05 18:24:45 -05001180 elif 'GetObjectInfo' in proto.name:
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001181 using_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Mark Lobodzinski7a3d5ff2015-05-05 18:24:45 -05001182 using_line += ' validateObjectType("vk%s", objType, object);\n' % (proto.name)
Tobin Ehlis586aa012015-06-08 17:36:28 -06001183 mutex_unlock = True
Mike Stroyan723913e2015-04-03 14:39:16 -06001184 elif 'GetFenceStatus' in proto.name:
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001185 using_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Mike Stroyan723913e2015-04-03 14:39:16 -06001186 using_line += ' // Warn if submitted_flag is not set\n'
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -05001187 using_line += ' validate_status(fence, VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED, OBJSTATUS_FENCE_IS_SUBMITTED, VK_DBG_MSG_ERROR, OBJTRACK_INVALID_FENCE, "Status Requested for Unsubmitted Fence");\n'
Tobin Ehlis586aa012015-06-08 17:36:28 -06001188 mutex_unlock = True
Mark Lobodzinskid3464592015-04-22 15:06:12 -06001189 elif 'WaitForFences' in proto.name:
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001190 using_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Mark Lobodzinskid3464592015-04-22 15:06:12 -06001191 using_line += ' // Warn if waiting on unsubmitted fence\n'
1192 using_line += ' for (uint32_t i = 0; i < fenceCount; i++) {\n'
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -05001193 using_line += ' validate_status(pFences[i], VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED, OBJSTATUS_FENCE_IS_SUBMITTED, VK_DBG_MSG_ERROR, OBJTRACK_INVALID_FENCE, "Waiting for Unsubmitted Fence");\n'
Mark Lobodzinskid3464592015-04-22 15:06:12 -06001194 using_line += ' }\n'
Tobin Ehlis586aa012015-06-08 17:36:28 -06001195 mutex_unlock = True
Mike Stroyan723913e2015-04-03 14:39:16 -06001196 elif 'MapMemory' in proto.name:
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001197 using_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -05001198 using_line += ' set_status(mem, VK_OBJECT_TYPE_DEVICE_MEMORY, OBJSTATUS_GPU_MEM_MAPPED);\n'
Tobin Ehlis586aa012015-06-08 17:36:28 -06001199 mutex_unlock = True
Mike Stroyan723913e2015-04-03 14:39:16 -06001200 elif 'UnmapMemory' in proto.name:
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001201 using_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -05001202 using_line += ' reset_status(mem, VK_OBJECT_TYPE_DEVICE_MEMORY, OBJSTATUS_GPU_MEM_MAPPED);\n'
Tobin Ehlis586aa012015-06-08 17:36:28 -06001203 mutex_unlock = True
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001204 elif 'AllocDescriptor' in proto.name: # Allocates array of DSs
1205 create_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
1206 create_line += ' for (uint32_t i = 0; i < *pCount; i++) {\n'
Tobin Ehlis586aa012015-06-08 17:36:28 -06001207 create_line += ' create_obj(pDescriptorSets[i], VK_OBJECT_TYPE_DESCRIPTOR_SET);\n'
Mike Stroyan723913e2015-04-03 14:39:16 -06001208 create_line += ' }\n'
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001209 create_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Mike Stroyan723913e2015-04-03 14:39:16 -06001210 elif 'Create' in proto.name or 'Alloc' in proto.name:
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001211 create_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Tobin Ehlis586aa012015-06-08 17:36:28 -06001212 create_line += ' create_obj(*%s, %s);\n' % (proto.params[-1].name, obj_type_mapping[proto.params[-1].ty.strip('*').replace('const ', '')])
Mike Stroyan723913e2015-04-03 14:39:16 -06001213 create_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001214 if 'GetDeviceQueue' in proto.name:
1215 destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
1216 destroy_line += ' addQueueInfo(queueNodeIndex, *pQueue);\n'
1217 destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
1218 elif 'DestroyObject' in proto.name:
1219 destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Mark Lobodzinski7a3d5ff2015-05-05 18:24:45 -05001220 destroy_line += ' validateObjectType("vk%s", objType, object);\n' % (proto.name)
Tobin Ehlis586aa012015-06-08 17:36:28 -06001221 destroy_line += ' destroy_obj(%s);\n' % (proto.params[2].name)
Mike Stroyan723913e2015-04-03 14:39:16 -06001222 destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001223 elif 'DestroyDevice' in proto.name:
1224 destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Tobin Ehlis586aa012015-06-08 17:36:28 -06001225 destroy_line += ' destroy_obj(device);\n'
1226 destroy_line += ' // Report any remaining objects\n'
1227 destroy_line += ' for (auto it = objMap.begin(); it != objMap.end(); ++it) {\n'
1228 destroy_line += ' OBJTRACK_NODE* pNode = it->second;'
1229 destroy_line += ' if ((pNode->objType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) || (pNode->objType == VK_OBJECT_TYPE_QUEUE)) {\n'
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001230 destroy_line += ' // Cannot destroy physical device so ignore\n'
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001231 destroy_line += ' } else {\n'
1232 destroy_line += ' char str[1024];\n'
Tobin Ehlis586aa012015-06-08 17:36:28 -06001233 destroy_line += ' sprintf(str, "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_from_vulkan_object_type(pNode->objType), reinterpret_cast<VkUintPtrLeast64>(pNode->vkObj));\n'
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001234 destroy_line += ' layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, device, 0, OBJTRACK_OBJECT_LEAK, "OBJTRACK", str);\n'
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001235 destroy_line += ' }\n'
1236 destroy_line += ' }\n'
1237 destroy_line += ' // Clean up Queue\'s MemRef Linked Lists\n'
1238 destroy_line += ' destroyQueueMemRefLists();\n'
1239 destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
1240 elif 'Free' in proto.name:
1241 destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Tobin Ehlis586aa012015-06-08 17:36:28 -06001242 destroy_line += ' destroy_obj(%s);\n' % (proto.params[1].name)
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001243 destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Tobin Ehlis586aa012015-06-08 17:36:28 -06001244 elif 'Destroy' in proto.name:
1245 destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
1246 destroy_line += ' destroy_obj(%s);\n' % (param0_name)
1247 destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
1248 if len(object_params) > 0:
1249 if not mutex_unlock:
1250 using_line += ' loader_platform_thread_lock_mutex(&objLock);\n'
1251 mutex_unlock = True
1252 for opn in object_params:
1253 using_line += ' validate_object(%s);\n' % (opn)
1254 if mutex_unlock:
1255 using_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Mike Stroyan723913e2015-04-03 14:39:16 -06001256 ret_val = ''
1257 stmt = ''
Jon Ashburn52c1d732015-05-12 17:23:55 -06001258 table = ''
Mike Stroyan723913e2015-04-03 14:39:16 -06001259 if proto.ret != "void":
Jon Ashburn53c16772015-05-06 10:15:07 -06001260 ret_val = "%s result = " % proto.ret
Mike Stroyan723913e2015-04-03 14:39:16 -06001261 stmt = " return result;\n"
Jon Ashburn52c1d732015-05-12 17:23:55 -06001262 if proto.params[0].ty == "VkInstance" or proto.name == "CreateInstance":
1263 table = 'Instance'
1264
Mike Stroyan723913e2015-04-03 14:39:16 -06001265 if proto.name == "EnumerateLayers":
Mike Stroyan723913e2015-04-03 14:39:16 -06001266 funcs.append('%s%s\n'
1267 '{\n'
Tony Barbour11e76ac2015-04-20 16:28:46 -06001268 ' if (gpu != VK_NULL_HANDLE) {\n'
Jon Ashburn630e44f2015-04-08 21:33:34 -06001269 ' pCurObj = (VkBaseLayerObject *) gpu;\n'
Jon Ashburnd9564002015-05-07 10:27:37 -06001270 ' loader_platform_thread_once(&initOnce, init%s);\n'
1271 ' loader_platform_thread_once(&tabDeviceOnce, initDeviceTable);\n'
Jon Ashburn52c1d732015-05-12 17:23:55 -06001272 ' %snext%sTable.%s;\n'
Mike Stroyan723913e2015-04-03 14:39:16 -06001273 ' %s%s'
1274 ' %s'
1275 ' } else {\n'
Courtney Goeltzenleuchterbb1f3602015-04-20 11:04:54 -06001276 ' if (pLayerCount == NULL || pOutLayers == NULL || pOutLayers[0] == NULL)\n'
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001277 ' return VK_ERROR_INVALID_POINTER;\n'
Mike Stroyan723913e2015-04-03 14:39:16 -06001278 ' // This layer compatible with all GPUs\n'
Courtney Goeltzenleuchterbb1f3602015-04-20 11:04:54 -06001279 ' *pLayerCount = 1;\n'
Mike Stroyan723913e2015-04-03 14:39:16 -06001280 ' strncpy((char *) pOutLayers[0], "%s", maxStringSize);\n'
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001281 ' return VK_SUCCESS;\n'
Mike Stroyan723913e2015-04-03 14:39:16 -06001282 ' }\n'
Jon Ashburn52c1d732015-05-12 17:23:55 -06001283 '}' % (qual, decl, self.layer_name, ret_val, table, proto.c_call(), create_line, destroy_line, stmt, self.layer_name))
Tony Barbour8205d902015-04-16 15:59:00 -06001284 elif 'GetPhysicalDeviceInfo' in proto.name:
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001285 gpu_state = ' if (infoType == VK_PHYSICAL_DEVICE_INFO_TYPE_QUEUE_PROPERTIES) {\n'
Jon Ashburn630e44f2015-04-08 21:33:34 -06001286 gpu_state += ' if (pData != NULL) {\n'
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001287 gpu_state += ' loader_platform_thread_lock_mutex(&objLock);\n'
Mark Lobodzinskifaa29822015-04-30 17:04:27 -05001288 gpu_state += ' setGpuQueueInfoState(pDataSize, pData);\n'
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001289 gpu_state += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Jon Ashburn630e44f2015-04-08 21:33:34 -06001290 gpu_state += ' }\n'
1291 gpu_state += ' }\n'
1292 funcs.append('%s%s\n'
1293 '{\n'
Jon Ashburn52c1d732015-05-12 17:23:55 -06001294 ' %snext%sTable.%s;\n'
Jon Ashburn630e44f2015-04-08 21:33:34 -06001295 '%s%s'
1296 '%s'
1297 '%s'
Jon Ashburn52c1d732015-05-12 17:23:55 -06001298 '}' % (qual, decl, ret_val, table, proto.c_call(), create_line, destroy_line, gpu_state, stmt))
Jon Ashburn630e44f2015-04-08 21:33:34 -06001299 else:
Mike Stroyan723913e2015-04-03 14:39:16 -06001300 funcs.append('%s%s\n'
1301 '{\n'
1302 '%s'
Jon Ashburn52c1d732015-05-12 17:23:55 -06001303 ' %snext%sTable.%s;\n'
Mike Stroyan723913e2015-04-03 14:39:16 -06001304 '%s%s'
1305 '%s'
Jon Ashburn52c1d732015-05-12 17:23:55 -06001306 '}' % (qual, decl, using_line, ret_val, table, proto.c_call(), create_line, destroy_line, stmt))
Mike Stroyan723913e2015-04-03 14:39:16 -06001307 return "\n\n".join(funcs)
1308
Tobin Ehlis92dbf802014-10-22 09:06:33 -06001309 def generate_body(self):
Mike Stroyan3aecdb42015-04-03 17:13:23 -06001310 self.layer_name = "ObjectTracker"
1311 body = [self._generate_layer_initialization(True, lockname='obj'),
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001312 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Tobin Ehlis3c26a542014-11-18 11:28:33 -07001313 self._generate_extensions(),
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -05001314 self._generate_layer_gpa_function(extensions=['objTrackGetObjectsCount', 'objTrackGetObjects', 'objTrackGetObjectsOfTypeCount', 'objTrackGetObjectsOfType'])]
Tobin Ehlis92dbf802014-10-22 09:06:33 -06001315 return "\n\n".join(body)
Courtney Goeltzenleuchtere6094fc2014-11-18 10:40:29 -07001316
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001317class ThreadingSubcommand(Subcommand):
1318 def generate_header(self):
1319 header_txt = []
1320 header_txt.append('#include <stdio.h>')
1321 header_txt.append('#include <stdlib.h>')
1322 header_txt.append('#include <string.h>')
1323 header_txt.append('#include <unordered_map>')
1324 header_txt.append('#include "loader_platform.h"')
1325 header_txt.append('#include "vkLayer.h"')
1326 header_txt.append('#include "threading.h"')
1327 header_txt.append('#include "layers_config.h"')
1328 header_txt.append('#include "vk_enum_validate_helper.h"')
1329 header_txt.append('#include "vk_struct_validate_helper.h"')
1330 header_txt.append('//The following is #included again to catch certain OS-specific functions being used:')
1331 header_txt.append('#include "loader_platform.h"\n')
1332 header_txt.append('#include "layers_msg.h"\n')
1333 header_txt.append('static VkLayerDispatchTable nextTable;')
Jon Ashburnd9564002015-05-07 10:27:37 -06001334 header_txt.append('static VkLayerInstanceDispatchTable nextInstanceTable;')
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001335 header_txt.append('static VkBaseLayerObject *pCurObj;')
Jon Ashburnd9564002015-05-07 10:27:37 -06001336 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(tabDeviceOnce);')
1337 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(tabInstanceOnce);')
1338 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);\n')
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001339 header_txt.append('using namespace std;')
1340 header_txt.append('static unordered_map<int, void*> proxy_objectsInUse;\n')
1341 header_txt.append('static unordered_map<VkObject, loader_platform_thread_id> objectsInUse;\n')
1342 header_txt.append('static int threadingLockInitialized = 0;')
1343 header_txt.append('static loader_platform_thread_mutex threadingLock;')
Mike Stroyan354ed672015-05-15 08:50:57 -06001344 header_txt.append('static loader_platform_thread_cond threadingCond;')
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001345 header_txt.append('static int printLockInitialized = 0;')
1346 header_txt.append('static loader_platform_thread_mutex printLock;\n')
1347 header_txt.append('')
1348 header_txt.append('static void useObject(VkObject object, const char* type)')
1349 header_txt.append('{')
1350 header_txt.append(' loader_platform_thread_id tid = loader_platform_get_thread_id();')
1351 header_txt.append(' loader_platform_thread_lock_mutex(&threadingLock);')
1352 header_txt.append(' if (objectsInUse.find(object) == objectsInUse.end()) {')
1353 header_txt.append(' objectsInUse[object] = tid;')
1354 header_txt.append(' } else {')
Mike Stroyanae0eafd2015-05-11 17:18:14 -06001355 header_txt.append(' if (objectsInUse[object] != tid) {')
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001356 header_txt.append(' char str[1024];')
1357 header_txt.append(' sprintf(str, "THREADING ERROR : object of type %s is simultaneously used in thread %ld and thread %ld", type, objectsInUse[object], tid);')
1358 header_txt.append(' layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, 0, 0, THREADING_CHECKER_MULTIPLE_THREADS, "THREADING", str);')
Mike Stroyan354ed672015-05-15 08:50:57 -06001359 header_txt.append(' // Wait for thread-safe access to object')
1360 header_txt.append(' while (objectsInUse.find(object) != objectsInUse.end()) {')
1361 header_txt.append(' loader_platform_thread_cond_wait(&threadingCond, &threadingLock);')
1362 header_txt.append(' }')
1363 header_txt.append(' objectsInUse[object] = tid;')
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001364 header_txt.append(' } else {')
1365 header_txt.append(' char str[1024];')
1366 header_txt.append(' sprintf(str, "THREADING ERROR : object of type %s is recursively used in thread %ld", type, tid);')
1367 header_txt.append(' layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, 0, 0, THREADING_CHECKER_SINGLE_THREAD_REUSE, "THREADING", str);')
1368 header_txt.append(' }')
1369 header_txt.append(' }')
1370 header_txt.append(' loader_platform_thread_unlock_mutex(&threadingLock);')
1371 header_txt.append('}')
1372 header_txt.append('static void finishUsingObject(VkObject object)')
1373 header_txt.append('{')
1374 header_txt.append(' // Object is no longer in use')
1375 header_txt.append(' loader_platform_thread_lock_mutex(&threadingLock);')
1376 header_txt.append(' objectsInUse.erase(object);')
Mike Stroyan354ed672015-05-15 08:50:57 -06001377 header_txt.append(' loader_platform_thread_cond_broadcast(&threadingCond);')
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001378 header_txt.append(' loader_platform_thread_unlock_mutex(&threadingLock);')
1379 header_txt.append('}')
1380 return "\n".join(header_txt)
1381
1382 def generate_intercept(self, proto, qual):
1383 if proto.name in [ 'DbgRegisterMsgCallback', 'DbgUnregisterMsgCallback' ]:
1384 # use default version
1385 return None
1386 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyanae0eafd2015-05-11 17:18:14 -06001387 thread_check_objects = [
1388 "VkQueue",
1389 "VkDeviceMemory",
1390 "VkObject",
1391 "VkBuffer",
1392 "VkImage",
1393 "VkDescriptorSet",
1394 "VkDescriptorPool",
1395 "VkCmdBuffer",
1396 "VkSemaphore"
1397 ]
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001398 ret_val = ''
1399 stmt = ''
1400 funcs = []
Jon Ashburn52c1d732015-05-12 17:23:55 -06001401 table = ''
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001402 if proto.ret != "void":
Jon Ashburn53c16772015-05-06 10:15:07 -06001403 ret_val = "%s result = " % proto.ret
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001404 stmt = " return result;\n"
Jon Ashburn52c1d732015-05-12 17:23:55 -06001405 if proto.params[0].ty == "VkInstance" or proto.name == "CreateInstance":
1406 table = 'Instance'
1407
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001408 if proto.name == "EnumerateLayers":
1409 funcs.append('%s%s\n'
1410 '{\n'
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001411 ' if (gpu != NULL) {\n'
1412 ' pCurObj = (VkBaseLayerObject *) %s;\n'
Jon Ashburnd9564002015-05-07 10:27:37 -06001413 ' loader_platform_thread_once(&initOnce, init%s);\n'
1414 ' loader_platform_thread_once(&tabDeviceOnce, initDeviceTable);\n'
Jon Ashburn52c1d732015-05-12 17:23:55 -06001415 ' %snext%sTable.%s;\n'
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001416 ' fflush(stdout);\n'
1417 ' %s'
1418 ' } else {\n'
Courtney Goeltzenleuchterbb1f3602015-04-20 11:04:54 -06001419 ' if (pLayerCount == NULL || pOutLayers == NULL || pOutLayers[0] == NULL)\n'
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001420 ' return VK_ERROR_INVALID_POINTER;\n'
1421 ' // This layer compatible with all GPUs\n'
Courtney Goeltzenleuchterbb1f3602015-04-20 11:04:54 -06001422 ' *pLayerCount = 1;\n'
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001423 ' strncpy((char *) pOutLayers[0], "%s", maxStringSize);\n'
1424 ' return VK_SUCCESS;\n'
1425 ' }\n'
Jon Ashburn52c1d732015-05-12 17:23:55 -06001426 '}' % (qual, decl, proto.params[0].name, self.layer_name, ret_val, table, proto.c_call(), stmt, self.layer_name))
Mike Stroyanae0eafd2015-05-11 17:18:14 -06001427 return "\n".join(funcs)
1428 # Memory range calls are special in needed thread checking within structs
1429 if proto.name in ["FlushMappedMemoryRanges","InvalidateMappedMemoryRanges"]:
1430 funcs.append('%s%s\n'
1431 '{\n'
1432 ' for (int i=0; i<memRangeCount; i++) {\n'
1433 ' useObject((VkObject) pMemRanges[i].mem, "VkDeviceMemory");\n'
1434 ' }\n'
1435 ' %snextTable.%s;\n'
1436 ' for (int i=0; i<memRangeCount; i++) {\n'
1437 ' finishUsingObject((VkObject) pMemRanges[i].mem);\n'
1438 ' }\n'
1439 '%s'
1440 '}' % (qual, decl, ret_val, proto.c_call(), stmt))
1441 return "\n".join(funcs)
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001442 # All functions that do a Get are thread safe
Mike Stroyanae0eafd2015-05-11 17:18:14 -06001443 if 'Get' in proto.name:
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001444 return None
Mike Stroyanae0eafd2015-05-11 17:18:14 -06001445 # All WSI functions are thread safe
1446 if 'WSI' in proto.name:
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001447 return None
Mike Stroyanae0eafd2015-05-11 17:18:14 -06001448 # Initialize in early calls
1449 if proto.params[0].ty == "VkPhysicalDevice":
1450 funcs.append('%s%s\n'
1451 '{\n'
Jon Ashburn52c1d732015-05-12 17:23:55 -06001452 ' %snext%sTable.%s;\n'
Mike Stroyanae0eafd2015-05-11 17:18:14 -06001453 '%s'
Jon Ashburn52c1d732015-05-12 17:23:55 -06001454 '}' % (qual, decl, ret_val, table, proto.c_call(), stmt))
Mike Stroyanae0eafd2015-05-11 17:18:14 -06001455 return "\n".join(funcs)
1456 # Functions changing command buffers need thread safe use of first parameter
1457 if proto.params[0].ty == "VkCmdBuffer":
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001458 funcs.append('%s%s\n'
1459 '{\n'
1460 ' useObject((VkObject) %s, "%s");\n'
Jon Ashburn52c1d732015-05-12 17:23:55 -06001461 ' %snext%sTable.%s;\n'
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001462 ' finishUsingObject((VkObject) %s);\n'
1463 '%s'
Jon Ashburn52c1d732015-05-12 17:23:55 -06001464 '}' % (qual, decl, proto.params[0].name, proto.params[0].ty, ret_val, table, proto.c_call(), proto.params[0].name, stmt))
Mike Stroyanae0eafd2015-05-11 17:18:14 -06001465 return "\n".join(funcs)
1466 # Non-Cmd functions that do a Wait are thread safe
1467 if 'Wait' in proto.name:
1468 return None
1469 # Watch use of certain types of objects passed as any parameter
1470 checked_params = []
1471 for param in proto.params:
1472 if param.ty in thread_check_objects:
1473 checked_params.append(param)
1474 if len(checked_params) == 0:
1475 return None
1476 # Surround call with useObject and finishUsingObject for each checked_param
1477 funcs.append('%s%s' % (qual, decl))
1478 funcs.append('{')
1479 for param in checked_params:
1480 funcs.append(' useObject((VkObject) %s, "%s");' % (param.name, param.ty))
Jon Ashburn52c1d732015-05-12 17:23:55 -06001481 funcs.append(' %snext%sTable.%s;' % (ret_val, table, proto.c_call()))
Mike Stroyanae0eafd2015-05-11 17:18:14 -06001482 for param in checked_params:
1483 funcs.append(' finishUsingObject((VkObject) %s);' % param.name)
1484 funcs.append('%s'
1485 '}' % stmt)
1486 return "\n".join(funcs)
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001487
1488 def generate_body(self):
1489 self.layer_name = "Threading"
Mike Stroyan354ed672015-05-15 08:50:57 -06001490 body = [self._generate_layer_initialization(True, lockname='threading', condname='threading'),
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001491 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
1492 self._generate_layer_gpa_function()]
1493 return "\n\n".join(body)
1494
Tobin Ehlis92dbf802014-10-22 09:06:33 -06001495def main():
1496 subcommands = {
1497 "layer-funcs" : LayerFuncsSubcommand,
1498 "layer-dispatch" : LayerDispatchSubcommand,
Tobin Ehlis907a0522014-11-25 16:59:27 -07001499 "Generic" : GenericLayerSubcommand,
Tobin Ehlis4a636a12015-04-09 09:19:36 -06001500 "APIDump" : APIDumpSubcommand,
Tobin Ehlis907a0522014-11-25 16:59:27 -07001501 "ObjectTracker" : ObjectTrackerSubcommand,
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001502 "Threading" : ThreadingSubcommand,
Tobin Ehlis92dbf802014-10-22 09:06:33 -06001503 }
1504
Tobin Ehlis6cd06372014-12-17 17:44:50 -07001505 if len(sys.argv) < 3 or sys.argv[1] not in subcommands or not os.path.exists(sys.argv[2]):
1506 print("Usage: %s <subcommand> <input_header> [options]" % sys.argv[0])
Tobin Ehlis92dbf802014-10-22 09:06:33 -06001507 print
Tobin Ehlis2f3726c2015-01-15 17:51:52 -07001508 print("Available subcommands are: %s" % " ".join(subcommands))
Tobin Ehlis92dbf802014-10-22 09:06:33 -06001509 exit(1)
1510
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001511 hfp = vk_helper.HeaderFileParser(sys.argv[2])
Tobin Ehlis6cd06372014-12-17 17:44:50 -07001512 hfp.parse()
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001513 vk_helper.enum_val_dict = hfp.get_enum_val_dict()
1514 vk_helper.enum_type_dict = hfp.get_enum_type_dict()
1515 vk_helper.struct_dict = hfp.get_struct_dict()
1516 vk_helper.typedef_fwd_dict = hfp.get_typedef_fwd_dict()
1517 vk_helper.typedef_rev_dict = hfp.get_typedef_rev_dict()
1518 vk_helper.types_dict = hfp.get_types_dict()
Tobin Ehlis6cd06372014-12-17 17:44:50 -07001519
Tobin Ehlis92dbf802014-10-22 09:06:33 -06001520 subcmd = subcommands[sys.argv[1]](sys.argv[2:])
1521 subcmd.run()
1522
1523if __name__ == "__main__":
1524 main()