blob: fc9c0bd6271010960e3551029a5a4d97b7283779 [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07003# Copyright (c) 2015-2019 Valve Corporation
4# Copyright (c) 2015-2019 LunarG, Inc.
5# Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06006#
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 Lobodzinski09f86362018-12-13 14:07:20 -0700126 manual_functions = [
127 # Include functions here to be interecpted w/ manually implemented function bodies
128 'vkGetDeviceProcAddr',
129 'vkGetInstanceProcAddr',
130 'vkGetPhysicalDeviceProcAddr',
131 'vkCreateDevice',
132 'vkDestroyDevice',
133 'vkCreateInstance',
134 'vkDestroyInstance',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700135 'vkEnumerateInstanceLayerProperties',
136 'vkEnumerateInstanceExtensionProperties',
137 'vkEnumerateDeviceLayerProperties',
138 'vkEnumerateDeviceExtensionProperties',
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700139 # ValidationCache functions do not get dispatched
140 'vkCreateValidationCacheEXT',
141 'vkDestroyValidationCacheEXT',
142 'vkMergeValidationCachesEXT',
143 'vkGetValidationCacheDataEXT',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700144 ]
145
146 alt_ret_codes = [
147 # Include functions here which must tolerate VK_INCOMPLETE as a return code
148 'vkEnumeratePhysicalDevices',
149 'vkEnumeratePhysicalDeviceGroupsKHR',
150 'vkGetValidationCacheDataEXT',
151 'vkGetPipelineCacheData',
152 'vkGetShaderInfoAMD',
153 'vkGetPhysicalDeviceDisplayPropertiesKHR',
154 'vkGetPhysicalDeviceDisplayProperties2KHR',
155 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
156 'vkGetDisplayPlaneSupportedDisplaysKHR',
157 'vkGetDisplayModePropertiesKHR',
158 'vkGetDisplayModeProperties2KHR',
159 'vkGetPhysicalDeviceSurfaceFormatsKHR',
160 'vkGetPhysicalDeviceSurfacePresentModesKHR',
161 'vkGetPhysicalDevicePresentRectanglesKHR',
162 'vkGetPastPresentationTimingGOOGLE',
163 'vkGetSwapchainImagesKHR',
164 'vkEnumerateInstanceLayerProperties',
165 'vkEnumerateDeviceLayerProperties',
166 'vkEnumerateInstanceExtensionProperties',
167 'vkEnumerateDeviceExtensionProperties',
168 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
169 ]
170
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700171 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700172 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
173 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700174 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
175 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
176 'vkCmdBeginDebugUtilsLabelEXT' : 'BeginCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
177 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
178 }
179
180 post_dispatch_debug_utils_functions = {
181 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
182 'vkCmdEndDebugUtilsLabelEXT' : 'EndCmdDebugUtilsLabel(layer_data->report_data, commandBuffer);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700183 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
184 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
185 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
186 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
187 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700188 }
189
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600190 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
191 precallrecord_loop = precallvalidate_loop
192 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600193
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700194 inline_custom_header_preamble = """
195#define NOMINMAX
196#include <mutex>
197#include <cinttypes>
198#include <stdio.h>
199#include <stdlib.h>
200#include <string.h>
201#include <unordered_map>
202#include <unordered_set>
203#include <algorithm>
204#include <memory>
205
206#include "vk_loader_platform.h"
207#include "vulkan/vulkan.h"
208#include "vk_layer_config.h"
209#include "vk_layer_data.h"
210#include "vk_layer_logging.h"
211#include "vk_object_types.h"
212#include "vulkan/vk_layer.h"
213#include "vk_enum_string_helper.h"
214#include "vk_layer_extension_utils.h"
215#include "vk_layer_utils.h"
216#include "vulkan/vk_layer.h"
217#include "vk_dispatch_table_helper.h"
218#include "vk_validation_error_messages.h"
219#include "vk_extension_helper.h"
220#include "vk_safe_struct.h"
221
222extern uint64_t global_unique_id;
223extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
224"""
225
226 inline_custom_header_class_definition = """
227
228// Layer object type identifiers
229enum LayerObjectTypeId {
230 LayerObjectTypeThreading,
231 LayerObjectTypeParameterValidation,
232 LayerObjectTypeObjectTracker,
233 LayerObjectTypeCoreValidation,
234};
235
236struct TEMPLATE_STATE {
237 VkDescriptorUpdateTemplateKHR desc_update_template;
238 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
239
240 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
241 : desc_update_template(update_template), create_info(*pCreateInfo) {}
242};
243
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700244class LAYER_PHYS_DEV_PROPERTIES {
245public:
246 VkPhysicalDeviceProperties properties;
247 std::vector<VkQueueFamilyProperties> queue_family_properties;
248};
249
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700250// Layer chassis validation object base class definition
251class ValidationObject {
252 public:
253 uint32_t api_version;
254 debug_report_data* report_data = nullptr;
255 std::vector<VkDebugReportCallbackEXT> logging_callback;
256 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
257
258 VkLayerInstanceDispatchTable instance_dispatch_table;
259 VkLayerDispatchTable device_dispatch_table;
260
261 InstanceExtensions instance_extensions;
262 DeviceExtensions device_extensions = {};
263
264 VkInstance instance = VK_NULL_HANDLE;
265 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
266 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700267 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700268
269 std::vector<ValidationObject*> object_dispatch;
270 LayerObjectTypeId container_type;
271
272 // Constructor
273 ValidationObject(){};
274 // Destructor
275 virtual ~ValidationObject() {};
276
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700277 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700278 virtual std::unique_lock<std::mutex> write_lock() {
279 return std::unique_lock<std::mutex>(validation_object_mutex);
280 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700281
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700282 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
283 for (auto validation_object : object_dispatch) {
284 if (validation_object->container_type == object_type) {
285 return validation_object;
286 }
287 }
288 return nullptr;
289 };
290
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700291 std::string layer_name = "CHASSIS";
292
293 // Handle Wrapping Data
294 // Reverse map display handles
295 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
296 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700297 struct SubpassesUsageStates {
298 std::unordered_set<uint32_t> subpasses_using_color_attachment;
299 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
300 };
301 // Uses unwrapped handles
302 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
303 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
304 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
305 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700306 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
307 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700308
309
310 // Unwrap a handle. Must hold lock.
311 template <typename HandleType>
312 HandleType Unwrap(HandleType wrappedHandle) {
313 // TODO: don't use operator[] here.
314 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
315 }
316
317 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
318 template <typename HandleType>
319 HandleType WrapNew(HandleType newlyCreatedHandle) {
320 auto unique_id = global_unique_id++;
321 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
322 return (HandleType)unique_id;
323 }
324
325 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
326 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
327 auto unique_id = global_unique_id++;
328 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
329 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
330 return (VkDisplayKHR)unique_id;
331 }
332
333 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
334 // creating another. Must hold lock.
335 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
336 // See if this display is already known
337 auto it = map_data->display_id_reverse_mapping.find(handle);
338 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
339 // Unknown, so wrap
340 return WrapDisplay(handle, map_data);
341 }
342
343 // Pre/post hook point declarations
344"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600345
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700346 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600347// This file is ***GENERATED***. Do Not Edit.
348// See layer_chassis_generator.py for modifications.
349
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700350/* Copyright (c) 2015-2019 The Khronos Group Inc.
351 * Copyright (c) 2015-2019 Valve Corporation
352 * Copyright (c) 2015-2019 LunarG, Inc.
353 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600354 *
355 * Licensed under the Apache License, Version 2.0 (the "License");
356 * you may not use this file except in compliance with the License.
357 * You may obtain a copy of the License at
358 *
359 * http://www.apache.org/licenses/LICENSE-2.0
360 *
361 * Unless required by applicable law or agreed to in writing, software
362 * distributed under the License is distributed on an "AS IS" BASIS,
363 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
364 * See the License for the specific language governing permissions and
365 * limitations under the License.
366 *
367 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700368 */"""
369
370 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600371
372#include <string.h>
373#include <mutex>
374
375#define VALIDATION_ERROR_MAP_IMPL
376
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600377#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700378#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600379
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600380std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600381
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700382// Global unique object identifier. All increments must be guarded by a lock.
383uint64_t global_unique_id = 1;
384// Map uniqueID to actual object handle
385std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
386
387// TODO: This variable controls handle wrapping -- in the future it should be hooked
388// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
389#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
390bool wrap_handles = true;
391#else
392const bool wrap_handles = false;
393#endif
394
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600395// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700396#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600397#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700398#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700399#elif BUILD_THREAD_SAFETY
Mark Lobodzinski706e52b2018-12-11 13:21:52 -0700400#include "thread_safety.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700401#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
402#elif BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700403#include "stateless_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700404#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
405#elif BUILD_CORE_VALIDATION
406#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
407#else
408#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
409#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600410
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600411namespace vulkan_layer_chassis {
412
413using std::unordered_map;
414
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600415static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700416 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600417};
418
419static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
420
421extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
422
423
424// Manually written functions
425
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700426// Check enabled instance extensions against supported instance extension whitelist
427static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
428 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
429 // Check for recognized instance extensions
430 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
431 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
432 kVUIDUndefined,
433 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
434 "results and/or produce undefined behavior.",
435 pCreateInfo->ppEnabledExtensionNames[i]);
436 }
437 }
438}
439
440// Check enabled device extensions against supported device extension whitelist
441static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
442 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
443 // Check for recognized device extensions
444 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
445 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
446 kVUIDUndefined,
447 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
448 "results and/or produce undefined behavior.",
449 pCreateInfo->ppEnabledExtensionNames[i]);
450 }
451 }
452}
453
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600454VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600455 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700456 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700457 return nullptr;
458 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600459 const auto &item = name_to_funcptr_map.find(funcName);
460 if (item != name_to_funcptr_map.end()) {
461 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
462 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600463 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600464 if (!table.GetDeviceProcAddr) return nullptr;
465 return table.GetDeviceProcAddr(device, funcName);
466}
467
468VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600469 const auto &item = name_to_funcptr_map.find(funcName);
470 if (item != name_to_funcptr_map.end()) {
471 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
472 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600473 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
474 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600475 if (!table.GetInstanceProcAddr) return nullptr;
476 return table.GetInstanceProcAddr(instance, funcName);
477}
478
479VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600480 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
481 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600482 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
483 return table.GetPhysicalDeviceProcAddr(instance, funcName);
484}
485
486VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
487 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
488}
489
490VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
491 VkLayerProperties *pProperties) {
492 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
493}
494
495VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
496 VkExtensionProperties *pProperties) {
497 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
498 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
499
500 return VK_ERROR_LAYER_NOT_PRESENT;
501}
502
503VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
504 uint32_t *pCount, VkExtensionProperties *pProperties) {
505 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600506 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600507 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
508 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600509}
510
511VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
512 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600513 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600514
515 assert(chain_info->u.pLayerInfo);
516 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
517 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
518 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
519 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700520 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
521 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
522
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600523
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600524 // Create temporary dispatch vector for pre-calls until instance is created
525 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700526#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600527 auto object_tracker = new ObjectLifetimes;
528 local_object_dispatch.emplace_back(object_tracker);
529 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700530 object_tracker->api_version = api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700531#elif BUILD_THREAD_SAFETY
532 auto thread_checker = new ThreadSafety;
533 local_object_dispatch.emplace_back(thread_checker);
534 thread_checker->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700535 thread_checker->api_version = api_version;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700536#elif BUILD_PARAMETER_VALIDATION
537 auto parameter_validation = new StatelessValidation;
538 local_object_dispatch.emplace_back(parameter_validation);
539 parameter_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700540 parameter_validation->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700541#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600542
543
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600544 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600545 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600546 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
547 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600548 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600549 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
550 }
551
552 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600553 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600554
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600555 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600556
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600557 framework->object_dispatch = local_object_dispatch;
558
559 framework->instance = *pInstance;
560 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
561 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
562 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700563 framework->api_version = api_version;
564 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
565
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700566#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600567 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700568 object_tracker->report_data = framework->report_data;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700569#elif BUILD_THREAD_SAFETY
570 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "google_thread_checker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700571 thread_checker->report_data = framework->report_data;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700572#elif BUILD_PARAMETER_VALIDATION
573 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_parameter_validation");
574 parameter_validation->report_data = framework->report_data;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700575#else
576 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
577#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600578
579 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700580 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600581 }
582
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700583 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
584
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600585 return result;
586}
587
588VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
589 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600590 auto layer_data = GetLayerDataPtr(key, layer_data_map);
591 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700592 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600593 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
594 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600595 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700596 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600597 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
598 }
599
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600600 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600601
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600602 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700603 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600604 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
605 }
606 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600607 while (layer_data->logging_messenger.size() > 0) {
608 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
609 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
610 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600611 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600612 while (layer_data->logging_callback.size() > 0) {
613 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
614 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
615 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600616 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600617
618 layer_debug_utils_destroy_instance(layer_data->report_data);
619
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700620 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
621 delete *item;
622 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600623 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600624}
625
626VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
627 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600628 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600629
630 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
631
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600632 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
633 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600634 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
635 if (fpCreateDevice == NULL) {
636 return VK_ERROR_INITIALIZATION_FAILED;
637 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600638 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
639
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700640 // Get physical device limits for device
641 VkPhysicalDeviceProperties device_properties = {};
642 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
643
644 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
645 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
646
647 DeviceExtensions device_extensions = {};
648 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
649 for (auto item : instance_interceptor->object_dispatch) {
650 item->device_extensions = device_extensions;
651 }
652
653 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600654 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700655 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700656 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700657 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600658 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600659 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700660 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600661 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
662 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600663
664 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600665 if (result != VK_SUCCESS) {
666 return result;
667 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600668
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600669 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700670
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700671 // Save local info in device object
672 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700673 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
674 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700675 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700676
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600677 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700678
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600679 device_interceptor->device = *pDevice;
680 device_interceptor->physical_device = gpu;
681 device_interceptor->instance = instance_interceptor->instance;
682 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600683
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700684#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600685 // Create child layer objects for this key and add to dispatch vector
686 auto object_tracker = new ObjectLifetimes;
687 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
688 object_tracker->container_type = LayerObjectTypeObjectTracker;
689 object_tracker->physical_device = gpu;
690 object_tracker->instance = instance_interceptor->instance;
691 object_tracker->report_data = device_interceptor->report_data;
692 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700693 object_tracker->api_version = device_interceptor->api_version;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600694 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700695#elif BUILD_THREAD_SAFETY
696 auto thread_safety = new ThreadSafety;
697 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
698 thread_safety->container_type = LayerObjectTypeThreading;
699 thread_safety->physical_device = gpu;
700 thread_safety->instance = instance_interceptor->instance;
701 thread_safety->report_data = device_interceptor->report_data;
702 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700703 thread_safety->api_version = device_interceptor->api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700704 device_interceptor->object_dispatch.emplace_back(thread_safety);
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700705#elif BUILD_PARAMETER_VALIDATION
706 auto stateless_validation = new StatelessValidation;
707 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
708 stateless_validation->container_type = LayerObjectTypeParameterValidation;
709 stateless_validation->physical_device = gpu;
710 stateless_validation->instance = instance_interceptor->instance;
711 stateless_validation->report_data = device_interceptor->report_data;
712 stateless_validation->device_dispatch_table = device_interceptor->device_dispatch_table;
713 stateless_validation->api_version = device_interceptor->api_version;
714 device_interceptor->object_dispatch.emplace_back(stateless_validation);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700715#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600716
717 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700718 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700719 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600720 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600721
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700722 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
723
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600724 return result;
725}
726
727VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
728 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600729 auto layer_data = GetLayerDataPtr(key, layer_data_map);
730 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700731 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600732 intercept->PreCallValidateDestroyDevice(device, pAllocator);
733 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600734 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700735 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600736 intercept->PreCallRecordDestroyDevice(device, pAllocator);
737 }
738 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600739
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600740 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600741
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600742 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700743 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600744 intercept->PostCallRecordDestroyDevice(device, pAllocator);
745 }
746
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700747 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
748 delete *item;
749 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600750 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700751}
752
753
754
755
756VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
757 VkDevice device,
758 const VkValidationCacheCreateInfoEXT* pCreateInfo,
759 const VkAllocationCallbacks* pAllocator,
760 VkValidationCacheEXT* pValidationCache) {
761 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
762 VkResult result = VK_SUCCESS;
763
764 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
765 if (validation_data) {
766 auto lock = validation_data->write_lock();
767 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
768 }
769 return result;
770}
771
772VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
773 VkDevice device,
774 VkValidationCacheEXT validationCache,
775 const VkAllocationCallbacks* pAllocator) {
776 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
777
778 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
779 if (validation_data) {
780 auto lock = validation_data->write_lock();
781 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
782 }
783}
784
785VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
786 VkDevice device,
787 VkValidationCacheEXT dstCache,
788 uint32_t srcCacheCount,
789 const VkValidationCacheEXT* pSrcCaches) {
790 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
791 VkResult result = VK_SUCCESS;
792
793 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
794 if (validation_data) {
795 auto lock = validation_data->write_lock();
796 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
797 }
798 return result;
799}
800
801VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
802 VkDevice device,
803 VkValidationCacheEXT validationCache,
804 size_t* pDataSize,
805 void* pData) {
806 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
807 VkResult result = VK_SUCCESS;
808
809 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
810 if (validation_data) {
811 auto lock = validation_data->write_lock();
812 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
813 }
814 return result;
815
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700816}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600817
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700818 inline_custom_validation_class_definitions = """
819 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
820 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
821 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
822 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
823"""
824
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600825 inline_custom_source_postamble = """
826// loader-layer interface v0, just wrappers since there is only a layer
827
828VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
829 VkExtensionProperties *pProperties) {
830 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
831}
832
833VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
834 VkLayerProperties *pProperties) {
835 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
836}
837
838VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
839 VkLayerProperties *pProperties) {
840 // the layer command handles VK_NULL_HANDLE just fine internally
841 assert(physicalDevice == VK_NULL_HANDLE);
842 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
843}
844
845VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
846 const char *pLayerName, uint32_t *pCount,
847 VkExtensionProperties *pProperties) {
848 // the layer command handles VK_NULL_HANDLE just fine internally
849 assert(physicalDevice == VK_NULL_HANDLE);
850 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
851}
852
853VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
854 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
855}
856
857VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
858 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
859}
860
861VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
862 const char *funcName) {
863 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
864}
865
866VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
867 assert(pVersionStruct != NULL);
868 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
869
870 // Fill in the function pointers if our version is at least capable of having the structure contain them.
871 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
872 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
873 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
874 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
875 }
876
877 return VK_SUCCESS;
878}"""
879
880
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600881 def __init__(self,
882 errFile = sys.stderr,
883 warnFile = sys.stderr,
884 diagFile = sys.stdout):
885 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
886 # Internal state - accumulators for different inner block text
887 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
888 self.intercepts = []
889 self.layer_factory = '' # String containing base layer factory class definition
890
891 # Check if the parameter passed in is a pointer to an array
892 def paramIsArray(self, param):
893 return param.attrib.get('len') is not None
894
895 # Check if the parameter passed in is a pointer
896 def paramIsPointer(self, param):
897 ispointer = False
898 for elem in param:
899 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
900 ispointer = True
901 return ispointer
902
903 # Check if an object is a non-dispatchable handle
904 def isHandleTypeNonDispatchable(self, handletype):
905 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
906 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
907 return True
908 else:
909 return False
910
911 # Check if an object is a dispatchable handle
912 def isHandleTypeDispatchable(self, handletype):
913 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
914 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
915 return True
916 else:
917 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700918 #
919 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600920 def beginFile(self, genOpts):
921 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700922 # Output Copyright
923 write(self.inline_copyright_message, file=self.outFile)
924 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600925 self.header = False
926 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
927 self.header = True
928 write('#pragma once', file=self.outFile)
929 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600930 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700931 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600932 else:
933 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700934 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700935 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600936 #
937 def endFile(self):
938 # Finish C++ namespace and multiple inclusion protection
939 self.newline()
940 if not self.header:
941 # Record intercepted procedures
942 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
943 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
944 write('\n'.join(self.intercepts), file=self.outFile)
945 write('};\n', file=self.outFile)
946 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600947 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600948 if self.header:
949 self.newline()
950 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700951 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600952 self.layer_factory += '};\n\n'
953 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600954 write(self.layer_factory, file=self.outFile)
955 else:
956 write(self.inline_custom_source_postamble, file=self.outFile)
957 # Finish processing in superclass
958 OutputGenerator.endFile(self)
959
960 def beginFeature(self, interface, emit):
961 # Start processing in superclass
962 OutputGenerator.beginFeature(self, interface, emit)
963 # Get feature extra protect
964 self.featureExtraProtect = GetFeatureProtect(interface)
965 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
966 # feature. They're only printed in endFeature().
967 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
968
969 def endFeature(self):
970 # Actually write the interface to the output file.
971 if (self.emit):
972 self.newline()
973 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
974 # or move it below the 'for section...' loop.
975 if (self.featureExtraProtect != None):
976 write('#ifdef', self.featureExtraProtect, file=self.outFile)
977 for section in self.TYPE_SECTIONS:
978 contents = self.sections[section]
979 if contents:
980 write('\n'.join(contents), file=self.outFile)
981 self.newline()
982 if (self.sections['command']):
983 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
984 self.newline()
985 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600986 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600987 # Finish processing in superclass
988 OutputGenerator.endFeature(self)
989 #
990 # Append a definition to the specified section
991 def appendSection(self, section, text):
992 self.sections[section].append(text)
993 #
994 # Type generation
995 def genType(self, typeinfo, name, alias):
996 pass
997 #
998 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
999 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1000 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1001 # structs etc.)
1002 def genStruct(self, typeinfo, typeName):
1003 OutputGenerator.genStruct(self, typeinfo, typeName)
1004 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1005 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1006 for member in typeinfo.elem.findall('.//member'):
1007 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1008 body += ';\n'
1009 body += '} ' + typeName + ';\n'
1010 self.appendSection('struct', body)
1011 #
1012 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1013 def genGroup(self, groupinfo, groupName, alias):
1014 pass
1015 # Enumerant generation
1016 # <enum> tags may specify their values in several ways, but are usually just integers.
1017 def genEnum(self, enuminfo, name, alias):
1018 pass
1019 #
1020 # Customize Cdecl for layer factory base class
1021 def BaseClassCdecl(self, elem, name):
1022 raw = self.makeCDecls(elem)[1]
1023
1024 # Toss everything before the undecorated name
1025 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1026 prototype = prototype.replace(")", "", 1)
1027 prototype = prototype.replace(";", " {};")
1028
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001029 # Build up pre/post call virtual function declarations
1030 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1031 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1032 pre_call_record = 'virtual void PreCallRecord' + prototype
1033 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001034 resulttype = elem.find('proto/type')
1035 if resulttype.text == 'VkResult':
1036 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001037 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1038 #
1039 # Command generation
1040 def genCmd(self, cmdinfo, name, alias):
1041 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001042 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001043 ]
1044
1045 if name in ignore_functions:
1046 return
1047
1048 if self.header: # In the header declare all intercepts
1049 self.appendSection('command', '')
1050 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1051 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001052 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1053 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001054 if 'ValidationCache' not in name:
1055 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001056 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001057 self.layer_factory += '#endif\n'
1058 return
1059
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001060 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001061 if 'ValidationCache' not in name:
1062 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1063 else:
1064 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1065 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1066 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001067 return
1068 # Record that the function will be intercepted
1069 if (self.featureExtraProtect != None):
1070 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1071 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1072 if (self.featureExtraProtect != None):
1073 self.intercepts += [ '#endif' ]
1074 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1075 #
1076 decls = self.makeCDecls(cmdinfo.elem)
1077 self.appendSection('command', '')
1078 self.appendSection('command', '%s {' % decls[0][:-1])
1079 # Setup common to call wrappers. First parameter is always dispatchable
1080 dispatchable_type = cmdinfo.elem.find('param/type').text
1081 dispatchable_name = cmdinfo.elem.find('param/name').text
1082 # Default to device
1083 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001084 dispatch_table_name = 'VkLayerDispatchTable'
1085 # Set to instance as necessary
1086 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1087 device_or_instance = 'instance'
1088 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001089 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001090 api_function_name = cmdinfo.elem.attrib.get('name')
1091 params = cmdinfo.elem.findall('param/name')
1092 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001093 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001094
1095 # Declare result variable, if any.
1096 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001097 'PFN_vkVoidFunction': 'return nullptr;',
1098 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001099 'VkDeviceAddress': 'return 0;',
1100 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1101 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001102 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001103 }
1104 resulttype = cmdinfo.elem.find('proto/type')
1105 assignresult = ''
1106 if (resulttype.text != 'void'):
1107 assignresult = resulttype.text + ' result = '
1108
1109 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001110 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001111
1112 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001113 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001114 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001115 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1116 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1117 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001118
1119 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001120 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001121 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001122 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001123 self.appendSection('command', ' }')
1124
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001125 # Insert pre-dispatch debug utils function call
1126 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001127 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001128
1129 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001130 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001131
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001132 # Insert post-dispatch debug utils function call
1133 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001134 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001135
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001136 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001137 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001138 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001139 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001140 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001141 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001142 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001143 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001144 # Return result variable, if any.
1145 if (resulttype.text != 'void'):
1146 self.appendSection('command', ' return result;')
1147 self.appendSection('command', '}')
1148 #
1149 # Override makeProtoName to drop the "vk" prefix
1150 def makeProtoName(self, name, tail):
1151 return self.genOpts.apientry + name[2:] + tail