blob: b204c0a8fe2bf2cc06d2cb12fdb8bf6b051f3347 [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 = {
169 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->debugUtilsObjectNameMap->insert(std::make_pair<uint64_t, std::string>((uint64_t &&) pNameInfo->objectHandle, pNameInfo->pObjectName));',
170 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
171 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
172 'vkCmdBeginDebugUtilsLabelEXT' : 'BeginCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
173 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
174 }
175
176 post_dispatch_debug_utils_functions = {
177 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
178 'vkCmdEndDebugUtilsLabelEXT' : 'EndCmdDebugUtilsLabel(layer_data->report_data, commandBuffer);',
179 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
180 }
181
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600182 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
183 precallrecord_loop = precallvalidate_loop
184 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600185
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700186 inline_custom_header_preamble = """
187#define NOMINMAX
188#include <mutex>
189#include <cinttypes>
190#include <stdio.h>
191#include <stdlib.h>
192#include <string.h>
193#include <unordered_map>
194#include <unordered_set>
195#include <algorithm>
196#include <memory>
197
198#include "vk_loader_platform.h"
199#include "vulkan/vulkan.h"
200#include "vk_layer_config.h"
201#include "vk_layer_data.h"
202#include "vk_layer_logging.h"
203#include "vk_object_types.h"
204#include "vulkan/vk_layer.h"
205#include "vk_enum_string_helper.h"
206#include "vk_layer_extension_utils.h"
207#include "vk_layer_utils.h"
208#include "vulkan/vk_layer.h"
209#include "vk_dispatch_table_helper.h"
210#include "vk_validation_error_messages.h"
211#include "vk_extension_helper.h"
212#include "vk_safe_struct.h"
213
214extern uint64_t global_unique_id;
215extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
216"""
217
218 inline_custom_header_class_definition = """
219
220// Layer object type identifiers
221enum LayerObjectTypeId {
222 LayerObjectTypeThreading,
223 LayerObjectTypeParameterValidation,
224 LayerObjectTypeObjectTracker,
225 LayerObjectTypeCoreValidation,
226};
227
228struct TEMPLATE_STATE {
229 VkDescriptorUpdateTemplateKHR desc_update_template;
230 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
231
232 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
233 : desc_update_template(update_template), create_info(*pCreateInfo) {}
234};
235
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700236class LAYER_PHYS_DEV_PROPERTIES {
237public:
238 VkPhysicalDeviceProperties properties;
239 std::vector<VkQueueFamilyProperties> queue_family_properties;
240};
241
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700242// Layer chassis validation object base class definition
243class ValidationObject {
244 public:
245 uint32_t api_version;
246 debug_report_data* report_data = nullptr;
247 std::vector<VkDebugReportCallbackEXT> logging_callback;
248 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
249
250 VkLayerInstanceDispatchTable instance_dispatch_table;
251 VkLayerDispatchTable device_dispatch_table;
252
253 InstanceExtensions instance_extensions;
254 DeviceExtensions device_extensions = {};
255
256 VkInstance instance = VK_NULL_HANDLE;
257 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
258 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700259 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700260
261 std::vector<ValidationObject*> object_dispatch;
262 LayerObjectTypeId container_type;
263
264 // Constructor
265 ValidationObject(){};
266 // Destructor
267 virtual ~ValidationObject() {};
268
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700269 std::mutex validation_object_mutex;
270 virtual void write_lock() { validation_object_mutex.lock(); }
271 virtual void write_unlock() { validation_object_mutex.unlock(); }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700272
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700273 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
274 for (auto validation_object : object_dispatch) {
275 if (validation_object->container_type == object_type) {
276 return validation_object;
277 }
278 }
279 return nullptr;
280 };
281
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700282 std::string layer_name = "CHASSIS";
283
284 // Handle Wrapping Data
285 // Reverse map display handles
286 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
287 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700288 struct SubpassesUsageStates {
289 std::unordered_set<uint32_t> subpasses_using_color_attachment;
290 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
291 };
292 // Uses unwrapped handles
293 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
294 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
295 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
296 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700297 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
298 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700299
300
301 // Unwrap a handle. Must hold lock.
302 template <typename HandleType>
303 HandleType Unwrap(HandleType wrappedHandle) {
304 // TODO: don't use operator[] here.
305 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
306 }
307
308 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
309 template <typename HandleType>
310 HandleType WrapNew(HandleType newlyCreatedHandle) {
311 auto unique_id = global_unique_id++;
312 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
313 return (HandleType)unique_id;
314 }
315
316 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
317 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
318 auto unique_id = global_unique_id++;
319 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
320 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
321 return (VkDisplayKHR)unique_id;
322 }
323
324 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
325 // creating another. Must hold lock.
326 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
327 // See if this display is already known
328 auto it = map_data->display_id_reverse_mapping.find(handle);
329 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
330 // Unknown, so wrap
331 return WrapDisplay(handle, map_data);
332 }
333
334 // Pre/post hook point declarations
335"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600336
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700337 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600338// This file is ***GENERATED***. Do Not Edit.
339// See layer_chassis_generator.py for modifications.
340
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700341/* Copyright (c) 2015-2019 The Khronos Group Inc.
342 * Copyright (c) 2015-2019 Valve Corporation
343 * Copyright (c) 2015-2019 LunarG, Inc.
344 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600345 *
346 * Licensed under the Apache License, Version 2.0 (the "License");
347 * you may not use this file except in compliance with the License.
348 * You may obtain a copy of the License at
349 *
350 * http://www.apache.org/licenses/LICENSE-2.0
351 *
352 * Unless required by applicable law or agreed to in writing, software
353 * distributed under the License is distributed on an "AS IS" BASIS,
354 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
355 * See the License for the specific language governing permissions and
356 * limitations under the License.
357 *
358 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700359 */"""
360
361 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600362
363#include <string.h>
364#include <mutex>
365
366#define VALIDATION_ERROR_MAP_IMPL
367
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600368#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700369#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600370
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600371std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600372
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700373// Global unique object identifier. All increments must be guarded by a lock.
374uint64_t global_unique_id = 1;
375// Map uniqueID to actual object handle
376std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
377
378// TODO: This variable controls handle wrapping -- in the future it should be hooked
379// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
380#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
381bool wrap_handles = true;
382#else
383const bool wrap_handles = false;
384#endif
385
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600386// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700387#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600388#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700389#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700390#elif BUILD_THREAD_SAFETY
Mark Lobodzinski706e52b2018-12-11 13:21:52 -0700391#include "thread_safety.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700392#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
393#elif BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700394#include "stateless_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700395#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
396#elif BUILD_CORE_VALIDATION
397#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
398#else
399#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
400#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600401
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600402namespace vulkan_layer_chassis {
403
404using std::unordered_map;
405
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600406static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700407 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600408};
409
410static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
411
412extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
413
414
415// Manually written functions
416
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700417// Check enabled instance extensions against supported instance extension whitelist
418static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
419 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
420 // Check for recognized instance extensions
421 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
422 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
423 kVUIDUndefined,
424 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
425 "results and/or produce undefined behavior.",
426 pCreateInfo->ppEnabledExtensionNames[i]);
427 }
428 }
429}
430
431// Check enabled device extensions against supported device extension whitelist
432static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
433 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
434 // Check for recognized device extensions
435 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
436 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
437 kVUIDUndefined,
438 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
439 "results and/or produce undefined behavior.",
440 pCreateInfo->ppEnabledExtensionNames[i]);
441 }
442 }
443}
444
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600445VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600446 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700447 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700448 return nullptr;
449 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600450 const auto &item = name_to_funcptr_map.find(funcName);
451 if (item != name_to_funcptr_map.end()) {
452 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
453 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600454 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600455 if (!table.GetDeviceProcAddr) return nullptr;
456 return table.GetDeviceProcAddr(device, funcName);
457}
458
459VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600460 const auto &item = name_to_funcptr_map.find(funcName);
461 if (item != name_to_funcptr_map.end()) {
462 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
463 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600464 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
465 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600466 if (!table.GetInstanceProcAddr) return nullptr;
467 return table.GetInstanceProcAddr(instance, funcName);
468}
469
470VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600471 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
472 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600473 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
474 return table.GetPhysicalDeviceProcAddr(instance, funcName);
475}
476
477VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
478 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
479}
480
481VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
482 VkLayerProperties *pProperties) {
483 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
484}
485
486VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
487 VkExtensionProperties *pProperties) {
488 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
489 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
490
491 return VK_ERROR_LAYER_NOT_PRESENT;
492}
493
494VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
495 uint32_t *pCount, VkExtensionProperties *pProperties) {
496 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600497 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600498 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
499 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600500}
501
502VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
503 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600504 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600505
506 assert(chain_info->u.pLayerInfo);
507 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
508 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
509 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
510 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700511 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
512 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
513
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600514
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600515 // Create temporary dispatch vector for pre-calls until instance is created
516 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700517#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600518 auto object_tracker = new ObjectLifetimes;
519 local_object_dispatch.emplace_back(object_tracker);
520 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700521 object_tracker->api_version = api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700522#elif BUILD_THREAD_SAFETY
523 auto thread_checker = new ThreadSafety;
524 local_object_dispatch.emplace_back(thread_checker);
525 thread_checker->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700526 thread_checker->api_version = api_version;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700527#elif BUILD_PARAMETER_VALIDATION
528 auto parameter_validation = new StatelessValidation;
529 local_object_dispatch.emplace_back(parameter_validation);
530 parameter_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700531 parameter_validation->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700532#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600533
534
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600535 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600536 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600537 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
538 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600539 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600540 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
541 }
542
543 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600544 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600545
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600546 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600547
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600548 framework->object_dispatch = local_object_dispatch;
549
550 framework->instance = *pInstance;
551 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
552 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
553 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700554 framework->api_version = api_version;
555 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
556
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700557#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600558 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700559 object_tracker->report_data = framework->report_data;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700560#elif BUILD_THREAD_SAFETY
561 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "google_thread_checker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700562 thread_checker->report_data = framework->report_data;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700563#elif BUILD_PARAMETER_VALIDATION
564 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_parameter_validation");
565 parameter_validation->report_data = framework->report_data;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700566#else
567 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
568#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600569
570 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600571 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
572 }
573
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700574 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
575
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600576 return result;
577}
578
579VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
580 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600581 auto layer_data = GetLayerDataPtr(key, layer_data_map);
582 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700583 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600584 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700585 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600586 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600587 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700588 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600589 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700590 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600591 }
592
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600593 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600594
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600595 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700596 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600597 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700598 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600599 }
600 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600601 while (layer_data->logging_messenger.size() > 0) {
602 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
603 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
604 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600605 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600606 while (layer_data->logging_callback.size() > 0) {
607 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
608 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
609 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600610 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600611
612 layer_debug_utils_destroy_instance(layer_data->report_data);
613
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700614 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
615 delete *item;
616 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600617 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600618}
619
620VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
621 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600622 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600623
624 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
625
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600626 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
627 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600628 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
629 if (fpCreateDevice == NULL) {
630 return VK_ERROR_INITIALIZATION_FAILED;
631 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600632 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
633
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700634 // Get physical device limits for device
635 VkPhysicalDeviceProperties device_properties = {};
636 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
637
638 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
639 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
640
641 DeviceExtensions device_extensions = {};
642 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
643 for (auto item : instance_interceptor->object_dispatch) {
644 item->device_extensions = device_extensions;
645 }
646
647 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600648 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700649 intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700650 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700651 intercept->write_unlock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700652 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600653 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600654 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700655 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600656 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700657 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600658 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600659
660 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600661 if (result != VK_SUCCESS) {
662 return result;
663 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600664
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600665 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700666
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700667 // Save local info in device object
668 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700669 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
670 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700671 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700672
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600673 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700674
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600675 device_interceptor->device = *pDevice;
676 device_interceptor->physical_device = gpu;
677 device_interceptor->instance = instance_interceptor->instance;
678 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600679
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700680#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600681 // Create child layer objects for this key and add to dispatch vector
682 auto object_tracker = new ObjectLifetimes;
683 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
684 object_tracker->container_type = LayerObjectTypeObjectTracker;
685 object_tracker->physical_device = gpu;
686 object_tracker->instance = instance_interceptor->instance;
687 object_tracker->report_data = device_interceptor->report_data;
688 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700689 object_tracker->api_version = device_interceptor->api_version;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600690 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700691#elif BUILD_THREAD_SAFETY
692 auto thread_safety = new ThreadSafety;
693 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
694 thread_safety->container_type = LayerObjectTypeThreading;
695 thread_safety->physical_device = gpu;
696 thread_safety->instance = instance_interceptor->instance;
697 thread_safety->report_data = device_interceptor->report_data;
698 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700699 thread_safety->api_version = device_interceptor->api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700700 device_interceptor->object_dispatch.emplace_back(thread_safety);
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700701#elif BUILD_PARAMETER_VALIDATION
702 auto stateless_validation = new StatelessValidation;
703 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
704 stateless_validation->container_type = LayerObjectTypeParameterValidation;
705 stateless_validation->physical_device = gpu;
706 stateless_validation->instance = instance_interceptor->instance;
707 stateless_validation->report_data = device_interceptor->report_data;
708 stateless_validation->device_dispatch_table = device_interceptor->device_dispatch_table;
709 stateless_validation->api_version = device_interceptor->api_version;
710 device_interceptor->object_dispatch.emplace_back(stateless_validation);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700711#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600712
713 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700714 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600715 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700716 intercept->write_unlock();
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 + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700728 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600729 intercept->PreCallValidateDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700730 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600731 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600732 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700733 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600734 intercept->PreCallRecordDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700735 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600736 }
737 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600738
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600739 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600740
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600741 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700742 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600743 intercept->PostCallRecordDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700744 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600745 }
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);
751}
752
753VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
754 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
755 const VkAllocationCallbacks *pAllocator,
756 VkDebugReportCallbackEXT *pCallback) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600757 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
758 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700759 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600760 intercept->PreCallValidateCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700761 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600762 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600763 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700764 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600765 intercept->PreCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700766 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600767 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700768 VkResult result = DispatchCreateDebugReportCallbackEXT(layer_data, instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600769 result = layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);
770 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700771 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600772 intercept->PostCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700773 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600774 }
775 return result;
776}
777
778VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
779 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600780 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
781 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700782 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600783 intercept->PreCallValidateDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700784 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600785 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600786 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700787 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600788 intercept->PreCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700789 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600790 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700791 DispatchDestroyDebugReportCallbackEXT(layer_data, instance, callback, pAllocator);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600792 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
793 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700794 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600795 intercept->PostCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700796 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600797 }
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700798}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600799
800 inline_custom_source_postamble = """
801// loader-layer interface v0, just wrappers since there is only a layer
802
803VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
804 VkExtensionProperties *pProperties) {
805 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
806}
807
808VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
809 VkLayerProperties *pProperties) {
810 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
811}
812
813VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
814 VkLayerProperties *pProperties) {
815 // the layer command handles VK_NULL_HANDLE just fine internally
816 assert(physicalDevice == VK_NULL_HANDLE);
817 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
818}
819
820VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
821 const char *pLayerName, uint32_t *pCount,
822 VkExtensionProperties *pProperties) {
823 // the layer command handles VK_NULL_HANDLE just fine internally
824 assert(physicalDevice == VK_NULL_HANDLE);
825 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
826}
827
828VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
829 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
830}
831
832VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
833 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
834}
835
836VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
837 const char *funcName) {
838 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
839}
840
841VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
842 assert(pVersionStruct != NULL);
843 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
844
845 // Fill in the function pointers if our version is at least capable of having the structure contain them.
846 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
847 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
848 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
849 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
850 }
851
852 return VK_SUCCESS;
853}"""
854
855
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600856 def __init__(self,
857 errFile = sys.stderr,
858 warnFile = sys.stderr,
859 diagFile = sys.stdout):
860 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
861 # Internal state - accumulators for different inner block text
862 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
863 self.intercepts = []
864 self.layer_factory = '' # String containing base layer factory class definition
865
866 # Check if the parameter passed in is a pointer to an array
867 def paramIsArray(self, param):
868 return param.attrib.get('len') is not None
869
870 # Check if the parameter passed in is a pointer
871 def paramIsPointer(self, param):
872 ispointer = False
873 for elem in param:
874 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
875 ispointer = True
876 return ispointer
877
878 # Check if an object is a non-dispatchable handle
879 def isHandleTypeNonDispatchable(self, handletype):
880 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
881 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
882 return True
883 else:
884 return False
885
886 # Check if an object is a dispatchable handle
887 def isHandleTypeDispatchable(self, handletype):
888 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
889 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
890 return True
891 else:
892 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700893 #
894 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600895 def beginFile(self, genOpts):
896 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700897 # Output Copyright
898 write(self.inline_copyright_message, file=self.outFile)
899 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600900 self.header = False
901 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
902 self.header = True
903 write('#pragma once', file=self.outFile)
904 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600905 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700906 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600907 else:
908 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700909 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700910 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600911 #
912 def endFile(self):
913 # Finish C++ namespace and multiple inclusion protection
914 self.newline()
915 if not self.header:
916 # Record intercepted procedures
917 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
918 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
919 write('\n'.join(self.intercepts), file=self.outFile)
920 write('};\n', file=self.outFile)
921 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600922 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600923 if self.header:
924 self.newline()
925 # Output Layer Factory Class Definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600926 self.layer_factory += '};\n\n'
927 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600928 write(self.layer_factory, file=self.outFile)
929 else:
930 write(self.inline_custom_source_postamble, file=self.outFile)
931 # Finish processing in superclass
932 OutputGenerator.endFile(self)
933
934 def beginFeature(self, interface, emit):
935 # Start processing in superclass
936 OutputGenerator.beginFeature(self, interface, emit)
937 # Get feature extra protect
938 self.featureExtraProtect = GetFeatureProtect(interface)
939 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
940 # feature. They're only printed in endFeature().
941 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
942
943 def endFeature(self):
944 # Actually write the interface to the output file.
945 if (self.emit):
946 self.newline()
947 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
948 # or move it below the 'for section...' loop.
949 if (self.featureExtraProtect != None):
950 write('#ifdef', self.featureExtraProtect, file=self.outFile)
951 for section in self.TYPE_SECTIONS:
952 contents = self.sections[section]
953 if contents:
954 write('\n'.join(contents), file=self.outFile)
955 self.newline()
956 if (self.sections['command']):
957 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
958 self.newline()
959 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600960 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600961 # Finish processing in superclass
962 OutputGenerator.endFeature(self)
963 #
964 # Append a definition to the specified section
965 def appendSection(self, section, text):
966 self.sections[section].append(text)
967 #
968 # Type generation
969 def genType(self, typeinfo, name, alias):
970 pass
971 #
972 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
973 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
974 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
975 # structs etc.)
976 def genStruct(self, typeinfo, typeName):
977 OutputGenerator.genStruct(self, typeinfo, typeName)
978 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
979 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
980 for member in typeinfo.elem.findall('.//member'):
981 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
982 body += ';\n'
983 body += '} ' + typeName + ';\n'
984 self.appendSection('struct', body)
985 #
986 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
987 def genGroup(self, groupinfo, groupName, alias):
988 pass
989 # Enumerant generation
990 # <enum> tags may specify their values in several ways, but are usually just integers.
991 def genEnum(self, enuminfo, name, alias):
992 pass
993 #
994 # Customize Cdecl for layer factory base class
995 def BaseClassCdecl(self, elem, name):
996 raw = self.makeCDecls(elem)[1]
997
998 # Toss everything before the undecorated name
999 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1000 prototype = prototype.replace(")", "", 1)
1001 prototype = prototype.replace(";", " {};")
1002
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001003 # Build up pre/post call virtual function declarations
1004 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1005 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1006 pre_call_record = 'virtual void PreCallRecord' + prototype
1007 post_call_record = 'virtual void PostCallRecord' + prototype
1008 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1009 #
1010 # Command generation
1011 def genCmd(self, cmdinfo, name, alias):
1012 ignore_functions = [
1013 'vkEnumerateInstanceVersion'
1014 ]
1015
1016 if name in ignore_functions:
1017 return
1018
1019 if self.header: # In the header declare all intercepts
1020 self.appendSection('command', '')
1021 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1022 if (self.featureExtraProtect != None):
1023 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1024 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1025 # Update base class with virtual function declarations
1026 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
1027 # Update function intercepts
1028 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1029 if (self.featureExtraProtect != None):
1030 self.intercepts += [ '#endif' ]
1031 self.layer_factory += '#endif\n'
1032 return
1033
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001034 if name in self.manual_functions:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001035 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1036 return
1037 # Record that the function will be intercepted
1038 if (self.featureExtraProtect != None):
1039 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1040 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1041 if (self.featureExtraProtect != None):
1042 self.intercepts += [ '#endif' ]
1043 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1044 #
1045 decls = self.makeCDecls(cmdinfo.elem)
1046 self.appendSection('command', '')
1047 self.appendSection('command', '%s {' % decls[0][:-1])
1048 # Setup common to call wrappers. First parameter is always dispatchable
1049 dispatchable_type = cmdinfo.elem.find('param/type').text
1050 dispatchable_name = cmdinfo.elem.find('param/name').text
1051 # Default to device
1052 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001053 dispatch_table_name = 'VkLayerDispatchTable'
1054 # Set to instance as necessary
1055 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1056 device_or_instance = 'instance'
1057 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001058 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001059 api_function_name = cmdinfo.elem.attrib.get('name')
1060 params = cmdinfo.elem.findall('param/name')
1061 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001062 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001063
1064 # Declare result variable, if any.
1065 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001066 'PFN_vkVoidFunction': 'return nullptr;',
1067 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001068 'VkDeviceAddress': 'return 0;',
1069 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1070 'void': 'return;',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001071 }
1072 resulttype = cmdinfo.elem.find('proto/type')
1073 assignresult = ''
1074 if (resulttype.text != 'void'):
1075 assignresult = resulttype.text + ' result = '
1076
1077 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001078 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001079
1080 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001081 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001082 self.appendSection('command', ' intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001083 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001084 self.appendSection('command', ' intercept->write_unlock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001085 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1086 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001087
1088 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001089 self.appendSection('command', ' %s' % self.precallrecord_loop)
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001090 self.appendSection('command', ' intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001091 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001092 self.appendSection('command', ' intercept->write_unlock();')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001093 self.appendSection('command', ' }')
1094
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001095 # Insert pre-dispatch debug utils function call
1096 if name in self.pre_dispatch_debug_utils_functions:
1097 self.appendSection('command', ' {')
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001098 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->validation_object_mutex);')
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001099 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
1100 self.appendSection('command', ' }')
1101
1102 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001103 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001104
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001105 # Insert post-dispatch debug utils function call
1106 if name in self.post_dispatch_debug_utils_functions:
1107 self.appendSection('command', ' {')
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001108 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->validation_object_mutex);')
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001109 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
1110 self.appendSection('command', ' }')
1111
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001112 # Generate post-call object processing source code
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001113 return_type_indent = ''
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001114
1115 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001116 if (resulttype.text == 'VkResult'):
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001117 return_type_indent = ' '
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001118 if name in self.alt_ret_codes:
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001119 self.appendSection('command', '%s if (((VK_SUCCESS == result) || (VK_INCOMPLETE == result)) || (intercept->container_type == LayerObjectTypeThreading)) {' % return_type_indent)
Mark Lobodzinskib3c94842018-11-27 10:01:51 -07001120 else:
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001121 self.appendSection('command', '%s if ((VK_SUCCESS == result) || (intercept->container_type == LayerObjectTypeThreading)) {' % return_type_indent)
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001122
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001123 #self.appendSection('command', '%s %s' % (return_type_indent, self.postcallrecord_loop))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001124 self.appendSection('command', '%s intercept->write_lock();' % return_type_indent)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001125 self.appendSection('command', '%s intercept->PostCallRecord%s(%s);' % (return_type_indent,api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001126 self.appendSection('command', '%s intercept->write_unlock();' % return_type_indent)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001127 self.appendSection('command', '%s }' % return_type_indent)
1128 if (resulttype.text == 'VkResult'):
1129 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001130
1131 # Return result variable, if any.
1132 if (resulttype.text != 'void'):
1133 self.appendSection('command', ' return result;')
1134 self.appendSection('command', '}')
1135 #
1136 # Override makeProtoName to drop the "vk" prefix
1137 def makeProtoName(self, name, tail):
1138 return self.genOpts.apientry + name[2:] + tail