blob: 9ee1e4435df25f879f1b591fb6e35312224a4ebc [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
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
273 std::string layer_name = "CHASSIS";
274
275 // Handle Wrapping Data
276 // Reverse map display handles
277 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
278 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700279 struct SubpassesUsageStates {
280 std::unordered_set<uint32_t> subpasses_using_color_attachment;
281 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
282 };
283 // Uses unwrapped handles
284 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
285 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
286 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
287 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700288 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
289 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700290
291
292 // Unwrap a handle. Must hold lock.
293 template <typename HandleType>
294 HandleType Unwrap(HandleType wrappedHandle) {
295 // TODO: don't use operator[] here.
296 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
297 }
298
299 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
300 template <typename HandleType>
301 HandleType WrapNew(HandleType newlyCreatedHandle) {
302 auto unique_id = global_unique_id++;
303 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
304 return (HandleType)unique_id;
305 }
306
307 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
308 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
309 auto unique_id = global_unique_id++;
310 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
311 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
312 return (VkDisplayKHR)unique_id;
313 }
314
315 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
316 // creating another. Must hold lock.
317 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
318 // See if this display is already known
319 auto it = map_data->display_id_reverse_mapping.find(handle);
320 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
321 // Unknown, so wrap
322 return WrapDisplay(handle, map_data);
323 }
324
325 // Pre/post hook point declarations
326"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600327
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700328 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600329// This file is ***GENERATED***. Do Not Edit.
330// See layer_chassis_generator.py for modifications.
331
332/* Copyright (c) 2015-2018 The Khronos Group Inc.
333 * Copyright (c) 2015-2018 Valve Corporation
334 * Copyright (c) 2015-2018 LunarG, Inc.
335 * Copyright (c) 2015-2018 Google Inc.
336 *
337 * Licensed under the Apache License, Version 2.0 (the "License");
338 * you may not use this file except in compliance with the License.
339 * You may obtain a copy of the License at
340 *
341 * http://www.apache.org/licenses/LICENSE-2.0
342 *
343 * Unless required by applicable law or agreed to in writing, software
344 * distributed under the License is distributed on an "AS IS" BASIS,
345 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
346 * See the License for the specific language governing permissions and
347 * limitations under the License.
348 *
349 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700350 */"""
351
352 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600353
354#include <string.h>
355#include <mutex>
356
357#define VALIDATION_ERROR_MAP_IMPL
358
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600359#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700360#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600361
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600362std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600363
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700364// Global unique object identifier. All increments must be guarded by a lock.
365uint64_t global_unique_id = 1;
366// Map uniqueID to actual object handle
367std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
368
369// TODO: This variable controls handle wrapping -- in the future it should be hooked
370// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
371#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
372bool wrap_handles = true;
373#else
374const bool wrap_handles = false;
375#endif
376
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600377// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700378#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600379#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700380#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700381#elif BUILD_THREAD_SAFETY
Mark Lobodzinski706e52b2018-12-11 13:21:52 -0700382#include "thread_safety.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700383#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
384#elif BUILD_PARAMETER_VALIDATION
385#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
386#elif BUILD_CORE_VALIDATION
387#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
388#else
389#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
390#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600391
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600392namespace vulkan_layer_chassis {
393
394using std::unordered_map;
395
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600396static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700397 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600398};
399
400static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
401
402extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
403
404
405// Manually written functions
406
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700407// Check enabled instance extensions against supported instance extension whitelist
408static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
409 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
410 // Check for recognized instance extensions
411 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
412 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
413 kVUIDUndefined,
414 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
415 "results and/or produce undefined behavior.",
416 pCreateInfo->ppEnabledExtensionNames[i]);
417 }
418 }
419}
420
421// Check enabled device extensions against supported device extension whitelist
422static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
423 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
424 // Check for recognized device extensions
425 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
426 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
427 kVUIDUndefined,
428 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
429 "results and/or produce undefined behavior.",
430 pCreateInfo->ppEnabledExtensionNames[i]);
431 }
432 }
433}
434
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600435VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600436 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700437 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700438 return nullptr;
439 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600440 const auto &item = name_to_funcptr_map.find(funcName);
441 if (item != name_to_funcptr_map.end()) {
442 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
443 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600444 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600445 if (!table.GetDeviceProcAddr) return nullptr;
446 return table.GetDeviceProcAddr(device, funcName);
447}
448
449VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
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 layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
455 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600456 if (!table.GetInstanceProcAddr) return nullptr;
457 return table.GetInstanceProcAddr(instance, funcName);
458}
459
460VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600461 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
462 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600463 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
464 return table.GetPhysicalDeviceProcAddr(instance, funcName);
465}
466
467VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
468 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
469}
470
471VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
472 VkLayerProperties *pProperties) {
473 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
474}
475
476VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
477 VkExtensionProperties *pProperties) {
478 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
479 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
480
481 return VK_ERROR_LAYER_NOT_PRESENT;
482}
483
484VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
485 uint32_t *pCount, VkExtensionProperties *pProperties) {
486 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600487 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600488 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
489 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600490}
491
492VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
493 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600494 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600495
496 assert(chain_info->u.pLayerInfo);
497 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
498 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
499 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
500 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
501
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600502 // Create temporary dispatch vector for pre-calls until instance is created
503 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700504#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600505 auto object_tracker = new ObjectLifetimes;
506 local_object_dispatch.emplace_back(object_tracker);
507 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700508#elif BUILD_THREAD_SAFETY
509 auto thread_checker = new ThreadSafety;
510 local_object_dispatch.emplace_back(thread_checker);
511 thread_checker->container_type = LayerObjectTypeThreading;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700512#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600513
514
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600515 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600516 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600517 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
518 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600519 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600520 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
521 }
522
523 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600524 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600525
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600526 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600527
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600528 framework->object_dispatch = local_object_dispatch;
529
530 framework->instance = *pInstance;
531 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
532 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
533 pCreateInfo->ppEnabledExtensionNames);
534 framework->api_version = framework->instance_extensions.InitFromInstanceCreateInfo(
535 (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0), pCreateInfo);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700536#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600537 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700538#elif BUILD_THREAD_SAFETY
539 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "google_thread_checker");
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700540#else
541 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
542#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600543
544 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600545 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
546 }
547
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700548 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
549
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600550 return result;
551}
552
553VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
554 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600555 auto layer_data = GetLayerDataPtr(key, layer_data_map);
556 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700557 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600558 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700559 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600560 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600561 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700562 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600563 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700564 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600565 }
566
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600567 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600568
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600569 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700570 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600571 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700572 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600573 }
574 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600575 while (layer_data->logging_messenger.size() > 0) {
576 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
577 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
578 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600579 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600580 while (layer_data->logging_callback.size() > 0) {
581 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
582 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
583 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600584 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600585
586 layer_debug_utils_destroy_instance(layer_data->report_data);
587
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700588 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
589 delete *item;
590 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600591 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600592}
593
594VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
595 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600596 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600597
598 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
599
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600600 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
601 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600602 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
603 if (fpCreateDevice == NULL) {
604 return VK_ERROR_INITIALIZATION_FAILED;
605 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600606 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
607
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->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700611 intercept->write_unlock();
612
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600613 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600614 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700615 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600616 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700617 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600618 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600619
620 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600621 if (result != VK_SUCCESS) {
622 return result;
623 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600624
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600625 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700626
627 // Get physical device limits for device
628 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(
629 gpu, &(device_interceptor->phys_dev_properties.properties));
630
631 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
632 uint32_t effective_api_version = std::min(device_interceptor->api_version, instance_interceptor->api_version);
633 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
634 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
635
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600636 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700637
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600638 device_interceptor->device = *pDevice;
639 device_interceptor->physical_device = gpu;
640 device_interceptor->instance = instance_interceptor->instance;
641 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
642 device_interceptor->api_version = instance_interceptor->api_version;
643
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700644#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600645 // Create child layer objects for this key and add to dispatch vector
646 auto object_tracker = new ObjectLifetimes;
647 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
648 object_tracker->container_type = LayerObjectTypeObjectTracker;
649 object_tracker->physical_device = gpu;
650 object_tracker->instance = instance_interceptor->instance;
651 object_tracker->report_data = device_interceptor->report_data;
652 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
653 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700654#elif BUILD_THREAD_SAFETY
655 auto thread_safety = new ThreadSafety;
656 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
657 thread_safety->container_type = LayerObjectTypeThreading;
658 thread_safety->physical_device = gpu;
659 thread_safety->instance = instance_interceptor->instance;
660 thread_safety->report_data = device_interceptor->report_data;
661 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
662 device_interceptor->object_dispatch.emplace_back(thread_safety);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700663#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600664
665 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700666 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600667 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700668 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600669 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600670
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700671 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
672
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600673 return result;
674}
675
676VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
677 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600678 auto layer_data = GetLayerDataPtr(key, layer_data_map);
679 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700680 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600681 intercept->PreCallValidateDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700682 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600683 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600684 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700685 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600686 intercept->PreCallRecordDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700687 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600688 }
689 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600690
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600691 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600692
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600693 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700694 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600695 intercept->PostCallRecordDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700696 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600697 }
698
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700699 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
700 delete *item;
701 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600702 FreeLayerDataPtr(key, layer_data_map);
703}
704
705VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
706 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
707 const VkAllocationCallbacks *pAllocator,
708 VkDebugReportCallbackEXT *pCallback) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600709 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
710 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700711 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600712 intercept->PreCallValidateCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700713 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600714 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600715 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700716 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600717 intercept->PreCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700718 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600719 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700720 VkResult result = DispatchCreateDebugReportCallbackEXT(layer_data, instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600721 result = layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);
722 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700723 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600724 intercept->PostCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700725 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600726 }
727 return result;
728}
729
730VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
731 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600732 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
733 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700734 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600735 intercept->PreCallValidateDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700736 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600737 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600738 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700739 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600740 intercept->PreCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700741 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600742 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700743 DispatchDestroyDebugReportCallbackEXT(layer_data, instance, callback, pAllocator);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600744 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
745 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700746 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600747 intercept->PostCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700748 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600749 }
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700750}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600751
752 inline_custom_source_postamble = """
753// loader-layer interface v0, just wrappers since there is only a layer
754
755VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
756 VkExtensionProperties *pProperties) {
757 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
758}
759
760VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
761 VkLayerProperties *pProperties) {
762 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
763}
764
765VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
766 VkLayerProperties *pProperties) {
767 // the layer command handles VK_NULL_HANDLE just fine internally
768 assert(physicalDevice == VK_NULL_HANDLE);
769 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
770}
771
772VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
773 const char *pLayerName, uint32_t *pCount,
774 VkExtensionProperties *pProperties) {
775 // the layer command handles VK_NULL_HANDLE just fine internally
776 assert(physicalDevice == VK_NULL_HANDLE);
777 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
778}
779
780VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
781 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
782}
783
784VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
785 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
786}
787
788VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
789 const char *funcName) {
790 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
791}
792
793VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
794 assert(pVersionStruct != NULL);
795 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
796
797 // Fill in the function pointers if our version is at least capable of having the structure contain them.
798 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
799 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
800 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
801 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
802 }
803
804 return VK_SUCCESS;
805}"""
806
807
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600808 def __init__(self,
809 errFile = sys.stderr,
810 warnFile = sys.stderr,
811 diagFile = sys.stdout):
812 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
813 # Internal state - accumulators for different inner block text
814 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
815 self.intercepts = []
816 self.layer_factory = '' # String containing base layer factory class definition
817
818 # Check if the parameter passed in is a pointer to an array
819 def paramIsArray(self, param):
820 return param.attrib.get('len') is not None
821
822 # Check if the parameter passed in is a pointer
823 def paramIsPointer(self, param):
824 ispointer = False
825 for elem in param:
826 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
827 ispointer = True
828 return ispointer
829
830 # Check if an object is a non-dispatchable handle
831 def isHandleTypeNonDispatchable(self, handletype):
832 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
833 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
834 return True
835 else:
836 return False
837
838 # Check if an object is a dispatchable handle
839 def isHandleTypeDispatchable(self, handletype):
840 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
841 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
842 return True
843 else:
844 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700845 #
846 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600847 def beginFile(self, genOpts):
848 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700849 # Output Copyright
850 write(self.inline_copyright_message, file=self.outFile)
851 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600852 self.header = False
853 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
854 self.header = True
855 write('#pragma once', file=self.outFile)
856 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600857 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700858 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600859 else:
860 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700861 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700862 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600863 #
864 def endFile(self):
865 # Finish C++ namespace and multiple inclusion protection
866 self.newline()
867 if not self.header:
868 # Record intercepted procedures
869 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
870 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
871 write('\n'.join(self.intercepts), file=self.outFile)
872 write('};\n', file=self.outFile)
873 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600874 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600875 if self.header:
876 self.newline()
877 # Output Layer Factory Class Definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600878 self.layer_factory += '};\n\n'
879 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600880 write(self.layer_factory, file=self.outFile)
881 else:
882 write(self.inline_custom_source_postamble, file=self.outFile)
883 # Finish processing in superclass
884 OutputGenerator.endFile(self)
885
886 def beginFeature(self, interface, emit):
887 # Start processing in superclass
888 OutputGenerator.beginFeature(self, interface, emit)
889 # Get feature extra protect
890 self.featureExtraProtect = GetFeatureProtect(interface)
891 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
892 # feature. They're only printed in endFeature().
893 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
894
895 def endFeature(self):
896 # Actually write the interface to the output file.
897 if (self.emit):
898 self.newline()
899 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
900 # or move it below the 'for section...' loop.
901 if (self.featureExtraProtect != None):
902 write('#ifdef', self.featureExtraProtect, file=self.outFile)
903 for section in self.TYPE_SECTIONS:
904 contents = self.sections[section]
905 if contents:
906 write('\n'.join(contents), file=self.outFile)
907 self.newline()
908 if (self.sections['command']):
909 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
910 self.newline()
911 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600912 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600913 # Finish processing in superclass
914 OutputGenerator.endFeature(self)
915 #
916 # Append a definition to the specified section
917 def appendSection(self, section, text):
918 self.sections[section].append(text)
919 #
920 # Type generation
921 def genType(self, typeinfo, name, alias):
922 pass
923 #
924 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
925 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
926 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
927 # structs etc.)
928 def genStruct(self, typeinfo, typeName):
929 OutputGenerator.genStruct(self, typeinfo, typeName)
930 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
931 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
932 for member in typeinfo.elem.findall('.//member'):
933 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
934 body += ';\n'
935 body += '} ' + typeName + ';\n'
936 self.appendSection('struct', body)
937 #
938 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
939 def genGroup(self, groupinfo, groupName, alias):
940 pass
941 # Enumerant generation
942 # <enum> tags may specify their values in several ways, but are usually just integers.
943 def genEnum(self, enuminfo, name, alias):
944 pass
945 #
946 # Customize Cdecl for layer factory base class
947 def BaseClassCdecl(self, elem, name):
948 raw = self.makeCDecls(elem)[1]
949
950 # Toss everything before the undecorated name
951 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
952 prototype = prototype.replace(")", "", 1)
953 prototype = prototype.replace(";", " {};")
954
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600955 # Build up pre/post call virtual function declarations
956 pre_call_validate = 'virtual bool PreCallValidate' + prototype
957 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
958 pre_call_record = 'virtual void PreCallRecord' + prototype
959 post_call_record = 'virtual void PostCallRecord' + prototype
960 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
961 #
962 # Command generation
963 def genCmd(self, cmdinfo, name, alias):
964 ignore_functions = [
965 'vkEnumerateInstanceVersion'
966 ]
967
968 if name in ignore_functions:
969 return
970
971 if self.header: # In the header declare all intercepts
972 self.appendSection('command', '')
973 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
974 if (self.featureExtraProtect != None):
975 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
976 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
977 # Update base class with virtual function declarations
978 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
979 # Update function intercepts
980 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
981 if (self.featureExtraProtect != None):
982 self.intercepts += [ '#endif' ]
983 self.layer_factory += '#endif\n'
984 return
985
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700986 if name in self.manual_functions:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600987 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
988 return
989 # Record that the function will be intercepted
990 if (self.featureExtraProtect != None):
991 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
992 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
993 if (self.featureExtraProtect != None):
994 self.intercepts += [ '#endif' ]
995 OutputGenerator.genCmd(self, cmdinfo, name, alias)
996 #
997 decls = self.makeCDecls(cmdinfo.elem)
998 self.appendSection('command', '')
999 self.appendSection('command', '%s {' % decls[0][:-1])
1000 # Setup common to call wrappers. First parameter is always dispatchable
1001 dispatchable_type = cmdinfo.elem.find('param/type').text
1002 dispatchable_name = cmdinfo.elem.find('param/name').text
1003 # Default to device
1004 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001005 dispatch_table_name = 'VkLayerDispatchTable'
1006 # Set to instance as necessary
1007 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1008 device_or_instance = 'instance'
1009 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001010 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001011 api_function_name = cmdinfo.elem.attrib.get('name')
1012 params = cmdinfo.elem.findall('param/name')
1013 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001014 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001015
1016 # Declare result variable, if any.
1017 return_map = {
1018 'void': 'return;',
1019 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1020 'PFN_vkVoidFunction': 'return nullptr;',
1021 'VkBool32': 'return VK_FALSE;',
1022 }
1023 resulttype = cmdinfo.elem.find('proto/type')
1024 assignresult = ''
1025 if (resulttype.text != 'void'):
1026 assignresult = resulttype.text + ' result = '
1027
1028 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001029 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001030
1031 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001032 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001033 self.appendSection('command', ' intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001034 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001035 self.appendSection('command', ' intercept->write_unlock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001036 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1037 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001038
1039 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001040 self.appendSection('command', ' %s' % self.precallrecord_loop)
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001041 self.appendSection('command', ' intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001042 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001043 self.appendSection('command', ' intercept->write_unlock();')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001044 self.appendSection('command', ' }')
1045
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001046 # Insert pre-dispatch debug utils function call
1047 if name in self.pre_dispatch_debug_utils_functions:
1048 self.appendSection('command', ' {')
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001049 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->validation_object_mutex);')
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001050 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
1051 self.appendSection('command', ' }')
1052
1053 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001054 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001055
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001056 # Insert post-dispatch debug utils function call
1057 if name in self.post_dispatch_debug_utils_functions:
1058 self.appendSection('command', ' {')
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001059 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->validation_object_mutex);')
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001060 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
1061 self.appendSection('command', ' }')
1062
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001063 # Generate post-call object processing source code
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001064 return_type_indent = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001065 if (resulttype.text == 'VkResult'):
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001066 return_type_indent = ' '
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001067 if name in self.alt_ret_codes:
Mark Lobodzinskib3c94842018-11-27 10:01:51 -07001068 self.appendSection('command', ' if ((VK_SUCCESS == result) || (VK_INCOMPLETE == result)) {')
1069 else:
1070 self.appendSection('command', ' if (VK_SUCCESS == result) {')
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001071
1072 self.appendSection('command', '%s %s' % (return_type_indent, self.postcallrecord_loop))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001073 self.appendSection('command', '%s intercept->write_lock();' % return_type_indent)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001074 self.appendSection('command', '%s intercept->PostCallRecord%s(%s);' % (return_type_indent,api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001075 self.appendSection('command', '%s intercept->write_unlock();' % return_type_indent)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001076 self.appendSection('command', '%s }' % return_type_indent)
1077 if (resulttype.text == 'VkResult'):
1078 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001079
1080 # Return result variable, if any.
1081 if (resulttype.text != 'void'):
1082 self.appendSection('command', ' return result;')
1083 self.appendSection('command', '}')
1084 #
1085 # Override makeProtoName to drop the "vk" prefix
1086 def makeProtoName(self, name, tail):
1087 return self.genOpts.apientry + name[2:] + tail