blob: 8fb2b77389a59d26bdcf0b23c1188e654246c9e4 [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#
Courtney Goeltzenleuchter8a17da52015-10-29 13:50:34 -06005# Copyright (C) 2015 Valve Corporation
Michael Lentine81f1fd92015-12-03 14:33:09 -08006# Copyright (C) 2015 Google Inc.
Tobin Ehlis92dbf802014-10-22 09:06:33 -06007#
8# Permission is hereby granted, free of charge, to any person obtaining a
9# copy of this software and associated documentation files (the "Software"),
10# to deal in the Software without restriction, including without limitation
11# the rights to use, copy, modify, merge, publish, distribute, sublicense,
12# and/or sell copies of the Software, and to permit persons to whom the
13# Software is furnished to do so, subject to the following conditions:
14#
15# The above copyright notice and this permission notice shall be included
16# in all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24# DEALINGS IN THE SOFTWARE.
25#
Courtney Goeltzenleuchter96cd7952015-10-30 11:14:30 -060026# Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
27# Author: Jon Ashburn <jon@lunarg.com>
28# Author: Mark Lobodzinski <mark@lunarg.com>
29# Author: Mike Stroyan <mike@LunarG.com>
30# Author: Tony Barbour <tony@LunarG.com>
Jon Ashburn01e96962015-11-03 11:57:00 -070031# Author: Chia-I Wu <olv@lunarg.com>
Tobin Ehlis92dbf802014-10-22 09:06:33 -060032
33import sys
Tobin Ehlis6cd06372014-12-17 17:44:50 -070034import os
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -050035import re
Tobin Ehlis92dbf802014-10-22 09:06:33 -060036
Courtney Goeltzenleuchtera8c06282015-04-14 14:55:44 -060037import vulkan
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060038import vk_helper
Tobin Ehlisfde2fc32015-06-12 12:49:01 -060039from source_line_info import sourcelineinfo
Tobin Ehlis18cf7262015-08-26 11:22:09 -060040from collections import defaultdict
Tobin Ehlis92dbf802014-10-22 09:06:33 -060041
Jon Ashburn2666e2f2015-05-15 15:09:35 -060042def proto_is_global(proto):
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -070043 global_function_names = [
44 "CreateInstance",
45 "EnumerateInstanceLayerProperties",
46 "EnumerateInstanceExtensionProperties",
47 "EnumerateDeviceLayerProperties",
48 "EnumerateDeviceExtensionProperties",
49 "CreateXcbSurfaceKHR",
50 "vkGetPhysicalDeviceXcbPresentationSupportKHR",
51 "CreateXlibSurfaceKHR",
52 "vkGetPhysicalDeviceXlibPresentationSupportKHR",
53 "CreateWaylandSurfaceKHR",
54 "vkGetPhysicalDeviceWaylandPresentationSupportKHR",
55 "CreateMirSurfaceKHR",
56 "vkGetPhysicalDeviceMirPresentationSupportKHR",
57 "CreateAndroidSurfaceKHR",
58 "CreateWin32SurfaceKHR",
59 "vkGetPhysicalDeviceWin32PresentationSupportKHR"
60 ]
61 if proto.params[0].ty == "VkInstance" or proto.params[0].ty == "VkPhysicalDevice" or proto.name in global_function_names:
Jon Ashburn2666e2f2015-05-15 15:09:35 -060062 return True
63 else:
64 return False
65
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -070066def wsi_name(ext_name):
67 wsi_prefix = ""
68 if 'Xcb' in ext_name:
69 wsi_prefix = 'XCB'
70 elif 'Xlib' in ext_name:
71 wsi_prefix = 'XLIB'
72 elif 'Win32' in ext_name:
73 wsi_prefix = 'WIN32'
74 elif 'Mir' in ext_name:
75 wsi_prefix = 'MIR'
76 elif 'Wayland' in ext_name:
77 wsi_prefix = 'WAYLAND'
78 elif 'Android' in ext_name:
79 wsi_prefix = 'ANDROID'
80 else:
81 wsi_prefix = ''
82 return wsi_prefix
83
84def wsi_ifdef(ext_name):
85 wsi_prefix = wsi_name(ext_name)
86 if not wsi_prefix:
87 return ''
88 else:
89 return "#ifdef VK_USE_PLATFORM_%s_KHR" % wsi_prefix
90
91def wsi_endif(ext_name):
92 wsi_prefix = wsi_name(ext_name)
93 if not wsi_prefix:
94 return ''
95 else:
96 return "#endif // VK_USE_PLATFORM_%s_KHR" % wsi_prefix
97
Mike Stroyan7c2efaa2015-04-03 13:58:35 -060098def generate_get_proc_addr_check(name):
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060099 return " if (!%s || %s[0] != 'v' || %s[1] != 'k')\n" \
100 " return NULL;" % ((name,) * 3)
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600101
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -0500102def ucc_to_U_C_C(CamelCase):
103 temp = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', CamelCase)
104 return re.sub('([a-z0-9])([A-Z])', r'\1_\2', temp).upper()
105
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600106class Subcommand(object):
107 def __init__(self, argv):
108 self.argv = argv
Courtney Goeltzenleuchtera8c06282015-04-14 14:55:44 -0600109 self.headers = vulkan.headers
110 self.protos = vulkan.protos
Mike Stroyan3aecdb42015-04-03 17:13:23 -0600111 self.no_addr = False
112 self.layer_name = ""
Tobin Ehlisfde2fc32015-06-12 12:49:01 -0600113 self.lineinfo = sourcelineinfo()
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600114
115 def run(self):
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600116 print(self.generate())
117
118 def generate(self):
119 copyright = self.generate_copyright()
120 header = self.generate_header()
121 body = self.generate_body()
122 footer = self.generate_footer()
123
124 contents = []
125 if copyright:
126 contents.append(copyright)
127 if header:
128 contents.append(header)
129 if body:
130 contents.append(body)
131 if footer:
132 contents.append(footer)
133
134 return "\n\n".join(contents)
135
136 def generate_copyright(self):
137 return """/* THIS FILE IS GENERATED. DO NOT EDIT. */
138
139/*
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600140 *
Courtney Goeltzenleuchter8a17da52015-10-29 13:50:34 -0600141 * Copyright (C) 2015 Valve Corporation
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600142 *
143 * Permission is hereby granted, free of charge, to any person obtaining a
144 * copy of this software and associated documentation files (the "Software"),
145 * to deal in the Software without restriction, including without limitation
146 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
147 * and/or sell copies of the Software, and to permit persons to whom the
148 * Software is furnished to do so, subject to the following conditions:
149 *
150 * The above copyright notice and this permission notice shall be included
151 * in all copies or substantial portions of the Software.
152 *
153 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
154 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
155 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
156 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
157 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
158 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
159 * DEALINGS IN THE SOFTWARE.
Courtney Goeltzenleuchter96cd7952015-10-30 11:14:30 -0600160 *
161 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
162 * Author: Jon Ashburn <jon@lunarg.com>
163 * Author: Mark Lobodzinski <mark@lunarg.com>
164 * Author: Mike Stroyan <mike@LunarG.com>
165 * Author: Tony Barbour <tony@LunarG.com>
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600166 */"""
167
168 def generate_header(self):
169 return "\n".join(["#include <" + h + ">" for h in self.headers])
170
171 def generate_body(self):
172 pass
173
174 def generate_footer(self):
175 pass
176
177 # Return set of printf '%' qualifier and input to that qualifier
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600178 def _get_printf_params(self, vk_type, name, output_param, cpp=False):
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600179 # TODO : Need ENUM and STRUCT checks here
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600180 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 -0600181 return ("%s", "string_%s(%s)" % (vk_type.replace('const ', '').strip('*'), name))
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600182 if "char*" == vk_type:
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600183 return ("%s", name)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600184 if "uint64" in vk_type:
185 if '*' in vk_type:
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600186 return ("%lu", "*%s" % name)
187 return ("%lu", name)
Tobin Ehlis0b9c1952015-07-06 14:02:36 -0600188 if vk_type.strip('*') in vulkan.object_non_dispatch_list:
189 if '*' in vk_type:
Chia-I Wue420a332015-10-26 20:04:44 +0800190 return ("%lu", "%s" % name)
191 return ("%lu", "%s" % name)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600192 if "size" in vk_type:
193 if '*' in vk_type:
Mark Lobodzinskib7c5b232015-10-06 09:57:52 -0600194 return ("%lu", "(unsigned long)*%s" % name)
195 return ("%lu", "(unsigned long)%s" % name)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600196 if "float" in vk_type:
197 if '[' in vk_type: # handle array, current hard-coded to 4 (TODO: Make this dynamic)
Tobin Ehlis434db7c2015-01-10 12:42:41 -0700198 if cpp:
199 return ("[%i, %i, %i, %i]", '"[" << %s[0] << "," << %s[1] << "," << %s[2] << "," << %s[3] << "]"' % (name, name, name, name))
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600200 return ("[%f, %f, %f, %f]", "%s[0], %s[1], %s[2], %s[3]" % (name, name, name, name))
201 return ("%f", name)
Courtney Goeltzenleuchter1f41f542015-07-09 11:44:38 -0600202 if "bool" in vk_type.lower() or 'xcb_randr_crtc_t' in vk_type:
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600203 return ("%u", name)
Tobin Ehlisf29da382015-04-15 07:46:12 -0600204 if True in [t in vk_type.lower() for t in ["int", "flags", "mask", "xcb_window_t"]]:
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600205 if '[' in vk_type: # handle array, current hard-coded to 4 (TODO: Make this dynamic)
Tobin Ehlis434db7c2015-01-10 12:42:41 -0700206 if cpp:
207 return ("[%i, %i, %i, %i]", "%s[0] << %s[1] << %s[2] << %s[3]" % (name, name, name, name))
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600208 return ("[%i, %i, %i, %i]", "%s[0], %s[1], %s[2], %s[3]" % (name, name, name, name))
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600209 if '*' in vk_type:
Tobin Ehlis1336c8d2015-02-04 15:15:11 -0700210 if 'pUserData' == name:
211 return ("%i", "((pUserData == 0) ? 0 : *(pUserData))")
Tobin Ehlisa74d53a2015-04-17 13:26:33 -0600212 if 'const' in vk_type.lower():
213 return ("%p", "(void*)(%s)" % name)
Jon Ashburn1f7e2d72014-12-12 16:10:45 -0700214 return ("%i", "*(%s)" % name)
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600215 return ("%i", name)
Tobin Ehlis0a1e06d2014-11-11 17:28:22 -0700216 # 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 -0600217 if "VkFormat" == vk_type:
Tobin Ehlis434db7c2015-01-10 12:42:41 -0700218 if cpp:
219 return ("%p", "&%s" % name)
Chia-I Wuc51b1212015-10-27 19:25:11 +0800220 return ("{%s.channelFormat = %%s, %s.numericFormat = %%s}" % (name, name), "string_VK_COLOR_COMPONENT_FORMAT(%s.channelFormat), string_VK_FORMAT_RANGE_SIZE(%s.numericFormat)" % (name, name))
Tobin Ehlisa554dc32014-11-19 15:52:46 -0700221 if output_param:
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600222 return ("%p", "(void*)*%s" % name)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600223 if vk_helper.is_type(vk_type, 'struct') and '*' not in vk_type:
Courtney Goeltzenleuchter9a1ded82015-04-03 16:35:32 -0600224 return ("%p", "(void*)(&%s)" % name)
Jon Ashburn1f7e2d72014-12-12 16:10:45 -0700225 return ("%p", "(void*)(%s)" % name)
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600226
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600227 def _gen_create_msg_callback(self):
Tobin Ehlisc54139f2014-12-17 08:01:59 -0700228 r_body = []
Tobin Ehlisfde2fc32015-06-12 12:49:01 -0600229 r_body.append('%s' % self.lineinfo.get())
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +0800230 r_body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkDbgCreateMsgCallback(VkInstance instance, VkFlags msgFlags, const PFN_vkDbgMsgCallback pfnMsgCallback, void* pUserData, VkDbgMsgCallback* pMsgCallback)')
Tobin Ehlisc54139f2014-12-17 08:01:59 -0700231 r_body.append('{')
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600232 # Switch to this code section for the new per-instance storage and debug callbacks
Mike Stroyan90a166e2015-08-10 16:42:53 -0600233 if self.layer_name == 'ObjectTracker' or self.layer_name == 'Threading':
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600234 r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
235 r_body.append(' VkResult result = pInstanceTable->DbgCreateMsgCallback(instance, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);')
236 r_body.append(' if (VK_SUCCESS == result) {')
237 r_body.append(' layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
238 r_body.append(' result = layer_create_msg_callback(my_data->report_data, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);')
239 r_body.append(' }')
240 r_body.append(' return result;')
241 else:
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600242 r_body.append(' VkResult result = instance_dispatch_table(instance)->DbgCreateMsgCallback(instance, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);')
243 r_body.append(' if (VK_SUCCESS == result) {')
244 r_body.append(' layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
245 r_body.append(' result = layer_create_msg_callback(my_data->report_data, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);')
246 r_body.append(' }')
247 r_body.append(' return result;')
Tobin Ehlisc54139f2014-12-17 08:01:59 -0700248 r_body.append('}')
249 return "\n".join(r_body)
250
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600251 def _gen_destroy_msg_callback(self):
252 r_body = []
Tobin Ehlisfde2fc32015-06-12 12:49:01 -0600253 r_body.append('%s' % self.lineinfo.get())
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +0800254 r_body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkDbgDestroyMsgCallback(VkInstance instance, VkDbgMsgCallback msgCallback)')
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600255 r_body.append('{')
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600256 # Switch to this code section for the new per-instance storage and debug callbacks
Mike Stroyan90a166e2015-08-10 16:42:53 -0600257 if self.layer_name == 'ObjectTracker' or self.layer_name == 'Threading':
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600258 r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
259 r_body.append(' VkResult result = pInstanceTable->DbgDestroyMsgCallback(instance, msgCallback);')
260 r_body.append(' layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
261 r_body.append(' layer_destroy_msg_callback(my_data->report_data, msgCallback);')
262 r_body.append(' return result;')
263 else:
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600264 r_body.append(' VkResult result = instance_dispatch_table(instance)->DbgDestroyMsgCallback(instance, msgCallback);')
265 r_body.append(' layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
266 r_body.append(' layer_destroy_msg_callback(my_data->report_data, msgCallback);')
267 r_body.append(' return result;')
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600268 r_body.append('}')
269 return "\n".join(r_body)
Tobin Ehlisc54139f2014-12-17 08:01:59 -0700270
Tony Barbour426b9052015-06-24 16:06:58 -0600271 def _gen_layer_get_global_extension_props(self, layer="Generic"):
272 ggep_body = []
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600273 # generated layers do not provide any global extensions
274 ggep_body.append('%s' % self.lineinfo.get())
275
276 ggep_body.append('')
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +0800277 ggep_body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties* pProperties)')
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600278 ggep_body.append('{')
279 ggep_body.append(' return util_GetExtensionProperties(0, NULL, pCount, pProperties);')
280 ggep_body.append('}')
281 return "\n".join(ggep_body)
282
283 def _gen_layer_get_global_layer_props(self, layer="Generic"):
284 ggep_body = []
285 if layer == 'Generic':
286 # Do nothing, extension definition part of generic.h
Tony Barbour426b9052015-06-24 16:06:58 -0600287 ggep_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -0600288 else:
Tony Barbour426b9052015-06-24 16:06:58 -0600289 ggep_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter79d8d2c2015-07-07 17:51:45 -0600290 ggep_body.append('static const VkLayerProperties globalLayerProps[] = {')
Tony Barbour426b9052015-06-24 16:06:58 -0600291 ggep_body.append(' {')
Tony Barbour426b9052015-06-24 16:06:58 -0600292 ggep_body.append(' "%s",' % layer)
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600293 ggep_body.append(' VK_API_VERSION, // specVersion')
Chia-I Wu1f851912015-10-27 18:04:07 +0800294 ggep_body.append(' VK_MAKE_VERSION(0, 1, 0), // implementationVersion')
Tony Barbour426b9052015-06-24 16:06:58 -0600295 ggep_body.append(' "layer: %s",' % layer)
296 ggep_body.append(' }')
297 ggep_body.append('};')
298 ggep_body.append('')
299 ggep_body.append('%s' % self.lineinfo.get())
Tony Barbour426b9052015-06-24 16:06:58 -0600300 ggep_body.append('')
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +0800301 ggep_body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties* pProperties)')
Tony Barbour426b9052015-06-24 16:06:58 -0600302 ggep_body.append('{')
Courtney Goeltzenleuchter79d8d2c2015-07-07 17:51:45 -0600303 ggep_body.append(' return util_GetLayerProperties(ARRAY_SIZE(globalLayerProps), globalLayerProps, pCount, pProperties);')
Tony Barbour426b9052015-06-24 16:06:58 -0600304 ggep_body.append('}')
305 return "\n".join(ggep_body)
306
Courtney Goeltzenleuchter03f1c8c2015-07-06 09:11:12 -0600307 def _gen_layer_get_physical_device_layer_props(self, layer="Generic"):
308 gpdlp_body = []
309 if layer == 'Generic':
310 # Do nothing, extension definition part of generic.h
311 gpdlp_body.append('%s' % self.lineinfo.get())
312 else:
313 gpdlp_body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter79d8d2c2015-07-07 17:51:45 -0600314 gpdlp_body.append('static const VkLayerProperties deviceLayerProps[] = {')
Courtney Goeltzenleuchter03f1c8c2015-07-06 09:11:12 -0600315 gpdlp_body.append(' {')
316 gpdlp_body.append(' "%s",' % layer)
317 gpdlp_body.append(' VK_API_VERSION,')
318 gpdlp_body.append(' VK_MAKE_VERSION(0, 1, 0),')
319 gpdlp_body.append(' "layer: %s",' % layer)
320 gpdlp_body.append(' }')
321 gpdlp_body.append('};')
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +0800322 gpdlp_body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties* pProperties)')
Courtney Goeltzenleuchter03f1c8c2015-07-06 09:11:12 -0600323 gpdlp_body.append('{')
Courtney Goeltzenleuchter79d8d2c2015-07-07 17:51:45 -0600324 gpdlp_body.append(' return util_GetLayerProperties(ARRAY_SIZE(deviceLayerProps), deviceLayerProps, pCount, pProperties);')
Courtney Goeltzenleuchter03f1c8c2015-07-06 09:11:12 -0600325 gpdlp_body.append('}')
326 gpdlp_body.append('')
327 return "\n".join(gpdlp_body)
328
Mike Stroyan2ad66f12015-04-03 17:45:53 -0600329 def _generate_dispatch_entrypoints(self, qual=""):
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600330 if qual:
331 qual += " "
332
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600333 funcs = []
334 intercepted = []
335 for proto in self.protos:
Jon Ashburn1245cec2015-05-18 13:20:15 -0600336 if proto.name == "GetDeviceProcAddr" or proto.name == "GetInstanceProcAddr":
Jon Ashburn4f2575f2015-05-28 16:25:02 -0600337 continue
Mike Stroyan88f0ecf2015-04-08 10:27:43 -0600338 else:
Mike Stroyan3aecdb42015-04-03 17:13:23 -0600339 intercept = self.generate_intercept(proto, qual)
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600340 if intercept is None:
341 # fill in default intercept for certain entrypoints
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600342 if 'DbgCreateMsgCallback' == proto.name:
343 intercept = self._gen_layer_dbg_create_msg_callback()
344 elif 'DbgDestroyMsgCallback' == proto.name:
345 intercept = self._gen_layer_dbg_destroy_msg_callback()
346 elif 'CreateDevice' == proto.name:
347 funcs.append('/* CreateDevice HERE */')
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600348 elif 'EnumerateInstanceExtensionProperties' == proto.name:
Tony Barbour426b9052015-06-24 16:06:58 -0600349 intercept = self._gen_layer_get_global_extension_props(self.layer_name)
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600350 elif 'EnumerateInstanceLayerProperties' == proto.name:
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600351 intercept = self._gen_layer_get_global_layer_props(self.layer_name)
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600352 elif 'EnumerateDeviceLayerProperties' == proto.name:
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600353 intercept = self._gen_layer_get_physical_device_layer_props(self.layer_name)
Tony Barbour426b9052015-06-24 16:06:58 -0600354
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600355 if intercept is not None:
356 funcs.append(intercept)
Ian Elliott338dedb2015-08-21 15:09:33 -0600357 if not "KHR" in proto.name:
Jon Ashburn7e07faf2015-06-18 15:02:58 -0600358 intercepted.append(proto)
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600359
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600360 prefix="vk"
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600361 lookups = []
362 for proto in intercepted:
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600363 lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600364 lookups.append(" return (PFN_vkVoidFunction) %s%s;" %
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600365 (prefix, proto.name))
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600366
367 # add customized layer_intercept_proc
368 body = []
Tobin Ehlisfde2fc32015-06-12 12:49:01 -0600369 body.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600370 body.append("static inline PFN_vkVoidFunction layer_intercept_proc(const char *name)")
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600371 body.append("{")
372 body.append(generate_get_proc_addr_check("name"))
373 body.append("")
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600374 body.append(" name += 2;")
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600375 body.append(" %s" % "\n ".join(lookups))
376 body.append("")
377 body.append(" return NULL;")
378 body.append("}")
Jon Ashburn79b78ac2015-05-05 14:22:52 -0600379 # add layer_intercept_instance_proc
380 lookups = []
381 for proto in self.protos:
Jon Ashburn2666e2f2015-05-15 15:09:35 -0600382 if not proto_is_global(proto):
Jon Ashburn79b78ac2015-05-05 14:22:52 -0600383 continue
384
385 if not proto in intercepted:
386 continue
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -0600387 if proto.name == "CreateDevice":
388 continue
Jon Ashburn79b78ac2015-05-05 14:22:52 -0600389 lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600390 lookups.append(" return (PFN_vkVoidFunction) %s%s;" % (prefix, proto.name))
Jon Ashburn79b78ac2015-05-05 14:22:52 -0600391
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600392 body.append("static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char *name)")
Jon Ashburn79b78ac2015-05-05 14:22:52 -0600393 body.append("{")
394 body.append(generate_get_proc_addr_check("name"))
395 body.append("")
396 body.append(" name += 2;")
397 body.append(" %s" % "\n ".join(lookups))
398 body.append("")
399 body.append(" return NULL;")
400 body.append("}")
401
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600402 funcs.append("\n".join(body))
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600403 return "\n\n".join(funcs)
404
Tobin Ehlis3c26a542014-11-18 11:28:33 -0700405 def _generate_extensions(self):
406 exts = []
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600407 exts.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600408 exts.append(self._gen_create_msg_callback())
409 exts.append(self._gen_destroy_msg_callback())
Tobin Ehlisf29da382015-04-15 07:46:12 -0600410 return "\n".join(exts)
411
Jon Ashburn79b78ac2015-05-05 14:22:52 -0600412 def _generate_layer_gpa_function(self, extensions=[], instance_extensions=[]):
Jon Ashburn301c5f02015-04-06 10:58:22 -0600413 func_body = []
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600414#
Courtney Goeltzenleuchter03f1c8c2015-07-06 09:11:12 -0600415# New style of GPA Functions for the new layer_data/layer_logging changes
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600416#
Mike Stroyan90a166e2015-08-10 16:42:53 -0600417 if self.layer_name == 'ObjectTracker' or self.layer_name == 'Threading':
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +0800418 func_body.append("VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)\n"
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600419 "{\n"
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600420 " PFN_vkVoidFunction addr;\n"
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600421 " if (device == VK_NULL_HANDLE) {\n"
422 " return NULL;\n"
423 " }\n"
424 " /* loader uses this to force layer initialization; device object is wrapped */\n"
425 " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
426 " initDeviceTable(%s_device_table_map, (const VkBaseLayerObject *) device);\n"
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600427 " return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600428 " }\n\n"
429 " addr = layer_intercept_proc(funcName);\n"
430 " if (addr)\n"
431 " return addr;" % self.layer_name)
432 if 0 != len(extensions):
Courtney Goeltzenleuchter03f1c8c2015-07-06 09:11:12 -0600433 func_body.append('%s' % self.lineinfo.get())
434 func_body.append(' layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);')
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600435 for (ext_enable, ext_list) in extensions:
436 extra_space = ""
437 if 0 != len(ext_enable):
Courtney Goeltzenleuchter03f1c8c2015-07-06 09:11:12 -0600438 func_body.append(' if (my_device_data->%s) {' % ext_enable)
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600439 extra_space = " "
440 for ext_name in ext_list:
441 func_body.append(' %sif (!strcmp("%s", funcName))\n'
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600442 ' %sreturn reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, extra_space, ext_name))
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600443 if 0 != len(ext_enable):
444 func_body.append(' }\n')
445 func_body.append("\n if (get_dispatch_table(%s_device_table_map, device)->GetDeviceProcAddr == NULL)\n"
446 " return NULL;\n"
447 " return get_dispatch_table(%s_device_table_map, device)->GetDeviceProcAddr(device, funcName);\n"
448 "}\n" % (self.layer_name, self.layer_name))
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +0800449 func_body.append("VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600450 "{\n"
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600451 " PFN_vkVoidFunction addr;\n"
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600452 " if (instance == VK_NULL_HANDLE) {\n"
453 " return NULL;\n"
454 " }\n"
455 " /* loader uses this to force layer initialization; instance object is wrapped */\n"
456 " if (!strcmp(\"vkGetInstanceProcAddr\", funcName)) {\n"
457 " initInstanceTable(%s_instance_table_map, (const VkBaseLayerObject *) instance);\n"
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600458 " return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600459 " }\n\n"
460 " addr = layer_intercept_instance_proc(funcName);\n"
461 " if (addr) {\n"
462 " return addr;"
463 " }\n" % self.layer_name)
Jon Ashburn301c5f02015-04-06 10:58:22 -0600464
Jon Ashburnde4f1102015-09-17 10:00:32 -0600465 table_declared = False
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600466 if 0 != len(instance_extensions):
Jon Ashburnde4f1102015-09-17 10:00:32 -0600467 for (ext_enable, ext_list) in instance_extensions:
468 extra_space = ""
469 if 0 != len(ext_enable):
470 if ext_enable == 'msg_callback_get_proc_addr':
471 func_body.append(" layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);\n"
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600472 " addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);\n"
473 " if (addr) {\n"
474 " return addr;\n"
Jon Ashburnde4f1102015-09-17 10:00:32 -0600475 " }\n")
476 else:
477 if table_declared == False:
478 func_body.append(" VkLayerInstanceDispatchTable* pTable = get_dispatch_table(%s_instance_table_map, instance);" % self.layer_name)
479 table_declared = True
480 func_body.append(' if (instanceExtMap.size() != 0 && instanceExtMap[pTable].%s)' % ext_enable)
481 func_body.append(' {')
482 extra_space = " "
483 for ext_name in ext_list:
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -0700484 if wsi_name(ext_name):
485 func_body.append('%s' % wsi_ifdef(ext_name))
Jon Ashburnde4f1102015-09-17 10:00:32 -0600486 func_body.append(' %sif (!strcmp("%s", funcName))\n'
487 ' return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -0700488 if wsi_name(ext_name):
489 func_body.append('%s' % wsi_endif(ext_name))
Jon Ashburnde4f1102015-09-17 10:00:32 -0600490 if 0 != len(ext_enable):
491 func_body.append(' }\n')
492
493 func_body.append(" if (get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr == NULL) {\n"
494 " return NULL;\n"
495 " }\n"
496 " return get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr(instance, funcName);\n"
497 "}\n" % (self.layer_name, self.layer_name))
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600498 return "\n".join(func_body)
499 else:
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600500 func_body.append('%s' % self.lineinfo.get())
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +0800501 func_body.append("VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)\n"
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600502 "{\n"
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600503 " PFN_vkVoidFunction addr;\n"
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600504 " if (device == VK_NULL_HANDLE) {\n"
505 " return NULL;\n"
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600506 " }\n")
507 if self.layer_name == 'Generic':
508 func_body.append("\n"
509 " /* loader uses this to force layer initialization; device object is wrapped */\n"
510 " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
511 " initDeviceTable((const VkBaseLayerObject *) device);\n"
512 " return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
513 " }\n\n"
514 " addr = layer_intercept_proc(funcName);\n"
515 " if (addr)\n"
516 " return addr;")
517 else:
518 func_body.append("\n"
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600519 " loader_platform_thread_once(&initOnce, init%s);\n\n"
520 " /* loader uses this to force layer initialization; device object is wrapped */\n"
521 " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
522 " initDeviceTable((const VkBaseLayerObject *) device);\n"
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600523 " return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600524 " }\n\n"
525 " addr = layer_intercept_proc(funcName);\n"
526 " if (addr)\n"
527 " return addr;" % self.layer_name)
528 func_body.append('')
529 func_body.append(' VkLayerDispatchTable *pDisp = device_dispatch_table(device);')
530 if 0 != len(extensions):
531 extra_space = ""
532 for (ext_enable, ext_list) in extensions:
533 if 0 != len(ext_enable):
Jon Ashburn83334db2015-09-16 18:08:32 -0600534 func_body.append(' if (deviceExtMap.size() != 0 && deviceExtMap[pDisp].%s)' % ext_enable)
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600535 func_body.append(' {')
536 extra_space = " "
537 for ext_name in ext_list:
538 func_body.append(' %sif (!strcmp("%s", funcName))\n'
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600539 ' return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600540 if 0 != len(ext_enable):
541 func_body.append(' }')
542 func_body.append('%s' % self.lineinfo.get())
543 func_body.append(" {\n"
544 " if (pDisp->GetDeviceProcAddr == NULL)\n"
545 " return NULL;\n"
546 " return pDisp->GetDeviceProcAddr(device, funcName);\n"
547 " }\n"
548 "}\n")
Jon Ashburnde4f1102015-09-17 10:00:32 -0600549 func_body.append('%s' % self.lineinfo.get())
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +0800550 func_body.append("VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600551 "{\n"
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600552 " PFN_vkVoidFunction addr;\n"
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600553 " if (instance == VK_NULL_HANDLE) {\n"
554 " return NULL;\n"
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600555 " }\n")
556 if self.layer_name == 'Generic':
557 func_body.append("\n"
558 " /* loader uses this to force layer initialization; instance object is wrapped */\n"
559 " if (!strcmp(\"vkGetInstanceProcAddr\", funcName)) {\n"
560 " initInstanceTable((const VkBaseLayerObject *) instance);\n"
561 " return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
562 " }\n\n"
563 " addr = layer_intercept_instance_proc(funcName);\n"
564 " if (addr)\n"
565 " return addr;")
566 else:
567 func_body.append(
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600568 " loader_platform_thread_once(&initOnce, init%s);\n\n"
569 " /* loader uses this to force layer initialization; instance object is wrapped */\n"
570 " if (!strcmp(\"vkGetInstanceProcAddr\", funcName)) {\n"
571 " initInstanceTable((const VkBaseLayerObject *) instance);\n"
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600572 " return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600573 " }\n\n"
574 " addr = layer_intercept_instance_proc(funcName);\n"
575 " if (addr)\n"
576 " return addr;" % self.layer_name)
Jon Ashburnde4f1102015-09-17 10:00:32 -0600577 func_body.append("")
578 func_body.append(" VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(instance);")
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600579 if 0 != len(instance_extensions):
Jon Ashburnde4f1102015-09-17 10:00:32 -0600580 extra_space = ""
581 for (ext_enable, ext_list) in instance_extensions:
582 if 0 != len(ext_enable):
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600583 if ext_enable == 'msg_callback_get_proc_addr':
584 func_body.append(" layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);\n"
585 " addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);\n"
586 " if (addr) {\n"
587 " return addr;\n"
588 " }\n")
589 else:
590 func_body.append(' if (instanceExtMap.size() != 0 && instanceExtMap[pTable].%s)' % ext_enable)
591 func_body.append(' {')
592 extra_space = " "
593 for ext_name in ext_list:
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -0700594 if wsi_name(ext_name):
595 func_body.append('%s' % wsi_ifdef(ext_name))
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600596 func_body.append(' %sif (!strcmp("%s", funcName))\n'
Jon Ashburnde4f1102015-09-17 10:00:32 -0600597 ' return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -0700598 if wsi_name(ext_name):
599 func_body.append('%s' % wsi_endif(ext_name))
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600600 if 0 != len(ext_enable):
601 func_body.append(' }\n')
Jon Ashburnde4f1102015-09-17 10:00:32 -0600602
603 func_body.append(" if (pTable->GetInstanceProcAddr == NULL)\n"
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600604 " return NULL;\n"
605 " return pTable->GetInstanceProcAddr(instance, funcName);\n"
606 "}\n")
607 return "\n".join(func_body)
Jon Ashburn79b78ac2015-05-05 14:22:52 -0600608
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600609
Mike Stroyan354ed672015-05-15 08:50:57 -0600610 def _generate_layer_initialization(self, init_opts=False, prefix='vk', lockname=None, condname=None):
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600611 func_body = ["#include \"vk_dispatch_table_helper.h\""]
Tobin Ehlisfde2fc32015-06-12 12:49:01 -0600612 func_body.append('%s' % self.lineinfo.get())
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600613 func_body.append('static void init%s(layer_data *my_data)\n'
Mike Stroyan3aecdb42015-04-03 17:13:23 -0600614 '{\n' % self.layer_name)
Jon Ashburn21001f62015-02-16 08:26:50 -0700615 if init_opts:
Tobin Ehlisfde2fc32015-06-12 12:49:01 -0600616 func_body.append('%s' % self.lineinfo.get())
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600617 func_body.append(' uint32_t report_flags = 0;')
618 func_body.append(' uint32_t debug_action = 0;')
619 func_body.append(' FILE *log_output = NULL;')
620 func_body.append(' const char *option_str;\n')
Mike Stroyan3aecdb42015-04-03 17:13:23 -0600621 func_body.append(' // initialize %s options' % self.layer_name)
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600622 func_body.append(' report_flags = getLayerOptionFlags("%sReportFlags", 0);' % self.layer_name)
623 func_body.append(' getLayerOptionEnum("%sDebugAction", (uint32_t *) &debug_action);' % self.layer_name)
Jon Ashburn21001f62015-02-16 08:26:50 -0700624 func_body.append('')
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600625 func_body.append(' if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)')
Jon Ashburn21001f62015-02-16 08:26:50 -0700626 func_body.append(' {')
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600627 func_body.append(' option_str = getLayerOption("%sLogFilename");' % self.layer_name)
628 func_body.append(' log_output = getLayerLogOutput(option_str,"%s");' % self.layer_name)
629 func_body.append(' layer_create_msg_callback(my_data->report_data, report_flags,')
630 func_body.append(' log_callback, (void *) log_output,')
631 func_body.append(' &my_data->logging_callback);')
Jon Ashburn21001f62015-02-16 08:26:50 -0700632 func_body.append(' }')
633 func_body.append('')
Tobin Ehlis84a8a9b2015-02-23 14:09:16 -0700634 if lockname is not None:
Tobin Ehlisfde2fc32015-06-12 12:49:01 -0600635 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlis84a8a9b2015-02-23 14:09:16 -0700636 func_body.append(" if (!%sLockInitialized)" % lockname)
637 func_body.append(" {")
638 func_body.append(" // TODO/TBD: Need to delete this mutex sometime. How???")
639 func_body.append(" loader_platform_thread_create_mutex(&%sLock);" % lockname)
Mike Stroyan354ed672015-05-15 08:50:57 -0600640 if condname is not None:
641 func_body.append(" loader_platform_thread_init_cond(&%sCond);" % condname)
Tobin Ehlis84a8a9b2015-02-23 14:09:16 -0700642 func_body.append(" %sLockInitialized = 1;" % lockname)
643 func_body.append(" }")
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600644 func_body.append("}\n")
Jon Ashburnd9564002015-05-07 10:27:37 -0600645 func_body.append('')
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600646 return "\n".join(func_body)
647
Mike Stroyan90a166e2015-08-10 16:42:53 -0600648 def _generate_new_layer_initialization(self, init_opts=False, prefix='vk', lockname=None, condname=None):
649 func_body = ["#include \"vk_dispatch_table_helper.h\""]
650 func_body.append('%s' % self.lineinfo.get())
651 func_body.append('static void init%s(layer_data *my_data)\n'
652 '{\n' % self.layer_name)
653 if init_opts:
654 func_body.append('%s' % self.lineinfo.get())
655 func_body.append(' uint32_t report_flags = 0;')
656 func_body.append(' uint32_t debug_action = 0;')
657 func_body.append(' FILE *log_output = NULL;')
658 func_body.append(' const char *strOpt;')
659 func_body.append(' // initialize %s options' % self.layer_name)
660 func_body.append(' report_flags = getLayerOptionFlags("%sReportFlags", 0);' % self.layer_name)
Jon Ashburnf73135a2015-10-06 17:20:01 -0600661 func_body.append(' getLayerOptionEnum("%sDebugAction", (uint32_t *) &debug_action);' % self.layer_name)
Mike Stroyan90a166e2015-08-10 16:42:53 -0600662 func_body.append('')
663 func_body.append(' if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)')
664 func_body.append(' {')
665 func_body.append(' strOpt = getLayerOption("%sLogFilename");' % self.layer_name)
Tobin Ehlisb4b6e7c2015-09-15 09:55:54 -0600666 func_body.append(' log_output = getLayerLogOutput(strOpt, "%s");' % self.layer_name)
Mike Stroyan90a166e2015-08-10 16:42:53 -0600667 func_body.append(' layer_create_msg_callback(my_data->report_data, report_flags, log_callback, (void *) log_output, &my_data->logging_callback);')
668 func_body.append(' }')
669 func_body.append('')
670 if lockname is not None:
671 func_body.append('%s' % self.lineinfo.get())
672 func_body.append(" if (!%sLockInitialized)" % lockname)
673 func_body.append(" {")
674 func_body.append(" // TODO/TBD: Need to delete this mutex sometime. How???")
675 func_body.append(" loader_platform_thread_create_mutex(&%sLock);" % lockname)
676 if condname is not None:
677 func_body.append(" loader_platform_thread_init_cond(&%sCond);" % condname)
678 func_body.append(" %sLockInitialized = 1;" % lockname)
679 func_body.append(" }")
680 func_body.append("}\n")
681 func_body.append('')
682 return "\n".join(func_body)
683
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600684class LayerFuncsSubcommand(Subcommand):
685 def generate_header(self):
David Pinedo329ca9e2015-11-06 12:54:48 -0700686 return '#include <vulkan/vk_layer.h>\n#include "loader.h"'
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600687
688 def generate_body(self):
Mike Stroyan3aecdb42015-04-03 17:13:23 -0600689 return self._generate_dispatch_entrypoints("static")
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600690
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600691class GenericLayerSubcommand(Subcommand):
692 def generate_header(self):
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -0500693 gen_header = []
Courtney Goeltzenleuchter79d8d2c2015-07-07 17:51:45 -0600694 gen_header.append('%s' % self.lineinfo.get())
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -0500695 gen_header.append('#include <stdio.h>')
696 gen_header.append('#include <stdlib.h>')
697 gen_header.append('#include <string.h>')
698 gen_header.append('#include <unordered_map>')
Tobin Ehlis7a51d902015-07-03 10:34:49 -0600699 gen_header.append('#include "vk_loader_platform.h"')
David Pinedo329ca9e2015-11-06 12:54:48 -0700700 gen_header.append('#include "vulkan/vk_layer.h"')
Tobin Ehlis56d204a2015-07-03 10:15:26 -0600701 gen_header.append('#include "vk_layer_config.h"')
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600702 gen_header.append('#include "vk_layer_logging.h"')
Tobin Ehlis56d204a2015-07-03 10:15:26 -0600703 gen_header.append('#include "vk_layer_table.h"')
Courtney Goeltzenleuchter03f1c8c2015-07-06 09:11:12 -0600704 gen_header.append('#include "vk_layer_extension_utils.h"')
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -0500705 gen_header.append('')
Courtney Goeltzenleuchter79d8d2c2015-07-07 17:51:45 -0600706 gen_header.append('#include "generic.h"')
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600707 gen_header.append('')
Tobin Ehlis0b9c1952015-07-06 14:02:36 -0600708 gen_header.append('%s' % self.lineinfo.get())
709 gen_header.append('#define LAYER_EXT_ARRAY_SIZE 1')
710 gen_header.append('#define LAYER_DEV_EXT_ARRAY_SIZE 1')
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600711 gen_header.append('//static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
712 gen_header.append('static std::unordered_map<void *, layer_data *> layer_data_map;\n')
713 gen_header.append('template layer_data *get_my_data_ptr<layer_data>(')
714 gen_header.append(' void *data_key,')
715 gen_header.append(' std::unordered_map<void *, layer_data *> &data_map);\n')
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -0500716 gen_header.append('')
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -0500717 return "\n".join(gen_header)
Tobin Ehlis65d94ad2015-07-07 11:02:44 -0600718
Mike Stroyan3aecdb42015-04-03 17:13:23 -0600719 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600720 if proto.name in [ 'EnumerateInstanceLayerProperties', 'EnumerateInstanceExtensionProperties', 'EnumerateDeviceLayerProperties', 'EnumerateDeviceExtensionProperties' ]:
Mike Stroyan723913e2015-04-03 14:39:16 -0600721 # use default version
722 return None
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600723 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600724 ret_val = ''
725 stmt = ''
726 funcs = []
Jon Ashburn52c1d732015-05-12 17:23:55 -0600727 table = ''
Jon Ashburn2666e2f2015-05-15 15:09:35 -0600728 if proto_is_global(proto):
Jon Ashburn52c1d732015-05-12 17:23:55 -0600729 table = 'Instance'
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600730 if proto.ret != "void":
Courtney Goeltzenleuchter4843dda2015-06-26 15:07:53 -0600731 funcs.append('%s' % self.lineinfo.get())
Jon Ashburn53c16772015-05-06 10:15:07 -0600732 ret_val = "%s result = " % proto.ret
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600733 stmt = " return result;\n"
Jon Ashburn7cdb8c32015-05-22 12:01:50 -0600734 if proto.name == "CreateDevice":
Courtney Goeltzenleuchter4843dda2015-06-26 15:07:53 -0600735 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600736 funcs.append('%s%s\n'
737 '{\n'
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -0500738 ' char str[1024];\n'
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600739 ' layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);\n'
740 ' sprintf(str, "At start of Generic layered %s\\n");\n'
Courtney Goeltzenleuchterf8fe1282015-11-25 10:30:56 -0700741 ' log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT, VK_OBJECT_TYPE_PHYSICAL_DEVICE,'
Michael Lentinecbc4a5e2015-11-03 16:19:46 -0800742 ' (uint64_t)physicalDevice, 0, 0, (char *) "Generic", "%%s", (char *) str);\n'
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -0600743 ' %sdevice_dispatch_table(*pDevice)->%s;\n'
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600744 ' if (result == VK_SUCCESS) {\n'
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600745 ' my_data->report_data = layer_debug_report_create_device(my_data->report_data, *pDevice);\n'
Jon Ashburn7e07faf2015-06-18 15:02:58 -0600746 ' createDeviceRegisterExtensions(pCreateInfo, *pDevice);\n'
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600747 ' }\n'
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600748 ' sprintf(str, "Completed Generic layered %s\\n");\n'
Courtney Goeltzenleuchterf8fe1282015-11-25 10:30:56 -0700749 ' log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT, VK_OBJECT_TYPE_PHYSICAL_DEVICE, (uint64_t)physicalDevice, 0, 0, (char *) "Generic", "%%s", (char *) str);\n'
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -0500750 ' %s'
751 '}' % (qual, decl, proto.name, ret_val, proto.c_call(), proto.name, stmt))
752 elif proto.name == "DestroyDevice":
Courtney Goeltzenleuchter4843dda2015-06-26 15:07:53 -0600753 funcs.append('%s' % self.lineinfo.get())
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -0500754 funcs.append('%s%s\n'
755 '{\n'
Courtney Goeltzenleuchter9f171942015-06-13 21:22:12 -0600756 ' dispatch_key key = get_dispatch_key(device);\n'
Jon Ashburn7e07faf2015-06-18 15:02:58 -0600757 ' VkLayerDispatchTable *pDisp = device_dispatch_table(device);\n'
Chia-I Wu69f40122015-10-26 21:10:41 +0800758 ' pDisp->DestroyDevice(device, pAllocator);\n'
Jon Ashburn7e07faf2015-06-18 15:02:58 -0600759 ' deviceExtMap.erase(pDisp);\n'
Courtney Goeltzenleuchter9f171942015-06-13 21:22:12 -0600760 ' destroy_device_dispatch_table(key);\n'
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -0500761 '}\n' % (qual, decl))
762 elif proto.name == "DestroyInstance":
Courtney Goeltzenleuchter4843dda2015-06-26 15:07:53 -0600763 funcs.append('%s' % self.lineinfo.get())
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -0500764 funcs.append('%s%s\n'
765 '{\n'
Courtney Goeltzenleuchter9f171942015-06-13 21:22:12 -0600766 ' dispatch_key key = get_dispatch_key(instance);\n'
Jon Ashburnde4f1102015-09-17 10:00:32 -0600767 ' VkLayerInstanceDispatchTable *pDisp = instance_dispatch_table(instance);\n'
Chia-I Wu69f40122015-10-26 21:10:41 +0800768 ' pDisp->DestroyInstance(instance, pAllocator);\n'
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600769 ' // Clean up logging callback, if any\n'
770 ' layer_data *my_data = get_my_data_ptr(key, layer_data_map);\n'
771 ' if (my_data->logging_callback) {\n'
772 ' layer_destroy_msg_callback(my_data->report_data, my_data->logging_callback);\n'
773 ' }\n\n'
774 ' layer_debug_report_destroy_instance(my_data->report_data);\n'
775 ' layer_data_map.erase(key);\n'
Jon Ashburnde4f1102015-09-17 10:00:32 -0600776 ' instanceExtMap.erase(pDisp);\n'
Courtney Goeltzenleuchter9f171942015-06-13 21:22:12 -0600777 ' destroy_instance_dispatch_table(key);\n'
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -0500778 '}\n' % (qual, decl))
Jon Ashburnde4f1102015-09-17 10:00:32 -0600779 elif proto.name == "CreateInstance":
Courtney Goeltzenleuchter4843dda2015-06-26 15:07:53 -0600780 funcs.append('%s' % self.lineinfo.get())
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -0500781 # CreateInstance needs to use the second parm instead of the first to set the correct dispatch table
Jon Ashburnde4f1102015-09-17 10:00:32 -0600782 funcs.append('%s%s\n'
783 '{\n'
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600784 ' char str[1024];\n'
Jon Ashburnde4f1102015-09-17 10:00:32 -0600785 ' %sinstance_dispatch_table(*pInstance)->%s;\n'
786 ' if (result == VK_SUCCESS) {\n'
787 ' createInstanceRegisterExtensions(pCreateInfo, *pInstance);\n'
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600788 ' layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);\n'
789 ' my_data->report_data = debug_report_create_instance(\n'
790 ' instance_dispatch_table(*pInstance),\n'
791 ' *pInstance,\n'
Chia-I Wu763a7492015-10-26 20:48:51 +0800792 ' pCreateInfo->enabledExtensionNameCount,\n'
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600793 ' pCreateInfo->ppEnabledExtensionNames);\n'
794 ' initGeneric(my_data);\n'
795 ' sprintf(str, "Completed Generic layered %s\\n");\n'
Courtney Goeltzenleuchterf8fe1282015-11-25 10:30:56 -0700796 ' log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT, VK_OBJECT_TYPE_INSTANCE, (uint64_t)*pInstance, 0, 0, (char *) "Generic", "%%s", (char *) str);\n'
Jon Ashburnde4f1102015-09-17 10:00:32 -0600797 ' }\n'
Tobin Ehlis488e9202015-09-17 16:27:04 -0600798 ' return result;\n'
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600799 '}\n' % (qual, decl, ret_val, proto.c_call(), proto.name))
Jon Ashburnde4f1102015-09-17 10:00:32 -0600800 else:
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -0700801 if wsi_name(proto.name):
802 funcs.append('%s' % wsi_ifdef(proto.name))
Jon Ashburnde4f1102015-09-17 10:00:32 -0600803 funcs.append('%s' % self.lineinfo.get())
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -0500804 dispatch_param = proto.params[0].name
805 # Must use 'instance' table for these APIs, 'device' table otherwise
806 table_type = ""
807 if proto_is_global(proto):
808 table_type = "instance"
809 else:
810 table_type = "device"
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600811 funcs.append('%s%s\n'
812 '{\n'
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -0500813 ' %s%s_dispatch_table(%s)->%s;\n'
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600814 '%s'
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -0500815 '}' % (qual, decl, ret_val, table_type, dispatch_param, proto.c_call(), stmt))
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -0700816 if wsi_name(proto.name):
817 funcs.append('%s' % wsi_endif(proto.name))
Mike Stroyan7c2efaa2015-04-03 13:58:35 -0600818 return "\n\n".join(funcs)
819
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600820 def generate_body(self):
Mike Stroyan3aecdb42015-04-03 17:13:23 -0600821 self.layer_name = "Generic"
Jon Ashburn649d0ca2015-10-06 17:05:21 -0600822 instance_extensions=[('msg_callback_get_proc_addr', []),
823 ('wsi_enabled',
Ian Elliottc623ba52015-11-20 14:13:17 -0700824 ['vkGetPhysicalDeviceSurfaceSupportKHR',
825 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
826 'vkGetPhysicalDeviceSurfaceFormatsKHR',
827 'vkGetPhysicalDeviceSurfacePresentModesKHR'])]
Ian Elliottb134e842015-07-06 14:31:32 -0600828 extensions=[('wsi_enabled',
Ian Elliottc623ba52015-11-20 14:13:17 -0700829 ['vkCreateSwapchainKHR',
Jon Ashburn83334db2015-09-16 18:08:32 -0600830 'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
831 'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
Mike Stroyan3aecdb42015-04-03 17:13:23 -0600832 body = [self._generate_layer_initialization(True),
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600833 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600834 self._gen_create_msg_callback(),
835 self._gen_destroy_msg_callback(),
Jon Ashburnde4f1102015-09-17 10:00:32 -0600836 self._generate_layer_gpa_function(extensions, instance_extensions)]
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600837
838 return "\n\n".join(body)
839
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600840class APIDumpSubcommand(Subcommand):
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600841 def generate_header(self):
Tobin Ehlis0c68c9c2014-11-24 15:46:55 -0700842 header_txt = []
Tobin Ehlisfde2fc32015-06-12 12:49:01 -0600843 header_txt.append('%s' % self.lineinfo.get())
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600844 header_txt.append('#include <fstream>')
845 header_txt.append('#include <iostream>')
846 header_txt.append('#include <string>')
Jon Ashburn7e07faf2015-06-18 15:02:58 -0600847 header_txt.append('#include <string.h>')
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600848 header_txt.append('')
Tobin Ehlisdc749502015-08-28 09:57:53 -0600849 header_txt.append('#include "vk_loader_platform.h"')
David Pinedo329ca9e2015-11-06 12:54:48 -0700850 header_txt.append('#include "vulkan/vk_layer.h"')
Tobin Ehlisdc749502015-08-28 09:57:53 -0600851 header_txt.append('#include "vk_struct_string_helper_cpp.h"')
852 header_txt.append('#include "vk_layer_table.h"')
853 header_txt.append('#include "vk_layer_extension_utils.h"')
854 header_txt.append('#include <unordered_map>')
Jon Ashburnd3e4a762015-09-17 15:28:12 -0600855 header_txt.append('#include "apidump.h"')
Tobin Ehlisdc749502015-08-28 09:57:53 -0600856 header_txt.append('')
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600857 header_txt.append('static std::ofstream fileStream;')
858 header_txt.append('static std::string fileName = "vk_apidump.txt";')
859 header_txt.append('std::ostream* outputStream = NULL;')
860 header_txt.append('void ConfigureOutputStream(bool writeToFile, bool flushAfterWrite)')
861 header_txt.append('{')
862 header_txt.append(' if(writeToFile)')
863 header_txt.append(' {')
Tobin Ehlisebd34682015-09-18 14:32:12 -0600864 header_txt.append(' if (fileName == "stdout")')
865 header_txt.append(' {')
Tobin Ehlisdc749502015-08-28 09:57:53 -0600866 header_txt.append(' outputStream = &std::cout;')
Tobin Ehlisebd34682015-09-18 14:32:12 -0600867 header_txt.append(' (*outputStream) << endl << "APIDump output filename \'stdout\' specified. Writing to STDOUT instead of a file." << endl << endl;')
868 header_txt.append(' } else {')
869 header_txt.append(' fileStream.open(fileName);')
870 header_txt.append(' if ((fileStream.rdstate() & fileStream.failbit) != 0) {')
871 header_txt.append(' outputStream = &std::cout;')
872 header_txt.append(' (*outputStream) << endl << "APIDump ERROR: Bad output filename specified: " << fileName << ". Writing to STDOUT instead" << endl << endl;')
873 header_txt.append(' }')
874 header_txt.append(' else')
875 header_txt.append(' outputStream = &fileStream;')
Tobin Ehlisdc749502015-08-28 09:57:53 -0600876 header_txt.append(' }')
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600877 header_txt.append(' }')
878 header_txt.append(' else')
879 header_txt.append(' {')
880 header_txt.append(' outputStream = &std::cout;')
881 header_txt.append(' }')
882 header_txt.append('')
883 header_txt.append(' if(flushAfterWrite)')
884 header_txt.append(' {')
885 header_txt.append(' outputStream->sync_with_stdio(true);')
886 header_txt.append(' }')
887 header_txt.append(' else')
888 header_txt.append(' {')
889 header_txt.append(' outputStream->sync_with_stdio(false);')
890 header_txt.append(' }')
891 header_txt.append('}')
892 header_txt.append('')
Tobin Ehlisfde2fc32015-06-12 12:49:01 -0600893 header_txt.append('%s' % self.lineinfo.get())
Jon Ashburn301c5f02015-04-06 10:58:22 -0600894 header_txt.append('static VkBaseLayerObject *pCurObj;')
Tobin Ehlis55c40412015-04-27 17:30:04 -0600895 header_txt.append('static bool g_APIDumpDetailed = true;')
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600896 header_txt.append('')
Jon Ashburnd9564002015-05-07 10:27:37 -0600897 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
Mark Lobodzinskibf7c7002015-05-26 09:29:09 -0500898 header_txt.append('')
Ian Elliott81ac44c2015-01-13 17:52:38 -0700899 header_txt.append('static int printLockInitialized = 0;')
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600900 header_txt.append('static loader_platform_thread_mutex printLock;')
901 header_txt.append('')
Tobin Ehlisfde2fc32015-06-12 12:49:01 -0600902 header_txt.append('%s' % self.lineinfo.get())
Tobin Ehlis0b9c1952015-07-06 14:02:36 -0600903 header_txt.append('#define LAYER_EXT_ARRAY_SIZE 1')
904 header_txt.append('#define LAYER_DEV_EXT_ARRAY_SIZE 1')
Tobin Ehlis0c68c9c2014-11-24 15:46:55 -0700905 header_txt.append('#define MAX_TID 513')
Ian Elliott81ac44c2015-01-13 17:52:38 -0700906 header_txt.append('static loader_platform_thread_id tidMapping[MAX_TID] = {0};')
Tobin Ehlis0c68c9c2014-11-24 15:46:55 -0700907 header_txt.append('static uint32_t maxTID = 0;')
908 header_txt.append('// Map actual TID to an index value and return that index')
909 header_txt.append('// This keeps TIDs in range from 0-MAX_TID and simplifies compares between runs')
910 header_txt.append('static uint32_t getTIDIndex() {')
Ian Elliott81ac44c2015-01-13 17:52:38 -0700911 header_txt.append(' loader_platform_thread_id tid = loader_platform_get_thread_id();')
Tobin Ehlis0c68c9c2014-11-24 15:46:55 -0700912 header_txt.append(' for (uint32_t i = 0; i < maxTID; i++) {')
913 header_txt.append(' if (tid == tidMapping[i])')
914 header_txt.append(' return i;')
915 header_txt.append(' }')
916 header_txt.append(" // Don't yet have mapping, set it and return newly set index")
Ian Elliott81ac44c2015-01-13 17:52:38 -0700917 header_txt.append(' uint32_t retVal = (uint32_t) maxTID;')
Tobin Ehlis0c68c9c2014-11-24 15:46:55 -0700918 header_txt.append(' tidMapping[maxTID++] = tid;')
919 header_txt.append(' assert(maxTID < MAX_TID);')
920 header_txt.append(' return retVal;')
921 header_txt.append('}')
Mark Lobodzinskibf7c7002015-05-26 09:29:09 -0500922 header_txt.append('')
Chia-I Wu1f851912015-10-27 18:04:07 +0800923 header_txt.append('void interpret_memBarriers(const void* const* ppMemoryBarriers, uint32_t memoryBarrierCount)')
Mark Lobodzinski98586a92015-07-30 10:11:32 -0600924 header_txt.append('{')
Chia-I Wu1f851912015-10-27 18:04:07 +0800925 header_txt.append(' if (ppMemoryBarriers) {')
Mark Lobodzinski98586a92015-07-30 10:11:32 -0600926 header_txt.append(' string tmp_str;')
Chia-I Wu1f851912015-10-27 18:04:07 +0800927 header_txt.append(' for (uint32_t i = 0; i < memoryBarrierCount; i++) {')
928 header_txt.append(' switch(*(VkStructureType*)ppMemoryBarriers[i])')
Mark Lobodzinski98586a92015-07-30 10:11:32 -0600929 header_txt.append(' {')
930 header_txt.append(' case VK_STRUCTURE_TYPE_MEMORY_BARRIER:')
Chia-I Wu1f851912015-10-27 18:04:07 +0800931 header_txt.append(' tmp_str = vk_print_vkmemorybarrier((VkMemoryBarrier*)ppMemoryBarriers[i], " ");')
Mark Lobodzinski98586a92015-07-30 10:11:32 -0600932 header_txt.append(' break;')
933 header_txt.append(' case VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER:')
Chia-I Wu1f851912015-10-27 18:04:07 +0800934 header_txt.append(' tmp_str = vk_print_vkbuffermemorybarrier((VkBufferMemoryBarrier*)ppMemoryBarriers[i], " ");')
Mark Lobodzinski98586a92015-07-30 10:11:32 -0600935 header_txt.append(' break;')
936 header_txt.append(' case VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER:')
Chia-I Wu1f851912015-10-27 18:04:07 +0800937 header_txt.append(' tmp_str = vk_print_vkimagememorybarrier((VkImageMemoryBarrier*)ppMemoryBarriers[i], " ");')
Mark Lobodzinski98586a92015-07-30 10:11:32 -0600938 header_txt.append(' break;')
939 header_txt.append(' default:')
940 header_txt.append(' break;')
941 header_txt.append(' }')
942 header_txt.append('')
943 header_txt.append(' if (StreamControl::writeAddress == true) {')
Chia-I Wu1f851912015-10-27 18:04:07 +0800944 header_txt.append(' (*outputStream) << " ppMemoryBarriers[" << i << "] (" << &ppMemoryBarriers[i] << ")" << endl << tmp_str << endl;')
Mark Lobodzinski98586a92015-07-30 10:11:32 -0600945 header_txt.append(' } else {')
Chia-I Wu1f851912015-10-27 18:04:07 +0800946 header_txt.append(' (*outputStream) << " ppMemoryBarriers[" << i << "] (address)" << endl << " address" << endl;')
Mark Lobodzinski98586a92015-07-30 10:11:32 -0600947 header_txt.append(' }')
948 header_txt.append(' }')
949 header_txt.append(' }')
950 header_txt.append('}')
951 header_txt.append('')
Tobin Ehlis0c68c9c2014-11-24 15:46:55 -0700952 return "\n".join(header_txt)
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600953
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600954 def generate_init(self):
955 func_body = []
Tobin Ehlisfde2fc32015-06-12 12:49:01 -0600956 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600957 func_body.append('#include "vk_dispatch_table_helper.h"')
Tobin Ehlis56d204a2015-07-03 10:15:26 -0600958 func_body.append('#include "vk_layer_config.h"')
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600959 func_body.append('')
960 func_body.append('static void init%s(void)' % self.layer_name)
961 func_body.append('{')
962 func_body.append(' using namespace StreamControl;')
963 func_body.append('')
Tobin Ehlis3234aba2015-08-26 16:18:52 -0600964 func_body.append(' char const*const logName = getLayerOption("APIDumpLogFilename");')
965 func_body.append(' if(logName != NULL)')
966 func_body.append(' {')
967 func_body.append(' fileName = logName;')
968 func_body.append(' }')
969 func_body.append('')
Tobin Ehlis55c40412015-04-27 17:30:04 -0600970 func_body.append(' char const*const detailedStr = getLayerOption("APIDumpDetailed");')
971 func_body.append(' if(detailedStr != NULL)')
972 func_body.append(' {')
973 func_body.append(' if(strcmp(detailedStr, "TRUE") == 0)')
974 func_body.append(' {')
975 func_body.append(' g_APIDumpDetailed = true;')
976 func_body.append(' }')
977 func_body.append(' else if(strcmp(detailedStr, "FALSE") == 0)')
978 func_body.append(' {')
979 func_body.append(' g_APIDumpDetailed = false;')
980 func_body.append(' }')
981 func_body.append(' }')
982 func_body.append('')
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600983 func_body.append(' char const*const writeToFileStr = getLayerOption("APIDumpFile");')
984 func_body.append(' bool writeToFile = false;')
985 func_body.append(' if(writeToFileStr != NULL)')
986 func_body.append(' {')
987 func_body.append(' if(strcmp(writeToFileStr, "TRUE") == 0)')
988 func_body.append(' {')
989 func_body.append(' writeToFile = true;')
990 func_body.append(' }')
991 func_body.append(' else if(strcmp(writeToFileStr, "FALSE") == 0)')
992 func_body.append(' {')
993 func_body.append(' writeToFile = false;')
994 func_body.append(' }')
995 func_body.append(' }')
996 func_body.append('')
Tobin Ehlisfde2fc32015-06-12 12:49:01 -0600997 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlis4a636a12015-04-09 09:19:36 -0600998 func_body.append(' char const*const noAddrStr = getLayerOption("APIDumpNoAddr");')
999 func_body.append(' if(noAddrStr != NULL)')
1000 func_body.append(' {')
1001 func_body.append(' if(strcmp(noAddrStr, "FALSE") == 0)')
1002 func_body.append(' {')
1003 func_body.append(' StreamControl::writeAddress = true;')
1004 func_body.append(' }')
1005 func_body.append(' else if(strcmp(noAddrStr, "TRUE") == 0)')
1006 func_body.append(' {')
1007 func_body.append(' StreamControl::writeAddress = false;')
1008 func_body.append(' }')
1009 func_body.append(' }')
1010 func_body.append('')
1011 func_body.append(' char const*const flushAfterWriteStr = getLayerOption("APIDumpFlush");')
1012 func_body.append(' bool flushAfterWrite = false;')
1013 func_body.append(' if(flushAfterWriteStr != NULL)')
1014 func_body.append(' {')
1015 func_body.append(' if(strcmp(flushAfterWriteStr, "TRUE") == 0)')
1016 func_body.append(' {')
1017 func_body.append(' flushAfterWrite = true;')
1018 func_body.append(' }')
1019 func_body.append(' else if(strcmp(flushAfterWriteStr, "FALSE") == 0)')
1020 func_body.append(' {')
1021 func_body.append(' flushAfterWrite = false;')
1022 func_body.append(' }')
1023 func_body.append(' }')
1024 func_body.append('')
Tobin Ehlisfde2fc32015-06-12 12:49:01 -06001025 func_body.append('%s' % self.lineinfo.get())
Tobin Ehlis4a636a12015-04-09 09:19:36 -06001026 func_body.append(' ConfigureOutputStream(writeToFile, flushAfterWrite);')
1027 func_body.append('')
Tobin Ehlis4a636a12015-04-09 09:19:36 -06001028 func_body.append(' if (!printLockInitialized)')
1029 func_body.append(' {')
1030 func_body.append(' // TODO/TBD: Need to delete this mutex sometime. How???')
1031 func_body.append(' loader_platform_thread_create_mutex(&printLock);')
1032 func_body.append(' printLockInitialized = 1;')
1033 func_body.append(' }')
1034 func_body.append('}')
1035 func_body.append('')
1036 return "\n".join(func_body)
Tobin Ehlis434db7c2015-01-10 12:42:41 -07001037
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001038 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001039 if proto.name in [ 'EnumerateInstanceLayerProperties','EnumerateInstanceExtensionProperties','EnumerateDeviceLayerProperties','EnumerateDeviceExtensionProperties']:
Jon Ashburneb2728b2015-04-10 14:33:07 -06001040 return None
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001041 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001042 ret_val = ''
1043 stmt = ''
1044 funcs = []
1045 sp_param_dict = {} # Store 'index' for struct param to print, or an name of binding "Count" param for array to print
1046 create_params = 0 # Num of params at end of function that are created and returned as output values
Chia-I Wu1f851912015-10-27 18:04:07 +08001047 if 'AllocateDescriptorSets' in proto.name:
Cody Northropc8aa4a52015-08-03 12:47:29 -06001048 create_params = -1
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001049 elif 'Create' in proto.name or 'Alloc' in proto.name or 'MapMemory' in proto.name:
1050 create_params = -1
1051 if proto.ret != "void":
Jon Ashburn53c16772015-05-06 10:15:07 -06001052 ret_val = "%s result = " % proto.ret
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001053 stmt = " return result;\n"
Tobin Ehlis4a636a12015-04-09 09:19:36 -06001054 f_open = 'loader_platform_thread_lock_mutex(&printLock);\n '
Tobin Ehlisfde2fc32015-06-12 12:49:01 -06001055 log_func = '%s\n' % self.lineinfo.get()
1056 log_func += ' if (StreamControl::writeAddress == true) {'
Tobin Ehlis4a636a12015-04-09 09:19:36 -06001057 log_func += '\n (*outputStream) << "t{" << getTIDIndex() << "} vk%s(' % proto.name
1058 log_func_no_addr = '\n (*outputStream) << "t{" << getTIDIndex() << "} vk%s(' % proto.name
1059 f_close = '\n loader_platform_thread_unlock_mutex(&printLock);'
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001060 pindex = 0
1061 prev_count_name = ''
1062 for p in proto.params:
1063 cp = False
1064 if 0 != create_params:
1065 # If this is any of the N last params of the func, treat as output
1066 for y in range(-1, create_params-1, -1):
1067 if p.name == proto.params[y].name:
1068 cp = True
1069 (pft, pfi) = self._get_printf_params(p.ty, p.name, cp, cpp=True)
Jon Ashburn83334db2015-09-16 18:08:32 -06001070 if p.name == "pSwapchain" or p.name == "pSwapchainImages":
Chia-I Wue420a332015-10-26 20:04:44 +08001071 log_func += '%s = " << %s << ", ' % (p.name, p.name)
Mark Lobodzinski1592aac2015-12-02 16:12:08 -07001072 elif p.name == "swapchain" or p.name == "visual_id":
Chia-I Wue420a332015-10-26 20:04:44 +08001073 log_func += '%s = " << %s << ", ' % (p.name, p.name)
Ian Elliottb134e842015-07-06 14:31:32 -06001074 else:
1075 log_func += '%s = " << %s << ", ' % (p.name, pfi)
Tobin Ehlis4a636a12015-04-09 09:19:36 -06001076 if "%p" == pft:
1077 log_func_no_addr += '%s = address, ' % (p.name)
1078 else:
1079 log_func_no_addr += '%s = " << %s << ", ' % (p.name, pfi)
Tobin Ehlisc99cb0d2015-04-16 15:56:11 -06001080 if prev_count_name != '' and (prev_count_name.replace('Count', '')[1:] in p.name):
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001081 sp_param_dict[pindex] = prev_count_name
Tobin Ehlisc99cb0d2015-04-16 15:56:11 -06001082 prev_count_name = ''
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001083 elif vk_helper.is_type(p.ty.strip('*').replace('const ', ''), 'struct'):
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001084 sp_param_dict[pindex] = 'index'
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001085 if p.name.endswith('Count'):
1086 if '*' in p.ty:
1087 prev_count_name = "*%s" % p.name
1088 else:
1089 prev_count_name = p.name
Courtney Goeltzenleuchter70a0c752015-09-23 12:28:10 -06001090 else:
1091 prev_count_name = ''
Jon Ashburneb2728b2015-04-10 14:33:07 -06001092 pindex += 1
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001093 log_func = log_func.strip(', ')
Tobin Ehlis4a636a12015-04-09 09:19:36 -06001094 log_func_no_addr = log_func_no_addr.strip(', ')
Jon Ashburn53c16772015-05-06 10:15:07 -06001095 if proto.ret == "VkResult":
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -06001096 log_func += ') = " << string_VkResult((VkResult)result) << endl'
1097 log_func_no_addr += ') = " << string_VkResult((VkResult)result) << endl'
Jon Ashburn53c16772015-05-06 10:15:07 -06001098 elif proto.ret == "void*":
1099 log_func += ') = " << result << endl'
1100 log_func_no_addr += ') = " << result << endl'
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001101 else:
1102 log_func += ')\\n"'
Tobin Ehlis4a636a12015-04-09 09:19:36 -06001103 log_func_no_addr += ')\\n"'
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001104 log_func += ';'
Tobin Ehlis4a636a12015-04-09 09:19:36 -06001105 log_func_no_addr += ';'
Tobin Ehlis0b9c1952015-07-06 14:02:36 -06001106 log_func += '\n }\n else {%s\n }' % log_func_no_addr;
Tobin Ehlisfde2fc32015-06-12 12:49:01 -06001107 log_func += '\n%s' % self.lineinfo.get()
Courtney Goeltzenleuchter70a0c752015-09-23 12:28:10 -06001108 # log_func += '\n// Proto %s has param_dict: %s' % (proto.name, sp_param_dict)
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001109 if len(sp_param_dict) > 0:
Tobin Ehlis55c40412015-04-27 17:30:04 -06001110 indent = ' '
1111 log_func += '\n%sif (g_APIDumpDetailed) {' % indent
1112 indent += ' '
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001113 i_decl = False
Tobin Ehlisfde2fc32015-06-12 12:49:01 -06001114 log_func += '\n%s' % self.lineinfo.get()
Tobin Ehlis55c40412015-04-27 17:30:04 -06001115 log_func += '\n%sstring tmp_str;' % indent
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001116 for sp_index in sp_param_dict:
Courtney Goeltzenleuchter70a0c752015-09-23 12:28:10 -06001117 # log_func += '\n// sp_index: %s' % str(sp_index)
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001118 if 'index' == sp_param_dict[sp_index]:
Courtney Goeltzenleuchterddcb6192015-04-14 18:48:46 -06001119 cis_print_func = 'vk_print_%s' % (proto.params[sp_index].ty.replace('const ', '').strip('*').lower())
Tobin Ehlis4a636a12015-04-09 09:19:36 -06001120 local_name = proto.params[sp_index].name
1121 if '*' not in proto.params[sp_index].ty:
1122 local_name = '&%s' % proto.params[sp_index].name
Tobin Ehlisfde2fc32015-06-12 12:49:01 -06001123 log_func += '\n%s' % self.lineinfo.get()
Tobin Ehlis55c40412015-04-27 17:30:04 -06001124 log_func += '\n%sif (%s) {' % (indent, local_name)
1125 indent += ' '
1126 log_func += '\n%stmp_str = %s(%s, " ");' % (indent, cis_print_func, local_name)
1127 log_func += '\n%s(*outputStream) << " %s (" << %s << ")" << endl << tmp_str << endl;' % (indent, local_name, local_name)
1128 indent = indent[4:]
1129 log_func += '\n%s}' % (indent)
Chia-I Wu1f851912015-10-27 18:04:07 +08001130 elif 'memoryBarrierCount' == sp_param_dict[sp_index]: # call helper function
1131 log_func += '\n%sif (ppMemoryBarriers) {' % (indent)
1132 log_func += '\n%s interpret_memBarriers(ppMemoryBarriers, memoryBarrierCount);' % (indent)
Mark Lobodzinski98586a92015-07-30 10:11:32 -06001133 log_func += '\n%s}' % (indent)
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001134 else: # We have a count value stored to iterate over an array
1135 print_cast = ''
1136 print_func = ''
Courtney Goeltzenleuchterddcb6192015-04-14 18:48:46 -06001137 if vk_helper.is_type(proto.params[sp_index].ty.strip('*').replace('const ', ''), 'struct'):
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001138 print_cast = '&'
Courtney Goeltzenleuchterddcb6192015-04-14 18:48:46 -06001139 print_func = 'vk_print_%s' % proto.params[sp_index].ty.replace('const ', '').strip('*').lower()
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001140 else:
Tobin Ehlis4a636a12015-04-09 09:19:36 -06001141 print_cast = ''
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001142 print_func = 'string_convert_helper'
1143 #cis_print_func = 'tmp_str = string_convert_helper((void*)%s[i], " ");' % proto.params[sp_index].name
Chia-I Wue420a332015-10-26 20:04:44 +08001144 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 -06001145 if not i_decl:
Tobin Ehlis55c40412015-04-27 17:30:04 -06001146 log_func += '\n%suint32_t i;' % (indent)
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001147 i_decl = True
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001148 log_func += '\n%sif (%s) {' % (indent, proto.params[sp_index].name)
1149 indent += ' '
Tobin Ehlisfde2fc32015-06-12 12:49:01 -06001150 log_func += '\n%s' % self.lineinfo.get()
Tobin Ehlis55c40412015-04-27 17:30:04 -06001151 log_func += '\n%sfor (i = 0; i < %s; i++) {' % (indent, sp_param_dict[sp_index])
1152 indent += ' '
1153 log_func += '\n%s%s' % (indent, cis_print_func)
Tobin Ehlis8ad15742015-04-28 10:58:20 -06001154 log_func += '\n%sif (StreamControl::writeAddress == true) {' % (indent)
1155 indent += ' '
Tobin Ehlis55c40412015-04-27 17:30:04 -06001156 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)
1157 indent = indent[4:]
Tobin Ehlis8ad15742015-04-28 10:58:20 -06001158 log_func += '\n%s} else {' % (indent)
1159 indent += ' '
1160 log_func += '\n%s(*outputStream) << " %s[" << i << "] (address)" << endl << " address" << endl;' % (indent, proto.params[sp_index].name)
1161 indent = indent[4:]
1162 log_func += '\n%s}' % (indent)
1163 indent = indent[4:]
Tobin Ehlis55c40412015-04-27 17:30:04 -06001164 log_func += '\n%s}' % (indent)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001165 indent = indent[4:]
1166 log_func += '\n%s}' % (indent)
Tobin Ehlis55c40412015-04-27 17:30:04 -06001167 indent = indent[4:]
1168 log_func += '\n%s}' % (indent)
Mark Lobodzinskibf7c7002015-05-26 09:29:09 -05001169 table_type = ''
Jon Ashburn2666e2f2015-05-15 15:09:35 -06001170 if proto_is_global(proto):
Mark Lobodzinskibf7c7002015-05-26 09:29:09 -05001171 table_type = 'instance'
1172 else:
1173 table_type = 'device'
Jon Ashburnde4f1102015-09-17 10:00:32 -06001174 dispatch_param = proto.params[0].name
Jon Ashburn52c1d732015-05-12 17:23:55 -06001175
Mark Lobodzinskibf7c7002015-05-26 09:29:09 -05001176 if proto.name == "CreateInstance":
1177 dispatch_param = '*' + proto.params[1].name
Jon Ashburnde4f1102015-09-17 10:00:32 -06001178 funcs.append('%s%s\n'
1179 '{\n'
1180 ' using namespace StreamControl;\n'
1181 ' %sinstance_dispatch_table(*pInstance)->%s;\n'
1182 ' if (result == VK_SUCCESS) {\n'
1183 ' createInstanceRegisterExtensions(pCreateInfo, *pInstance);\n'
1184 ' }\n'
1185 ' %s%s%s\n'
1186 '%s'
1187 '}\n' % (qual, decl, ret_val, proto.c_call(), f_open, log_func, f_close, stmt))
Mark Lobodzinskibf7c7002015-05-26 09:29:09 -05001188
Jon Ashburnde4f1102015-09-17 10:00:32 -06001189 elif proto.name == "CreateDevice":
Courtney Goeltzenleuchter4843dda2015-06-26 15:07:53 -06001190 funcs.append('%s\n' % self.lineinfo.get())
Jon Ashburn7e07faf2015-06-18 15:02:58 -06001191 funcs.append('%s%s\n'
1192 '{\n'
1193 ' using namespace StreamControl;\n'
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06001194 ' %sdevice_dispatch_table(*pDevice)->%s;\n'
Jon Ashburn7e07faf2015-06-18 15:02:58 -06001195 ' if (result == VK_SUCCESS)\n'
1196 ' createDeviceRegisterExtensions(pCreateInfo, *pDevice);\n'
1197 ' %s%s%s\n'
1198 '%s'
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06001199 '}' % (qual, decl, ret_val, proto.c_call(), f_open, log_func, f_close, stmt))
Jon Ashburn7e07faf2015-06-18 15:02:58 -06001200 elif proto.name == "DestroyDevice":
Mark Lobodzinskibf7c7002015-05-26 09:29:09 -05001201 funcs.append('%s%s\n'
1202 '{\n'
1203 ' using namespace StreamControl;\n'
Courtney Goeltzenleuchter9f171942015-06-13 21:22:12 -06001204 ' dispatch_key key = get_dispatch_key(device);\n'
Jon Ashburnde4f1102015-09-17 10:00:32 -06001205 ' VkLayerDispatchTable *pDisp = %s_dispatch_table(%s);\n'
Jon Ashburn7e07faf2015-06-18 15:02:58 -06001206 ' %spDisp->%s;\n'
1207 ' deviceExtMap.erase(pDisp);\n'
Courtney Goeltzenleuchter9f171942015-06-13 21:22:12 -06001208 ' destroy_device_dispatch_table(key);\n'
Mark Lobodzinskibf7c7002015-05-26 09:29:09 -05001209 ' %s%s%s\n'
1210 '%s'
Jon Ashburn7e07faf2015-06-18 15:02:58 -06001211 '}' % (qual, decl, table_type, dispatch_param, ret_val, proto.c_call(), f_open, log_func, f_close, stmt))
Mark Lobodzinskibf7c7002015-05-26 09:29:09 -05001212 elif proto.name == "DestroyInstance":
1213 funcs.append('%s%s\n'
1214 '{\n'
1215 ' using namespace StreamControl;\n'
Courtney Goeltzenleuchter9f171942015-06-13 21:22:12 -06001216 ' dispatch_key key = get_dispatch_key(instance);\n'
Jon Ashburnde4f1102015-09-17 10:00:32 -06001217 ' VkLayerInstanceDispatchTable *pDisp = %s_dispatch_table(%s);\n'
1218 ' %spDisp->%s;\n'
1219 ' instanceExtMap.erase(pDisp);\n'
Courtney Goeltzenleuchter9f171942015-06-13 21:22:12 -06001220 ' destroy_instance_dispatch_table(key);\n'
Mark Lobodzinskibf7c7002015-05-26 09:29:09 -05001221 ' %s%s%s\n'
1222 '%s'
Jon Ashburnde4f1102015-09-17 10:00:32 -06001223 '}' % (qual, decl, table_type, dispatch_param, ret_val, proto.c_call(), f_open, log_func, f_close, stmt))
Mark Lobodzinskibf7c7002015-05-26 09:29:09 -05001224 else:
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -07001225 if wsi_name(decl):
1226 funcs.append('%s' % wsi_ifdef(decl))
Mark Lobodzinskibf7c7002015-05-26 09:29:09 -05001227 funcs.append('%s%s\n'
1228 '{\n'
1229 ' using namespace StreamControl;\n'
1230 ' %s%s_dispatch_table(%s)->%s;\n'
Jon Ashburn301c5f02015-04-06 10:58:22 -06001231 ' %s%s%s\n'
1232 '%s'
Mark Lobodzinskibf7c7002015-05-26 09:29:09 -05001233 '}' % (qual, decl, ret_val, table_type, dispatch_param, proto.c_call(), f_open, log_func, f_close, stmt))
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -07001234 if wsi_name(decl):
1235 funcs.append('%s' % wsi_endif(decl))
Mike Stroyan2ad66f12015-04-03 17:45:53 -06001236 return "\n\n".join(funcs)
1237
Tobin Ehlis434db7c2015-01-10 12:42:41 -07001238 def generate_body(self):
Tobin Ehlis4a636a12015-04-09 09:19:36 -06001239 self.layer_name = "APIDump"
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -07001240 if sys.platform.startswith('win32'):
Michael Lentine81f1fd92015-12-03 14:33:09 -08001241 instance_extensions=[('wsi_enabled',
1242 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1243 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1244 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1245 'vkGetPhysicalDeviceSurfacePresentModesKHR',
1246 'vkCreateWin32SurfaceKHR',
1247 'vkGetPhysicalDeviceWin32PresentationSupportKHR'])]
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -07001248 elif sys.platform.startswith('linux'):
Michael Lentine81f1fd92015-12-03 14:33:09 -08001249 instance_extensions=[('wsi_enabled',
1250 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1251 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1252 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1253 'vkGetPhysicalDeviceSurfacePresentModesKHR',
1254 'vkCreateXcbSurfaceKHR',
Mark Lobodzinski6f92feb2015-11-26 10:59:58 -07001255 'vkGetPhysicalDeviceXcbPresentationSupportKHR'])]
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -07001256 # TODO: Add cases for Mir, Xlib, Wayland
1257 else:
1258 instance_extensions=[('wsi_enabled',
1259 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1260 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1261 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1262 'vkGetPhysicalDeviceSurfacePresentModesKHR'])]
Ian Elliottb134e842015-07-06 14:31:32 -06001263 extensions=[('wsi_enabled',
Ian Elliottc623ba52015-11-20 14:13:17 -07001264 ['vkCreateSwapchainKHR',
Jon Ashburn83334db2015-09-16 18:08:32 -06001265 'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
1266 'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
Tobin Ehlis4a636a12015-04-09 09:19:36 -06001267 body = [self.generate_init(),
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001268 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Jon Ashburnde4f1102015-09-17 10:00:32 -06001269 self._generate_layer_gpa_function(extensions, instance_extensions)]
Tobin Ehlis434db7c2015-01-10 12:42:41 -07001270 return "\n\n".join(body)
1271
Tobin Ehlis92dbf802014-10-22 09:06:33 -06001272class ObjectTrackerSubcommand(Subcommand):
1273 def generate_header(self):
1274 header_txt = []
Tobin Ehlisfde2fc32015-06-12 12:49:01 -06001275 header_txt.append('%s' % self.lineinfo.get())
Mark Lobodzinski14305ad2015-06-23 11:35:12 -06001276 header_txt.append('#include <stdio.h>')
1277 header_txt.append('#include <stdlib.h>')
1278 header_txt.append('#include <string.h>')
1279 header_txt.append('#include <inttypes.h>')
1280 header_txt.append('')
David Pinedo329ca9e2015-11-06 12:54:48 -07001281 header_txt.append('#include "vulkan/vulkan.h"')
Tobin Ehlis7a51d902015-07-03 10:34:49 -06001282 header_txt.append('#include "vk_loader_platform.h"')
Mark Lobodzinski14305ad2015-06-23 11:35:12 -06001283 header_txt.append('')
Tobin Ehlis586aa012015-06-08 17:36:28 -06001284 header_txt.append('#include <unordered_map>')
1285 header_txt.append('using namespace std;')
David Pinedo329ca9e2015-11-06 12:54:48 -07001286 header_txt.append('#include "vulkan/vk_layer.h"')
Tobin Ehlis56d204a2015-07-03 10:15:26 -06001287 header_txt.append('#include "vk_layer_config.h"')
David Pinedoa31fe0b2015-11-24 09:00:24 -07001288 header_txt.append('#include "vulkan/vk_lunarg_debug_report.h"')
Tobin Ehlis56d204a2015-07-03 10:15:26 -06001289 header_txt.append('#include "vk_layer_table.h"')
1290 header_txt.append('#include "vk_layer_data.h"')
1291 header_txt.append('#include "vk_layer_logging.h"')
Mark Lobodzinski14305ad2015-06-23 11:35:12 -06001292 header_txt.append('')
1293# NOTE: The non-autoGenerated code is in the object_track.h header file
1294 header_txt.append('#include "object_track.h"')
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -05001295 header_txt.append('')
Jon Ashburnd9564002015-05-07 10:27:37 -06001296 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -05001297 header_txt.append('')
Tobin Ehlis92dbf802014-10-22 09:06:33 -06001298 return "\n".join(header_txt)
1299
Tony Barbour2a199c12015-07-09 17:31:46 -06001300 def generate_maps(self):
1301 maps_txt = []
1302 for o in vulkan.core.objects:
Michael Lentine1a85aa12015-11-04 14:35:12 -08001303 maps_txt.append('unordered_map<uint64_t, OBJTRACK_NODE*> %sMap;' % (o))
1304 maps_txt.append('unordered_map<uint64_t, OBJTRACK_NODE*> VkSwapchainKHRMap;')
Tony Barbour2a199c12015-07-09 17:31:46 -06001305 return "\n".join(maps_txt)
1306
1307 def generate_procs(self):
1308 procs_txt = []
1309 for o in vulkan.core.objects:
1310 procs_txt.append('%s' % self.lineinfo.get())
Michael Lentine1a85aa12015-11-04 14:35:12 -08001311 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o)
1312 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001313 if o in vulkan.object_dispatch_list:
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001314 procs_txt.append('static void create_%s(%s dispatchable_object, %s vkObj, VkDebugReportObjectTypeLUNARG objType)' % (name, o, o))
Tony Barbour2a199c12015-07-09 17:31:46 -06001315 else:
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001316 procs_txt.append('static void create_%s(VkDevice dispatchable_object, %s vkObj, VkDebugReportObjectTypeLUNARG objType)' % (name, o))
Chia-I Wue420a332015-10-26 20:04:44 +08001317 procs_txt.append('{')
Courtney Goeltzenleuchterf8fe1282015-11-25 10:30:56 -07001318 procs_txt.append(' log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFO_BIT, objType, reinterpret_cast<uint64_t>(vkObj), 0, OBJTRACK_NONE, "OBJTRACK",')
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001319 procs_txt.append(' "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64 , object_track_index++, string_VkDebugReportObjectTypeLUNARG(objType),')
Chia-I Wue420a332015-10-26 20:04:44 +08001320 procs_txt.append(' reinterpret_cast<uint64_t>(vkObj));')
Tony Barbour2a199c12015-07-09 17:31:46 -06001321 procs_txt.append('')
1322 procs_txt.append(' OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE;')
1323 procs_txt.append(' pNewObjNode->objType = objType;')
1324 procs_txt.append(' pNewObjNode->status = OBJSTATUS_NONE;')
Chia-I Wue420a332015-10-26 20:04:44 +08001325 procs_txt.append(' pNewObjNode->vkObj = reinterpret_cast<uint64_t>(vkObj);')
Michael Lentine1a85aa12015-11-04 14:35:12 -08001326 procs_txt.append(' %sMap[(uint64_t)vkObj] = pNewObjNode;' % (o))
Tony Barbour2a199c12015-07-09 17:31:46 -06001327 procs_txt.append(' uint32_t objIndex = objTypeToIndex(objType);')
1328 procs_txt.append(' numObjs[objIndex]++;')
1329 procs_txt.append(' numTotalObjs++;')
1330 procs_txt.append('}')
1331 procs_txt.append('')
1332 procs_txt.append('%s' % self.lineinfo.get())
Tobin Ehlis87f115c2015-09-15 15:02:17 -06001333 # TODO : This is not complete and currently requires some hand-coded function in the header
1334 # Really we want to capture the set of all objects and their associated dispatchable objects
1335 # that are bound by the API calls:
1336 # foreach API Call
1337 # foreach object type seen by call
1338 # create validate_object(disp_obj, object)
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001339 if o in vulkan.object_dispatch_list:
Michael Lentine1a85aa12015-11-04 14:35:12 -08001340 procs_txt.append('static VkBool32 validate_%s(%s dispatchable_object, %s object)' % (name, o, o))
Tony Barbour2a199c12015-07-09 17:31:46 -06001341 else:
Michael Lentine1a85aa12015-11-04 14:35:12 -08001342 procs_txt.append('static VkBool32 validate_%s(VkDevice dispatchable_object, %s object)' % (name, o))
Tony Barbour2a199c12015-07-09 17:31:46 -06001343 procs_txt.append('{')
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001344 if o in vulkan.object_dispatch_list:
Michael Lentine1a85aa12015-11-04 14:35:12 -08001345 procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (o, o))
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001346 procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT, (VkDebugReportObjectTypeLUNARG ) 0, reinterpret_cast<uint64_t>(object), 0, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
Michael Lentinecbc4a5e2015-11-03 16:19:46 -08001347 procs_txt.append(' "Invalid %s Object 0x%%" PRIx64 ,reinterpret_cast<uint64_t>(object));' % o)
Tony Barbour2a199c12015-07-09 17:31:46 -06001348 else:
Mark Lobodzinski9c483302015-10-14 13:16:33 -06001349 if o == "VkImage":
1350 procs_txt.append(' // We need to validate normal image objects and those from the swapchain')
Michael Lentine1a85aa12015-11-04 14:35:12 -08001351 procs_txt.append(' if ((%sMap.find((uint64_t)object) == %sMap.end()) &&' % (o, o))
1352 procs_txt.append(' (swapchainImageMap.find((uint64_t)object) == swapchainImageMap.end())) {')
Mark Lobodzinski9c483302015-10-14 13:16:33 -06001353 else:
Michael Lentine1a85aa12015-11-04 14:35:12 -08001354 procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (o, o))
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001355 procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT, (VkDebugReportObjectTypeLUNARG ) 0, (uint64_t) object, 0, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
Michael Lentinecbc4a5e2015-11-03 16:19:46 -08001356 procs_txt.append(' "Invalid %s Object 0x%%" PRIx64, reinterpret_cast<uint64_t>(object));' % o)
Tony Barbour2a199c12015-07-09 17:31:46 -06001357 procs_txt.append(' }')
Tobin Ehlisf2f97402015-09-11 12:57:55 -06001358 procs_txt.append(' return VK_FALSE;')
Tony Barbour2a199c12015-07-09 17:31:46 -06001359 procs_txt.append('}')
1360 procs_txt.append('')
1361 procs_txt.append('')
1362 procs_txt.append('%s' % self.lineinfo.get())
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001363 if o in vulkan.object_dispatch_list:
Michael Lentine1a85aa12015-11-04 14:35:12 -08001364 procs_txt.append('static void destroy_%s(%s dispatchable_object, %s object)' % (name, o, o))
Tony Barbour2a199c12015-07-09 17:31:46 -06001365 else:
Michael Lentine1a85aa12015-11-04 14:35:12 -08001366 procs_txt.append('static void destroy_%s(VkDevice dispatchable_object, %s object)' % (name, o))
Tony Barbour2a199c12015-07-09 17:31:46 -06001367 procs_txt.append('{')
Michael Lentine1a85aa12015-11-04 14:35:12 -08001368 procs_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
1369 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
1370 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[(uint64_t)object];' % (o))
Tony Barbour2a199c12015-07-09 17:31:46 -06001371 procs_txt.append(' uint32_t objIndex = objTypeToIndex(pNode->objType);')
1372 procs_txt.append(' assert(numTotalObjs > 0);')
1373 procs_txt.append(' numTotalObjs--;')
1374 procs_txt.append(' assert(numObjs[objIndex] > 0);')
1375 procs_txt.append(' numObjs[objIndex]--;')
Courtney Goeltzenleuchterf8fe1282015-11-25 10:30:56 -07001376 procs_txt.append(' log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFO_BIT, pNode->objType, object_handle, 0, OBJTRACK_NONE, "OBJTRACK",')
Michael Lentinecbc4a5e2015-11-03 16:19:46 -08001377 procs_txt.append(' "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%" PRIu64 " total objs remain & %" PRIu64 " %s objs).",')
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001378 procs_txt.append(' string_VkDebugReportObjectTypeLUNARG(pNode->objType), reinterpret_cast<uint64_t>(object), numTotalObjs, numObjs[objIndex],')
1379 procs_txt.append(' string_VkDebugReportObjectTypeLUNARG(pNode->objType));')
Tony Barbour2a199c12015-07-09 17:31:46 -06001380 procs_txt.append(' delete pNode;')
Michael Lentine1a85aa12015-11-04 14:35:12 -08001381 procs_txt.append(' %sMap.erase(object_handle);' % (o))
Chia-I Wue420a332015-10-26 20:04:44 +08001382 procs_txt.append(' } else {')
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001383 procs_txt.append(' log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT, (VkDebugReportObjectTypeLUNARG ) 0, object_handle, 0, OBJTRACK_NONE, "OBJTRACK",')
Chia-I Wue420a332015-10-26 20:04:44 +08001384 procs_txt.append(' "Unable to remove obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?",')
Michael Lentine1a85aa12015-11-04 14:35:12 -08001385 procs_txt.append(' object_handle);')
Chia-I Wue420a332015-10-26 20:04:44 +08001386 procs_txt.append(' }')
Tony Barbour2a199c12015-07-09 17:31:46 -06001387 procs_txt.append('}')
1388 procs_txt.append('')
1389 procs_txt.append('%s' % self.lineinfo.get())
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001390 if o in vulkan.object_dispatch_list:
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001391 procs_txt.append('static VkBool32 set_%s_status(%s dispatchable_object, %s object, VkDebugReportObjectTypeLUNARG objType, ObjectStatusFlags status_flag)' % (name, o, o))
Tony Barbour2a199c12015-07-09 17:31:46 -06001392 else:
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001393 procs_txt.append('static VkBool32 set_%s_status(VkDevice dispatchable_object, %s object, VkDebugReportObjectTypeLUNARG objType, ObjectStatusFlags status_flag)' % (name, o))
Chia-I Wue420a332015-10-26 20:04:44 +08001394 procs_txt.append('{')
1395 procs_txt.append(' if (object != VK_NULL_HANDLE) {')
Michael Lentine1a85aa12015-11-04 14:35:12 -08001396 procs_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
1397 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
1398 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[object_handle];' % (o))
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001399 procs_txt.append(' pNode->status |= status_flag;')
Tony Barbour2a199c12015-07-09 17:31:46 -06001400 procs_txt.append(' }')
1401 procs_txt.append(' else {')
1402 procs_txt.append(' // If we do not find it print an error')
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001403 procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT, (VkDebugReportObjectTypeLUNARG ) 0, object_handle, 0, OBJTRACK_NONE, "OBJTRACK",')
Chia-I Wue420a332015-10-26 20:04:44 +08001404 procs_txt.append(' "Unable to set status for non-existent object 0x%" PRIxLEAST64 " of %s type",')
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001405 procs_txt.append(' object_handle, string_VkDebugReportObjectTypeLUNARG(objType));')
Tony Barbour2a199c12015-07-09 17:31:46 -06001406 procs_txt.append(' }')
1407 procs_txt.append(' }')
Tobin Ehlisf2f97402015-09-11 12:57:55 -06001408 procs_txt.append(' return VK_FALSE;')
Tony Barbour2a199c12015-07-09 17:31:46 -06001409 procs_txt.append('}')
1410 procs_txt.append('')
1411 procs_txt.append('%s' % self.lineinfo.get())
Michael Lentine1a85aa12015-11-04 14:35:12 -08001412 procs_txt.append('static VkBool32 validate_%s_status(' % (name))
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001413 if o in vulkan.object_dispatch_list:
Tony Barbour2a199c12015-07-09 17:31:46 -06001414 procs_txt.append('%s dispatchable_object, %s object,' % (o, o))
1415 else:
1416 procs_txt.append('VkDevice dispatchable_object, %s object,' % (o))
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001417 procs_txt.append(' VkDebugReportObjectTypeLUNARG objType,')
Tony Barbour2a199c12015-07-09 17:31:46 -06001418 procs_txt.append(' ObjectStatusFlags status_mask,')
1419 procs_txt.append(' ObjectStatusFlags status_flag,')
1420 procs_txt.append(' VkFlags msg_flags,')
1421 procs_txt.append(' OBJECT_TRACK_ERROR error_code,')
1422 procs_txt.append(' const char *fail_msg)')
1423 procs_txt.append('{')
Michael Lentine1a85aa12015-11-04 14:35:12 -08001424 procs_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
1425 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
1426 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[object_handle];' % (o))
Tony Barbour2a199c12015-07-09 17:31:46 -06001427 procs_txt.append(' if ((pNode->status & status_mask) != status_flag) {')
Michael Lentine1a85aa12015-11-04 14:35:12 -08001428 procs_txt.append(' log_msg(mdd(dispatchable_object), msg_flags, pNode->objType, object_handle, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",')
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001429 procs_txt.append(' "OBJECT VALIDATION WARNING: %s object 0x%" PRIxLEAST64 ": %s", string_VkDebugReportObjectTypeLUNARG(objType),')
Michael Lentine1a85aa12015-11-04 14:35:12 -08001430 procs_txt.append(' object_handle, fail_msg);')
Tony Barbour2a199c12015-07-09 17:31:46 -06001431 procs_txt.append(' return VK_FALSE;')
1432 procs_txt.append(' }')
1433 procs_txt.append(' return VK_TRUE;')
1434 procs_txt.append(' }')
1435 procs_txt.append(' else {')
1436 procs_txt.append(' // If we do not find it print an error')
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001437 procs_txt.append(' log_msg(mdd(dispatchable_object), msg_flags, (VkDebugReportObjectTypeLUNARG) 0, object_handle, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",')
Chia-I Wue420a332015-10-26 20:04:44 +08001438 procs_txt.append(' "Unable to obtain status for non-existent object 0x%" PRIxLEAST64 " of %s type",')
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001439 procs_txt.append(' object_handle, string_VkDebugReportObjectTypeLUNARG(objType));')
Tony Barbour2a199c12015-07-09 17:31:46 -06001440 procs_txt.append(' return VK_FALSE;')
1441 procs_txt.append(' }')
1442 procs_txt.append('}')
1443 procs_txt.append('')
1444 procs_txt.append('%s' % self.lineinfo.get())
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001445 if o in vulkan.object_dispatch_list:
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001446 procs_txt.append('static VkBool32 reset_%s_status(%s dispatchable_object, %s object, VkDebugReportObjectTypeLUNARG objType, ObjectStatusFlags status_flag)' % (name, o, o))
Tony Barbour2a199c12015-07-09 17:31:46 -06001447 else:
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001448 procs_txt.append('static VkBool32 reset_%s_status(VkDevice dispatchable_object, %s object, VkDebugReportObjectTypeLUNARG objType, ObjectStatusFlags status_flag)' % (name, o))
Chia-I Wue420a332015-10-26 20:04:44 +08001449 procs_txt.append('{')
Michael Lentine1a85aa12015-11-04 14:35:12 -08001450 procs_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
1451 procs_txt.append(' if (%sMap.find(object_handle) != %sMap.end()) {' % (o, o))
1452 procs_txt.append(' OBJTRACK_NODE* pNode = %sMap[object_handle];' % (o))
Tony Barbour2a199c12015-07-09 17:31:46 -06001453 procs_txt.append(' pNode->status &= ~status_flag;')
Tony Barbour2a199c12015-07-09 17:31:46 -06001454 procs_txt.append(' }')
1455 procs_txt.append(' else {')
1456 procs_txt.append(' // If we do not find it print an error')
Courtney Goeltzenleuchterf8fe1282015-11-25 10:30:56 -07001457 procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT, objType, object_handle, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",')
Chia-I Wue420a332015-10-26 20:04:44 +08001458 procs_txt.append(' "Unable to reset status for non-existent object 0x%" PRIxLEAST64 " of %s type",')
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001459 procs_txt.append(' object_handle, string_VkDebugReportObjectTypeLUNARG(objType));')
Tony Barbour2a199c12015-07-09 17:31:46 -06001460 procs_txt.append(' }')
Tobin Ehlisf2f97402015-09-11 12:57:55 -06001461 procs_txt.append(' return VK_FALSE;')
Tony Barbour2a199c12015-07-09 17:31:46 -06001462 procs_txt.append('}')
1463 procs_txt.append('')
1464 return "\n".join(procs_txt)
1465
Mark Lobodzinski4a611132015-07-17 11:51:24 -06001466 def generate_destroy_instance(self):
Tony Barbour2a199c12015-07-09 17:31:46 -06001467 gedi_txt = []
1468 gedi_txt.append('%s' % self.lineinfo.get())
Mark Lobodzinski67b42b72015-09-07 13:59:43 -06001469 gedi_txt.append('void vkDestroyInstance(')
Chia-I Wu69f40122015-10-26 21:10:41 +08001470 gedi_txt.append('VkInstance instance,')
Chia-I Wu1f851912015-10-27 18:04:07 +08001471 gedi_txt.append('const VkAllocationCallbacks* pAllocator)')
Tony Barbour2a199c12015-07-09 17:31:46 -06001472 gedi_txt.append('{')
1473 gedi_txt.append(' loader_platform_thread_lock_mutex(&objLock);')
Michael Lentine1a85aa12015-11-04 14:35:12 -08001474 gedi_txt.append(' validate_instance(instance, instance);')
Tony Barbour2a199c12015-07-09 17:31:46 -06001475 gedi_txt.append('')
Michael Lentine1a85aa12015-11-04 14:35:12 -08001476 gedi_txt.append(' destroy_instance(instance, instance);')
Tony Barbour2a199c12015-07-09 17:31:46 -06001477 gedi_txt.append(' // Report any remaining objects in LL')
1478 for o in vulkan.core.objects:
Mike Stroyan09b75852015-08-18 14:48:34 -06001479 if o in ['VkInstance', 'VkPhysicalDevice', 'VkQueue']:
Tony Barbour2a199c12015-07-09 17:31:46 -06001480 continue
1481 gedi_txt.append(' for (auto it = %sMap.begin(); it != %sMap.end(); ++it) {' % (o, o))
1482 gedi_txt.append(' OBJTRACK_NODE* pNode = it->second;')
Courtney Goeltzenleuchterf8fe1282015-11-25 10:30:56 -07001483 gedi_txt.append(' log_msg(mid(instance), VK_DEBUG_REPORT_ERROR_BIT, pNode->objType, pNode->vkObj, 0, OBJTRACK_OBJECT_LEAK, "OBJTRACK",')
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001484 gedi_txt.append(' "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeLUNARG(pNode->objType),')
Tony Barbour8db65372015-07-10 18:32:33 -06001485 gedi_txt.append(' pNode->vkObj);')
Tony Barbour2a199c12015-07-09 17:31:46 -06001486 gedi_txt.append(' }')
Mike Stroyan09b75852015-08-18 14:48:34 -06001487 gedi_txt.append(' %sMap.clear();' % (o))
Tony Barbour2a199c12015-07-09 17:31:46 -06001488 gedi_txt.append('')
1489 gedi_txt.append(' dispatch_key key = get_dispatch_key(instance);')
1490 gedi_txt.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(ObjectTracker_instance_table_map, instance);')
Chia-I Wu69f40122015-10-26 21:10:41 +08001491 gedi_txt.append(' pInstanceTable->DestroyInstance(instance, pAllocator);')
Tony Barbour2a199c12015-07-09 17:31:46 -06001492 gedi_txt.append('')
1493 gedi_txt.append(' // Clean up logging callback, if any')
1494 gedi_txt.append(' layer_data *my_data = get_my_data_ptr(key, layer_data_map);')
1495 gedi_txt.append(' if (my_data->logging_callback) {')
1496 gedi_txt.append(' layer_destroy_msg_callback(my_data->report_data, my_data->logging_callback);')
1497 gedi_txt.append(' }')
1498 gedi_txt.append('')
1499 gedi_txt.append(' layer_debug_report_destroy_instance(mid(instance));')
1500 gedi_txt.append(' layer_data_map.erase(pInstanceTable);')
1501 gedi_txt.append('')
Jon Ashburnde4f1102015-09-17 10:00:32 -06001502 gedi_txt.append(' instanceExtMap.erase(pInstanceTable);')
Tony Barbour2a199c12015-07-09 17:31:46 -06001503 gedi_txt.append(' loader_platform_thread_unlock_mutex(&objLock);')
Mike Stroyan09b75852015-08-18 14:48:34 -06001504 # The loader holds a mutex that protects this from other threads
1505 gedi_txt.append(' ObjectTracker_instance_table_map.erase(key);')
1506 gedi_txt.append(' if (ObjectTracker_instance_table_map.empty()) {')
1507 gedi_txt.append(' // Release mutex when destroying last instance.')
1508 gedi_txt.append(' loader_platform_thread_delete_mutex(&objLock);')
1509 gedi_txt.append(' objLockInitialized = 0;')
1510 gedi_txt.append(' }')
Tony Barbour2a199c12015-07-09 17:31:46 -06001511 gedi_txt.append('}')
1512 gedi_txt.append('')
1513 return "\n".join(gedi_txt)
1514
Mark Lobodzinski4a611132015-07-17 11:51:24 -06001515 def generate_destroy_device(self):
Tony Barbour2a199c12015-07-09 17:31:46 -06001516 gedd_txt = []
1517 gedd_txt.append('%s' % self.lineinfo.get())
Mark Lobodzinski67b42b72015-09-07 13:59:43 -06001518 gedd_txt.append('void vkDestroyDevice(')
Chia-I Wu69f40122015-10-26 21:10:41 +08001519 gedd_txt.append('VkDevice device,')
Chia-I Wu1f851912015-10-27 18:04:07 +08001520 gedd_txt.append('const VkAllocationCallbacks* pAllocator)')
Tony Barbour2a199c12015-07-09 17:31:46 -06001521 gedd_txt.append('{')
1522 gedd_txt.append(' loader_platform_thread_lock_mutex(&objLock);')
Michael Lentine1a85aa12015-11-04 14:35:12 -08001523 gedd_txt.append(' validate_device(device, device);')
Tony Barbour2a199c12015-07-09 17:31:46 -06001524 gedd_txt.append('')
Michael Lentine1a85aa12015-11-04 14:35:12 -08001525 gedd_txt.append(' destroy_device(device, device);')
Tony Barbour2a199c12015-07-09 17:31:46 -06001526 gedd_txt.append(' // Report any remaining objects in LL')
1527 for o in vulkan.core.objects:
Mark Lobodzinski60b2b332015-11-12 16:02:35 -07001528 # DescriptorSets and Command Buffers are destroyed through their pools, not explicitly
1529 if o in ['VkInstance', 'VkPhysicalDevice', 'VkQueue', 'VkDevice', 'VkDescriptorSet', 'VkCommandBuffer']:
Tony Barbour2a199c12015-07-09 17:31:46 -06001530 continue
Mark Lobodzinski60b2b332015-11-12 16:02:35 -07001531 gedd_txt.append(' for (auto it = %sMap.begin(); it != %sMap.end(); ++it) {' % (o, o))
1532 gedd_txt.append(' OBJTRACK_NODE* pNode = it->second;')
Courtney Goeltzenleuchterf8fe1282015-11-25 10:30:56 -07001533 gedd_txt.append(' log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT, pNode->objType, pNode->vkObj, 0, OBJTRACK_OBJECT_LEAK, "OBJTRACK",')
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001534 gedd_txt.append(' "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeLUNARG(pNode->objType),')
Mark Lobodzinski60b2b332015-11-12 16:02:35 -07001535 gedd_txt.append(' pNode->vkObj);')
1536 gedd_txt.append(' }')
Mike Stroyan09b75852015-08-18 14:48:34 -06001537 gedd_txt.append(' %sMap.clear();' % (o))
Tony Barbour2a199c12015-07-09 17:31:46 -06001538 gedd_txt.append('')
1539 gedd_txt.append(" // Clean up Queue's MemRef Linked Lists")
1540 gedd_txt.append(' destroyQueueMemRefLists();')
1541 gedd_txt.append('')
1542 gedd_txt.append(' loader_platform_thread_unlock_mutex(&objLock);')
1543 gedd_txt.append('')
1544 gedd_txt.append(' dispatch_key key = get_dispatch_key(device);')
1545 gedd_txt.append(' VkLayerDispatchTable *pDisp = get_dispatch_table(ObjectTracker_device_table_map, device);')
Chia-I Wu69f40122015-10-26 21:10:41 +08001546 gedd_txt.append(' pDisp->DestroyDevice(device, pAllocator);')
Tony Barbour2a199c12015-07-09 17:31:46 -06001547 gedd_txt.append(' ObjectTracker_device_table_map.erase(key);')
1548 gedd_txt.append(' assert(ObjectTracker_device_table_map.size() == 0 && "Should not have any instance mappings hanging around");')
1549 gedd_txt.append('')
Tony Barbour2a199c12015-07-09 17:31:46 -06001550 gedd_txt.append('}')
1551 gedd_txt.append('')
1552 return "\n".join(gedd_txt)
1553
1554 def generate_command_buffer_validates(self):
1555 cbv_txt = []
1556 cbv_txt.append('%s' % self.lineinfo.get())
Courtney Goeltzenleuchter09772bb2015-09-17 15:06:17 -06001557 for o in ['VkPipeline',
Tony Barbour2a199c12015-07-09 17:31:46 -06001558 'VkPipelineLayout', 'VkBuffer', 'VkEvent', 'VkQueryPool', 'VkRenderPass', 'VkFramebuffer']:
Michael Lentine1a85aa12015-11-04 14:35:12 -08001559 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o)
1560 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
1561 cbv_txt.append('static VkBool32 validate_%s(VkCommandBuffer dispatchable_object, %s object)' % (name, o))
Tony Barbour2a199c12015-07-09 17:31:46 -06001562 cbv_txt.append('{')
Michael Lentine1a85aa12015-11-04 14:35:12 -08001563 cbv_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
1564 cbv_txt.append(' if (%sMap.find(object_handle) == %sMap.end()) {' % (o, o))
Courtney Goeltzenleuchter95e6dba2015-11-25 11:38:54 -07001565 cbv_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT, (VkDebugReportObjectTypeLUNARG ) 0, object_handle, 0, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
Michael Lentine1a85aa12015-11-04 14:35:12 -08001566 cbv_txt.append(' "Invalid %s Object 0x%%" PRIx64, object_handle);' % (o))
Tony Barbour2a199c12015-07-09 17:31:46 -06001567 cbv_txt.append(' }')
Tobin Ehlisf2f97402015-09-11 12:57:55 -06001568 cbv_txt.append(' return VK_FALSE;')
Tony Barbour2a199c12015-07-09 17:31:46 -06001569 cbv_txt.append('}')
1570 cbv_txt.append('')
1571 return "\n".join(cbv_txt)
1572
Mike Stroyan3aecdb42015-04-03 17:13:23 -06001573 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001574 if proto.name in [ 'DbgCreateMsgCallback', 'EnumerateInstanceLayerProperties', 'EnumerateInstanceExtensionProperties','EnumerateDeviceLayerProperties', 'EnumerateDeviceExtensionProperties' ]:
Mike Stroyan723913e2015-04-03 14:39:16 -06001575 # use default version
1576 return None
Mark Lobodzinski4e5016f2015-05-05 15:01:37 -05001577
Tony Barbour2a199c12015-07-09 17:31:46 -06001578 # Create map of object names to object type enums of the form VkName : VkObjectTypeName
1579 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 -05001580 # Convert object type enum names from UpperCamelCase to UPPER_CASE_WITH_UNDERSCORES
1581 for objectName, objectTypeEnum in obj_type_mapping.items():
1582 obj_type_mapping[objectName] = ucc_to_U_C_C(objectTypeEnum);
1583 # Command Buffer Object doesn't follow the rule.
Chia-I Wu1f851912015-10-27 18:04:07 +08001584 obj_type_mapping['VkCommandBuffer'] = "VK_OBJECT_TYPE_COMMAND_BUFFER"
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -06001585 obj_type_mapping['VkShaderModule'] = "VK_OBJECT_TYPE_SHADER_MODULE"
Mike Stroyan723913e2015-04-03 14:39:16 -06001586
Mark Lobodzinski14305ad2015-06-23 11:35:12 -06001587 explicit_object_tracker_functions = [
1588 "CreateInstance",
Tobin Ehlis87f115c2015-09-15 15:02:17 -06001589 "EnumeratePhysicalDevices",
Cody Northropef72e2a2015-08-03 17:04:53 -06001590 "GetPhysicalDeviceQueueFamilyProperties",
Mark Lobodzinski14305ad2015-06-23 11:35:12 -06001591 "CreateDevice",
Mark Lobodzinski14305ad2015-06-23 11:35:12 -06001592 "GetDeviceQueue",
Chia-I Wu06809d52015-10-26 16:55:27 +08001593 "QueueBindSparse",
Chia-I Wu1f851912015-10-27 18:04:07 +08001594 "AllocateDescriptorSets",
Tony Barbour912e8152015-07-20 10:52:13 -06001595 "FreeDescriptorSets",
Mark Lobodzinski60b2b332015-11-12 16:02:35 -07001596 "AllocateCommandBuffers",
1597 "FreeCommandBuffers",
1598 "DestroyDescriptorPool",
1599 "DestroyCommandPool",
Mark Lobodzinski14305ad2015-06-23 11:35:12 -06001600 "MapMemory",
1601 "UnmapMemory",
1602 "FreeMemory",
Mark Lobodzinski9c483302015-10-14 13:16:33 -06001603 "DestroySwapchainKHR",
1604 "GetSwapchainImagesKHR"
Mark Lobodzinski14305ad2015-06-23 11:35:12 -06001605 ]
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001606 decl = proto.c_func(prefix="vk", attr="VKAPI")
Mike Stroyan723913e2015-04-03 14:39:16 -06001607 param0_name = proto.params[0].name
Mark Lobodzinskic44a5a12015-05-08 09:12:28 -05001608 using_line = ''
Mike Stroyan723913e2015-04-03 14:39:16 -06001609 create_line = ''
Mark Lobodzinski4a611132015-07-17 11:51:24 -06001610 destroy_line = ''
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001611 # Dict below tracks params that are vk objects. Dict is "loop count"->["params w/ that loop count"] where '0' is params that aren't in an array
1612 loop_params = defaultdict(list) # Dict uses loop count as key to make final code generation cleaner so params shared in single loop where needed
Michael Lentine1a85aa12015-11-04 14:35:12 -08001613 loop_types = defaultdict(list)
Tobin Ehlis33ce8fd2015-07-10 18:25:07 -06001614 # TODO : For now skipping objs that can be NULL. Really should check these and have special case that allows them to be NULL
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001615 # or better yet, these should be encoded into an API json definition and we generate checks from there
1616 # Until then, this is a dict where each func name is a list of object params that can be null (so don't need to be validated)
1617 # param names may be directly passed to the function, or may be a field in a struct param
1618 valid_null_object_names = {'CreateGraphicsPipelines' : ['basePipelineHandle'],
1619 'CreateComputePipelines' : ['basePipelineHandle'],
1620 'BeginCommandBuffer' : ['renderPass', 'framebuffer'],
Tobin Ehlis87f115c2015-09-15 15:02:17 -06001621 'QueueSubmit' : ['fence'],
Tobin Ehlis093ef922015-11-02 15:24:32 -07001622 'UpdateDescriptorSets' : ['pTexelBufferView'],
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001623 }
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001624 param_count = 'NONE' # keep track of arrays passed directly into API functions
Tobin Ehlis586aa012015-06-08 17:36:28 -06001625 for p in proto.params:
Tobin Ehlis87f115c2015-09-15 15:02:17 -06001626 base_type = p.ty.replace('const ', '').strip('*')
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001627 if 'count' in p.name.lower():
1628 param_count = p.name
Tobin Ehlis87f115c2015-09-15 15:02:17 -06001629 if base_type in vulkan.core.objects:
1630 # This is an object to potentially check for validity. First see if it's an array
1631 if '*' in p.ty and 'const' in p.ty and param_count != 'NONE':
1632 loop_params[param_count].append(p.name)
Michael Lentine1a85aa12015-11-04 14:35:12 -08001633 loop_types[param_count].append(str(p.ty[6:-1]))
Tobin Ehlis87f115c2015-09-15 15:02:17 -06001634 # Not an array, check for just a base Object that's not in exceptions
1635 elif '*' not in p.ty and (proto.name not in valid_null_object_names or p.name not in valid_null_object_names[proto.name]):
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001636 loop_params[0].append(p.name)
Michael Lentine1a85aa12015-11-04 14:35:12 -08001637 loop_types[0].append(str(p.ty))
Tobin Ehlis87f115c2015-09-15 15:02:17 -06001638 elif vk_helper.is_type(base_type, 'struct'):
1639 struct_type = base_type
Tobin Ehlis25756af2015-06-30 14:32:16 -06001640 if vk_helper.typedef_rev_dict[struct_type] in vk_helper.struct_dict:
1641 struct_type = vk_helper.typedef_rev_dict[struct_type]
Tobin Ehlis04c05842015-10-23 17:52:53 -06001642 # Parse elements of this struct param to identify objects and/or arrays of objects
Tobin Ehlis25756af2015-06-30 14:32:16 -06001643 for m in sorted(vk_helper.struct_dict[struct_type]):
1644 if vk_helper.struct_dict[struct_type][m]['type'] in vulkan.core.objects and vk_helper.struct_dict[struct_type][m]['type'] not in ['VkPhysicalDevice', 'VkQueue', 'VkFence', 'VkImage', 'VkDeviceMemory']:
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001645 if proto.name not in valid_null_object_names or vk_helper.struct_dict[struct_type][m]['name'] not in valid_null_object_names[proto.name]:
Tobin Ehlis04c05842015-10-23 17:52:53 -06001646 # This is not great, but gets the job done for now, but If we have a count and this param is a ptr w/
1647 # last letter 's' OR non-'count' string of count is in the param name, then this is a dynamically sized array param
1648 param_array = False
1649 if param_count != 'NONE':
1650 if '*' in p.ty:
1651 if 's' == p.name[-1] or param_count.lower().replace('count', '') in p.name.lower():
1652 param_array = True
1653 if param_array:
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001654 param_name = '%s[i].%s' % (p.name, vk_helper.struct_dict[struct_type][m]['name'])
Tobin Ehlis157e28d2015-07-10 11:10:21 -06001655 else:
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001656 param_name = '%s->%s' % (p.name, vk_helper.struct_dict[struct_type][m]['name'])
1657 if vk_helper.struct_dict[struct_type][m]['dyn_array']:
Tobin Ehlis04c05842015-10-23 17:52:53 -06001658 if param_count != 'NONE': # this will be a double-embedded loop, use comma delineated 'count,name' for param_name
1659 loop_count = '%s[i].%s' % (p.name, vk_helper.struct_dict[struct_type][m]['array_size'])
1660 loop_params[param_count].append('%s,%s' % (loop_count, param_name))
Michael Lentine1a85aa12015-11-04 14:35:12 -08001661 loop_types[param_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Tobin Ehlis04c05842015-10-23 17:52:53 -06001662 else:
1663 loop_count = '%s->%s' % (p.name, vk_helper.struct_dict[struct_type][m]['array_size'])
1664 loop_params[loop_count].append(param_name)
Michael Lentine1a85aa12015-11-04 14:35:12 -08001665 loop_types[loop_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001666 else:
1667 if '[' in param_name: # dynamic array param, set size
1668 loop_params[param_count].append(param_name)
Michael Lentine1a85aa12015-11-04 14:35:12 -08001669 loop_types[param_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001670 else:
1671 loop_params[0].append(param_name)
Michael Lentine1a85aa12015-11-04 14:35:12 -08001672 loop_types[0].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
Mike Stroyan723913e2015-04-03 14:39:16 -06001673 funcs = []
Tobin Ehlis586aa012015-06-08 17:36:28 -06001674 mutex_unlock = False
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001675 funcs.append('%s\n' % self.lineinfo.get())
Mark Lobodzinski14305ad2015-06-23 11:35:12 -06001676 if proto.name in explicit_object_tracker_functions:
Jon Ashburn630e44f2015-04-08 21:33:34 -06001677 funcs.append('%s%s\n'
1678 '{\n'
Mark Lobodzinski14305ad2015-06-23 11:35:12 -06001679 ' return explicit_%s;\n'
1680 '}' % (qual, decl, proto.c_call()))
1681 return "".join(funcs)
Mark Lobodzinski956e4ac2015-11-24 10:28:31 -07001682 # Temporarily prevent DestroySurface call from being generated until WSI layer support is fleshed out
Mark Lobodzinski6f92feb2015-11-26 10:59:58 -07001683 elif 'DestroyInstance' in proto.name or 'DestroyDevice' in proto.name: # LUGMAL or 'SurfaceKHR' in proto.name:
Mark Lobodzinski4a611132015-07-17 11:51:24 -06001684 return ""
Jon Ashburn630e44f2015-04-08 21:33:34 -06001685 else:
Mark Lobodzinski14305ad2015-06-23 11:35:12 -06001686 if 'Create' in proto.name or 'Alloc' in proto.name:
Michael Lentine1a85aa12015-11-04 14:35:12 -08001687 typ = proto.params[-1].ty.strip('*').replace('const ', '');
1688 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1689 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Mark Lobodzinski14305ad2015-06-23 11:35:12 -06001690 create_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
1691 create_line += ' if (result == VK_SUCCESS) {\n'
Michael Lentine1a85aa12015-11-04 14:35:12 -08001692 create_line += ' create_%s(%s, *%s, %s);\n' % (name, param0_name, proto.params[-1].name, obj_type_mapping[typ])
Mark Lobodzinski14305ad2015-06-23 11:35:12 -06001693 create_line += ' }\n'
1694 create_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Courtney Goeltzenleuchter831c1832015-10-23 14:21:05 -06001695 if 'FreeCommandBuffers' in proto.name:
Michael Lentine1a85aa12015-11-04 14:35:12 -08001696 typ = proto.params[-1].ty.strip('*').replace('const ', '');
1697 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1698 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Courtney Goeltzenleuchter831c1832015-10-23 14:21:05 -06001699 funcs.append('%s\n' % self.lineinfo.get())
1700 destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Chia-I Wu763a7492015-10-26 20:48:51 +08001701 destroy_line += ' for (uint32_t i = 0; i < commandBufferCount; i++) {\n'
Michael Lentine1a85aa12015-11-04 14:35:12 -08001702 destroy_line += ' destroy_%s(%s[i], %s[i]);\n' % (name, proto.params[-1].name, proto.params[-1].name)
Courtney Goeltzenleuchter831c1832015-10-23 14:21:05 -06001703 destroy_line += ' }\n'
1704 destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Mark Lobodzinski4a611132015-07-17 11:51:24 -06001705 if 'Destroy' in proto.name:
Michael Lentine1a85aa12015-11-04 14:35:12 -08001706 typ = proto.params[-2].ty.strip('*').replace('const ', '');
1707 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1708 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Courtney Goeltzenleuchter831c1832015-10-23 14:21:05 -06001709 funcs.append('%s\n' % self.lineinfo.get())
Mark Lobodzinski4a611132015-07-17 11:51:24 -06001710 destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
Mark Lobodzinski67b42b72015-09-07 13:59:43 -06001711# destroy_line += ' if (result == VK_SUCCESS) {\n'
Michael Lentine1a85aa12015-11-04 14:35:12 -08001712 destroy_line += ' destroy_%s(%s, %s);\n' % (name, param0_name, proto.params[-2].name)
Mark Lobodzinski67b42b72015-09-07 13:59:43 -06001713# destroy_line += ' }\n'
Mark Lobodzinski4a611132015-07-17 11:51:24 -06001714 destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001715 if len(loop_params) > 0:
Tobin Ehlisf2f97402015-09-11 12:57:55 -06001716 using_line += ' VkBool32 skipCall = VK_FALSE;\n'
Mark Lobodzinski14305ad2015-06-23 11:35:12 -06001717 if not mutex_unlock:
1718 using_line += ' loader_platform_thread_lock_mutex(&objLock);\n'
1719 mutex_unlock = True
Michael Lentine1a85aa12015-11-04 14:35:12 -08001720 for lc,lt in zip(loop_params,loop_types):
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001721 if 0 == lc: # No looping required for these params
Michael Lentine1a85aa12015-11-04 14:35:12 -08001722 for opn,typ in zip(loop_params[lc],loop_types[lt]):
1723 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1724 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001725 if '->' in opn:
1726 using_line += ' if (%s)\n' % (opn.split('-')[0])
Michael Lentine1a85aa12015-11-04 14:35:12 -08001727 using_line += ' skipCall |= validate_%s(%s, %s);\n' % (name, param0_name, opn)
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001728 else:
Mark Lobodzinski956e4ac2015-11-24 10:28:31 -07001729 if 'AcquireNext' in proto.name and 'fence' == name:
1730 using_line += ' if (fence != VK_NULL_HANDLE) {\n'
1731 using_line += ' skipCall |= validate_%s(%s, %s);\n' % (name, param0_name, opn)
1732 using_line += ' }\n'
Mark Lobodzinskida98f4d2015-12-07 15:55:11 -07001733 elif ('CreateGraphicsPipelines' in proto.name or 'CreateComputePipelines' in proto.name) and 'pipelineCache' == opn:
1734 using_line += ' // PipelineCache is optional, validate if present\n'
1735 using_line += ' if (pipelineCache != VK_NULL_HANDLE) {\n'
1736 using_line += ' skipCall |= validate_%s(%s, %s);\n' % (name, param0_name, opn)
1737 using_line += ' }\n'
Mark Lobodzinski956e4ac2015-11-24 10:28:31 -07001738 else:
1739 using_line += ' skipCall |= validate_%s(%s, %s);\n' % (name, param0_name, opn)
Tobin Ehlis25756af2015-06-30 14:32:16 -06001740 else:
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001741 base_param = loop_params[lc][0].split('-')[0].split('[')[0]
1742 using_line += ' if (%s) {\n' % base_param
Tobin Ehlis41b35502015-10-23 16:57:03 -06001743 using_line += ' for (uint32_t i=0; i<%s; i++) {\n' % lc
Michael Lentine1a85aa12015-11-04 14:35:12 -08001744 for opn,typ in zip(loop_params[lc],loop_types[lt]):
1745 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
1746 name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
Tobin Ehlis04c05842015-10-23 17:52:53 -06001747 if ',' in opn: # double-embedded loop
1748 (inner_lc, inner_param) = opn.split(',')
1749 using_line += ' if (%s) {\n' % inner_param
1750 using_line += ' for (uint32_t j=0; j<%s; j++) {\n' % inner_lc
Michael Lentine1a85aa12015-11-04 14:35:12 -08001751 using_line += ' skipCall |= validate_%s(%s, %s[j]);\n' % (name, param0_name, inner_param)
Tobin Ehlis04c05842015-10-23 17:52:53 -06001752 using_line += ' }\n'
1753 using_line += ' }\n'
1754 elif '[' in opn: # API func param is array
Michael Lentine1a85aa12015-11-04 14:35:12 -08001755 using_line += ' skipCall |= validate_%s(%s, %s);\n' % (name, param0_name, opn)
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001756 else: # struct element is array
Michael Lentine1a85aa12015-11-04 14:35:12 -08001757 using_line += ' skipCall |= validate_%s(%s, %s[i]);\n' % (name, param0_name, opn)
Tobin Ehlis18cf7262015-08-26 11:22:09 -06001758 using_line += ' }\n'
1759 using_line += ' }\n'
Mark Lobodzinski14305ad2015-06-23 11:35:12 -06001760 if mutex_unlock:
1761 using_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
Tobin Ehlisf2f97402015-09-11 12:57:55 -06001762 if len(loop_params) > 0:
1763 using_line += ' if (skipCall)\n'
1764 if proto.ret != "void":
1765 using_line += ' return VK_ERROR_VALIDATION_FAILED;\n'
1766 else:
1767 using_line += ' return;\n'
Mark Lobodzinski14305ad2015-06-23 11:35:12 -06001768 ret_val = ''
1769 stmt = ''
Mark Lobodzinski14305ad2015-06-23 11:35:12 -06001770 if proto.ret != "void":
1771 ret_val = "%s result = " % proto.ret
1772 stmt = " return result;\n"
1773
1774 dispatch_param = proto.params[0].name
1775 if 'CreateInstance' in proto.name:
1776 dispatch_param = '*' + proto.params[1].name
1777
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -05001778 # Must use 'instance' table for these APIs, 'device' table otherwise
1779 table_type = ""
1780 if proto_is_global(proto):
1781 table_type = "instance"
1782 else:
1783 table_type = "device"
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -07001784 if wsi_name(proto.name):
1785 funcs.append('%s' % wsi_ifdef(proto.name))
Mike Stroyan723913e2015-04-03 14:39:16 -06001786 funcs.append('%s%s\n'
1787 '{\n'
1788 '%s'
Mike Stroyan723913e2015-04-03 14:39:16 -06001789 '%s'
Mike Stroyane78816e2015-09-28 13:47:29 -06001790 ' %sget_dispatch_table(ObjectTracker_%s_table_map, %s)->%s;\n'
1791 '%s'
1792 '%s'
1793 '}' % (qual, decl, using_line, destroy_line, ret_val, table_type, dispatch_param, proto.c_call(), create_line, stmt))
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -07001794 if wsi_name(proto.name):
1795 funcs.append('%s' % wsi_endif(proto.name))
Mike Stroyan723913e2015-04-03 14:39:16 -06001796 return "\n\n".join(funcs)
1797
Tobin Ehlis92dbf802014-10-22 09:06:33 -06001798 def generate_body(self):
Mike Stroyan3aecdb42015-04-03 17:13:23 -06001799 self.layer_name = "ObjectTracker"
Ian Elliottb134e842015-07-06 14:31:32 -06001800 extensions=[('wsi_enabled',
Ian Elliottc623ba52015-11-20 14:13:17 -07001801 ['vkCreateSwapchainKHR',
Jon Ashburn83334db2015-09-16 18:08:32 -06001802 'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
1803 'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -07001804 if sys.platform.startswith('win32'):
Michael Lentine81f1fd92015-12-03 14:33:09 -08001805 instance_extensions=[('msg_callback_get_proc_addr', []),
1806 ('wsi_enabled',
1807 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1808 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1809 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1810 'vkGetPhysicalDeviceSurfacePresentModesKHR',
1811 'vkCreateWin32SurfaceKHR',
1812 'vkGetPhysicalDeviceWin32PresentationSupportKHR'])]
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -07001813 elif sys.platform.startswith('linux'):
Michael Lentine81f1fd92015-12-03 14:33:09 -08001814 instance_extensions=[('msg_callback_get_proc_addr', []),
1815 ('wsi_enabled',
1816 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1817 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1818 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1819 'vkGetPhysicalDeviceSurfacePresentModesKHR',
1820 'vkCreateXcbSurfaceKHR',
Mark Lobodzinski6f92feb2015-11-26 10:59:58 -07001821 'vkGetPhysicalDeviceXcbPresentationSupportKHR'])]
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -07001822 # TODO: Add cases for Mir, Wayland and Xlib
1823 else: # android
1824 instance_extensions=[('msg_callback_get_proc_addr', []),
1825 ('wsi_enabled',
1826 ['vkGetPhysicalDeviceSurfaceSupportKHR',
1827 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
1828 'vkGetPhysicalDeviceSurfaceFormatsKHR',
1829 'vkGetPhysicalDeviceSurfacePresentModesKHR'])]
Tony Barbour2a199c12015-07-09 17:31:46 -06001830 body = [self.generate_maps(),
1831 self.generate_procs(),
Mark Lobodzinski4a611132015-07-17 11:51:24 -06001832 self.generate_destroy_instance(),
1833 self.generate_destroy_device(),
Tony Barbour2a199c12015-07-09 17:31:46 -06001834 self.generate_command_buffer_validates(),
1835 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Tobin Ehlis3c26a542014-11-18 11:28:33 -07001836 self._generate_extensions(),
Jon Ashburn7e07faf2015-06-18 15:02:58 -06001837 self._generate_layer_gpa_function(extensions,
Jon Ashburnde4f1102015-09-17 10:00:32 -06001838 instance_extensions)]
Tobin Ehlis92dbf802014-10-22 09:06:33 -06001839 return "\n\n".join(body)
Courtney Goeltzenleuchtere6094fc2014-11-18 10:40:29 -07001840
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001841class ThreadingSubcommand(Subcommand):
Mike Stroyanc0e49b22015-07-09 11:01:07 -06001842 thread_check_dispatchable_objects = [
1843 "VkQueue",
Chia-I Wu1f851912015-10-27 18:04:07 +08001844 "VkCommandBuffer",
Mike Stroyanc0e49b22015-07-09 11:01:07 -06001845 ]
1846 thread_check_nondispatchable_objects = [
1847 "VkDeviceMemory",
1848 "VkBuffer",
1849 "VkImage",
1850 "VkDescriptorSet",
1851 "VkDescriptorPool",
1852 "VkSemaphore"
1853 ]
Mike Stroyan90a166e2015-08-10 16:42:53 -06001854 thread_check_object_types = {
1855 'VkInstance' : 'VK_OBJECT_TYPE_INSTANCE',
1856 'VkPhysicalDevice' : 'VK_OBJECT_TYPE_PHYSICAL_DEVICE',
1857 'VkDevice' : 'VK_OBJECT_TYPE_DEVICE',
1858 'VkQueue' : 'VK_OBJECT_TYPE_QUEUE',
Chia-I Wu1f851912015-10-27 18:04:07 +08001859 'VkCommandBuffer' : 'VK_OBJECT_TYPE_COMMAND_BUFFER',
Mike Stroyan90a166e2015-08-10 16:42:53 -06001860 'VkFence' : 'VK_OBJECT_TYPE_FENCE',
1861 'VkDeviceMemory' : 'VK_OBJECT_TYPE_DEVICE_MEMORY',
1862 'VkBuffer' : 'VK_OBJECT_TYPE_BUFFER',
1863 'VkImage' : 'VK_OBJECT_TYPE_IMAGE',
1864 'VkSemaphore' : 'VK_OBJECT_TYPE_SEMAPHORE',
1865 'VkEvent' : 'VK_OBJECT_TYPE_EVENT',
1866 'VkQueryPool' : 'VK_OBJECT_TYPE_QUERY_POOL',
1867 'VkBufferView' : 'VK_OBJECT_TYPE_BUFFER_VIEW',
1868 'VkImageView' : 'VK_OBJECT_TYPE_IMAGE_VIEW',
Mike Stroyan90a166e2015-08-10 16:42:53 -06001869 'VkShaderModule' : 'VK_OBJECT_TYPE_SHADER_MODULE',
1870 'VkShader' : 'VK_OBJECT_TYPE_SHADER',
1871 'VkPipelineCache' : 'VK_OBJECT_TYPE_PIPELINE_CACHE',
1872 'VkPipelineLayout' : 'VK_OBJECT_TYPE_PIPELINE_LAYOUT',
1873 'VkRenderPass' : 'VK_OBJECT_TYPE_RENDER_PASS',
1874 'VkPipeline' : 'VK_OBJECT_TYPE_PIPELINE',
1875 'VkDescriptorSetLayout' : 'VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT',
1876 'VkSampler' : 'VK_OBJECT_TYPE_SAMPLER',
1877 'VkDescriptorPool' : 'VK_OBJECT_TYPE_DESCRIPTOR_POOL',
1878 'VkDescriptorSet' : 'VK_OBJECT_TYPE_DESCRIPTOR_SET',
Mike Stroyan90a166e2015-08-10 16:42:53 -06001879 'VkFramebuffer' : 'VK_OBJECT_TYPE_FRAMEBUFFER',
Chia-I Wu1f851912015-10-27 18:04:07 +08001880 'VkCommandPool' : 'VK_OBJECT_TYPE_COMMAND_POOL',
Mike Stroyan90a166e2015-08-10 16:42:53 -06001881 }
1882 def generate_useObject(self, ty):
1883 obj_type = self.thread_check_object_types[ty]
Chia-I Wue420a332015-10-26 20:04:44 +08001884 key = "object"
1885 msg_object = "reinterpret_cast<uint64_t>(object)"
Mike Stroyanc0e49b22015-07-09 11:01:07 -06001886 header_txt = []
1887 header_txt.append('%s' % self.lineinfo.get())
Michael Lentine1a85aa12015-11-04 14:35:12 -08001888 header_txt.append('static void use%s(const void* dispatchable_object, %s object)' % (ty, ty))
Mike Stroyanc0e49b22015-07-09 11:01:07 -06001889 header_txt.append('{')
1890 header_txt.append(' loader_platform_thread_id tid = loader_platform_get_thread_id();')
1891 header_txt.append(' loader_platform_thread_lock_mutex(&threadingLock);')
1892 header_txt.append(' if (%sObjectsInUse.find(%s) == %sObjectsInUse.end()) {' % (ty, key, ty))
1893 header_txt.append(' %sObjectsInUse[%s] = tid;' % (ty, key))
1894 header_txt.append(' } else {')
1895 header_txt.append(' if (%sObjectsInUse[%s] != tid) {' % (ty, key))
Courtney Goeltzenleuchterf8fe1282015-11-25 10:30:56 -07001896 header_txt.append(' log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT, %s, %s,' % (obj_type, msg_object))
Mike Stroyan90a166e2015-08-10 16:42:53 -06001897 header_txt.append(' /*location*/ 0, THREADING_CHECKER_MULTIPLE_THREADS, "THREADING",')
1898 header_txt.append(' "THREADING ERROR : object of type %s is simultaneously used in thread %%ld and thread %%ld",' % (ty))
1899 header_txt.append(' %sObjectsInUse[%s], tid);' % (ty, key))
Mike Stroyanc0e49b22015-07-09 11:01:07 -06001900 header_txt.append(' // Wait for thread-safe access to object')
1901 header_txt.append(' while (%sObjectsInUse.find(%s) != %sObjectsInUse.end()) {' % (ty, key, ty))
1902 header_txt.append(' loader_platform_thread_cond_wait(&threadingCond, &threadingLock);')
1903 header_txt.append(' }')
1904 header_txt.append(' %sObjectsInUse[%s] = tid;' % (ty, key))
1905 header_txt.append(' } else {')
Courtney Goeltzenleuchterf8fe1282015-11-25 10:30:56 -07001906 header_txt.append(' log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT, %s, %s,' % (obj_type, msg_object))
Mike Stroyan90a166e2015-08-10 16:42:53 -06001907 header_txt.append(' /*location*/ 0, THREADING_CHECKER_MULTIPLE_THREADS, "THREADING",')
1908 header_txt.append(' "THREADING ERROR : object of type %s is recursively used in thread %%ld",' % (ty))
1909 header_txt.append(' tid);')
Mike Stroyanc0e49b22015-07-09 11:01:07 -06001910 header_txt.append(' }')
1911 header_txt.append(' }')
1912 header_txt.append(' loader_platform_thread_unlock_mutex(&threadingLock);')
1913 header_txt.append('}')
1914 return "\n".join(header_txt)
Mike Stroyan90a166e2015-08-10 16:42:53 -06001915 def generate_finishUsingObject(self, ty):
Chia-I Wue420a332015-10-26 20:04:44 +08001916 key = "object"
Mike Stroyanc0e49b22015-07-09 11:01:07 -06001917 header_txt = []
1918 header_txt.append('%s' % self.lineinfo.get())
Michael Lentine1a85aa12015-11-04 14:35:12 -08001919 header_txt.append('static void finishUsing%s(%s object)' % (ty, ty))
Mike Stroyanc0e49b22015-07-09 11:01:07 -06001920 header_txt.append('{')
1921 header_txt.append(' // Object is no longer in use')
1922 header_txt.append(' loader_platform_thread_lock_mutex(&threadingLock);')
1923 header_txt.append(' %sObjectsInUse.erase(%s);' % (ty, key))
1924 header_txt.append(' loader_platform_thread_cond_broadcast(&threadingCond);')
1925 header_txt.append(' loader_platform_thread_unlock_mutex(&threadingLock);')
1926 header_txt.append('}')
1927 return "\n".join(header_txt)
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001928 def generate_header(self):
1929 header_txt = []
Tobin Ehlisfde2fc32015-06-12 12:49:01 -06001930 header_txt.append('%s' % self.lineinfo.get())
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001931 header_txt.append('#include <stdio.h>')
1932 header_txt.append('#include <stdlib.h>')
1933 header_txt.append('#include <string.h>')
1934 header_txt.append('#include <unordered_map>')
Tobin Ehlis7a51d902015-07-03 10:34:49 -06001935 header_txt.append('#include "vk_loader_platform.h"')
David Pinedo329ca9e2015-11-06 12:54:48 -07001936 header_txt.append('#include "vulkan/vk_layer.h"')
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001937 header_txt.append('#include "threading.h"')
Tobin Ehlis56d204a2015-07-03 10:15:26 -06001938 header_txt.append('#include "vk_layer_config.h"')
Courtney Goeltzenleuchter03f1c8c2015-07-06 09:11:12 -06001939 header_txt.append('#include "vk_layer_extension_utils.h"')
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001940 header_txt.append('#include "vk_enum_validate_helper.h"')
1941 header_txt.append('#include "vk_struct_validate_helper.h"')
Mike Stroyan90a166e2015-08-10 16:42:53 -06001942 header_txt.append('#include "vk_layer_table.h"')
1943 header_txt.append('#include "vk_layer_logging.h"')
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -05001944 header_txt.append('')
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -05001945 header_txt.append('')
1946 header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
1947 header_txt.append('')
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001948 header_txt.append('using namespace std;')
Mike Stroyanc0e49b22015-07-09 11:01:07 -06001949 for ty in self.thread_check_dispatchable_objects:
1950 header_txt.append('static unordered_map<%s, loader_platform_thread_id> %sObjectsInUse;' % (ty, ty))
1951 for ty in self.thread_check_nondispatchable_objects:
Chia-I Wue420a332015-10-26 20:04:44 +08001952 header_txt.append('static unordered_map<%s, loader_platform_thread_id> %sObjectsInUse;' % (ty, ty))
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001953 header_txt.append('static int threadingLockInitialized = 0;')
1954 header_txt.append('static loader_platform_thread_mutex threadingLock;')
Mike Stroyan354ed672015-05-15 08:50:57 -06001955 header_txt.append('static loader_platform_thread_cond threadingCond;')
Tobin Ehlisfde2fc32015-06-12 12:49:01 -06001956 header_txt.append('%s' % self.lineinfo.get())
Mike Stroyan90a166e2015-08-10 16:42:53 -06001957 for ty in self.thread_check_dispatchable_objects + self.thread_check_nondispatchable_objects:
1958 header_txt.append(self.generate_useObject(ty))
1959 header_txt.append(self.generate_finishUsingObject(ty))
Mike Stroyanc0e49b22015-07-09 11:01:07 -06001960 header_txt.append('%s' % self.lineinfo.get())
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001961 return "\n".join(header_txt)
1962
1963 def generate_intercept(self, proto, qual):
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001964 if proto.name in [ 'DbgCreateMsgCallback' ]:
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001965 # use default version
1966 return None
1967 decl = proto.c_func(prefix="vk", attr="VKAPI")
1968 ret_val = ''
1969 stmt = ''
1970 funcs = []
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -05001971 table = 'device'
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001972 if proto.ret != "void":
Jon Ashburn53c16772015-05-06 10:15:07 -06001973 ret_val = "%s result = " % proto.ret
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001974 stmt = " return result;\n"
Jon Ashburn2666e2f2015-05-15 15:09:35 -06001975 if proto_is_global(proto):
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -05001976 table = 'instance'
Jon Ashburn52c1d732015-05-12 17:23:55 -06001977
Mike Stroyanae0eafd2015-05-11 17:18:14 -06001978 # Memory range calls are special in needed thread checking within structs
1979 if proto.name in ["FlushMappedMemoryRanges","InvalidateMappedMemoryRanges"]:
Mike Stroyan90a166e2015-08-10 16:42:53 -06001980 funcs.append('%s' % self.lineinfo.get())
1981 funcs.append('%s%s\n' % (qual, decl) +
Mike Stroyanae0eafd2015-05-11 17:18:14 -06001982 '{\n'
Chia-I Wu1f851912015-10-27 18:04:07 +08001983 ' for (uint32_t i=0; i<memoryRangeCount; i++) {\n'
Michael Lentine1a85aa12015-11-04 14:35:12 -08001984 ' useVkDeviceMemory((const void *) %s, pMemoryRanges[i].memory);\n' % proto.params[0].name +
Mike Stroyanae0eafd2015-05-11 17:18:14 -06001985 ' }\n'
Mike Stroyan90a166e2015-08-10 16:42:53 -06001986 ' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(Threading_%s_table_map, %s);\n' % (table, proto.params[0].name) +
1987 ' %s pDeviceTable->%s;\n' % (ret_val, proto.c_call()) +
Chia-I Wu1f851912015-10-27 18:04:07 +08001988 ' for (uint32_t i=0; i<memoryRangeCount; i++) {\n'
Michael Lentine1a85aa12015-11-04 14:35:12 -08001989 ' finishUsingVkDeviceMemory(pMemoryRanges[i].memory);\n'
Mike Stroyanae0eafd2015-05-11 17:18:14 -06001990 ' }\n'
Mike Stroyan90a166e2015-08-10 16:42:53 -06001991 '%s' % (stmt) +
1992 '}')
Mike Stroyanae0eafd2015-05-11 17:18:14 -06001993 return "\n".join(funcs)
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001994 # All functions that do a Get are thread safe
Mike Stroyanae0eafd2015-05-11 17:18:14 -06001995 if 'Get' in proto.name:
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001996 return None
Mike Stroyanae0eafd2015-05-11 17:18:14 -06001997 # All WSI functions are thread safe
Ian Elliott338dedb2015-08-21 15:09:33 -06001998 if 'KHR' in proto.name:
Mike Stroyanb326d2c2015-04-02 11:59:05 -06001999 return None
Mike Stroyanae0eafd2015-05-11 17:18:14 -06002000 # Initialize in early calls
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002001 if proto.name == "CreateDevice":
2002 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan90a166e2015-08-10 16:42:53 -06002003 funcs.append('%s%s\n' % (qual, decl) +
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002004 '{\n'
Mike Stroyan90a166e2015-08-10 16:42:53 -06002005 ' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(Threading_device_table_map, (void *) *pDevice);\n'
2006 ' VkResult result = pDeviceTable->%s;\n' % (proto.c_call()) +
2007 ' if (result == VK_SUCCESS) {\n'
2008 ' layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(%s), layer_data_map);\n' % proto.params[0].name +
2009 ' layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);\n'
2010 ' my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);\n'
2011 ' }\n'
2012 '\n'
2013 ' return result;'
2014 '}')
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002015 return "\n".join(funcs)
2016 elif proto.params[0].ty == "VkPhysicalDevice":
Mike Stroyan90a166e2015-08-10 16:42:53 -06002017 return None
Mike Stroyanae0eafd2015-05-11 17:18:14 -06002018 # Functions changing command buffers need thread safe use of first parameter
Chia-I Wu1f851912015-10-27 18:04:07 +08002019 if proto.params[0].ty == "VkCommandBuffer":
Tobin Ehlisfde2fc32015-06-12 12:49:01 -06002020 funcs.append('%s' % self.lineinfo.get())
Mike Stroyan90a166e2015-08-10 16:42:53 -06002021 funcs.append('%s%s\n' % (qual, decl) +
Mike Stroyanb326d2c2015-04-02 11:59:05 -06002022 '{\n'
Michael Lentine1a85aa12015-11-04 14:35:12 -08002023 ' use%s((const void *) %s, %s);\n' % (proto.params[0].ty, proto.params[0].name, proto.params[0].name) +
Mike Stroyan90a166e2015-08-10 16:42:53 -06002024 ' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(Threading_%s_table_map, %s);\n' % (table, proto.params[0].name) +
2025 ' %spDeviceTable->%s;\n' % (ret_val, proto.c_call()) +
Michael Lentine1a85aa12015-11-04 14:35:12 -08002026 ' finishUsing%s(%s);\n' % (proto.params[0].ty, proto.params[0].name) +
Mike Stroyan90a166e2015-08-10 16:42:53 -06002027 '%s' % stmt +
2028 '}')
Mike Stroyanae0eafd2015-05-11 17:18:14 -06002029 return "\n".join(funcs)
2030 # Non-Cmd functions that do a Wait are thread safe
2031 if 'Wait' in proto.name:
2032 return None
2033 # Watch use of certain types of objects passed as any parameter
2034 checked_params = []
2035 for param in proto.params:
Mike Stroyanc0e49b22015-07-09 11:01:07 -06002036 if param.ty in self.thread_check_dispatchable_objects or param.ty in self.thread_check_nondispatchable_objects:
Mike Stroyanae0eafd2015-05-11 17:18:14 -06002037 checked_params.append(param)
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -05002038 if proto.name == "DestroyDevice":
Mike Stroyan90a166e2015-08-10 16:42:53 -06002039 funcs.append('%s%s\n' % (qual, decl) +
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -05002040 '{\n'
Courtney Goeltzenleuchter9f171942015-06-13 21:22:12 -06002041 ' dispatch_key key = get_dispatch_key(device);\n'
Mike Stroyan90a166e2015-08-10 16:42:53 -06002042 ' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(Threading_%s_table_map, %s);\n' % (table, proto.params[0].name) +
2043 ' %spDeviceTable->%s;\n' % (ret_val, proto.c_call()) +
2044 ' Threading_device_table_map.erase(key);\n'
Mike Stroyan90a166e2015-08-10 16:42:53 -06002045 '}\n')
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -05002046 return "\n".join(funcs);
2047 elif proto.name == "DestroyInstance":
Mike Stroyan90a166e2015-08-10 16:42:53 -06002048 funcs.append('%s%s\n' % (qual, decl) +
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -05002049 '{\n'
Courtney Goeltzenleuchter9f171942015-06-13 21:22:12 -06002050 ' dispatch_key key = get_dispatch_key(instance);\n'
Mike Stroyan90a166e2015-08-10 16:42:53 -06002051 ' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(Threading_instance_table_map, %s);\n' % proto.params[0].name +
2052 ' %spInstanceTable->%s;\n' % (ret_val, proto.c_call()) +
Courtney Goeltzenleuchter9f171942015-06-13 21:22:12 -06002053 ' destroy_instance_dispatch_table(key);\n'
Mike Stroyan90a166e2015-08-10 16:42:53 -06002054 '\n'
2055 ' // Clean up logging callback, if any\n'
2056 ' layer_data *my_data = get_my_data_ptr(key, layer_data_map);\n'
2057 ' if (my_data->logging_callback) {\n'
2058 ' layer_destroy_msg_callback(my_data->report_data, my_data->logging_callback);\n'
2059 ' }\n'
2060 '\n'
2061 ' layer_debug_report_destroy_instance(my_data->report_data);\n'
2062 ' layer_data_map.erase(pInstanceTable);\n'
2063 '\n'
2064 ' Threading_instance_table_map.erase(key);\n'
Mike Stroyan90a166e2015-08-10 16:42:53 -06002065 '}\n')
Mark Lobodzinskibbbc4842015-05-22 14:15:36 -05002066 return "\n".join(funcs);
Courtney Goeltzenleuchterf4a2eba2015-06-08 14:58:39 -06002067 elif proto.name == "CreateInstance":
2068 funcs.append('%s%s\n'
2069 '{\n'
Mike Stroyan90a166e2015-08-10 16:42:53 -06002070 ' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(Threading_instance_table_map, *pInstance);\n'
Chia-I Wu69f40122015-10-26 21:10:41 +08002071 ' VkResult result = pInstanceTable->CreateInstance(pCreateInfo, pAllocator, pInstance);\n'
Courtney Goeltzenleuchterf4a2eba2015-06-08 14:58:39 -06002072 '\n'
2073 ' if (result == VK_SUCCESS) {\n'
Mike Stroyan90a166e2015-08-10 16:42:53 -06002074 ' layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);\n'
2075 ' my_data->report_data = debug_report_create_instance(\n'
2076 ' pInstanceTable,\n'
2077 ' *pInstance,\n'
Chia-I Wu763a7492015-10-26 20:48:51 +08002078 ' pCreateInfo->enabledExtensionNameCount,\n'
Mike Stroyan90a166e2015-08-10 16:42:53 -06002079 ' pCreateInfo->ppEnabledExtensionNames);\n'
2080 ' initThreading(my_data);\n'
Courtney Goeltzenleuchterf4a2eba2015-06-08 14:58:39 -06002081 ' }\n'
2082 ' return result;\n'
Mike Stroyan90a166e2015-08-10 16:42:53 -06002083 '}\n' % (qual, decl))
Courtney Goeltzenleuchterf4a2eba2015-06-08 14:58:39 -06002084 return "\n".join(funcs);
Mike Stroyanae0eafd2015-05-11 17:18:14 -06002085 if len(checked_params) == 0:
2086 return None
2087 # Surround call with useObject and finishUsingObject for each checked_param
Tobin Ehlisfde2fc32015-06-12 12:49:01 -06002088 funcs.append('%s' % self.lineinfo.get())
Mike Stroyanae0eafd2015-05-11 17:18:14 -06002089 funcs.append('%s%s' % (qual, decl))
2090 funcs.append('{')
2091 for param in checked_params:
Michael Lentine1a85aa12015-11-04 14:35:12 -08002092 funcs.append(' use%s((const void *) %s, %s);' % (param.ty, proto.params[0].name, param.name))
Mike Stroyan90a166e2015-08-10 16:42:53 -06002093 funcs.append(' VkLayerDispatchTable *pDeviceTable = get_dispatch_table(Threading_%s_table_map, %s);' % (table, proto.params[0].name));
2094 funcs.append(' %spDeviceTable->%s;' % (ret_val, proto.c_call()))
Mike Stroyanae0eafd2015-05-11 17:18:14 -06002095 for param in checked_params:
Michael Lentine1a85aa12015-11-04 14:35:12 -08002096 funcs.append(' finishUsing%s(%s);' % (param.ty, param.name))
Mike Stroyanae0eafd2015-05-11 17:18:14 -06002097 funcs.append('%s'
2098 '}' % stmt)
2099 return "\n".join(funcs)
Mike Stroyanb326d2c2015-04-02 11:59:05 -06002100
2101 def generate_body(self):
2102 self.layer_name = "Threading"
Mike Stroyan90a166e2015-08-10 16:42:53 -06002103 body = [self._generate_new_layer_initialization(True, lockname='threading', condname='threading'),
Mike Stroyanb326d2c2015-04-02 11:59:05 -06002104 self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
Courtney Goeltzenleuchterce445ad2015-06-01 14:52:57 -06002105 self._generate_layer_gpa_function(extensions=[],
Jon Ashburnde4f1102015-09-17 10:00:32 -06002106 instance_extensions=[('msg_callback_get_proc_addr', [])]),
Courtney Goeltzenleuchterce445ad2015-06-01 14:52:57 -06002107 self._gen_create_msg_callback(),
2108 self._gen_destroy_msg_callback()]
Mike Stroyanb326d2c2015-04-02 11:59:05 -06002109 return "\n\n".join(body)
2110
Tobin Ehlis92dbf802014-10-22 09:06:33 -06002111def main():
2112 subcommands = {
2113 "layer-funcs" : LayerFuncsSubcommand,
Tobin Ehlis907a0522014-11-25 16:59:27 -07002114 "Generic" : GenericLayerSubcommand,
Tobin Ehlis4a636a12015-04-09 09:19:36 -06002115 "APIDump" : APIDumpSubcommand,
Tobin Ehlis907a0522014-11-25 16:59:27 -07002116 "ObjectTracker" : ObjectTrackerSubcommand,
Mike Stroyanb326d2c2015-04-02 11:59:05 -06002117 "Threading" : ThreadingSubcommand,
Tobin Ehlis92dbf802014-10-22 09:06:33 -06002118 }
2119
Tobin Ehlis6cd06372014-12-17 17:44:50 -07002120 if len(sys.argv) < 3 or sys.argv[1] not in subcommands or not os.path.exists(sys.argv[2]):
2121 print("Usage: %s <subcommand> <input_header> [options]" % sys.argv[0])
Tobin Ehlis92dbf802014-10-22 09:06:33 -06002122 print
Tobin Ehlis2f3726c2015-01-15 17:51:52 -07002123 print("Available subcommands are: %s" % " ".join(subcommands))
Tobin Ehlis92dbf802014-10-22 09:06:33 -06002124 exit(1)
2125
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06002126 hfp = vk_helper.HeaderFileParser(sys.argv[2])
Tobin Ehlis6cd06372014-12-17 17:44:50 -07002127 hfp.parse()
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06002128 vk_helper.enum_val_dict = hfp.get_enum_val_dict()
2129 vk_helper.enum_type_dict = hfp.get_enum_type_dict()
2130 vk_helper.struct_dict = hfp.get_struct_dict()
2131 vk_helper.typedef_fwd_dict = hfp.get_typedef_fwd_dict()
2132 vk_helper.typedef_rev_dict = hfp.get_typedef_rev_dict()
2133 vk_helper.types_dict = hfp.get_types_dict()
Tobin Ehlis6cd06372014-12-17 17:44:50 -07002134
Tobin Ehlis92dbf802014-10-22 09:06:33 -06002135 subcmd = subcommands[sys.argv[1]](sys.argv[2:])
2136 subcmd.run()
2137
2138if __name__ == "__main__":
2139 main()