blob: d1744dc2427f659bed3e4284056b8af17b27bac8 [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
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700273 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
274 for (auto validation_object : object_dispatch) {
275 if (validation_object->container_type == object_type) {
276 return validation_object;
277 }
278 }
279 return nullptr;
280 };
281
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700282 std::string layer_name = "CHASSIS";
283
284 // Handle Wrapping Data
285 // Reverse map display handles
286 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
287 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700288 struct SubpassesUsageStates {
289 std::unordered_set<uint32_t> subpasses_using_color_attachment;
290 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
291 };
292 // Uses unwrapped handles
293 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
294 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
295 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
296 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700297 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
298 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700299
300
301 // Unwrap a handle. Must hold lock.
302 template <typename HandleType>
303 HandleType Unwrap(HandleType wrappedHandle) {
304 // TODO: don't use operator[] here.
305 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
306 }
307
308 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
309 template <typename HandleType>
310 HandleType WrapNew(HandleType newlyCreatedHandle) {
311 auto unique_id = global_unique_id++;
312 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
313 return (HandleType)unique_id;
314 }
315
316 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
317 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
318 auto unique_id = global_unique_id++;
319 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
320 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
321 return (VkDisplayKHR)unique_id;
322 }
323
324 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
325 // creating another. Must hold lock.
326 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
327 // See if this display is already known
328 auto it = map_data->display_id_reverse_mapping.find(handle);
329 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
330 // Unknown, so wrap
331 return WrapDisplay(handle, map_data);
332 }
333
334 // Pre/post hook point declarations
335"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600336
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700337 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600338// This file is ***GENERATED***. Do Not Edit.
339// See layer_chassis_generator.py for modifications.
340
341/* Copyright (c) 2015-2018 The Khronos Group Inc.
342 * Copyright (c) 2015-2018 Valve Corporation
343 * Copyright (c) 2015-2018 LunarG, Inc.
344 * Copyright (c) 2015-2018 Google Inc.
345 *
346 * Licensed under the Apache License, Version 2.0 (the "License");
347 * you may not use this file except in compliance with the License.
348 * You may obtain a copy of the License at
349 *
350 * http://www.apache.org/licenses/LICENSE-2.0
351 *
352 * Unless required by applicable law or agreed to in writing, software
353 * distributed under the License is distributed on an "AS IS" BASIS,
354 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
355 * See the License for the specific language governing permissions and
356 * limitations under the License.
357 *
358 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700359 */"""
360
361 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600362
363#include <string.h>
364#include <mutex>
365
366#define VALIDATION_ERROR_MAP_IMPL
367
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600368#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700369#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600370
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600371std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600372
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700373// Global unique object identifier. All increments must be guarded by a lock.
374uint64_t global_unique_id = 1;
375// Map uniqueID to actual object handle
376std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
377
378// TODO: This variable controls handle wrapping -- in the future it should be hooked
379// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
380#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
381bool wrap_handles = true;
382#else
383const bool wrap_handles = false;
384#endif
385
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600386// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700387#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600388#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700389#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700390#elif BUILD_THREAD_SAFETY
Mark Lobodzinski706e52b2018-12-11 13:21:52 -0700391#include "thread_safety.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700392#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
393#elif BUILD_PARAMETER_VALIDATION
394#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
395#elif BUILD_CORE_VALIDATION
396#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
397#else
398#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
399#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600400
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600401namespace vulkan_layer_chassis {
402
403using std::unordered_map;
404
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600405static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700406 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600407};
408
409static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
410
411extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
412
413
414// Manually written functions
415
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700416// Check enabled instance extensions against supported instance extension whitelist
417static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
418 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
419 // Check for recognized instance extensions
420 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
421 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
422 kVUIDUndefined,
423 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
424 "results and/or produce undefined behavior.",
425 pCreateInfo->ppEnabledExtensionNames[i]);
426 }
427 }
428}
429
430// Check enabled device extensions against supported device extension whitelist
431static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
432 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
433 // Check for recognized device extensions
434 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
435 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
436 kVUIDUndefined,
437 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
438 "results and/or produce undefined behavior.",
439 pCreateInfo->ppEnabledExtensionNames[i]);
440 }
441 }
442}
443
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600444VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600445 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700446 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700447 return nullptr;
448 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600449 const auto &item = name_to_funcptr_map.find(funcName);
450 if (item != name_to_funcptr_map.end()) {
451 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
452 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600453 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600454 if (!table.GetDeviceProcAddr) return nullptr;
455 return table.GetDeviceProcAddr(device, funcName);
456}
457
458VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600459 const auto &item = name_to_funcptr_map.find(funcName);
460 if (item != name_to_funcptr_map.end()) {
461 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
462 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600463 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
464 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600465 if (!table.GetInstanceProcAddr) return nullptr;
466 return table.GetInstanceProcAddr(instance, funcName);
467}
468
469VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600470 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
471 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600472 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
473 return table.GetPhysicalDeviceProcAddr(instance, funcName);
474}
475
476VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
477 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
478}
479
480VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
481 VkLayerProperties *pProperties) {
482 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
483}
484
485VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
486 VkExtensionProperties *pProperties) {
487 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
488 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
489
490 return VK_ERROR_LAYER_NOT_PRESENT;
491}
492
493VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
494 uint32_t *pCount, VkExtensionProperties *pProperties) {
495 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600496 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600497 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
498 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600499}
500
501VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
502 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600503 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600504
505 assert(chain_info->u.pLayerInfo);
506 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
507 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
508 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
509 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
510
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600511 // Create temporary dispatch vector for pre-calls until instance is created
512 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700513#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600514 auto object_tracker = new ObjectLifetimes;
515 local_object_dispatch.emplace_back(object_tracker);
516 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700517#elif BUILD_THREAD_SAFETY
518 auto thread_checker = new ThreadSafety;
519 local_object_dispatch.emplace_back(thread_checker);
520 thread_checker->container_type = LayerObjectTypeThreading;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700521#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600522
523
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600524 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600525 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600526 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
527 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600528 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600529 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
530 }
531
532 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600533 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600534
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600535 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600536
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600537 framework->object_dispatch = local_object_dispatch;
538
539 framework->instance = *pInstance;
540 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
541 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
542 pCreateInfo->ppEnabledExtensionNames);
543 framework->api_version = framework->instance_extensions.InitFromInstanceCreateInfo(
544 (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0), pCreateInfo);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700545#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600546 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700547#elif BUILD_THREAD_SAFETY
548 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "google_thread_checker");
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700549#else
550 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
551#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600552
553 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600554 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
555 }
556
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700557 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
558
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600559 return result;
560}
561
562VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
563 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600564 auto layer_data = GetLayerDataPtr(key, layer_data_map);
565 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700566 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600567 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700568 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600569 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600570 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700571 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600572 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700573 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600574 }
575
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600576 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600577
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600578 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700579 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600580 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700581 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600582 }
583 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600584 while (layer_data->logging_messenger.size() > 0) {
585 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
586 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
587 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600588 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600589 while (layer_data->logging_callback.size() > 0) {
590 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
591 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
592 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600593 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600594
595 layer_debug_utils_destroy_instance(layer_data->report_data);
596
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700597 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
598 delete *item;
599 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600600 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600601}
602
603VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
604 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600605 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600606
607 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
608
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600609 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
610 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600611 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
612 if (fpCreateDevice == NULL) {
613 return VK_ERROR_INITIALIZATION_FAILED;
614 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600615 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
616
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700617 // Get physical device limits for device
618 VkPhysicalDeviceProperties device_properties = {};
619 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
620
621 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
622 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
623
624 DeviceExtensions device_extensions = {};
625 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
626 for (auto item : instance_interceptor->object_dispatch) {
627 item->device_extensions = device_extensions;
628 }
629
630 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600631 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700632 intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700633 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700634 intercept->write_unlock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700635 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600636 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600637 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700638 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600639 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700640 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600641 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600642
643 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600644 if (result != VK_SUCCESS) {
645 return result;
646 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600647
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600648 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700649
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700650 // Save local info in device object
651 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700652 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
653 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700654 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700655
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600656 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700657
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600658 device_interceptor->device = *pDevice;
659 device_interceptor->physical_device = gpu;
660 device_interceptor->instance = instance_interceptor->instance;
661 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
662 device_interceptor->api_version = instance_interceptor->api_version;
663
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700664#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600665 // Create child layer objects for this key and add to dispatch vector
666 auto object_tracker = new ObjectLifetimes;
667 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
668 object_tracker->container_type = LayerObjectTypeObjectTracker;
669 object_tracker->physical_device = gpu;
670 object_tracker->instance = instance_interceptor->instance;
671 object_tracker->report_data = device_interceptor->report_data;
672 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
673 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700674#elif BUILD_THREAD_SAFETY
675 auto thread_safety = new ThreadSafety;
676 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
677 thread_safety->container_type = LayerObjectTypeThreading;
678 thread_safety->physical_device = gpu;
679 thread_safety->instance = instance_interceptor->instance;
680 thread_safety->report_data = device_interceptor->report_data;
681 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
682 device_interceptor->object_dispatch.emplace_back(thread_safety);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700683#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600684
685 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700686 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600687 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700688 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600689 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600690
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700691 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
692
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600693 return result;
694}
695
696VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
697 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600698 auto layer_data = GetLayerDataPtr(key, layer_data_map);
699 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700700 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600701 intercept->PreCallValidateDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700702 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600703 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600704 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700705 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600706 intercept->PreCallRecordDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700707 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600708 }
709 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600710
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600711 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600712
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600713 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700714 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600715 intercept->PostCallRecordDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700716 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600717 }
718
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700719 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
720 delete *item;
721 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600722 FreeLayerDataPtr(key, layer_data_map);
723}
724
725VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
726 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
727 const VkAllocationCallbacks *pAllocator,
728 VkDebugReportCallbackEXT *pCallback) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600729 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
730 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700731 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600732 intercept->PreCallValidateCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700733 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600734 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600735 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700736 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600737 intercept->PreCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700738 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600739 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700740 VkResult result = DispatchCreateDebugReportCallbackEXT(layer_data, instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600741 result = layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);
742 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700743 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600744 intercept->PostCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700745 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600746 }
747 return result;
748}
749
750VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
751 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600752 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
753 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700754 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600755 intercept->PreCallValidateDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700756 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600757 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600758 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700759 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600760 intercept->PreCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700761 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600762 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700763 DispatchDestroyDebugReportCallbackEXT(layer_data, instance, callback, pAllocator);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600764 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
765 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700766 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600767 intercept->PostCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700768 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600769 }
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700770}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600771
772 inline_custom_source_postamble = """
773// loader-layer interface v0, just wrappers since there is only a layer
774
775VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
776 VkExtensionProperties *pProperties) {
777 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
778}
779
780VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
781 VkLayerProperties *pProperties) {
782 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
783}
784
785VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
786 VkLayerProperties *pProperties) {
787 // the layer command handles VK_NULL_HANDLE just fine internally
788 assert(physicalDevice == VK_NULL_HANDLE);
789 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
790}
791
792VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
793 const char *pLayerName, uint32_t *pCount,
794 VkExtensionProperties *pProperties) {
795 // the layer command handles VK_NULL_HANDLE just fine internally
796 assert(physicalDevice == VK_NULL_HANDLE);
797 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
798}
799
800VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
801 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
802}
803
804VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
805 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
806}
807
808VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
809 const char *funcName) {
810 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
811}
812
813VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
814 assert(pVersionStruct != NULL);
815 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
816
817 // Fill in the function pointers if our version is at least capable of having the structure contain them.
818 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
819 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
820 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
821 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
822 }
823
824 return VK_SUCCESS;
825}"""
826
827
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600828 def __init__(self,
829 errFile = sys.stderr,
830 warnFile = sys.stderr,
831 diagFile = sys.stdout):
832 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
833 # Internal state - accumulators for different inner block text
834 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
835 self.intercepts = []
836 self.layer_factory = '' # String containing base layer factory class definition
837
838 # Check if the parameter passed in is a pointer to an array
839 def paramIsArray(self, param):
840 return param.attrib.get('len') is not None
841
842 # Check if the parameter passed in is a pointer
843 def paramIsPointer(self, param):
844 ispointer = False
845 for elem in param:
846 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
847 ispointer = True
848 return ispointer
849
850 # Check if an object is a non-dispatchable handle
851 def isHandleTypeNonDispatchable(self, handletype):
852 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
853 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
854 return True
855 else:
856 return False
857
858 # Check if an object is a dispatchable handle
859 def isHandleTypeDispatchable(self, handletype):
860 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
861 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
862 return True
863 else:
864 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700865 #
866 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600867 def beginFile(self, genOpts):
868 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700869 # Output Copyright
870 write(self.inline_copyright_message, file=self.outFile)
871 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600872 self.header = False
873 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
874 self.header = True
875 write('#pragma once', file=self.outFile)
876 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600877 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700878 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600879 else:
880 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700881 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700882 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600883 #
884 def endFile(self):
885 # Finish C++ namespace and multiple inclusion protection
886 self.newline()
887 if not self.header:
888 # Record intercepted procedures
889 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
890 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
891 write('\n'.join(self.intercepts), file=self.outFile)
892 write('};\n', file=self.outFile)
893 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600894 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600895 if self.header:
896 self.newline()
897 # Output Layer Factory Class Definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600898 self.layer_factory += '};\n\n'
899 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600900 write(self.layer_factory, file=self.outFile)
901 else:
902 write(self.inline_custom_source_postamble, file=self.outFile)
903 # Finish processing in superclass
904 OutputGenerator.endFile(self)
905
906 def beginFeature(self, interface, emit):
907 # Start processing in superclass
908 OutputGenerator.beginFeature(self, interface, emit)
909 # Get feature extra protect
910 self.featureExtraProtect = GetFeatureProtect(interface)
911 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
912 # feature. They're only printed in endFeature().
913 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
914
915 def endFeature(self):
916 # Actually write the interface to the output file.
917 if (self.emit):
918 self.newline()
919 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
920 # or move it below the 'for section...' loop.
921 if (self.featureExtraProtect != None):
922 write('#ifdef', self.featureExtraProtect, file=self.outFile)
923 for section in self.TYPE_SECTIONS:
924 contents = self.sections[section]
925 if contents:
926 write('\n'.join(contents), file=self.outFile)
927 self.newline()
928 if (self.sections['command']):
929 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
930 self.newline()
931 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600932 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600933 # Finish processing in superclass
934 OutputGenerator.endFeature(self)
935 #
936 # Append a definition to the specified section
937 def appendSection(self, section, text):
938 self.sections[section].append(text)
939 #
940 # Type generation
941 def genType(self, typeinfo, name, alias):
942 pass
943 #
944 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
945 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
946 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
947 # structs etc.)
948 def genStruct(self, typeinfo, typeName):
949 OutputGenerator.genStruct(self, typeinfo, typeName)
950 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
951 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
952 for member in typeinfo.elem.findall('.//member'):
953 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
954 body += ';\n'
955 body += '} ' + typeName + ';\n'
956 self.appendSection('struct', body)
957 #
958 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
959 def genGroup(self, groupinfo, groupName, alias):
960 pass
961 # Enumerant generation
962 # <enum> tags may specify their values in several ways, but are usually just integers.
963 def genEnum(self, enuminfo, name, alias):
964 pass
965 #
966 # Customize Cdecl for layer factory base class
967 def BaseClassCdecl(self, elem, name):
968 raw = self.makeCDecls(elem)[1]
969
970 # Toss everything before the undecorated name
971 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
972 prototype = prototype.replace(")", "", 1)
973 prototype = prototype.replace(";", " {};")
974
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600975 # Build up pre/post call virtual function declarations
976 pre_call_validate = 'virtual bool PreCallValidate' + prototype
977 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
978 pre_call_record = 'virtual void PreCallRecord' + prototype
979 post_call_record = 'virtual void PostCallRecord' + prototype
980 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
981 #
982 # Command generation
983 def genCmd(self, cmdinfo, name, alias):
984 ignore_functions = [
985 'vkEnumerateInstanceVersion'
986 ]
987
988 if name in ignore_functions:
989 return
990
991 if self.header: # In the header declare all intercepts
992 self.appendSection('command', '')
993 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
994 if (self.featureExtraProtect != None):
995 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
996 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
997 # Update base class with virtual function declarations
998 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
999 # Update function intercepts
1000 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1001 if (self.featureExtraProtect != None):
1002 self.intercepts += [ '#endif' ]
1003 self.layer_factory += '#endif\n'
1004 return
1005
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001006 if name in self.manual_functions:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001007 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1008 return
1009 # Record that the function will be intercepted
1010 if (self.featureExtraProtect != None):
1011 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1012 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1013 if (self.featureExtraProtect != None):
1014 self.intercepts += [ '#endif' ]
1015 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1016 #
1017 decls = self.makeCDecls(cmdinfo.elem)
1018 self.appendSection('command', '')
1019 self.appendSection('command', '%s {' % decls[0][:-1])
1020 # Setup common to call wrappers. First parameter is always dispatchable
1021 dispatchable_type = cmdinfo.elem.find('param/type').text
1022 dispatchable_name = cmdinfo.elem.find('param/name').text
1023 # Default to device
1024 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001025 dispatch_table_name = 'VkLayerDispatchTable'
1026 # Set to instance as necessary
1027 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1028 device_or_instance = 'instance'
1029 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001030 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001031 api_function_name = cmdinfo.elem.attrib.get('name')
1032 params = cmdinfo.elem.findall('param/name')
1033 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001034 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001035
1036 # Declare result variable, if any.
1037 return_map = {
1038 'void': 'return;',
1039 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1040 'PFN_vkVoidFunction': 'return nullptr;',
1041 'VkBool32': 'return VK_FALSE;',
1042 }
1043 resulttype = cmdinfo.elem.find('proto/type')
1044 assignresult = ''
1045 if (resulttype.text != 'void'):
1046 assignresult = resulttype.text + ' result = '
1047
1048 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001049 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001050
1051 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001052 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001053 self.appendSection('command', ' intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001054 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001055 self.appendSection('command', ' intercept->write_unlock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001056 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1057 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001058
1059 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001060 self.appendSection('command', ' %s' % self.precallrecord_loop)
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001061 self.appendSection('command', ' intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001062 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001063 self.appendSection('command', ' intercept->write_unlock();')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001064 self.appendSection('command', ' }')
1065
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001066 # Insert pre-dispatch debug utils function call
1067 if name in self.pre_dispatch_debug_utils_functions:
1068 self.appendSection('command', ' {')
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001069 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->validation_object_mutex);')
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001070 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
1071 self.appendSection('command', ' }')
1072
1073 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001074 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001075
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001076 # Insert post-dispatch debug utils function call
1077 if name in self.post_dispatch_debug_utils_functions:
1078 self.appendSection('command', ' {')
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001079 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->validation_object_mutex);')
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001080 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
1081 self.appendSection('command', ' }')
1082
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001083 # Generate post-call object processing source code
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001084 return_type_indent = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001085 if (resulttype.text == 'VkResult'):
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001086 return_type_indent = ' '
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001087 if name in self.alt_ret_codes:
Mark Lobodzinskib3c94842018-11-27 10:01:51 -07001088 self.appendSection('command', ' if ((VK_SUCCESS == result) || (VK_INCOMPLETE == result)) {')
1089 else:
1090 self.appendSection('command', ' if (VK_SUCCESS == result) {')
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001091
1092 self.appendSection('command', '%s %s' % (return_type_indent, self.postcallrecord_loop))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001093 self.appendSection('command', '%s intercept->write_lock();' % return_type_indent)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001094 self.appendSection('command', '%s intercept->PostCallRecord%s(%s);' % (return_type_indent,api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001095 self.appendSection('command', '%s intercept->write_unlock();' % return_type_indent)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001096 self.appendSection('command', '%s }' % return_type_indent)
1097 if (resulttype.text == 'VkResult'):
1098 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001099
1100 # Return result variable, if any.
1101 if (resulttype.text != 'void'):
1102 self.appendSection('command', ' return result;')
1103 self.appendSection('command', '}')
1104 #
1105 # Override makeProtoName to drop the "vk" prefix
1106 def makeProtoName(self, name, tail):
1107 return self.genOpts.apientry + name[2:] + tail