blob: 2741daa041439894be095e8af1f5261b43c31993 [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07003# Copyright (c) 2015-2019 Valve Corporation
4# Copyright (c) 2015-2019 LunarG, Inc.
5# Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06006#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
20# Author: Mark Lobodzinski <mark@lunarg.com>
21#
22# This script generates the dispatch portion of a factory layer which intercepts
23# all Vulkan functions. The resultant factory layer allows rapid development of
24# layers and interceptors.
25
26import os,re,sys
27from generator import *
28from common_codegen import *
29
30# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31#
32# Adds options used by LayerFactoryOutputGenerator objects during factory
33# layer generation.
34#
35# Additional members
36# prefixText - list of strings to prefix generated header with
37# (usually a copyright statement + calling convention macros).
38# protectFile - True if multiple inclusion protection should be
39# generated (based on the filename) around the entire header.
40# protectFeature - True if #ifndef..#endif protection should be
41# generated around a feature interface in the header file.
42# genFuncPointers - True if function pointer typedefs should be
43# generated
44# protectProto - If conditional protection should be generated
45# around prototype declarations, set to either '#ifdef'
46# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47# to require opt-out (#ifndef protectProtoStr). Otherwise
48# set to None.
49# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50# declarations, if protectProto is set
51# apicall - string to use for the function declaration prefix,
52# such as APICALL on Windows.
53# apientry - string to use for the calling convention macro,
54# in typedefs, such as APIENTRY.
55# apientryp - string to use for the calling convention macro
56# in function pointer typedefs, such as APIENTRYP.
57# indentFuncProto - True if prototype declarations should put each
58# parameter on a separate line
59# indentFuncPointer - True if typedefed function pointers should put each
60# parameter on a separate line
61# alignFuncParam - if nonzero and parameters are being put on a
62# separate line, align parameter names at the specified column
63class LayerChassisGeneratorOptions(GeneratorOptions):
64 def __init__(self,
65 filename = None,
66 directory = '.',
67 apiname = None,
68 profile = None,
69 versions = '.*',
70 emitversions = '.*',
71 defaultExtensions = None,
72 addExtensions = None,
73 removeExtensions = None,
74 emitExtensions = None,
75 sortProcedure = regSortFeatures,
76 prefixText = "",
77 genFuncPointers = True,
78 protectFile = True,
79 protectFeature = True,
80 apicall = '',
81 apientry = '',
82 apientryp = '',
83 indentFuncProto = True,
84 indentFuncPointer = False,
85 alignFuncParam = 0,
86 helper_file_type = '',
87 expandEnumerants = True):
88 GeneratorOptions.__init__(self, filename, directory, apiname, profile,
89 versions, emitversions, defaultExtensions,
90 addExtensions, removeExtensions, emitExtensions, sortProcedure)
91 self.prefixText = prefixText
92 self.genFuncPointers = genFuncPointers
93 self.protectFile = protectFile
94 self.protectFeature = protectFeature
95 self.apicall = apicall
96 self.apientry = apientry
97 self.apientryp = apientryp
98 self.indentFuncProto = indentFuncProto
99 self.indentFuncPointer = indentFuncPointer
100 self.alignFuncParam = alignFuncParam
101
102# LayerChassisOutputGenerator - subclass of OutputGenerator.
103# Generates a LayerFactory layer that intercepts all API entrypoints
104# This is intended to be used as a starting point for creating custom layers
105#
106# ---- methods ----
107# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
108# OutputGenerator. Defines additional internal state.
109# ---- methods overriding base class ----
110# beginFile(genOpts)
111# endFile()
112# beginFeature(interface, emit)
113# endFeature()
114# genType(typeinfo,name)
115# genStruct(typeinfo,name)
116# genGroup(groupinfo,name)
117# genEnum(enuminfo, name)
118# genCmd(cmdinfo)
119class LayerChassisOutputGenerator(OutputGenerator):
120 """Generate specified API interfaces in a specific style, such as a C header"""
121 # This is an ordered list of sections in the header file.
122 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
123 'group', 'bitmask', 'funcpointer', 'struct']
124 ALL_SECTIONS = TYPE_SECTIONS + ['command']
125
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700126 manual_functions = [
127 # Include functions here to be interecpted w/ manually implemented function bodies
128 'vkGetDeviceProcAddr',
129 'vkGetInstanceProcAddr',
130 'vkGetPhysicalDeviceProcAddr',
131 'vkCreateDevice',
132 'vkDestroyDevice',
133 'vkCreateInstance',
134 'vkDestroyInstance',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700135 'vkEnumerateInstanceLayerProperties',
136 'vkEnumerateInstanceExtensionProperties',
137 'vkEnumerateDeviceLayerProperties',
138 'vkEnumerateDeviceExtensionProperties',
139 ]
140
141 alt_ret_codes = [
142 # Include functions here which must tolerate VK_INCOMPLETE as a return code
143 'vkEnumeratePhysicalDevices',
144 'vkEnumeratePhysicalDeviceGroupsKHR',
145 'vkGetValidationCacheDataEXT',
146 'vkGetPipelineCacheData',
147 'vkGetShaderInfoAMD',
148 'vkGetPhysicalDeviceDisplayPropertiesKHR',
149 'vkGetPhysicalDeviceDisplayProperties2KHR',
150 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
151 'vkGetDisplayPlaneSupportedDisplaysKHR',
152 'vkGetDisplayModePropertiesKHR',
153 'vkGetDisplayModeProperties2KHR',
154 'vkGetPhysicalDeviceSurfaceFormatsKHR',
155 'vkGetPhysicalDeviceSurfacePresentModesKHR',
156 'vkGetPhysicalDevicePresentRectanglesKHR',
157 'vkGetPastPresentationTimingGOOGLE',
158 'vkGetSwapchainImagesKHR',
159 'vkEnumerateInstanceLayerProperties',
160 'vkEnumerateDeviceLayerProperties',
161 'vkEnumerateInstanceExtensionProperties',
162 'vkEnumerateDeviceExtensionProperties',
163 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
164 ]
165
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700166 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700167 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
168 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700169 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
170 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
171 'vkCmdBeginDebugUtilsLabelEXT' : 'BeginCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
172 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
173 }
174
175 post_dispatch_debug_utils_functions = {
176 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
177 'vkCmdEndDebugUtilsLabelEXT' : 'EndCmdDebugUtilsLabel(layer_data->report_data, commandBuffer);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700178 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
179 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
180 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
181 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
182 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700183 }
184
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600185 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
186 precallrecord_loop = precallvalidate_loop
187 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600188
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700189 inline_custom_header_preamble = """
190#define NOMINMAX
191#include <mutex>
192#include <cinttypes>
193#include <stdio.h>
194#include <stdlib.h>
195#include <string.h>
196#include <unordered_map>
197#include <unordered_set>
198#include <algorithm>
199#include <memory>
200
201#include "vk_loader_platform.h"
202#include "vulkan/vulkan.h"
203#include "vk_layer_config.h"
204#include "vk_layer_data.h"
205#include "vk_layer_logging.h"
206#include "vk_object_types.h"
207#include "vulkan/vk_layer.h"
208#include "vk_enum_string_helper.h"
209#include "vk_layer_extension_utils.h"
210#include "vk_layer_utils.h"
211#include "vulkan/vk_layer.h"
212#include "vk_dispatch_table_helper.h"
213#include "vk_validation_error_messages.h"
214#include "vk_extension_helper.h"
215#include "vk_safe_struct.h"
216
217extern uint64_t global_unique_id;
218extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
219"""
220
221 inline_custom_header_class_definition = """
222
223// Layer object type identifiers
224enum LayerObjectTypeId {
225 LayerObjectTypeThreading,
226 LayerObjectTypeParameterValidation,
227 LayerObjectTypeObjectTracker,
228 LayerObjectTypeCoreValidation,
229};
230
231struct TEMPLATE_STATE {
232 VkDescriptorUpdateTemplateKHR desc_update_template;
233 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
234
235 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
236 : desc_update_template(update_template), create_info(*pCreateInfo) {}
237};
238
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700239class LAYER_PHYS_DEV_PROPERTIES {
240public:
241 VkPhysicalDeviceProperties properties;
242 std::vector<VkQueueFamilyProperties> queue_family_properties;
243};
244
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700245// Layer chassis validation object base class definition
246class ValidationObject {
247 public:
248 uint32_t api_version;
249 debug_report_data* report_data = nullptr;
250 std::vector<VkDebugReportCallbackEXT> logging_callback;
251 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
252
253 VkLayerInstanceDispatchTable instance_dispatch_table;
254 VkLayerDispatchTable device_dispatch_table;
255
256 InstanceExtensions instance_extensions;
257 DeviceExtensions device_extensions = {};
258
259 VkInstance instance = VK_NULL_HANDLE;
260 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
261 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700262 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700263
264 std::vector<ValidationObject*> object_dispatch;
265 LayerObjectTypeId container_type;
266
267 // Constructor
268 ValidationObject(){};
269 // Destructor
270 virtual ~ValidationObject() {};
271
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700272 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700273 virtual std::unique_lock<std::mutex> write_lock() {
274 return std::unique_lock<std::mutex>(validation_object_mutex);
275 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700276
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700277 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
278 for (auto validation_object : object_dispatch) {
279 if (validation_object->container_type == object_type) {
280 return validation_object;
281 }
282 }
283 return nullptr;
284 };
285
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700286 std::string layer_name = "CHASSIS";
287
288 // Handle Wrapping Data
289 // Reverse map display handles
290 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
291 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700292 struct SubpassesUsageStates {
293 std::unordered_set<uint32_t> subpasses_using_color_attachment;
294 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
295 };
296 // Uses unwrapped handles
297 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
298 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
299 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
300 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700301 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
302 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700303
304
305 // Unwrap a handle. Must hold lock.
306 template <typename HandleType>
307 HandleType Unwrap(HandleType wrappedHandle) {
308 // TODO: don't use operator[] here.
309 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
310 }
311
312 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
313 template <typename HandleType>
314 HandleType WrapNew(HandleType newlyCreatedHandle) {
315 auto unique_id = global_unique_id++;
316 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
317 return (HandleType)unique_id;
318 }
319
320 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
321 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
322 auto unique_id = global_unique_id++;
323 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
324 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
325 return (VkDisplayKHR)unique_id;
326 }
327
328 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
329 // creating another. Must hold lock.
330 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
331 // See if this display is already known
332 auto it = map_data->display_id_reverse_mapping.find(handle);
333 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
334 // Unknown, so wrap
335 return WrapDisplay(handle, map_data);
336 }
337
338 // Pre/post hook point declarations
339"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600340
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700341 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600342// This file is ***GENERATED***. Do Not Edit.
343// See layer_chassis_generator.py for modifications.
344
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700345/* Copyright (c) 2015-2019 The Khronos Group Inc.
346 * Copyright (c) 2015-2019 Valve Corporation
347 * Copyright (c) 2015-2019 LunarG, Inc.
348 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600349 *
350 * Licensed under the Apache License, Version 2.0 (the "License");
351 * you may not use this file except in compliance with the License.
352 * You may obtain a copy of the License at
353 *
354 * http://www.apache.org/licenses/LICENSE-2.0
355 *
356 * Unless required by applicable law or agreed to in writing, software
357 * distributed under the License is distributed on an "AS IS" BASIS,
358 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
359 * See the License for the specific language governing permissions and
360 * limitations under the License.
361 *
362 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700363 */"""
364
365 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600366
367#include <string.h>
368#include <mutex>
369
370#define VALIDATION_ERROR_MAP_IMPL
371
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600372#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700373#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600374
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600375std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600376
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700377// Global unique object identifier. All increments must be guarded by a lock.
378uint64_t global_unique_id = 1;
379// Map uniqueID to actual object handle
380std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
381
382// TODO: This variable controls handle wrapping -- in the future it should be hooked
383// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
384#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
385bool wrap_handles = true;
386#else
387const bool wrap_handles = false;
388#endif
389
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600390// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700391#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600392#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700393#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700394#elif BUILD_THREAD_SAFETY
Mark Lobodzinski706e52b2018-12-11 13:21:52 -0700395#include "thread_safety.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700396#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
397#elif BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700398#include "stateless_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700399#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
400#elif BUILD_CORE_VALIDATION
401#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
402#else
403#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
404#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600405
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600406namespace vulkan_layer_chassis {
407
408using std::unordered_map;
409
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600410static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700411 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600412};
413
414static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
415
416extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
417
418
419// Manually written functions
420
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700421// Check enabled instance extensions against supported instance extension whitelist
422static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
423 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
424 // Check for recognized instance extensions
425 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
426 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
427 kVUIDUndefined,
428 "Instance 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
435// Check enabled device extensions against supported device extension whitelist
436static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
437 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
438 // Check for recognized device extensions
439 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
440 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
441 kVUIDUndefined,
442 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
443 "results and/or produce undefined behavior.",
444 pCreateInfo->ppEnabledExtensionNames[i]);
445 }
446 }
447}
448
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600449VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600450 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700451 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700452 return nullptr;
453 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600454 const auto &item = name_to_funcptr_map.find(funcName);
455 if (item != name_to_funcptr_map.end()) {
456 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
457 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600458 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600459 if (!table.GetDeviceProcAddr) return nullptr;
460 return table.GetDeviceProcAddr(device, funcName);
461}
462
463VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600464 const auto &item = name_to_funcptr_map.find(funcName);
465 if (item != name_to_funcptr_map.end()) {
466 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
467 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600468 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
469 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600470 if (!table.GetInstanceProcAddr) return nullptr;
471 return table.GetInstanceProcAddr(instance, funcName);
472}
473
474VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600475 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
476 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600477 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
478 return table.GetPhysicalDeviceProcAddr(instance, funcName);
479}
480
481VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
482 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
483}
484
485VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
486 VkLayerProperties *pProperties) {
487 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
488}
489
490VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
491 VkExtensionProperties *pProperties) {
492 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
493 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
494
495 return VK_ERROR_LAYER_NOT_PRESENT;
496}
497
498VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
499 uint32_t *pCount, VkExtensionProperties *pProperties) {
500 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600501 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600502 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
503 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600504}
505
506VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
507 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600508 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600509
510 assert(chain_info->u.pLayerInfo);
511 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
512 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
513 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
514 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700515 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
516 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
517
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600518
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600519 // Create temporary dispatch vector for pre-calls until instance is created
520 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700521#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600522 auto object_tracker = new ObjectLifetimes;
523 local_object_dispatch.emplace_back(object_tracker);
524 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700525 object_tracker->api_version = api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700526#elif BUILD_THREAD_SAFETY
527 auto thread_checker = new ThreadSafety;
528 local_object_dispatch.emplace_back(thread_checker);
529 thread_checker->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700530 thread_checker->api_version = api_version;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700531#elif BUILD_PARAMETER_VALIDATION
532 auto parameter_validation = new StatelessValidation;
533 local_object_dispatch.emplace_back(parameter_validation);
534 parameter_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700535 parameter_validation->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700536#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600537
538
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600539 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600540 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600541 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
542 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600543 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600544 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
545 }
546
547 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600548 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600549
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600550 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600551
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600552 framework->object_dispatch = local_object_dispatch;
553
554 framework->instance = *pInstance;
555 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
556 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
557 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700558 framework->api_version = api_version;
559 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
560
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700561#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600562 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700563 object_tracker->report_data = framework->report_data;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700564#elif BUILD_THREAD_SAFETY
565 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "google_thread_checker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700566 thread_checker->report_data = framework->report_data;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700567#elif BUILD_PARAMETER_VALIDATION
568 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_parameter_validation");
569 parameter_validation->report_data = framework->report_data;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700570#else
571 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
572#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600573
574 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700575 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600576 }
577
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700578 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
579
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600580 return result;
581}
582
583VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
584 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600585 auto layer_data = GetLayerDataPtr(key, layer_data_map);
586 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700587 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600588 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
589 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600590 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700591 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600592 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
593 }
594
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600595 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600596
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600597 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700598 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600599 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
600 }
601 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600602 while (layer_data->logging_messenger.size() > 0) {
603 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
604 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
605 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600606 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600607 while (layer_data->logging_callback.size() > 0) {
608 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
609 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
610 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600611 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600612
613 layer_debug_utils_destroy_instance(layer_data->report_data);
614
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700615 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
616 delete *item;
617 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600618 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600619}
620
621VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
622 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600623 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600624
625 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
626
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600627 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
628 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600629 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
630 if (fpCreateDevice == NULL) {
631 return VK_ERROR_INITIALIZATION_FAILED;
632 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600633 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
634
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700635 // Get physical device limits for device
636 VkPhysicalDeviceProperties device_properties = {};
637 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
638
639 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
640 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
641
642 DeviceExtensions device_extensions = {};
643 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
644 for (auto item : instance_interceptor->object_dispatch) {
645 item->device_extensions = device_extensions;
646 }
647
648 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600649 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700650 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700651 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700652 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600653 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600654 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700655 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600656 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
657 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600658
659 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600660 if (result != VK_SUCCESS) {
661 return result;
662 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600663
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600664 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700665
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700666 // Save local info in device object
667 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700668 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
669 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700670 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700671
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600672 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700673
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600674 device_interceptor->device = *pDevice;
675 device_interceptor->physical_device = gpu;
676 device_interceptor->instance = instance_interceptor->instance;
677 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600678
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700679#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600680 // Create child layer objects for this key and add to dispatch vector
681 auto object_tracker = new ObjectLifetimes;
682 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
683 object_tracker->container_type = LayerObjectTypeObjectTracker;
684 object_tracker->physical_device = gpu;
685 object_tracker->instance = instance_interceptor->instance;
686 object_tracker->report_data = device_interceptor->report_data;
687 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700688 object_tracker->api_version = device_interceptor->api_version;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600689 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700690#elif BUILD_THREAD_SAFETY
691 auto thread_safety = new ThreadSafety;
692 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
693 thread_safety->container_type = LayerObjectTypeThreading;
694 thread_safety->physical_device = gpu;
695 thread_safety->instance = instance_interceptor->instance;
696 thread_safety->report_data = device_interceptor->report_data;
697 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700698 thread_safety->api_version = device_interceptor->api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700699 device_interceptor->object_dispatch.emplace_back(thread_safety);
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700700#elif BUILD_PARAMETER_VALIDATION
701 auto stateless_validation = new StatelessValidation;
702 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
703 stateless_validation->container_type = LayerObjectTypeParameterValidation;
704 stateless_validation->physical_device = gpu;
705 stateless_validation->instance = instance_interceptor->instance;
706 stateless_validation->report_data = device_interceptor->report_data;
707 stateless_validation->device_dispatch_table = device_interceptor->device_dispatch_table;
708 stateless_validation->api_version = device_interceptor->api_version;
709 device_interceptor->object_dispatch.emplace_back(stateless_validation);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700710#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600711
712 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700713 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700714 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600715 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600716
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700717 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
718
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600719 return result;
720}
721
722VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
723 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600724 auto layer_data = GetLayerDataPtr(key, layer_data_map);
725 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700726 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600727 intercept->PreCallValidateDestroyDevice(device, pAllocator);
728 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600729 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700730 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600731 intercept->PreCallRecordDestroyDevice(device, pAllocator);
732 }
733 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600734
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600735 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600736
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600737 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700738 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600739 intercept->PostCallRecordDestroyDevice(device, pAllocator);
740 }
741
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700742 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
743 delete *item;
744 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600745 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700746}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600747
748 inline_custom_source_postamble = """
749// loader-layer interface v0, just wrappers since there is only a layer
750
751VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
752 VkExtensionProperties *pProperties) {
753 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
754}
755
756VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
757 VkLayerProperties *pProperties) {
758 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
759}
760
761VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
762 VkLayerProperties *pProperties) {
763 // the layer command handles VK_NULL_HANDLE just fine internally
764 assert(physicalDevice == VK_NULL_HANDLE);
765 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
766}
767
768VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
769 const char *pLayerName, uint32_t *pCount,
770 VkExtensionProperties *pProperties) {
771 // the layer command handles VK_NULL_HANDLE just fine internally
772 assert(physicalDevice == VK_NULL_HANDLE);
773 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
774}
775
776VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
777 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
778}
779
780VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
781 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
782}
783
784VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
785 const char *funcName) {
786 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
787}
788
789VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
790 assert(pVersionStruct != NULL);
791 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
792
793 // Fill in the function pointers if our version is at least capable of having the structure contain them.
794 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
795 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
796 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
797 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
798 }
799
800 return VK_SUCCESS;
801}"""
802
803
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600804 def __init__(self,
805 errFile = sys.stderr,
806 warnFile = sys.stderr,
807 diagFile = sys.stdout):
808 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
809 # Internal state - accumulators for different inner block text
810 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
811 self.intercepts = []
812 self.layer_factory = '' # String containing base layer factory class definition
813
814 # Check if the parameter passed in is a pointer to an array
815 def paramIsArray(self, param):
816 return param.attrib.get('len') is not None
817
818 # Check if the parameter passed in is a pointer
819 def paramIsPointer(self, param):
820 ispointer = False
821 for elem in param:
822 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
823 ispointer = True
824 return ispointer
825
826 # Check if an object is a non-dispatchable handle
827 def isHandleTypeNonDispatchable(self, handletype):
828 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
829 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
830 return True
831 else:
832 return False
833
834 # Check if an object is a dispatchable handle
835 def isHandleTypeDispatchable(self, handletype):
836 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
837 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
838 return True
839 else:
840 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700841 #
842 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600843 def beginFile(self, genOpts):
844 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700845 # Output Copyright
846 write(self.inline_copyright_message, file=self.outFile)
847 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600848 self.header = False
849 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
850 self.header = True
851 write('#pragma once', file=self.outFile)
852 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600853 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700854 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600855 else:
856 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700857 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700858 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600859 #
860 def endFile(self):
861 # Finish C++ namespace and multiple inclusion protection
862 self.newline()
863 if not self.header:
864 # Record intercepted procedures
865 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
866 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
867 write('\n'.join(self.intercepts), file=self.outFile)
868 write('};\n', file=self.outFile)
869 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600870 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600871 if self.header:
872 self.newline()
873 # Output Layer Factory Class Definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600874 self.layer_factory += '};\n\n'
875 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600876 write(self.layer_factory, file=self.outFile)
877 else:
878 write(self.inline_custom_source_postamble, file=self.outFile)
879 # Finish processing in superclass
880 OutputGenerator.endFile(self)
881
882 def beginFeature(self, interface, emit):
883 # Start processing in superclass
884 OutputGenerator.beginFeature(self, interface, emit)
885 # Get feature extra protect
886 self.featureExtraProtect = GetFeatureProtect(interface)
887 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
888 # feature. They're only printed in endFeature().
889 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
890
891 def endFeature(self):
892 # Actually write the interface to the output file.
893 if (self.emit):
894 self.newline()
895 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
896 # or move it below the 'for section...' loop.
897 if (self.featureExtraProtect != None):
898 write('#ifdef', self.featureExtraProtect, file=self.outFile)
899 for section in self.TYPE_SECTIONS:
900 contents = self.sections[section]
901 if contents:
902 write('\n'.join(contents), file=self.outFile)
903 self.newline()
904 if (self.sections['command']):
905 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
906 self.newline()
907 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600908 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600909 # Finish processing in superclass
910 OutputGenerator.endFeature(self)
911 #
912 # Append a definition to the specified section
913 def appendSection(self, section, text):
914 self.sections[section].append(text)
915 #
916 # Type generation
917 def genType(self, typeinfo, name, alias):
918 pass
919 #
920 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
921 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
922 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
923 # structs etc.)
924 def genStruct(self, typeinfo, typeName):
925 OutputGenerator.genStruct(self, typeinfo, typeName)
926 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
927 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
928 for member in typeinfo.elem.findall('.//member'):
929 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
930 body += ';\n'
931 body += '} ' + typeName + ';\n'
932 self.appendSection('struct', body)
933 #
934 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
935 def genGroup(self, groupinfo, groupName, alias):
936 pass
937 # Enumerant generation
938 # <enum> tags may specify their values in several ways, but are usually just integers.
939 def genEnum(self, enuminfo, name, alias):
940 pass
941 #
942 # Customize Cdecl for layer factory base class
943 def BaseClassCdecl(self, elem, name):
944 raw = self.makeCDecls(elem)[1]
945
946 # Toss everything before the undecorated name
947 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
948 prototype = prototype.replace(")", "", 1)
949 prototype = prototype.replace(";", " {};")
950
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600951 # Build up pre/post call virtual function declarations
952 pre_call_validate = 'virtual bool PreCallValidate' + prototype
953 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
954 pre_call_record = 'virtual void PreCallRecord' + prototype
955 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700956 resulttype = elem.find('proto/type')
957 if resulttype.text == 'VkResult':
958 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600959 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
960 #
961 # Command generation
962 def genCmd(self, cmdinfo, name, alias):
963 ignore_functions = [
964 'vkEnumerateInstanceVersion'
965 ]
966
967 if name in ignore_functions:
968 return
969
970 if self.header: # In the header declare all intercepts
971 self.appendSection('command', '')
972 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
973 if (self.featureExtraProtect != None):
974 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
975 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
976 # Update base class with virtual function declarations
977 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
978 # Update function intercepts
979 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
980 if (self.featureExtraProtect != None):
981 self.intercepts += [ '#endif' ]
982 self.layer_factory += '#endif\n'
983 return
984
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700985 if name in self.manual_functions:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600986 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
987 return
988 # Record that the function will be intercepted
989 if (self.featureExtraProtect != None):
990 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
991 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
992 if (self.featureExtraProtect != None):
993 self.intercepts += [ '#endif' ]
994 OutputGenerator.genCmd(self, cmdinfo, name, alias)
995 #
996 decls = self.makeCDecls(cmdinfo.elem)
997 self.appendSection('command', '')
998 self.appendSection('command', '%s {' % decls[0][:-1])
999 # Setup common to call wrappers. First parameter is always dispatchable
1000 dispatchable_type = cmdinfo.elem.find('param/type').text
1001 dispatchable_name = cmdinfo.elem.find('param/name').text
1002 # Default to device
1003 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001004 dispatch_table_name = 'VkLayerDispatchTable'
1005 # Set to instance as necessary
1006 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1007 device_or_instance = 'instance'
1008 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001009 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001010 api_function_name = cmdinfo.elem.attrib.get('name')
1011 params = cmdinfo.elem.findall('param/name')
1012 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001013 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001014
1015 # Declare result variable, if any.
1016 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001017 'PFN_vkVoidFunction': 'return nullptr;',
1018 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001019 'VkDeviceAddress': 'return 0;',
1020 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1021 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001022 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001023 }
1024 resulttype = cmdinfo.elem.find('proto/type')
1025 assignresult = ''
1026 if (resulttype.text != 'void'):
1027 assignresult = resulttype.text + ' result = '
1028
1029 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001030 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001031
1032 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001033 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001034 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001035 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1036 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)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001041 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001042 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001043 self.appendSection('command', ' }')
1044
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001045 # Insert pre-dispatch debug utils function call
1046 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001047 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001048
1049 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001050 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001051
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001052 # Insert post-dispatch debug utils function call
1053 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001054 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001055
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001056 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001057 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001058 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001059 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001060 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001061 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001062 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001063 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001064 # Return result variable, if any.
1065 if (resulttype.text != 'void'):
1066 self.appendSection('command', ' return result;')
1067 self.appendSection('command', '}')
1068 #
1069 # Override makeProtoName to drop the "vk" prefix
1070 def makeProtoName(self, name, tail):
1071 return self.genOpts.apientry + name[2:] + tail