blob: de4d98dd5325d7ec4b3dc08bc312a01374b934c6 [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
3# Copyright (c) 2015-2016 Valve Corporation
4# Copyright (c) 2015-2016 LunarG, Inc.
5# Copyright (c) 2015-2016 Google Inc.
6#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
20# Author: Mark Lobodzinski <mark@lunarg.com>
21#
22# This script generates the dispatch portion of a factory layer which intercepts
23# all Vulkan functions. The resultant factory layer allows rapid development of
24# layers and interceptors.
25
26import os,re,sys
27from generator import *
28from common_codegen import *
29
30# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31#
32# Adds options used by LayerFactoryOutputGenerator objects during factory
33# layer generation.
34#
35# Additional members
36# prefixText - list of strings to prefix generated header with
37# (usually a copyright statement + calling convention macros).
38# protectFile - True if multiple inclusion protection should be
39# generated (based on the filename) around the entire header.
40# protectFeature - True if #ifndef..#endif protection should be
41# generated around a feature interface in the header file.
42# genFuncPointers - True if function pointer typedefs should be
43# generated
44# protectProto - If conditional protection should be generated
45# around prototype declarations, set to either '#ifdef'
46# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47# to require opt-out (#ifndef protectProtoStr). Otherwise
48# set to None.
49# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50# declarations, if protectProto is set
51# apicall - string to use for the function declaration prefix,
52# such as APICALL on Windows.
53# apientry - string to use for the calling convention macro,
54# in typedefs, such as APIENTRY.
55# apientryp - string to use for the calling convention macro
56# in function pointer typedefs, such as APIENTRYP.
57# indentFuncProto - True if prototype declarations should put each
58# parameter on a separate line
59# indentFuncPointer - True if typedefed function pointers should put each
60# parameter on a separate line
61# alignFuncParam - if nonzero and parameters are being put on a
62# separate line, align parameter names at the specified column
63class LayerChassisGeneratorOptions(GeneratorOptions):
64 def __init__(self,
65 filename = None,
66 directory = '.',
67 apiname = None,
68 profile = None,
69 versions = '.*',
70 emitversions = '.*',
71 defaultExtensions = None,
72 addExtensions = None,
73 removeExtensions = None,
74 emitExtensions = None,
75 sortProcedure = regSortFeatures,
76 prefixText = "",
77 genFuncPointers = True,
78 protectFile = True,
79 protectFeature = True,
80 apicall = '',
81 apientry = '',
82 apientryp = '',
83 indentFuncProto = True,
84 indentFuncPointer = False,
85 alignFuncParam = 0,
86 helper_file_type = '',
87 expandEnumerants = True):
88 GeneratorOptions.__init__(self, filename, directory, apiname, profile,
89 versions, emitversions, defaultExtensions,
90 addExtensions, removeExtensions, emitExtensions, sortProcedure)
91 self.prefixText = prefixText
92 self.genFuncPointers = genFuncPointers
93 self.protectFile = protectFile
94 self.protectFeature = protectFeature
95 self.apicall = apicall
96 self.apientry = apientry
97 self.apientryp = apientryp
98 self.indentFuncProto = indentFuncProto
99 self.indentFuncPointer = indentFuncPointer
100 self.alignFuncParam = alignFuncParam
101
102# LayerChassisOutputGenerator - subclass of OutputGenerator.
103# Generates a LayerFactory layer that intercepts all API entrypoints
104# This is intended to be used as a starting point for creating custom layers
105#
106# ---- methods ----
107# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
108# OutputGenerator. Defines additional internal state.
109# ---- methods overriding base class ----
110# beginFile(genOpts)
111# endFile()
112# beginFeature(interface, emit)
113# endFeature()
114# genType(typeinfo,name)
115# genStruct(typeinfo,name)
116# genGroup(groupinfo,name)
117# genEnum(enuminfo, name)
118# genCmd(cmdinfo)
119class LayerChassisOutputGenerator(OutputGenerator):
120 """Generate specified API interfaces in a specific style, such as a C header"""
121 # This is an ordered list of sections in the header file.
122 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
123 'group', 'bitmask', 'funcpointer', 'struct']
124 ALL_SECTIONS = TYPE_SECTIONS + ['command']
125
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600126 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
127 precallrecord_loop = precallvalidate_loop
128 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600129
130
131 inline_custom_source_preamble = """
132// This file is ***GENERATED***. Do Not Edit.
133// See layer_chassis_generator.py for modifications.
134
135/* Copyright (c) 2015-2018 The Khronos Group Inc.
136 * Copyright (c) 2015-2018 Valve Corporation
137 * Copyright (c) 2015-2018 LunarG, Inc.
138 * Copyright (c) 2015-2018 Google Inc.
139 *
140 * Licensed under the Apache License, Version 2.0 (the "License");
141 * you may not use this file except in compliance with the License.
142 * You may obtain a copy of the License at
143 *
144 * http://www.apache.org/licenses/LICENSE-2.0
145 *
146 * Unless required by applicable law or agreed to in writing, software
147 * distributed under the License is distributed on an "AS IS" BASIS,
148 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
149 * See the License for the specific language governing permissions and
150 * limitations under the License.
151 *
152 * Author: Mark Lobodzinski <mark@lunarg.com>
153 */
154
155#include <string.h>
156#include <mutex>
157
158#define VALIDATION_ERROR_MAP_IMPL
159
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600160#include "chassis.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600161
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600162std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600163
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600164// Include child object (layer) definitions
165#include "object_lifetime_validation.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600166
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600167namespace vulkan_layer_chassis {
168
169using std::unordered_map;
170
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600171static const VkLayerProperties global_layer = {
Mark Lobodzinskiae3e3652018-11-28 10:48:52 -0700172 "VK_LAYER_LUNARG_object_tracker", VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600173};
174
175static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
176
177extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
178
179
180// Manually written functions
181
182VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600183 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600184 const auto &item = name_to_funcptr_map.find(funcName);
185 if (item != name_to_funcptr_map.end()) {
186 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
187 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600188 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600189 if (!table.GetDeviceProcAddr) return nullptr;
190 return table.GetDeviceProcAddr(device, funcName);
191}
192
193VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600194 const auto &item = name_to_funcptr_map.find(funcName);
195 if (item != name_to_funcptr_map.end()) {
196 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
197 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600198 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
199 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600200 if (!table.GetInstanceProcAddr) return nullptr;
201 return table.GetInstanceProcAddr(instance, funcName);
202}
203
204VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600205 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
206 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600207 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
208 return table.GetPhysicalDeviceProcAddr(instance, funcName);
209}
210
211VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
212 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
213}
214
215VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
216 VkLayerProperties *pProperties) {
217 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
218}
219
220VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
221 VkExtensionProperties *pProperties) {
222 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
223 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
224
225 return VK_ERROR_LAYER_NOT_PRESENT;
226}
227
228VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
229 uint32_t *pCount, VkExtensionProperties *pProperties) {
230 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600231 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600232 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
233 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600234}
235
236VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
237 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600238 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600239
240 assert(chain_info->u.pLayerInfo);
241 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
242 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
243 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
244 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
245
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600246 // Create temporary dispatch vector for pre-calls until instance is created
247 std::vector<ValidationObject*> local_object_dispatch;
248 auto object_tracker = new ObjectLifetimes;
249 local_object_dispatch.emplace_back(object_tracker);
250 object_tracker->container_type = LayerObjectTypeObjectTracker;
251
252
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600253 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600254 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600255 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
256 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600257 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600258 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
259 }
260
261 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600262 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600263
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600264 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600265
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600266 framework->object_dispatch = local_object_dispatch;
267
268 framework->instance = *pInstance;
269 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
270 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
271 pCreateInfo->ppEnabledExtensionNames);
272 framework->api_version = framework->instance_extensions.InitFromInstanceCreateInfo(
273 (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0), pCreateInfo);
274 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
275
276 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600277 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
278 }
279
280 return result;
281}
282
283VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
284 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600285 auto layer_data = GetLayerDataPtr(key, layer_data_map);
286 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700287 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600288 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
289 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600290 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700291 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600292 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
293 }
294
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600295 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600296
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600297 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700298 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600299 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
300 }
301 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600302 while (layer_data->logging_messenger.size() > 0) {
303 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
304 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
305 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600306 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600307 while (layer_data->logging_callback.size() > 0) {
308 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
309 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
310 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600311 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600312
313 layer_debug_utils_destroy_instance(layer_data->report_data);
314
315 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600316}
317
318VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
319 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600320 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600321
322 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
323
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600324 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
325 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600326 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
327 if (fpCreateDevice == NULL) {
328 return VK_ERROR_INITIALIZATION_FAILED;
329 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600330 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
331
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600332 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700333 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600334 intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
335 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600336 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700337 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600338 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
339 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600340
341 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600342 if (result != VK_SUCCESS) {
343 return result;
344 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600345
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600346 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
347 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
348 device_interceptor->device = *pDevice;
349 device_interceptor->physical_device = gpu;
350 device_interceptor->instance = instance_interceptor->instance;
351 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
352 device_interceptor->api_version = instance_interceptor->api_version;
353
354 // Create child layer objects for this key and add to dispatch vector
355 auto object_tracker = new ObjectLifetimes;
356 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
357 object_tracker->container_type = LayerObjectTypeObjectTracker;
358 object_tracker->physical_device = gpu;
359 object_tracker->instance = instance_interceptor->instance;
360 object_tracker->report_data = device_interceptor->report_data;
361 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
362 device_interceptor->object_dispatch.emplace_back(object_tracker);
363
364 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700365 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600366 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
367 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600368
369 return result;
370}
371
372VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
373 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600374 auto layer_data = GetLayerDataPtr(key, layer_data_map);
375 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700376 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600377 intercept->PreCallValidateDestroyDevice(device, pAllocator);
378 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600379 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700380 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600381 intercept->PreCallRecordDestroyDevice(device, pAllocator);
382 }
383 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600384
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600385 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600386
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600387 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700388 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600389 intercept->PostCallRecordDestroyDevice(device, pAllocator);
390 }
391
392 FreeLayerDataPtr(key, layer_data_map);
393}
394
395VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
396 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
397 const VkAllocationCallbacks *pAllocator,
398 VkDebugReportCallbackEXT *pCallback) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600399 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
400 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700401 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600402 intercept->PreCallValidateCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
403 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600404 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700405 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600406 intercept->PreCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
407 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600408 VkResult result = layer_data->instance_dispatch_table.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
409 result = layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);
410 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700411 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600412 intercept->PostCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
413 }
414 return result;
415}
416
417VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
418 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600419 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
420 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700421 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600422 intercept->PreCallValidateDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
423 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600424 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700425 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600426 intercept->PreCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
427 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600428 layer_data->instance_dispatch_table.DestroyDebugReportCallbackEXT(instance, callback, pAllocator);
429 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
430 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700431 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600432 intercept->PostCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
433 }
434}
435"""
436
437 inline_custom_source_postamble = """
438// loader-layer interface v0, just wrappers since there is only a layer
439
440VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
441 VkExtensionProperties *pProperties) {
442 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
443}
444
445VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
446 VkLayerProperties *pProperties) {
447 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
448}
449
450VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
451 VkLayerProperties *pProperties) {
452 // the layer command handles VK_NULL_HANDLE just fine internally
453 assert(physicalDevice == VK_NULL_HANDLE);
454 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
455}
456
457VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
458 const char *pLayerName, uint32_t *pCount,
459 VkExtensionProperties *pProperties) {
460 // the layer command handles VK_NULL_HANDLE just fine internally
461 assert(physicalDevice == VK_NULL_HANDLE);
462 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
463}
464
465VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
466 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
467}
468
469VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
470 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
471}
472
473VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
474 const char *funcName) {
475 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
476}
477
478VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
479 assert(pVersionStruct != NULL);
480 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
481
482 // Fill in the function pointers if our version is at least capable of having the structure contain them.
483 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
484 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
485 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
486 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
487 }
488
489 return VK_SUCCESS;
490}"""
491
492
493
494
495
496 def __init__(self,
497 errFile = sys.stderr,
498 warnFile = sys.stderr,
499 diagFile = sys.stdout):
500 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
501 # Internal state - accumulators for different inner block text
502 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
503 self.intercepts = []
504 self.layer_factory = '' # String containing base layer factory class definition
505
506 # Check if the parameter passed in is a pointer to an array
507 def paramIsArray(self, param):
508 return param.attrib.get('len') is not None
509
510 # Check if the parameter passed in is a pointer
511 def paramIsPointer(self, param):
512 ispointer = False
513 for elem in param:
514 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
515 ispointer = True
516 return ispointer
517
518 # Check if an object is a non-dispatchable handle
519 def isHandleTypeNonDispatchable(self, handletype):
520 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
521 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
522 return True
523 else:
524 return False
525
526 # Check if an object is a dispatchable handle
527 def isHandleTypeDispatchable(self, handletype):
528 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
529 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
530 return True
531 else:
532 return False
533
534 def beginFile(self, genOpts):
535 OutputGenerator.beginFile(self, genOpts)
536 # Multiple inclusion protection & C++ namespace.
537 self.header = False
538 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
539 self.header = True
540 write('#pragma once', file=self.outFile)
541 self.newline()
542 # User-supplied prefix text, if any (list of strings)
543 if self.header:
544 if (genOpts.prefixText):
545 for s in genOpts.prefixText:
546 write(s, file=self.outFile)
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600547 write('#define NOMINMAX', file=self.outFile)
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600548 write('#include <mutex>', file=self.outFile)
549 write('#include <cinttypes>', file=self.outFile)
550 write('#include <stdio.h>', file=self.outFile)
551 write('#include <stdlib.h>', file=self.outFile)
552 write('#include <string.h>', file=self.outFile)
553 write('#include <unordered_map>', file=self.outFile)
554 write('#include <unordered_set>', file=self.outFile)
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600555 write('#include <algorithm>', file=self.outFile)
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600556
557 write('#include "vk_loader_platform.h"', file=self.outFile)
558 write('#include "vulkan/vulkan.h"', file=self.outFile)
559 write('#include "vk_layer_config.h"', file=self.outFile)
560 write('#include "vk_layer_data.h"', file=self.outFile)
561 write('#include "vk_layer_logging.h"', file=self.outFile)
562 write('#include "vk_object_types.h"', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600563 write('#include "vulkan/vk_layer.h"', file=self.outFile)
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600564 write('#include "vk_enum_string_helper.h"', file=self.outFile)
565 write('#include "vk_layer_extension_utils.h"', file=self.outFile)
566 write('#include "vk_layer_utils.h"', file=self.outFile)
567 write('#include "vulkan/vk_layer.h"', file=self.outFile)
568 write('#include "vk_dispatch_table_helper.h"', file=self.outFile)
569 write('#include "vk_validation_error_messages.h"', file=self.outFile)
570 write('#include "vk_extension_helper.h"', file=self.outFile)
571 write('', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600572 else:
573 write(self.inline_custom_source_preamble, file=self.outFile)
574
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600575 # Define some useful types
576 self.layer_factory += '// Layer object type identifiers\n'
577 self.layer_factory += 'enum LayerObjectTypeId {\n'
578 self.layer_factory += ' LayerObjectTypeThreading,\n'
579 self.layer_factory += ' LayerObjectTypeParameterValidation,\n'
580 self.layer_factory += ' LayerObjectTypeObjectTracker,\n'
581 self.layer_factory += ' LayerObjectTypeCoreValidation,\n'
582 self.layer_factory += ' LayerObjectTypeUniqueObjects,\n'
583 self.layer_factory += '};\n\n'
584
585 # Define base class
586 self.layer_factory += '// Uber Layer validation object base class definition\n'
587 self.layer_factory += 'class ValidationObject {\n'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600588 self.layer_factory += ' public:\n'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600589 self.layer_factory += ' uint32_t api_version;\n'
590 self.layer_factory += ' debug_report_data* report_data = nullptr;\n'
591 self.layer_factory += ' std::vector<VkDebugReportCallbackEXT> logging_callback;\n'
592 self.layer_factory += ' std::vector<VkDebugUtilsMessengerEXT> logging_messenger;\n'
593 self.layer_factory += '\n'
594 self.layer_factory += ' VkLayerInstanceDispatchTable instance_dispatch_table;\n'
595 self.layer_factory += ' VkLayerDispatchTable device_dispatch_table;\n'
596 self.layer_factory += '\n'
597 self.layer_factory += ' InstanceExtensions instance_extensions;\n'
598 self.layer_factory += ' DeviceExtensions device_extensions = {};\n'
599 self.layer_factory += '\n'
600 self.layer_factory += ' VkInstance instance = VK_NULL_HANDLE;\n'
601 self.layer_factory += ' VkPhysicalDevice physical_device = VK_NULL_HANDLE;\n'
602 self.layer_factory += ' VkDevice device = VK_NULL_HANDLE;\n'
603 self.layer_factory += '\n'
604 self.layer_factory += ' std::vector<ValidationObject*> object_dispatch;\n'
605 self.layer_factory += ' LayerObjectTypeId container_type;\n'
606 self.layer_factory += '\n'
607 self.layer_factory += ' // Constructor\n'
608 self.layer_factory += ' ValidationObject(){};\n'
609 self.layer_factory += ' // Destructor\n'
610 self.layer_factory += ' virtual ~ValidationObject() {};\n'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600611 self.layer_factory += '\n'
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700612 self.layer_factory += ' std::mutex layer_mutex;\n'
613 self.layer_factory += '\n'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600614 self.layer_factory += ' std::string layer_name = "CHASSIS";\n'
615 self.layer_factory += '\n'
616 self.layer_factory += ' // Pre/post hook point declarations\n'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600617
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600618 #
619 def endFile(self):
620 # Finish C++ namespace and multiple inclusion protection
621 self.newline()
622 if not self.header:
623 # Record intercepted procedures
624 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
625 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
626 write('\n'.join(self.intercepts), file=self.outFile)
627 write('};\n', file=self.outFile)
628 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600629 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600630 if self.header:
631 self.newline()
632 # Output Layer Factory Class Definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600633 self.layer_factory += '};\n\n'
634 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600635 write(self.layer_factory, file=self.outFile)
636 else:
637 write(self.inline_custom_source_postamble, file=self.outFile)
638 # Finish processing in superclass
639 OutputGenerator.endFile(self)
640
641 def beginFeature(self, interface, emit):
642 # Start processing in superclass
643 OutputGenerator.beginFeature(self, interface, emit)
644 # Get feature extra protect
645 self.featureExtraProtect = GetFeatureProtect(interface)
646 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
647 # feature. They're only printed in endFeature().
648 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
649
650 def endFeature(self):
651 # Actually write the interface to the output file.
652 if (self.emit):
653 self.newline()
654 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
655 # or move it below the 'for section...' loop.
656 if (self.featureExtraProtect != None):
657 write('#ifdef', self.featureExtraProtect, file=self.outFile)
658 for section in self.TYPE_SECTIONS:
659 contents = self.sections[section]
660 if contents:
661 write('\n'.join(contents), file=self.outFile)
662 self.newline()
663 if (self.sections['command']):
664 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
665 self.newline()
666 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600667 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600668 # Finish processing in superclass
669 OutputGenerator.endFeature(self)
670 #
671 # Append a definition to the specified section
672 def appendSection(self, section, text):
673 self.sections[section].append(text)
674 #
675 # Type generation
676 def genType(self, typeinfo, name, alias):
677 pass
678 #
679 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
680 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
681 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
682 # structs etc.)
683 def genStruct(self, typeinfo, typeName):
684 OutputGenerator.genStruct(self, typeinfo, typeName)
685 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
686 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
687 for member in typeinfo.elem.findall('.//member'):
688 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
689 body += ';\n'
690 body += '} ' + typeName + ';\n'
691 self.appendSection('struct', body)
692 #
693 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
694 def genGroup(self, groupinfo, groupName, alias):
695 pass
696 # Enumerant generation
697 # <enum> tags may specify their values in several ways, but are usually just integers.
698 def genEnum(self, enuminfo, name, alias):
699 pass
700 #
701 # Customize Cdecl for layer factory base class
702 def BaseClassCdecl(self, elem, name):
703 raw = self.makeCDecls(elem)[1]
704
705 # Toss everything before the undecorated name
706 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
707 prototype = prototype.replace(")", "", 1)
708 prototype = prototype.replace(";", " {};")
709
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600710 # Build up pre/post call virtual function declarations
711 pre_call_validate = 'virtual bool PreCallValidate' + prototype
712 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
713 pre_call_record = 'virtual void PreCallRecord' + prototype
714 post_call_record = 'virtual void PostCallRecord' + prototype
715 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
716 #
717 # Command generation
718 def genCmd(self, cmdinfo, name, alias):
719 ignore_functions = [
720 'vkEnumerateInstanceVersion'
721 ]
722
723 if name in ignore_functions:
724 return
725
726 if self.header: # In the header declare all intercepts
727 self.appendSection('command', '')
728 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
729 if (self.featureExtraProtect != None):
730 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
731 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
732 # Update base class with virtual function declarations
733 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
734 # Update function intercepts
735 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
736 if (self.featureExtraProtect != None):
737 self.intercepts += [ '#endif' ]
738 self.layer_factory += '#endif\n'
739 return
740
741 manual_functions = [
742 # Include functions here to be interecpted w/ manually implemented function bodies
743 'vkGetDeviceProcAddr',
744 'vkGetInstanceProcAddr',
745 'vkGetPhysicalDeviceProcAddr',
746 'vkCreateDevice',
747 'vkDestroyDevice',
748 'vkCreateInstance',
749 'vkDestroyInstance',
750 'vkCreateDebugReportCallbackEXT',
751 'vkDestroyDebugReportCallbackEXT',
752 'vkEnumerateInstanceLayerProperties',
753 'vkEnumerateInstanceExtensionProperties',
754 'vkEnumerateDeviceLayerProperties',
755 'vkEnumerateDeviceExtensionProperties',
756 ]
757 if name in manual_functions:
758 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
759 return
760 # Record that the function will be intercepted
761 if (self.featureExtraProtect != None):
762 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
763 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
764 if (self.featureExtraProtect != None):
765 self.intercepts += [ '#endif' ]
766 OutputGenerator.genCmd(self, cmdinfo, name, alias)
767 #
768 decls = self.makeCDecls(cmdinfo.elem)
769 self.appendSection('command', '')
770 self.appendSection('command', '%s {' % decls[0][:-1])
771 # Setup common to call wrappers. First parameter is always dispatchable
772 dispatchable_type = cmdinfo.elem.find('param/type').text
773 dispatchable_name = cmdinfo.elem.find('param/name').text
774 # Default to device
775 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600776 dispatch_table_name = 'VkLayerDispatchTable'
777 # Set to instance as necessary
778 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
779 device_or_instance = 'instance'
780 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600781 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600782 api_function_name = cmdinfo.elem.attrib.get('name')
783 params = cmdinfo.elem.findall('param/name')
784 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600785 API = api_function_name.replace('vk','layer_data->%s_dispatch_table.' % (device_or_instance),1)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600786
787 # Declare result variable, if any.
788 return_map = {
789 'void': 'return;',
790 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
791 'PFN_vkVoidFunction': 'return nullptr;',
792 'VkBool32': 'return VK_FALSE;',
793 }
794 resulttype = cmdinfo.elem.find('proto/type')
795 assignresult = ''
796 if (resulttype.text != 'void'):
797 assignresult = resulttype.text + ' result = '
798
799 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700800 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600801
802 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600803 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700804 self.appendSection('command', ' std::lock_guard<std::mutex> lock(intercept->layer_mutex);')
805 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
806 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
807 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600808
809 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600810 self.appendSection('command', ' %s' % self.precallrecord_loop)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700811 self.appendSection('command', ' std::lock_guard<std::mutex> lock(intercept->layer_mutex);')
812 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600813 self.appendSection('command', ' }')
814
815 self.appendSection('command', ' ' + assignresult + API + '(' + paramstext + ');')
816
817 # Generate post-call object processing source code
Mark Lobodzinskib3c94842018-11-27 10:01:51 -0700818 alt_ret_codes = [
819 # Include functions here which must tolerate VK_INCOMPLETE as a return code
820 'vkEnumeratePhysicalDevices',
821 'vkEnumeratePhysicalDeviceGroupsKHR',
822 'vkGetValidationCacheDataEXT',
823 'vkGetPipelineCacheData',
824 'vkGetShaderInfoAMD',
825 'vkGetPhysicalDeviceDisplayPropertiesKHR',
826 'vkGetPhysicalDeviceDisplayProperties2KHR',
827 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
828 'vkGetDisplayPlaneSupportedDisplaysKHR',
829 'vkGetDisplayModePropertiesKHR',
830 'vkGetDisplayModeProperties2KHR',
831 'vkGetPhysicalDeviceSurfaceFormatsKHR',
832 'vkGetPhysicalDeviceSurfacePresentModesKHR',
833 'vkGetPhysicalDevicePresentRectanglesKHR',
834 'vkGetPastPresentationTimingGOOGLE',
835 'vkGetSwapchainImagesKHR',
836 'vkEnumerateInstanceLayerProperties',
837 'vkEnumerateDeviceLayerProperties',
838 'vkEnumerateInstanceExtensionProperties',
839 'vkEnumerateDeviceExtensionProperties',
840 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
841 ]
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700842 return_type_indent = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600843 if (resulttype.text == 'VkResult'):
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700844 return_type_indent = ' '
Mark Lobodzinskib3c94842018-11-27 10:01:51 -0700845 if name in alt_ret_codes:
846 self.appendSection('command', ' if ((VK_SUCCESS == result) || (VK_INCOMPLETE == result)) {')
847 else:
848 self.appendSection('command', ' if (VK_SUCCESS == result) {')
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600849
850 self.appendSection('command', '%s %s' % (return_type_indent, self.postcallrecord_loop))
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700851 self.appendSection('command', '%s std::lock_guard<std::mutex> lock(intercept->layer_mutex);' % return_type_indent)
852 self.appendSection('command', '%s intercept->PostCallRecord%s(%s);' % (return_type_indent,api_function_name[2:], paramstext))
853 self.appendSection('command', '%s }' % return_type_indent)
854 if (resulttype.text == 'VkResult'):
855 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600856
857 # Return result variable, if any.
858 if (resulttype.text != 'void'):
859 self.appendSection('command', ' return result;')
860 self.appendSection('command', '}')
861 #
862 # Override makeProtoName to drop the "vk" prefix
863 def makeProtoName(self, name, tail):
864 return self.genOpts.apientry + name[2:] + tail