blob: 4e35dd7e27b00ca228740a399f19e7ca325817d7 [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 Lobodzinskiadd93232018-10-09 11:49:42 -0600617 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700618 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600619 intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700620 intercept->write_unlock();
621
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600622 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600623 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700624 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600625 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700626 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600627 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600628
629 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600630 if (result != VK_SUCCESS) {
631 return result;
632 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600633
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600634 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700635
636 // Get physical device limits for device
637 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(
638 gpu, &(device_interceptor->phys_dev_properties.properties));
639
640 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
641 uint32_t effective_api_version = std::min(device_interceptor->api_version, instance_interceptor->api_version);
642 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
643 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
644
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600645 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700646
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600647 device_interceptor->device = *pDevice;
648 device_interceptor->physical_device = gpu;
649 device_interceptor->instance = instance_interceptor->instance;
650 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
651 device_interceptor->api_version = instance_interceptor->api_version;
652
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700653#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600654 // Create child layer objects for this key and add to dispatch vector
655 auto object_tracker = new ObjectLifetimes;
656 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
657 object_tracker->container_type = LayerObjectTypeObjectTracker;
658 object_tracker->physical_device = gpu;
659 object_tracker->instance = instance_interceptor->instance;
660 object_tracker->report_data = device_interceptor->report_data;
661 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
662 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700663#elif BUILD_THREAD_SAFETY
664 auto thread_safety = new ThreadSafety;
665 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
666 thread_safety->container_type = LayerObjectTypeThreading;
667 thread_safety->physical_device = gpu;
668 thread_safety->instance = instance_interceptor->instance;
669 thread_safety->report_data = device_interceptor->report_data;
670 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
671 device_interceptor->object_dispatch.emplace_back(thread_safety);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700672#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600673
674 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700675 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600676 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700677 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600678 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600679
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700680 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
681
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600682 return result;
683}
684
685VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
686 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600687 auto layer_data = GetLayerDataPtr(key, layer_data_map);
688 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700689 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600690 intercept->PreCallValidateDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700691 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600692 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600693 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700694 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600695 intercept->PreCallRecordDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700696 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600697 }
698 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600699
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600700 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600701
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600702 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700703 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600704 intercept->PostCallRecordDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700705 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600706 }
707
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700708 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
709 delete *item;
710 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600711 FreeLayerDataPtr(key, layer_data_map);
712}
713
714VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
715 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
716 const VkAllocationCallbacks *pAllocator,
717 VkDebugReportCallbackEXT *pCallback) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600718 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
719 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700720 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600721 intercept->PreCallValidateCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700722 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600723 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600724 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700725 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600726 intercept->PreCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700727 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600728 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700729 VkResult result = DispatchCreateDebugReportCallbackEXT(layer_data, instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600730 result = layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);
731 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700732 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600733 intercept->PostCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700734 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600735 }
736 return result;
737}
738
739VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
740 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600741 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
742 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700743 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600744 intercept->PreCallValidateDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700745 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600746 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600747 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700748 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600749 intercept->PreCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700750 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600751 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700752 DispatchDestroyDebugReportCallbackEXT(layer_data, instance, callback, pAllocator);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600753 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
754 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700755 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600756 intercept->PostCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700757 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600758 }
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700759}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600760
761 inline_custom_source_postamble = """
762// loader-layer interface v0, just wrappers since there is only a layer
763
764VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
765 VkExtensionProperties *pProperties) {
766 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
767}
768
769VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
770 VkLayerProperties *pProperties) {
771 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
772}
773
774VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
775 VkLayerProperties *pProperties) {
776 // the layer command handles VK_NULL_HANDLE just fine internally
777 assert(physicalDevice == VK_NULL_HANDLE);
778 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
779}
780
781VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
782 const char *pLayerName, uint32_t *pCount,
783 VkExtensionProperties *pProperties) {
784 // the layer command handles VK_NULL_HANDLE just fine internally
785 assert(physicalDevice == VK_NULL_HANDLE);
786 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
787}
788
789VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
790 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
791}
792
793VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
794 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
795}
796
797VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
798 const char *funcName) {
799 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
800}
801
802VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
803 assert(pVersionStruct != NULL);
804 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
805
806 // Fill in the function pointers if our version is at least capable of having the structure contain them.
807 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
808 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
809 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
810 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
811 }
812
813 return VK_SUCCESS;
814}"""
815
816
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600817 def __init__(self,
818 errFile = sys.stderr,
819 warnFile = sys.stderr,
820 diagFile = sys.stdout):
821 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
822 # Internal state - accumulators for different inner block text
823 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
824 self.intercepts = []
825 self.layer_factory = '' # String containing base layer factory class definition
826
827 # Check if the parameter passed in is a pointer to an array
828 def paramIsArray(self, param):
829 return param.attrib.get('len') is not None
830
831 # Check if the parameter passed in is a pointer
832 def paramIsPointer(self, param):
833 ispointer = False
834 for elem in param:
835 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
836 ispointer = True
837 return ispointer
838
839 # Check if an object is a non-dispatchable handle
840 def isHandleTypeNonDispatchable(self, handletype):
841 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
842 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
843 return True
844 else:
845 return False
846
847 # Check if an object is a dispatchable handle
848 def isHandleTypeDispatchable(self, handletype):
849 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
850 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
851 return True
852 else:
853 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700854 #
855 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600856 def beginFile(self, genOpts):
857 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700858 # Output Copyright
859 write(self.inline_copyright_message, file=self.outFile)
860 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600861 self.header = False
862 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
863 self.header = True
864 write('#pragma once', file=self.outFile)
865 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600866 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700867 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600868 else:
869 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700870 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700871 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600872 #
873 def endFile(self):
874 # Finish C++ namespace and multiple inclusion protection
875 self.newline()
876 if not self.header:
877 # Record intercepted procedures
878 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
879 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
880 write('\n'.join(self.intercepts), file=self.outFile)
881 write('};\n', file=self.outFile)
882 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600883 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600884 if self.header:
885 self.newline()
886 # Output Layer Factory Class Definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600887 self.layer_factory += '};\n\n'
888 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600889 write(self.layer_factory, file=self.outFile)
890 else:
891 write(self.inline_custom_source_postamble, file=self.outFile)
892 # Finish processing in superclass
893 OutputGenerator.endFile(self)
894
895 def beginFeature(self, interface, emit):
896 # Start processing in superclass
897 OutputGenerator.beginFeature(self, interface, emit)
898 # Get feature extra protect
899 self.featureExtraProtect = GetFeatureProtect(interface)
900 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
901 # feature. They're only printed in endFeature().
902 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
903
904 def endFeature(self):
905 # Actually write the interface to the output file.
906 if (self.emit):
907 self.newline()
908 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
909 # or move it below the 'for section...' loop.
910 if (self.featureExtraProtect != None):
911 write('#ifdef', self.featureExtraProtect, file=self.outFile)
912 for section in self.TYPE_SECTIONS:
913 contents = self.sections[section]
914 if contents:
915 write('\n'.join(contents), file=self.outFile)
916 self.newline()
917 if (self.sections['command']):
918 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
919 self.newline()
920 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600921 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600922 # Finish processing in superclass
923 OutputGenerator.endFeature(self)
924 #
925 # Append a definition to the specified section
926 def appendSection(self, section, text):
927 self.sections[section].append(text)
928 #
929 # Type generation
930 def genType(self, typeinfo, name, alias):
931 pass
932 #
933 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
934 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
935 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
936 # structs etc.)
937 def genStruct(self, typeinfo, typeName):
938 OutputGenerator.genStruct(self, typeinfo, typeName)
939 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
940 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
941 for member in typeinfo.elem.findall('.//member'):
942 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
943 body += ';\n'
944 body += '} ' + typeName + ';\n'
945 self.appendSection('struct', body)
946 #
947 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
948 def genGroup(self, groupinfo, groupName, alias):
949 pass
950 # Enumerant generation
951 # <enum> tags may specify their values in several ways, but are usually just integers.
952 def genEnum(self, enuminfo, name, alias):
953 pass
954 #
955 # Customize Cdecl for layer factory base class
956 def BaseClassCdecl(self, elem, name):
957 raw = self.makeCDecls(elem)[1]
958
959 # Toss everything before the undecorated name
960 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
961 prototype = prototype.replace(")", "", 1)
962 prototype = prototype.replace(";", " {};")
963
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600964 # Build up pre/post call virtual function declarations
965 pre_call_validate = 'virtual bool PreCallValidate' + prototype
966 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
967 pre_call_record = 'virtual void PreCallRecord' + prototype
968 post_call_record = 'virtual void PostCallRecord' + prototype
969 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
970 #
971 # Command generation
972 def genCmd(self, cmdinfo, name, alias):
973 ignore_functions = [
974 'vkEnumerateInstanceVersion'
975 ]
976
977 if name in ignore_functions:
978 return
979
980 if self.header: # In the header declare all intercepts
981 self.appendSection('command', '')
982 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
983 if (self.featureExtraProtect != None):
984 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
985 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
986 # Update base class with virtual function declarations
987 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
988 # Update function intercepts
989 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
990 if (self.featureExtraProtect != None):
991 self.intercepts += [ '#endif' ]
992 self.layer_factory += '#endif\n'
993 return
994
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700995 if name in self.manual_functions:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600996 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
997 return
998 # Record that the function will be intercepted
999 if (self.featureExtraProtect != None):
1000 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1001 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1002 if (self.featureExtraProtect != None):
1003 self.intercepts += [ '#endif' ]
1004 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1005 #
1006 decls = self.makeCDecls(cmdinfo.elem)
1007 self.appendSection('command', '')
1008 self.appendSection('command', '%s {' % decls[0][:-1])
1009 # Setup common to call wrappers. First parameter is always dispatchable
1010 dispatchable_type = cmdinfo.elem.find('param/type').text
1011 dispatchable_name = cmdinfo.elem.find('param/name').text
1012 # Default to device
1013 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001014 dispatch_table_name = 'VkLayerDispatchTable'
1015 # Set to instance as necessary
1016 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1017 device_or_instance = 'instance'
1018 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001019 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001020 api_function_name = cmdinfo.elem.attrib.get('name')
1021 params = cmdinfo.elem.findall('param/name')
1022 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001023 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001024
1025 # Declare result variable, if any.
1026 return_map = {
1027 'void': 'return;',
1028 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1029 'PFN_vkVoidFunction': 'return nullptr;',
1030 'VkBool32': 'return VK_FALSE;',
1031 }
1032 resulttype = cmdinfo.elem.find('proto/type')
1033 assignresult = ''
1034 if (resulttype.text != 'void'):
1035 assignresult = resulttype.text + ' result = '
1036
1037 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001038 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001039
1040 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001041 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001042 self.appendSection('command', ' intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001043 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001044 self.appendSection('command', ' intercept->write_unlock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001045 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1046 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001047
1048 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001049 self.appendSection('command', ' %s' % self.precallrecord_loop)
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001050 self.appendSection('command', ' intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001051 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001052 self.appendSection('command', ' intercept->write_unlock();')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001053 self.appendSection('command', ' }')
1054
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001055 # Insert pre-dispatch debug utils function call
1056 if name in self.pre_dispatch_debug_utils_functions:
1057 self.appendSection('command', ' {')
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001058 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->validation_object_mutex);')
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001059 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
1060 self.appendSection('command', ' }')
1061
1062 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001063 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001064
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001065 # Insert post-dispatch debug utils function call
1066 if name in self.post_dispatch_debug_utils_functions:
1067 self.appendSection('command', ' {')
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001068 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->validation_object_mutex);')
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001069 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
1070 self.appendSection('command', ' }')
1071
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001072 # Generate post-call object processing source code
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001073 return_type_indent = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001074 if (resulttype.text == 'VkResult'):
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001075 return_type_indent = ' '
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001076 if name in self.alt_ret_codes:
Mark Lobodzinskib3c94842018-11-27 10:01:51 -07001077 self.appendSection('command', ' if ((VK_SUCCESS == result) || (VK_INCOMPLETE == result)) {')
1078 else:
1079 self.appendSection('command', ' if (VK_SUCCESS == result) {')
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001080
1081 self.appendSection('command', '%s %s' % (return_type_indent, self.postcallrecord_loop))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001082 self.appendSection('command', '%s intercept->write_lock();' % return_type_indent)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001083 self.appendSection('command', '%s intercept->PostCallRecord%s(%s);' % (return_type_indent,api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001084 self.appendSection('command', '%s intercept->write_unlock();' % return_type_indent)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001085 self.appendSection('command', '%s }' % return_type_indent)
1086 if (resulttype.text == 'VkResult'):
1087 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001088
1089 # Return result variable, if any.
1090 if (resulttype.text != 'void'):
1091 self.appendSection('command', ' return result;')
1092 self.appendSection('command', '}')
1093 #
1094 # Override makeProtoName to drop the "vk" prefix
1095 def makeProtoName(self, name, tail):
1096 return self.genOpts.apientry + name[2:] + tail