blob: 66c1ebe926ab09957af741606d0533fd3fa4fe2c [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
3# Copyright (c) 2015-2016 Valve Corporation
4# Copyright (c) 2015-2016 LunarG, Inc.
5# Copyright (c) 2015-2016 Google Inc.
6#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
20# Author: Mark Lobodzinski <mark@lunarg.com>
21#
22# This script generates the dispatch portion of a factory layer which intercepts
23# all Vulkan functions. The resultant factory layer allows rapid development of
24# layers and interceptors.
25
26import os,re,sys
27from generator import *
28from common_codegen import *
29
30# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31#
32# Adds options used by LayerFactoryOutputGenerator objects during factory
33# layer generation.
34#
35# Additional members
36# prefixText - list of strings to prefix generated header with
37# (usually a copyright statement + calling convention macros).
38# protectFile - True if multiple inclusion protection should be
39# generated (based on the filename) around the entire header.
40# protectFeature - True if #ifndef..#endif protection should be
41# generated around a feature interface in the header file.
42# genFuncPointers - True if function pointer typedefs should be
43# generated
44# protectProto - If conditional protection should be generated
45# around prototype declarations, set to either '#ifdef'
46# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47# to require opt-out (#ifndef protectProtoStr). Otherwise
48# set to None.
49# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50# declarations, if protectProto is set
51# apicall - string to use for the function declaration prefix,
52# such as APICALL on Windows.
53# apientry - string to use for the calling convention macro,
54# in typedefs, such as APIENTRY.
55# apientryp - string to use for the calling convention macro
56# in function pointer typedefs, such as APIENTRYP.
57# indentFuncProto - True if prototype declarations should put each
58# parameter on a separate line
59# indentFuncPointer - True if typedefed function pointers should put each
60# parameter on a separate line
61# alignFuncParam - if nonzero and parameters are being put on a
62# separate line, align parameter names at the specified column
63class LayerChassisGeneratorOptions(GeneratorOptions):
64 def __init__(self,
65 filename = None,
66 directory = '.',
67 apiname = None,
68 profile = None,
69 versions = '.*',
70 emitversions = '.*',
71 defaultExtensions = None,
72 addExtensions = None,
73 removeExtensions = None,
74 emitExtensions = None,
75 sortProcedure = regSortFeatures,
76 prefixText = "",
77 genFuncPointers = True,
78 protectFile = True,
79 protectFeature = True,
80 apicall = '',
81 apientry = '',
82 apientryp = '',
83 indentFuncProto = True,
84 indentFuncPointer = False,
85 alignFuncParam = 0,
86 helper_file_type = '',
87 expandEnumerants = True):
88 GeneratorOptions.__init__(self, filename, directory, apiname, profile,
89 versions, emitversions, defaultExtensions,
90 addExtensions, removeExtensions, emitExtensions, sortProcedure)
91 self.prefixText = prefixText
92 self.genFuncPointers = genFuncPointers
93 self.protectFile = protectFile
94 self.protectFeature = protectFeature
95 self.apicall = apicall
96 self.apientry = apientry
97 self.apientryp = apientryp
98 self.indentFuncProto = indentFuncProto
99 self.indentFuncPointer = indentFuncPointer
100 self.alignFuncParam = alignFuncParam
101
102# LayerChassisOutputGenerator - subclass of OutputGenerator.
103# Generates a LayerFactory layer that intercepts all API entrypoints
104# This is intended to be used as a starting point for creating custom layers
105#
106# ---- methods ----
107# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
108# OutputGenerator. Defines additional internal state.
109# ---- methods overriding base class ----
110# beginFile(genOpts)
111# endFile()
112# beginFeature(interface, emit)
113# endFeature()
114# genType(typeinfo,name)
115# genStruct(typeinfo,name)
116# genGroup(groupinfo,name)
117# genEnum(enuminfo, name)
118# genCmd(cmdinfo)
119class LayerChassisOutputGenerator(OutputGenerator):
120 """Generate specified API interfaces in a specific style, such as a C header"""
121 # This is an ordered list of sections in the header file.
122 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
123 'group', 'bitmask', 'funcpointer', 'struct']
124 ALL_SECTIONS = TYPE_SECTIONS + ['command']
125
Mark 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
236// Layer chassis validation object base class definition
237class ValidationObject {
238 public:
239 uint32_t api_version;
240 debug_report_data* report_data = nullptr;
241 std::vector<VkDebugReportCallbackEXT> logging_callback;
242 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
243
244 VkLayerInstanceDispatchTable instance_dispatch_table;
245 VkLayerDispatchTable device_dispatch_table;
246
247 InstanceExtensions instance_extensions;
248 DeviceExtensions device_extensions = {};
249
250 VkInstance instance = VK_NULL_HANDLE;
251 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
252 VkDevice device = VK_NULL_HANDLE;
253
254 std::vector<ValidationObject*> object_dispatch;
255 LayerObjectTypeId container_type;
256
257 // Constructor
258 ValidationObject(){};
259 // Destructor
260 virtual ~ValidationObject() {};
261
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700262 std::mutex validation_object_mutex;
263 virtual void write_lock() { validation_object_mutex.lock(); }
264 virtual void write_unlock() { validation_object_mutex.unlock(); }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700265
266 std::string layer_name = "CHASSIS";
267
268 // Handle Wrapping Data
269 // Reverse map display handles
270 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
271 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
272 std::unordered_set<std::string> device_extension_set;
273 struct SubpassesUsageStates {
274 std::unordered_set<uint32_t> subpasses_using_color_attachment;
275 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
276 };
277 // Uses unwrapped handles
278 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
279 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
280 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
281 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700282 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
283 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700284
285
286 // Unwrap a handle. Must hold lock.
287 template <typename HandleType>
288 HandleType Unwrap(HandleType wrappedHandle) {
289 // TODO: don't use operator[] here.
290 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
291 }
292
293 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
294 template <typename HandleType>
295 HandleType WrapNew(HandleType newlyCreatedHandle) {
296 auto unique_id = global_unique_id++;
297 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
298 return (HandleType)unique_id;
299 }
300
301 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
302 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
303 auto unique_id = global_unique_id++;
304 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
305 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
306 return (VkDisplayKHR)unique_id;
307 }
308
309 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
310 // creating another. Must hold lock.
311 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
312 // See if this display is already known
313 auto it = map_data->display_id_reverse_mapping.find(handle);
314 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
315 // Unknown, so wrap
316 return WrapDisplay(handle, map_data);
317 }
318
319 // Pre/post hook point declarations
320"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600321
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700322 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600323// This file is ***GENERATED***. Do Not Edit.
324// See layer_chassis_generator.py for modifications.
325
326/* Copyright (c) 2015-2018 The Khronos Group Inc.
327 * Copyright (c) 2015-2018 Valve Corporation
328 * Copyright (c) 2015-2018 LunarG, Inc.
329 * Copyright (c) 2015-2018 Google Inc.
330 *
331 * Licensed under the Apache License, Version 2.0 (the "License");
332 * you may not use this file except in compliance with the License.
333 * You may obtain a copy of the License at
334 *
335 * http://www.apache.org/licenses/LICENSE-2.0
336 *
337 * Unless required by applicable law or agreed to in writing, software
338 * distributed under the License is distributed on an "AS IS" BASIS,
339 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
340 * See the License for the specific language governing permissions and
341 * limitations under the License.
342 *
343 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700344 */"""
345
346 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600347
348#include <string.h>
349#include <mutex>
350
351#define VALIDATION_ERROR_MAP_IMPL
352
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600353#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700354#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600355
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600356std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600357
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700358// Global unique object identifier. All increments must be guarded by a lock.
359uint64_t global_unique_id = 1;
360// Map uniqueID to actual object handle
361std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
362
363// TODO: This variable controls handle wrapping -- in the future it should be hooked
364// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
365#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
366bool wrap_handles = true;
367#else
368const bool wrap_handles = false;
369#endif
370
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600371// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700372#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600373#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700374#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700375#elif BUILD_THREAD_SAFETY
Mark Lobodzinski706e52b2018-12-11 13:21:52 -0700376#include "thread_safety.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700377#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
378#elif BUILD_PARAMETER_VALIDATION
379#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
380#elif BUILD_CORE_VALIDATION
381#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
382#else
383#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
384#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600385
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600386namespace vulkan_layer_chassis {
387
388using std::unordered_map;
389
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600390static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700391 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600392};
393
394static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
395
396extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
397
398
399// Manually written functions
400
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700401// Check enabled instance extensions against supported instance extension whitelist
402static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
403 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
404 // Check for recognized instance extensions
405 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
406 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
407 kVUIDUndefined,
408 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
409 "results and/or produce undefined behavior.",
410 pCreateInfo->ppEnabledExtensionNames[i]);
411 }
412 }
413}
414
415// Check enabled device extensions against supported device extension whitelist
416static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
417 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
418 // Check for recognized device extensions
419 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
420 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
421 kVUIDUndefined,
422 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
423 "results and/or produce undefined behavior.",
424 pCreateInfo->ppEnabledExtensionNames[i]);
425 }
426 }
427}
428
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600429VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600430 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700431 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extension_set)) {
432 return nullptr;
433 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600434 const auto &item = name_to_funcptr_map.find(funcName);
435 if (item != name_to_funcptr_map.end()) {
436 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
437 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600438 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600439 if (!table.GetDeviceProcAddr) return nullptr;
440 return table.GetDeviceProcAddr(device, funcName);
441}
442
443VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600444 const auto &item = name_to_funcptr_map.find(funcName);
445 if (item != name_to_funcptr_map.end()) {
446 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
447 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600448 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
449 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600450 if (!table.GetInstanceProcAddr) return nullptr;
451 return table.GetInstanceProcAddr(instance, funcName);
452}
453
454VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600455 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
456 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600457 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
458 return table.GetPhysicalDeviceProcAddr(instance, funcName);
459}
460
461VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
462 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
463}
464
465VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
466 VkLayerProperties *pProperties) {
467 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
468}
469
470VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
471 VkExtensionProperties *pProperties) {
472 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
473 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
474
475 return VK_ERROR_LAYER_NOT_PRESENT;
476}
477
478VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
479 uint32_t *pCount, VkExtensionProperties *pProperties) {
480 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600481 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600482 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
483 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600484}
485
486VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
487 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600488 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600489
490 assert(chain_info->u.pLayerInfo);
491 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
492 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
493 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
494 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
495
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600496 // Create temporary dispatch vector for pre-calls until instance is created
497 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700498#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600499 auto object_tracker = new ObjectLifetimes;
500 local_object_dispatch.emplace_back(object_tracker);
501 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700502#elif BUILD_THREAD_SAFETY
503 auto thread_checker = new ThreadSafety;
504 local_object_dispatch.emplace_back(thread_checker);
505 thread_checker->container_type = LayerObjectTypeThreading;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700506#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600507
508
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600509 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600510 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600511 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
512 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600513 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600514 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
515 }
516
517 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600518 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600519
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600520 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600521
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600522 framework->object_dispatch = local_object_dispatch;
523
524 framework->instance = *pInstance;
525 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
526 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
527 pCreateInfo->ppEnabledExtensionNames);
528 framework->api_version = framework->instance_extensions.InitFromInstanceCreateInfo(
529 (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0), pCreateInfo);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700530#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600531 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700532#elif BUILD_THREAD_SAFETY
533 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "google_thread_checker");
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700534#else
535 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
536#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600537
538 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600539 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
540 }
541
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700542 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
543
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600544 return result;
545}
546
547VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
548 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600549 auto layer_data = GetLayerDataPtr(key, layer_data_map);
550 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700551 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600552 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700553 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600554 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600555 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700556 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600557 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700558 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600559 }
560
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600561 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600562
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600563 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700564 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600565 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700566 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600567 }
568 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600569 while (layer_data->logging_messenger.size() > 0) {
570 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
571 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
572 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600573 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600574 while (layer_data->logging_callback.size() > 0) {
575 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
576 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
577 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600578 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600579
580 layer_debug_utils_destroy_instance(layer_data->report_data);
581
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700582 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
583 delete *item;
584 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600585 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600586}
587
588VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
589 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600590 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600591
592 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
593
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600594 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
595 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600596 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
597 if (fpCreateDevice == NULL) {
598 return VK_ERROR_INITIALIZATION_FAILED;
599 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600600 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
601
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600602 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700603 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600604 intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700605 intercept->write_unlock();
606
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600607 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600608 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700609 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600610 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700611 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600612 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600613
614 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600615 if (result != VK_SUCCESS) {
616 return result;
617 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600618
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600619 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
620 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700621 // Save pCreateInfo device extension list for GetDeviceProcAddr()
622 for (uint32_t extn = 0; extn < pCreateInfo->enabledExtensionCount; extn++) {
623 device_interceptor->device_extension_set.insert(pCreateInfo->ppEnabledExtensionNames[extn]);
624 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600625 device_interceptor->device = *pDevice;
626 device_interceptor->physical_device = gpu;
627 device_interceptor->instance = instance_interceptor->instance;
628 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
629 device_interceptor->api_version = instance_interceptor->api_version;
630
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700631#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600632 // Create child layer objects for this key and add to dispatch vector
633 auto object_tracker = new ObjectLifetimes;
634 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
635 object_tracker->container_type = LayerObjectTypeObjectTracker;
636 object_tracker->physical_device = gpu;
637 object_tracker->instance = instance_interceptor->instance;
638 object_tracker->report_data = device_interceptor->report_data;
639 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
640 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700641#elif BUILD_THREAD_SAFETY
642 auto thread_safety = new ThreadSafety;
643 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
644 thread_safety->container_type = LayerObjectTypeThreading;
645 thread_safety->physical_device = gpu;
646 thread_safety->instance = instance_interceptor->instance;
647 thread_safety->report_data = device_interceptor->report_data;
648 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
649 device_interceptor->object_dispatch.emplace_back(thread_safety);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700650#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600651
652 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700653 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600654 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700655 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600656 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600657
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700658 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
659
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600660 return result;
661}
662
663VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
664 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600665 auto layer_data = GetLayerDataPtr(key, layer_data_map);
666 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700667 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600668 intercept->PreCallValidateDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700669 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600670 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600671 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700672 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600673 intercept->PreCallRecordDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700674 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600675 }
676 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600677
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600678 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600679
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600680 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700681 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600682 intercept->PostCallRecordDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700683 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600684 }
685
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700686 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
687 delete *item;
688 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600689 FreeLayerDataPtr(key, layer_data_map);
690}
691
692VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
693 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
694 const VkAllocationCallbacks *pAllocator,
695 VkDebugReportCallbackEXT *pCallback) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600696 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
697 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700698 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600699 intercept->PreCallValidateCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700700 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600701 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600702 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700703 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600704 intercept->PreCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700705 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600706 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700707 VkResult result = DispatchCreateDebugReportCallbackEXT(layer_data, instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600708 result = layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);
709 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700710 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600711 intercept->PostCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700712 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600713 }
714 return result;
715}
716
717VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
718 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600719 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
720 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700721 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600722 intercept->PreCallValidateDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700723 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600724 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600725 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700726 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600727 intercept->PreCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700728 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600729 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700730 DispatchDestroyDebugReportCallbackEXT(layer_data, instance, callback, pAllocator);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600731 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
732 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700733 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600734 intercept->PostCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700735 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600736 }
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700737}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600738
739 inline_custom_source_postamble = """
740// loader-layer interface v0, just wrappers since there is only a layer
741
742VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
743 VkExtensionProperties *pProperties) {
744 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
745}
746
747VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
748 VkLayerProperties *pProperties) {
749 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
750}
751
752VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
753 VkLayerProperties *pProperties) {
754 // the layer command handles VK_NULL_HANDLE just fine internally
755 assert(physicalDevice == VK_NULL_HANDLE);
756 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
757}
758
759VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
760 const char *pLayerName, uint32_t *pCount,
761 VkExtensionProperties *pProperties) {
762 // the layer command handles VK_NULL_HANDLE just fine internally
763 assert(physicalDevice == VK_NULL_HANDLE);
764 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
765}
766
767VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
768 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
769}
770
771VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
772 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
773}
774
775VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
776 const char *funcName) {
777 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
778}
779
780VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
781 assert(pVersionStruct != NULL);
782 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
783
784 // Fill in the function pointers if our version is at least capable of having the structure contain them.
785 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
786 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
787 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
788 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
789 }
790
791 return VK_SUCCESS;
792}"""
793
794
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600795 def __init__(self,
796 errFile = sys.stderr,
797 warnFile = sys.stderr,
798 diagFile = sys.stdout):
799 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
800 # Internal state - accumulators for different inner block text
801 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
802 self.intercepts = []
803 self.layer_factory = '' # String containing base layer factory class definition
804
805 # Check if the parameter passed in is a pointer to an array
806 def paramIsArray(self, param):
807 return param.attrib.get('len') is not None
808
809 # Check if the parameter passed in is a pointer
810 def paramIsPointer(self, param):
811 ispointer = False
812 for elem in param:
813 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
814 ispointer = True
815 return ispointer
816
817 # Check if an object is a non-dispatchable handle
818 def isHandleTypeNonDispatchable(self, handletype):
819 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
820 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
821 return True
822 else:
823 return False
824
825 # Check if an object is a dispatchable handle
826 def isHandleTypeDispatchable(self, handletype):
827 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
828 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
829 return True
830 else:
831 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700832 #
833 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600834 def beginFile(self, genOpts):
835 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700836 # Output Copyright
837 write(self.inline_copyright_message, file=self.outFile)
838 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600839 self.header = False
840 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
841 self.header = True
842 write('#pragma once', file=self.outFile)
843 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600844 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700845 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600846 else:
847 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700848 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700849 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600850 #
851 def endFile(self):
852 # Finish C++ namespace and multiple inclusion protection
853 self.newline()
854 if not self.header:
855 # Record intercepted procedures
856 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
857 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
858 write('\n'.join(self.intercepts), file=self.outFile)
859 write('};\n', file=self.outFile)
860 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600861 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600862 if self.header:
863 self.newline()
864 # Output Layer Factory Class Definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600865 self.layer_factory += '};\n\n'
866 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600867 write(self.layer_factory, file=self.outFile)
868 else:
869 write(self.inline_custom_source_postamble, file=self.outFile)
870 # Finish processing in superclass
871 OutputGenerator.endFile(self)
872
873 def beginFeature(self, interface, emit):
874 # Start processing in superclass
875 OutputGenerator.beginFeature(self, interface, emit)
876 # Get feature extra protect
877 self.featureExtraProtect = GetFeatureProtect(interface)
878 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
879 # feature. They're only printed in endFeature().
880 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
881
882 def endFeature(self):
883 # Actually write the interface to the output file.
884 if (self.emit):
885 self.newline()
886 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
887 # or move it below the 'for section...' loop.
888 if (self.featureExtraProtect != None):
889 write('#ifdef', self.featureExtraProtect, file=self.outFile)
890 for section in self.TYPE_SECTIONS:
891 contents = self.sections[section]
892 if contents:
893 write('\n'.join(contents), file=self.outFile)
894 self.newline()
895 if (self.sections['command']):
896 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
897 self.newline()
898 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600899 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600900 # Finish processing in superclass
901 OutputGenerator.endFeature(self)
902 #
903 # Append a definition to the specified section
904 def appendSection(self, section, text):
905 self.sections[section].append(text)
906 #
907 # Type generation
908 def genType(self, typeinfo, name, alias):
909 pass
910 #
911 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
912 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
913 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
914 # structs etc.)
915 def genStruct(self, typeinfo, typeName):
916 OutputGenerator.genStruct(self, typeinfo, typeName)
917 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
918 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
919 for member in typeinfo.elem.findall('.//member'):
920 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
921 body += ';\n'
922 body += '} ' + typeName + ';\n'
923 self.appendSection('struct', body)
924 #
925 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
926 def genGroup(self, groupinfo, groupName, alias):
927 pass
928 # Enumerant generation
929 # <enum> tags may specify their values in several ways, but are usually just integers.
930 def genEnum(self, enuminfo, name, alias):
931 pass
932 #
933 # Customize Cdecl for layer factory base class
934 def BaseClassCdecl(self, elem, name):
935 raw = self.makeCDecls(elem)[1]
936
937 # Toss everything before the undecorated name
938 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
939 prototype = prototype.replace(")", "", 1)
940 prototype = prototype.replace(";", " {};")
941
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600942 # Build up pre/post call virtual function declarations
943 pre_call_validate = 'virtual bool PreCallValidate' + prototype
944 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
945 pre_call_record = 'virtual void PreCallRecord' + prototype
946 post_call_record = 'virtual void PostCallRecord' + prototype
947 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
948 #
949 # Command generation
950 def genCmd(self, cmdinfo, name, alias):
951 ignore_functions = [
952 'vkEnumerateInstanceVersion'
953 ]
954
955 if name in ignore_functions:
956 return
957
958 if self.header: # In the header declare all intercepts
959 self.appendSection('command', '')
960 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
961 if (self.featureExtraProtect != None):
962 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
963 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
964 # Update base class with virtual function declarations
965 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
966 # Update function intercepts
967 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
968 if (self.featureExtraProtect != None):
969 self.intercepts += [ '#endif' ]
970 self.layer_factory += '#endif\n'
971 return
972
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700973 if name in self.manual_functions:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600974 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
975 return
976 # Record that the function will be intercepted
977 if (self.featureExtraProtect != None):
978 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
979 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
980 if (self.featureExtraProtect != None):
981 self.intercepts += [ '#endif' ]
982 OutputGenerator.genCmd(self, cmdinfo, name, alias)
983 #
984 decls = self.makeCDecls(cmdinfo.elem)
985 self.appendSection('command', '')
986 self.appendSection('command', '%s {' % decls[0][:-1])
987 # Setup common to call wrappers. First parameter is always dispatchable
988 dispatchable_type = cmdinfo.elem.find('param/type').text
989 dispatchable_name = cmdinfo.elem.find('param/name').text
990 # Default to device
991 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600992 dispatch_table_name = 'VkLayerDispatchTable'
993 # Set to instance as necessary
994 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
995 device_or_instance = 'instance'
996 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600997 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600998 api_function_name = cmdinfo.elem.attrib.get('name')
999 params = cmdinfo.elem.findall('param/name')
1000 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001001 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001002
1003 # Declare result variable, if any.
1004 return_map = {
1005 'void': 'return;',
1006 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1007 'PFN_vkVoidFunction': 'return nullptr;',
1008 'VkBool32': 'return VK_FALSE;',
1009 }
1010 resulttype = cmdinfo.elem.find('proto/type')
1011 assignresult = ''
1012 if (resulttype.text != 'void'):
1013 assignresult = resulttype.text + ' result = '
1014
1015 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001016 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001017
1018 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001019 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001020 self.appendSection('command', ' intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001021 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001022 self.appendSection('command', ' intercept->write_unlock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001023 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1024 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001025
1026 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001027 self.appendSection('command', ' %s' % self.precallrecord_loop)
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001028 self.appendSection('command', ' intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001029 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001030 self.appendSection('command', ' intercept->write_unlock();')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001031 self.appendSection('command', ' }')
1032
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001033 # Insert pre-dispatch debug utils function call
1034 if name in self.pre_dispatch_debug_utils_functions:
1035 self.appendSection('command', ' {')
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001036 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->validation_object_mutex);')
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001037 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
1038 self.appendSection('command', ' }')
1039
1040 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001041 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001042
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001043 # Insert post-dispatch debug utils function call
1044 if name in self.post_dispatch_debug_utils_functions:
1045 self.appendSection('command', ' {')
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001046 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->validation_object_mutex);')
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001047 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
1048 self.appendSection('command', ' }')
1049
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001050 # Generate post-call object processing source code
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001051 return_type_indent = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001052 if (resulttype.text == 'VkResult'):
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001053 return_type_indent = ' '
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001054 if name in self.alt_ret_codes:
Mark Lobodzinskib3c94842018-11-27 10:01:51 -07001055 self.appendSection('command', ' if ((VK_SUCCESS == result) || (VK_INCOMPLETE == result)) {')
1056 else:
1057 self.appendSection('command', ' if (VK_SUCCESS == result) {')
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001058
1059 self.appendSection('command', '%s %s' % (return_type_indent, self.postcallrecord_loop))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001060 self.appendSection('command', '%s intercept->write_lock();' % return_type_indent)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001061 self.appendSection('command', '%s intercept->PostCallRecord%s(%s);' % (return_type_indent,api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001062 self.appendSection('command', '%s intercept->write_unlock();' % return_type_indent)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001063 self.appendSection('command', '%s }' % return_type_indent)
1064 if (resulttype.text == 'VkResult'):
1065 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001066
1067 # Return result variable, if any.
1068 if (resulttype.text != 'void'):
1069 self.appendSection('command', ' return result;')
1070 self.appendSection('command', '}')
1071 #
1072 # Override makeProtoName to drop the "vk" prefix
1073 def makeProtoName(self, name, tail):
1074 return self.genOpts.apientry + name[2:] + tail