blob: 7782ddc173740bdb3c3d48a2f40cdf4ea643c5d4 [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',
135 'vkCreateDebugReportCallbackEXT',
136 'vkDestroyDebugReportCallbackEXT',
137 'vkEnumerateInstanceLayerProperties',
138 'vkEnumerateInstanceExtensionProperties',
139 'vkEnumerateDeviceLayerProperties',
140 'vkEnumerateDeviceExtensionProperties',
141 ]
142
143 alt_ret_codes = [
144 # Include functions here which must tolerate VK_INCOMPLETE as a return code
145 'vkEnumeratePhysicalDevices',
146 'vkEnumeratePhysicalDeviceGroupsKHR',
147 'vkGetValidationCacheDataEXT',
148 'vkGetPipelineCacheData',
149 'vkGetShaderInfoAMD',
150 'vkGetPhysicalDeviceDisplayPropertiesKHR',
151 'vkGetPhysicalDeviceDisplayProperties2KHR',
152 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
153 'vkGetDisplayPlaneSupportedDisplaysKHR',
154 'vkGetDisplayModePropertiesKHR',
155 'vkGetDisplayModeProperties2KHR',
156 'vkGetPhysicalDeviceSurfaceFormatsKHR',
157 'vkGetPhysicalDeviceSurfacePresentModesKHR',
158 'vkGetPhysicalDevicePresentRectanglesKHR',
159 'vkGetPastPresentationTimingGOOGLE',
160 'vkGetSwapchainImagesKHR',
161 'vkEnumerateInstanceLayerProperties',
162 'vkEnumerateDeviceLayerProperties',
163 'vkEnumerateInstanceExtensionProperties',
164 'vkEnumerateDeviceExtensionProperties',
165 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
166 ]
167
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700168 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700169 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
170 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700171 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
172 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
173 'vkCmdBeginDebugUtilsLabelEXT' : 'BeginCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
174 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
175 }
176
177 post_dispatch_debug_utils_functions = {
178 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
179 'vkCmdEndDebugUtilsLabelEXT' : 'EndCmdDebugUtilsLabel(layer_data->report_data, commandBuffer);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700180 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
181 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
182 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
183 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
184 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700185 }
186
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600187 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
188 precallrecord_loop = precallvalidate_loop
189 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600190
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700191 inline_custom_header_preamble = """
192#define NOMINMAX
193#include <mutex>
194#include <cinttypes>
195#include <stdio.h>
196#include <stdlib.h>
197#include <string.h>
198#include <unordered_map>
199#include <unordered_set>
200#include <algorithm>
201#include <memory>
202
203#include "vk_loader_platform.h"
204#include "vulkan/vulkan.h"
205#include "vk_layer_config.h"
206#include "vk_layer_data.h"
207#include "vk_layer_logging.h"
208#include "vk_object_types.h"
209#include "vulkan/vk_layer.h"
210#include "vk_enum_string_helper.h"
211#include "vk_layer_extension_utils.h"
212#include "vk_layer_utils.h"
213#include "vulkan/vk_layer.h"
214#include "vk_dispatch_table_helper.h"
215#include "vk_validation_error_messages.h"
216#include "vk_extension_helper.h"
217#include "vk_safe_struct.h"
218
219extern uint64_t global_unique_id;
220extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
221"""
222
223 inline_custom_header_class_definition = """
224
225// Layer object type identifiers
226enum LayerObjectTypeId {
227 LayerObjectTypeThreading,
228 LayerObjectTypeParameterValidation,
229 LayerObjectTypeObjectTracker,
230 LayerObjectTypeCoreValidation,
231};
232
233struct TEMPLATE_STATE {
234 VkDescriptorUpdateTemplateKHR desc_update_template;
235 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
236
237 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
238 : desc_update_template(update_template), create_info(*pCreateInfo) {}
239};
240
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700241class LAYER_PHYS_DEV_PROPERTIES {
242public:
243 VkPhysicalDeviceProperties properties;
244 std::vector<VkQueueFamilyProperties> queue_family_properties;
245};
246
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700247// Layer chassis validation object base class definition
248class ValidationObject {
249 public:
250 uint32_t api_version;
251 debug_report_data* report_data = nullptr;
252 std::vector<VkDebugReportCallbackEXT> logging_callback;
253 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
254
255 VkLayerInstanceDispatchTable instance_dispatch_table;
256 VkLayerDispatchTable device_dispatch_table;
257
258 InstanceExtensions instance_extensions;
259 DeviceExtensions device_extensions = {};
260
261 VkInstance instance = VK_NULL_HANDLE;
262 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
263 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700264 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700265
266 std::vector<ValidationObject*> object_dispatch;
267 LayerObjectTypeId container_type;
268
269 // Constructor
270 ValidationObject(){};
271 // Destructor
272 virtual ~ValidationObject() {};
273
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700274 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700275 virtual std::unique_lock<std::mutex> write_lock() {
276 return std::unique_lock<std::mutex>(validation_object_mutex);
277 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700278
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700279 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
280 for (auto validation_object : object_dispatch) {
281 if (validation_object->container_type == object_type) {
282 return validation_object;
283 }
284 }
285 return nullptr;
286 };
287
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700288 std::string layer_name = "CHASSIS";
289
290 // Handle Wrapping Data
291 // Reverse map display handles
292 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
293 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700294 struct SubpassesUsageStates {
295 std::unordered_set<uint32_t> subpasses_using_color_attachment;
296 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
297 };
298 // Uses unwrapped handles
299 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
300 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
301 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
302 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700303 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
304 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700305
306
307 // Unwrap a handle. Must hold lock.
308 template <typename HandleType>
309 HandleType Unwrap(HandleType wrappedHandle) {
310 // TODO: don't use operator[] here.
311 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
312 }
313
314 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
315 template <typename HandleType>
316 HandleType WrapNew(HandleType newlyCreatedHandle) {
317 auto unique_id = global_unique_id++;
318 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
319 return (HandleType)unique_id;
320 }
321
322 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
323 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
324 auto unique_id = global_unique_id++;
325 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
326 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
327 return (VkDisplayKHR)unique_id;
328 }
329
330 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
331 // creating another. Must hold lock.
332 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
333 // See if this display is already known
334 auto it = map_data->display_id_reverse_mapping.find(handle);
335 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
336 // Unknown, so wrap
337 return WrapDisplay(handle, map_data);
338 }
339
340 // Pre/post hook point declarations
341"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600342
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700343 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600344// This file is ***GENERATED***. Do Not Edit.
345// See layer_chassis_generator.py for modifications.
346
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700347/* Copyright (c) 2015-2019 The Khronos Group Inc.
348 * Copyright (c) 2015-2019 Valve Corporation
349 * Copyright (c) 2015-2019 LunarG, Inc.
350 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600351 *
352 * Licensed under the Apache License, Version 2.0 (the "License");
353 * you may not use this file except in compliance with the License.
354 * You may obtain a copy of the License at
355 *
356 * http://www.apache.org/licenses/LICENSE-2.0
357 *
358 * Unless required by applicable law or agreed to in writing, software
359 * distributed under the License is distributed on an "AS IS" BASIS,
360 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
361 * See the License for the specific language governing permissions and
362 * limitations under the License.
363 *
364 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700365 */"""
366
367 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600368
369#include <string.h>
370#include <mutex>
371
372#define VALIDATION_ERROR_MAP_IMPL
373
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600374#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700375#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600376
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600377std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600378
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700379// Global unique object identifier. All increments must be guarded by a lock.
380uint64_t global_unique_id = 1;
381// Map uniqueID to actual object handle
382std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
383
384// TODO: This variable controls handle wrapping -- in the future it should be hooked
385// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
386#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
387bool wrap_handles = true;
388#else
389const bool wrap_handles = false;
390#endif
391
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600392// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700393#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600394#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700395#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700396#elif BUILD_THREAD_SAFETY
Mark Lobodzinski706e52b2018-12-11 13:21:52 -0700397#include "thread_safety.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700398#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
399#elif BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700400#include "stateless_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700401#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
402#elif BUILD_CORE_VALIDATION
403#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
404#else
405#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
406#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600407
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600408namespace vulkan_layer_chassis {
409
410using std::unordered_map;
411
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600412static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700413 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600414};
415
416static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
417
418extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
419
420
421// Manually written functions
422
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700423// Check enabled instance extensions against supported instance extension whitelist
424static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
425 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
426 // Check for recognized instance extensions
427 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
428 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
429 kVUIDUndefined,
430 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
431 "results and/or produce undefined behavior.",
432 pCreateInfo->ppEnabledExtensionNames[i]);
433 }
434 }
435}
436
437// Check enabled device extensions against supported device extension whitelist
438static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
439 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
440 // Check for recognized device extensions
441 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
442 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
443 kVUIDUndefined,
444 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
445 "results and/or produce undefined behavior.",
446 pCreateInfo->ppEnabledExtensionNames[i]);
447 }
448 }
449}
450
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600451VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600452 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700453 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700454 return nullptr;
455 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600456 const auto &item = name_to_funcptr_map.find(funcName);
457 if (item != name_to_funcptr_map.end()) {
458 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
459 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600460 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600461 if (!table.GetDeviceProcAddr) return nullptr;
462 return table.GetDeviceProcAddr(device, funcName);
463}
464
465VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600466 const auto &item = name_to_funcptr_map.find(funcName);
467 if (item != name_to_funcptr_map.end()) {
468 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
469 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600470 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
471 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600472 if (!table.GetInstanceProcAddr) return nullptr;
473 return table.GetInstanceProcAddr(instance, funcName);
474}
475
476VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600477 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
478 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600479 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
480 return table.GetPhysicalDeviceProcAddr(instance, funcName);
481}
482
483VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
484 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
485}
486
487VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
488 VkLayerProperties *pProperties) {
489 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
490}
491
492VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
493 VkExtensionProperties *pProperties) {
494 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
495 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
496
497 return VK_ERROR_LAYER_NOT_PRESENT;
498}
499
500VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
501 uint32_t *pCount, VkExtensionProperties *pProperties) {
502 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600503 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600504 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
505 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600506}
507
508VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
509 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600510 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600511
512 assert(chain_info->u.pLayerInfo);
513 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
514 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
515 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
516 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700517 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
518 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
519
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600520
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600521 // Create temporary dispatch vector for pre-calls until instance is created
522 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700523#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600524 auto object_tracker = new ObjectLifetimes;
525 local_object_dispatch.emplace_back(object_tracker);
526 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700527 object_tracker->api_version = api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700528#elif BUILD_THREAD_SAFETY
529 auto thread_checker = new ThreadSafety;
530 local_object_dispatch.emplace_back(thread_checker);
531 thread_checker->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700532 thread_checker->api_version = api_version;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700533#elif BUILD_PARAMETER_VALIDATION
534 auto parameter_validation = new StatelessValidation;
535 local_object_dispatch.emplace_back(parameter_validation);
536 parameter_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700537 parameter_validation->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700538#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600539
540
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600541 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600542 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600543 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
544 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600545 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600546 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
547 }
548
549 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600550 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600551
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600552 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600553
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600554 framework->object_dispatch = local_object_dispatch;
555
556 framework->instance = *pInstance;
557 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
558 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
559 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700560 framework->api_version = api_version;
561 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
562
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700563#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600564 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700565 object_tracker->report_data = framework->report_data;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700566#elif BUILD_THREAD_SAFETY
567 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "google_thread_checker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700568 thread_checker->report_data = framework->report_data;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700569#elif BUILD_PARAMETER_VALIDATION
570 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_parameter_validation");
571 parameter_validation->report_data = framework->report_data;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700572#else
573 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
574#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600575
576 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700577 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600578 }
579
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700580 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
581
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600582 return result;
583}
584
585VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
586 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600587 auto layer_data = GetLayerDataPtr(key, layer_data_map);
588 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700589 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600590 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
591 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600592 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700593 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600594 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
595 }
596
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600597 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600598
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600599 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700600 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600601 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
602 }
603 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600604 while (layer_data->logging_messenger.size() > 0) {
605 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
606 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
607 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600608 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600609 while (layer_data->logging_callback.size() > 0) {
610 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
611 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
612 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600613 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600614
615 layer_debug_utils_destroy_instance(layer_data->report_data);
616
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700617 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
618 delete *item;
619 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600620 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600621}
622
623VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
624 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600625 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600626
627 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
628
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600629 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
630 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600631 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
632 if (fpCreateDevice == NULL) {
633 return VK_ERROR_INITIALIZATION_FAILED;
634 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600635 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
636
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700637 // Get physical device limits for device
638 VkPhysicalDeviceProperties device_properties = {};
639 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
640
641 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
642 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
643
644 DeviceExtensions device_extensions = {};
645 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
646 for (auto item : instance_interceptor->object_dispatch) {
647 item->device_extensions = device_extensions;
648 }
649
650 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600651 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700652 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700653 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700654 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600655 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600656 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700657 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600658 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
659 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600660
661 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600662 if (result != VK_SUCCESS) {
663 return result;
664 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600665
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600666 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700667
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700668 // Save local info in device object
669 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700670 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
671 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700672 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700673
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600674 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700675
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600676 device_interceptor->device = *pDevice;
677 device_interceptor->physical_device = gpu;
678 device_interceptor->instance = instance_interceptor->instance;
679 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600680
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700681#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600682 // Create child layer objects for this key and add to dispatch vector
683 auto object_tracker = new ObjectLifetimes;
684 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
685 object_tracker->container_type = LayerObjectTypeObjectTracker;
686 object_tracker->physical_device = gpu;
687 object_tracker->instance = instance_interceptor->instance;
688 object_tracker->report_data = device_interceptor->report_data;
689 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700690 object_tracker->api_version = device_interceptor->api_version;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600691 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700692#elif BUILD_THREAD_SAFETY
693 auto thread_safety = new ThreadSafety;
694 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
695 thread_safety->container_type = LayerObjectTypeThreading;
696 thread_safety->physical_device = gpu;
697 thread_safety->instance = instance_interceptor->instance;
698 thread_safety->report_data = device_interceptor->report_data;
699 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700700 thread_safety->api_version = device_interceptor->api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700701 device_interceptor->object_dispatch.emplace_back(thread_safety);
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700702#elif BUILD_PARAMETER_VALIDATION
703 auto stateless_validation = new StatelessValidation;
704 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
705 stateless_validation->container_type = LayerObjectTypeParameterValidation;
706 stateless_validation->physical_device = gpu;
707 stateless_validation->instance = instance_interceptor->instance;
708 stateless_validation->report_data = device_interceptor->report_data;
709 stateless_validation->device_dispatch_table = device_interceptor->device_dispatch_table;
710 stateless_validation->api_version = device_interceptor->api_version;
711 device_interceptor->object_dispatch.emplace_back(stateless_validation);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700712#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600713
714 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700715 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700716 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600717 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600718
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700719 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
720
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600721 return result;
722}
723
724VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
725 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600726 auto layer_data = GetLayerDataPtr(key, layer_data_map);
727 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700728 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600729 intercept->PreCallValidateDestroyDevice(device, pAllocator);
730 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600731 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700732 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600733 intercept->PreCallRecordDestroyDevice(device, pAllocator);
734 }
735 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600736
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600737 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600738
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600739 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700740 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600741 intercept->PostCallRecordDestroyDevice(device, pAllocator);
742 }
743
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700744 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
745 delete *item;
746 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600747 FreeLayerDataPtr(key, layer_data_map);
748}
749
750VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
751 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
752 const VkAllocationCallbacks *pAllocator,
753 VkDebugReportCallbackEXT *pCallback) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600754 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
755 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700756 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600757 intercept->PreCallValidateCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
758 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600759 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700760 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600761 intercept->PreCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
762 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700763 VkResult result = DispatchCreateDebugReportCallbackEXT(layer_data, instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600764 result = layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);
765 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700766 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700767 intercept->PostCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600768 }
769 return result;
770}
771
772VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
773 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600774 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
775 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700776 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600777 intercept->PreCallValidateDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
778 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600779 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700780 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600781 intercept->PreCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
782 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700783 DispatchDestroyDebugReportCallbackEXT(layer_data, instance, callback, pAllocator);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600784 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
785 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700786 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600787 intercept->PostCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
788 }
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700789}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600790
791 inline_custom_source_postamble = """
792// loader-layer interface v0, just wrappers since there is only a layer
793
794VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
795 VkExtensionProperties *pProperties) {
796 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
797}
798
799VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
800 VkLayerProperties *pProperties) {
801 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
802}
803
804VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
805 VkLayerProperties *pProperties) {
806 // the layer command handles VK_NULL_HANDLE just fine internally
807 assert(physicalDevice == VK_NULL_HANDLE);
808 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
809}
810
811VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
812 const char *pLayerName, uint32_t *pCount,
813 VkExtensionProperties *pProperties) {
814 // the layer command handles VK_NULL_HANDLE just fine internally
815 assert(physicalDevice == VK_NULL_HANDLE);
816 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
817}
818
819VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
820 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
821}
822
823VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
824 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
825}
826
827VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
828 const char *funcName) {
829 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
830}
831
832VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
833 assert(pVersionStruct != NULL);
834 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
835
836 // Fill in the function pointers if our version is at least capable of having the structure contain them.
837 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
838 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
839 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
840 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
841 }
842
843 return VK_SUCCESS;
844}"""
845
846
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600847 def __init__(self,
848 errFile = sys.stderr,
849 warnFile = sys.stderr,
850 diagFile = sys.stdout):
851 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
852 # Internal state - accumulators for different inner block text
853 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
854 self.intercepts = []
855 self.layer_factory = '' # String containing base layer factory class definition
856
857 # Check if the parameter passed in is a pointer to an array
858 def paramIsArray(self, param):
859 return param.attrib.get('len') is not None
860
861 # Check if the parameter passed in is a pointer
862 def paramIsPointer(self, param):
863 ispointer = False
864 for elem in param:
865 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
866 ispointer = True
867 return ispointer
868
869 # Check if an object is a non-dispatchable handle
870 def isHandleTypeNonDispatchable(self, handletype):
871 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
872 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
873 return True
874 else:
875 return False
876
877 # Check if an object is a dispatchable handle
878 def isHandleTypeDispatchable(self, handletype):
879 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
880 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
881 return True
882 else:
883 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700884 #
885 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600886 def beginFile(self, genOpts):
887 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700888 # Output Copyright
889 write(self.inline_copyright_message, file=self.outFile)
890 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600891 self.header = False
892 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
893 self.header = True
894 write('#pragma once', file=self.outFile)
895 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600896 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700897 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600898 else:
899 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700900 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700901 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600902 #
903 def endFile(self):
904 # Finish C++ namespace and multiple inclusion protection
905 self.newline()
906 if not self.header:
907 # Record intercepted procedures
908 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
909 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
910 write('\n'.join(self.intercepts), file=self.outFile)
911 write('};\n', file=self.outFile)
912 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600913 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600914 if self.header:
915 self.newline()
916 # Output Layer Factory Class Definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600917 self.layer_factory += '};\n\n'
918 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600919 write(self.layer_factory, file=self.outFile)
920 else:
921 write(self.inline_custom_source_postamble, file=self.outFile)
922 # Finish processing in superclass
923 OutputGenerator.endFile(self)
924
925 def beginFeature(self, interface, emit):
926 # Start processing in superclass
927 OutputGenerator.beginFeature(self, interface, emit)
928 # Get feature extra protect
929 self.featureExtraProtect = GetFeatureProtect(interface)
930 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
931 # feature. They're only printed in endFeature().
932 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
933
934 def endFeature(self):
935 # Actually write the interface to the output file.
936 if (self.emit):
937 self.newline()
938 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
939 # or move it below the 'for section...' loop.
940 if (self.featureExtraProtect != None):
941 write('#ifdef', self.featureExtraProtect, file=self.outFile)
942 for section in self.TYPE_SECTIONS:
943 contents = self.sections[section]
944 if contents:
945 write('\n'.join(contents), file=self.outFile)
946 self.newline()
947 if (self.sections['command']):
948 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
949 self.newline()
950 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600951 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600952 # Finish processing in superclass
953 OutputGenerator.endFeature(self)
954 #
955 # Append a definition to the specified section
956 def appendSection(self, section, text):
957 self.sections[section].append(text)
958 #
959 # Type generation
960 def genType(self, typeinfo, name, alias):
961 pass
962 #
963 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
964 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
965 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
966 # structs etc.)
967 def genStruct(self, typeinfo, typeName):
968 OutputGenerator.genStruct(self, typeinfo, typeName)
969 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
970 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
971 for member in typeinfo.elem.findall('.//member'):
972 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
973 body += ';\n'
974 body += '} ' + typeName + ';\n'
975 self.appendSection('struct', body)
976 #
977 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
978 def genGroup(self, groupinfo, groupName, alias):
979 pass
980 # Enumerant generation
981 # <enum> tags may specify their values in several ways, but are usually just integers.
982 def genEnum(self, enuminfo, name, alias):
983 pass
984 #
985 # Customize Cdecl for layer factory base class
986 def BaseClassCdecl(self, elem, name):
987 raw = self.makeCDecls(elem)[1]
988
989 # Toss everything before the undecorated name
990 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
991 prototype = prototype.replace(")", "", 1)
992 prototype = prototype.replace(";", " {};")
993
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600994 # Build up pre/post call virtual function declarations
995 pre_call_validate = 'virtual bool PreCallValidate' + prototype
996 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
997 pre_call_record = 'virtual void PreCallRecord' + prototype
998 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700999 resulttype = elem.find('proto/type')
1000 if resulttype.text == 'VkResult':
1001 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001002 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1003 #
1004 # Command generation
1005 def genCmd(self, cmdinfo, name, alias):
1006 ignore_functions = [
1007 'vkEnumerateInstanceVersion'
1008 ]
1009
1010 if name in ignore_functions:
1011 return
1012
1013 if self.header: # In the header declare all intercepts
1014 self.appendSection('command', '')
1015 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1016 if (self.featureExtraProtect != None):
1017 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1018 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1019 # Update base class with virtual function declarations
1020 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
1021 # Update function intercepts
1022 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1023 if (self.featureExtraProtect != None):
1024 self.intercepts += [ '#endif' ]
1025 self.layer_factory += '#endif\n'
1026 return
1027
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001028 if name in self.manual_functions:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001029 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1030 return
1031 # Record that the function will be intercepted
1032 if (self.featureExtraProtect != None):
1033 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1034 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1035 if (self.featureExtraProtect != None):
1036 self.intercepts += [ '#endif' ]
1037 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1038 #
1039 decls = self.makeCDecls(cmdinfo.elem)
1040 self.appendSection('command', '')
1041 self.appendSection('command', '%s {' % decls[0][:-1])
1042 # Setup common to call wrappers. First parameter is always dispatchable
1043 dispatchable_type = cmdinfo.elem.find('param/type').text
1044 dispatchable_name = cmdinfo.elem.find('param/name').text
1045 # Default to device
1046 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001047 dispatch_table_name = 'VkLayerDispatchTable'
1048 # Set to instance as necessary
1049 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1050 device_or_instance = 'instance'
1051 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001052 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001053 api_function_name = cmdinfo.elem.attrib.get('name')
1054 params = cmdinfo.elem.findall('param/name')
1055 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001056 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001057
1058 # Declare result variable, if any.
1059 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001060 'PFN_vkVoidFunction': 'return nullptr;',
1061 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001062 'VkDeviceAddress': 'return 0;',
1063 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1064 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001065 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001066 }
1067 resulttype = cmdinfo.elem.find('proto/type')
1068 assignresult = ''
1069 if (resulttype.text != 'void'):
1070 assignresult = resulttype.text + ' result = '
1071
1072 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001073 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001074
1075 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001076 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001077 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001078 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1079 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1080 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001081
1082 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001083 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001084 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001085 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001086 self.appendSection('command', ' }')
1087
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001088 # Insert pre-dispatch debug utils function call
1089 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001090 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001091
1092 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001093 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001094
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001095 # Insert post-dispatch debug utils function call
1096 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001097 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001098
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001099 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001100 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001101 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001102 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001103 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001104 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001105 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001106 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001107 # Return result variable, if any.
1108 if (resulttype.text != 'void'):
1109 self.appendSection('command', ' return result;')
1110 self.appendSection('command', '}')
1111 #
1112 # Override makeProtoName to drop the "vk" prefix
1113 def makeProtoName(self, name, tail):
1114 return self.genOpts.apientry + name[2:] + tail