blob: f36c132ea049b83c9c6e78f1d05b8d7d3c6343a9 [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
3# Copyright (c) 2015-2016 Valve Corporation
4# Copyright (c) 2015-2016 LunarG, Inc.
5# Copyright (c) 2015-2016 Google Inc.
6#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
20# Author: Mark Lobodzinski <mark@lunarg.com>
21#
22# This script generates the dispatch portion of a factory layer which intercepts
23# all Vulkan functions. The resultant factory layer allows rapid development of
24# layers and interceptors.
25
26import os,re,sys
27from generator import *
28from common_codegen import *
29
30# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31#
32# Adds options used by LayerFactoryOutputGenerator objects during factory
33# layer generation.
34#
35# Additional members
36# prefixText - list of strings to prefix generated header with
37# (usually a copyright statement + calling convention macros).
38# protectFile - True if multiple inclusion protection should be
39# generated (based on the filename) around the entire header.
40# protectFeature - True if #ifndef..#endif protection should be
41# generated around a feature interface in the header file.
42# genFuncPointers - True if function pointer typedefs should be
43# generated
44# protectProto - If conditional protection should be generated
45# around prototype declarations, set to either '#ifdef'
46# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47# to require opt-out (#ifndef protectProtoStr). Otherwise
48# set to None.
49# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50# declarations, if protectProto is set
51# apicall - string to use for the function declaration prefix,
52# such as APICALL on Windows.
53# apientry - string to use for the calling convention macro,
54# in typedefs, such as APIENTRY.
55# apientryp - string to use for the calling convention macro
56# in function pointer typedefs, such as APIENTRYP.
57# indentFuncProto - True if prototype declarations should put each
58# parameter on a separate line
59# indentFuncPointer - True if typedefed function pointers should put each
60# parameter on a separate line
61# alignFuncParam - if nonzero and parameters are being put on a
62# separate line, align parameter names at the specified column
63class LayerChassisGeneratorOptions(GeneratorOptions):
64 def __init__(self,
65 filename = None,
66 directory = '.',
67 apiname = None,
68 profile = None,
69 versions = '.*',
70 emitversions = '.*',
71 defaultExtensions = None,
72 addExtensions = None,
73 removeExtensions = None,
74 emitExtensions = None,
75 sortProcedure = regSortFeatures,
76 prefixText = "",
77 genFuncPointers = True,
78 protectFile = True,
79 protectFeature = True,
80 apicall = '',
81 apientry = '',
82 apientryp = '',
83 indentFuncProto = True,
84 indentFuncPointer = False,
85 alignFuncParam = 0,
86 helper_file_type = '',
87 expandEnumerants = True):
88 GeneratorOptions.__init__(self, filename, directory, apiname, profile,
89 versions, emitversions, defaultExtensions,
90 addExtensions, removeExtensions, emitExtensions, sortProcedure)
91 self.prefixText = prefixText
92 self.genFuncPointers = genFuncPointers
93 self.protectFile = protectFile
94 self.protectFeature = protectFeature
95 self.apicall = apicall
96 self.apientry = apientry
97 self.apientryp = apientryp
98 self.indentFuncProto = indentFuncProto
99 self.indentFuncPointer = indentFuncPointer
100 self.alignFuncParam = alignFuncParam
101
102# LayerChassisOutputGenerator - subclass of OutputGenerator.
103# Generates a LayerFactory layer that intercepts all API entrypoints
104# This is intended to be used as a starting point for creating custom layers
105#
106# ---- methods ----
107# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
108# OutputGenerator. Defines additional internal state.
109# ---- methods overriding base class ----
110# beginFile(genOpts)
111# endFile()
112# beginFeature(interface, emit)
113# endFeature()
114# genType(typeinfo,name)
115# genStruct(typeinfo,name)
116# genGroup(groupinfo,name)
117# genEnum(enuminfo, name)
118# genCmd(cmdinfo)
119class LayerChassisOutputGenerator(OutputGenerator):
120 """Generate specified API interfaces in a specific style, such as a C header"""
121 # This is an ordered list of sections in the header file.
122 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
123 'group', 'bitmask', 'funcpointer', 'struct']
124 ALL_SECTIONS = TYPE_SECTIONS + ['command']
125
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700126 manual_functions = [
127 # Include functions here to be interecpted w/ manually implemented function bodies
128 'vkGetDeviceProcAddr',
129 'vkGetInstanceProcAddr',
130 'vkGetPhysicalDeviceProcAddr',
131 'vkCreateDevice',
132 'vkDestroyDevice',
133 'vkCreateInstance',
134 'vkDestroyInstance',
135 'vkCreateDebugReportCallbackEXT',
136 'vkDestroyDebugReportCallbackEXT',
137 'vkEnumerateInstanceLayerProperties',
138 'vkEnumerateInstanceExtensionProperties',
139 'vkEnumerateDeviceLayerProperties',
140 'vkEnumerateDeviceExtensionProperties',
141 ]
142
143 alt_ret_codes = [
144 # Include functions here which must tolerate VK_INCOMPLETE as a return code
145 'vkEnumeratePhysicalDevices',
146 'vkEnumeratePhysicalDeviceGroupsKHR',
147 'vkGetValidationCacheDataEXT',
148 'vkGetPipelineCacheData',
149 'vkGetShaderInfoAMD',
150 'vkGetPhysicalDeviceDisplayPropertiesKHR',
151 'vkGetPhysicalDeviceDisplayProperties2KHR',
152 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
153 'vkGetDisplayPlaneSupportedDisplaysKHR',
154 'vkGetDisplayModePropertiesKHR',
155 'vkGetDisplayModeProperties2KHR',
156 'vkGetPhysicalDeviceSurfaceFormatsKHR',
157 'vkGetPhysicalDeviceSurfacePresentModesKHR',
158 'vkGetPhysicalDevicePresentRectanglesKHR',
159 'vkGetPastPresentationTimingGOOGLE',
160 'vkGetSwapchainImagesKHR',
161 'vkEnumerateInstanceLayerProperties',
162 'vkEnumerateDeviceLayerProperties',
163 'vkEnumerateInstanceExtensionProperties',
164 'vkEnumerateDeviceExtensionProperties',
165 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
166 ]
167
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700168 pre_dispatch_debug_utils_functions = {
169 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->debugUtilsObjectNameMap->insert(std::make_pair<uint64_t, std::string>((uint64_t &&) pNameInfo->objectHandle, pNameInfo->pObjectName));',
170 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
171 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
172 'vkCmdBeginDebugUtilsLabelEXT' : 'BeginCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
173 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
174 }
175
176 post_dispatch_debug_utils_functions = {
177 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
178 'vkCmdEndDebugUtilsLabelEXT' : 'EndCmdDebugUtilsLabel(layer_data->report_data, commandBuffer);',
179 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
180 }
181
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600182 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
183 precallrecord_loop = precallvalidate_loop
184 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600185
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700186 inline_custom_header_preamble = """
187#define NOMINMAX
188#include <mutex>
189#include <cinttypes>
190#include <stdio.h>
191#include <stdlib.h>
192#include <string.h>
193#include <unordered_map>
194#include <unordered_set>
195#include <algorithm>
196#include <memory>
197
198#include "vk_loader_platform.h"
199#include "vulkan/vulkan.h"
200#include "vk_layer_config.h"
201#include "vk_layer_data.h"
202#include "vk_layer_logging.h"
203#include "vk_object_types.h"
204#include "vulkan/vk_layer.h"
205#include "vk_enum_string_helper.h"
206#include "vk_layer_extension_utils.h"
207#include "vk_layer_utils.h"
208#include "vulkan/vk_layer.h"
209#include "vk_dispatch_table_helper.h"
210#include "vk_validation_error_messages.h"
211#include "vk_extension_helper.h"
212#include "vk_safe_struct.h"
213
214extern uint64_t global_unique_id;
215extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
216"""
217
218 inline_custom_header_class_definition = """
219
220// Layer object type identifiers
221enum LayerObjectTypeId {
222 LayerObjectTypeThreading,
223 LayerObjectTypeParameterValidation,
224 LayerObjectTypeObjectTracker,
225 LayerObjectTypeCoreValidation,
226};
227
228struct TEMPLATE_STATE {
229 VkDescriptorUpdateTemplateKHR desc_update_template;
230 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
231
232 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
233 : desc_update_template(update_template), create_info(*pCreateInfo) {}
234};
235
236// Layer chassis validation object base class definition
237class ValidationObject {
238 public:
239 uint32_t api_version;
240 debug_report_data* report_data = nullptr;
241 std::vector<VkDebugReportCallbackEXT> logging_callback;
242 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
243
244 VkLayerInstanceDispatchTable instance_dispatch_table;
245 VkLayerDispatchTable device_dispatch_table;
246
247 InstanceExtensions instance_extensions;
248 DeviceExtensions device_extensions = {};
249
250 VkInstance instance = VK_NULL_HANDLE;
251 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
252 VkDevice device = VK_NULL_HANDLE;
253
254 std::vector<ValidationObject*> object_dispatch;
255 LayerObjectTypeId container_type;
256
257 // Constructor
258 ValidationObject(){};
259 // Destructor
260 virtual ~ValidationObject() {};
261
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700262 std::mutex validation_object_mutex;
263 virtual void write_lock() { validation_object_mutex.lock(); }
264 virtual void write_unlock() { validation_object_mutex.unlock(); }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700265
266 std::string layer_name = "CHASSIS";
267
268 // Handle Wrapping Data
269 // Reverse map display handles
270 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
271 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
272 std::unordered_set<std::string> device_extension_set;
273 struct SubpassesUsageStates {
274 std::unordered_set<uint32_t> subpasses_using_color_attachment;
275 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
276 };
277 // Uses unwrapped handles
278 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
279 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
280 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
281 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700282 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
283 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700284
285
286 // Unwrap a handle. Must hold lock.
287 template <typename HandleType>
288 HandleType Unwrap(HandleType wrappedHandle) {
289 // TODO: don't use operator[] here.
290 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
291 }
292
293 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
294 template <typename HandleType>
295 HandleType WrapNew(HandleType newlyCreatedHandle) {
296 auto unique_id = global_unique_id++;
297 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
298 return (HandleType)unique_id;
299 }
300
301 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
302 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
303 auto unique_id = global_unique_id++;
304 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
305 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
306 return (VkDisplayKHR)unique_id;
307 }
308
309 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
310 // creating another. Must hold lock.
311 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
312 // See if this display is already known
313 auto it = map_data->display_id_reverse_mapping.find(handle);
314 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
315 // Unknown, so wrap
316 return WrapDisplay(handle, map_data);
317 }
318
319 // Pre/post hook point declarations
320"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600321
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700322 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600323// This file is ***GENERATED***. Do Not Edit.
324// See layer_chassis_generator.py for modifications.
325
326/* Copyright (c) 2015-2018 The Khronos Group Inc.
327 * Copyright (c) 2015-2018 Valve Corporation
328 * Copyright (c) 2015-2018 LunarG, Inc.
329 * Copyright (c) 2015-2018 Google Inc.
330 *
331 * Licensed under the Apache License, Version 2.0 (the "License");
332 * you may not use this file except in compliance with the License.
333 * You may obtain a copy of the License at
334 *
335 * http://www.apache.org/licenses/LICENSE-2.0
336 *
337 * Unless required by applicable law or agreed to in writing, software
338 * distributed under the License is distributed on an "AS IS" BASIS,
339 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
340 * See the License for the specific language governing permissions and
341 * limitations under the License.
342 *
343 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700344 */"""
345
346 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600347
348#include <string.h>
349#include <mutex>
350
351#define VALIDATION_ERROR_MAP_IMPL
352
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600353#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700354#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600355
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600356std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600357
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700358// Global unique object identifier. All increments must be guarded by a lock.
359uint64_t global_unique_id = 1;
360// Map uniqueID to actual object handle
361std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
362
363// TODO: This variable controls handle wrapping -- in the future it should be hooked
364// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
365#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
366bool wrap_handles = true;
367#else
368const bool wrap_handles = false;
369#endif
370
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600371// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700372#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600373#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700374#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700375#elif BUILD_THREAD_SAFETY
376#include "thread_safety_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700377#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
378#elif BUILD_PARAMETER_VALIDATION
379#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
380#elif BUILD_CORE_VALIDATION
381#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
382#else
383#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
384#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600385
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600386namespace vulkan_layer_chassis {
387
388using std::unordered_map;
389
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600390static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700391 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600392};
393
394static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
395
396extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
397
398
399// Manually written functions
400
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700401// Check enabled instance extensions against supported instance extension whitelist
402static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
403 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
404 // Check for recognized instance extensions
405 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
406 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
407 kVUIDUndefined,
408 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
409 "results and/or produce undefined behavior.",
410 pCreateInfo->ppEnabledExtensionNames[i]);
411 }
412 }
413}
414
415// Check enabled device extensions against supported device extension whitelist
416static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
417 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
418 // Check for recognized device extensions
419 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
420 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
421 kVUIDUndefined,
422 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
423 "results and/or produce undefined behavior.",
424 pCreateInfo->ppEnabledExtensionNames[i]);
425 }
426 }
427}
428
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600429VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600430 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700431 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extension_set)) {
432 return nullptr;
433 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600434 const auto &item = name_to_funcptr_map.find(funcName);
435 if (item != name_to_funcptr_map.end()) {
436 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
437 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600438 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600439 if (!table.GetDeviceProcAddr) return nullptr;
440 return table.GetDeviceProcAddr(device, funcName);
441}
442
443VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600444 const auto &item = name_to_funcptr_map.find(funcName);
445 if (item != name_to_funcptr_map.end()) {
446 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
447 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600448 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
449 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600450 if (!table.GetInstanceProcAddr) return nullptr;
451 return table.GetInstanceProcAddr(instance, funcName);
452}
453
454VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600455 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
456 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600457 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
458 return table.GetPhysicalDeviceProcAddr(instance, funcName);
459}
460
461VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
462 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
463}
464
465VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
466 VkLayerProperties *pProperties) {
467 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
468}
469
470VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
471 VkExtensionProperties *pProperties) {
472 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
473 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
474
475 return VK_ERROR_LAYER_NOT_PRESENT;
476}
477
478VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
479 uint32_t *pCount, VkExtensionProperties *pProperties) {
480 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600481 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600482 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
483 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600484}
485
486VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
487 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600488 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600489
490 assert(chain_info->u.pLayerInfo);
491 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
492 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
493 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
494 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
495
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600496 // Create temporary dispatch vector for pre-calls until instance is created
497 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700498#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600499 auto object_tracker = new ObjectLifetimes;
500 local_object_dispatch.emplace_back(object_tracker);
501 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700502#elif BUILD_THREAD_SAFETY
503 auto thread_checker = new ThreadSafety;
504 local_object_dispatch.emplace_back(thread_checker);
505 thread_checker->container_type = LayerObjectTypeThreading;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700506#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600507
508
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600509 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600510 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600511 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
512 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600513 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600514 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
515 }
516
517 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600518 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600519
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600520 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600521
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600522 framework->object_dispatch = local_object_dispatch;
523
524 framework->instance = *pInstance;
525 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
526 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
527 pCreateInfo->ppEnabledExtensionNames);
528 framework->api_version = framework->instance_extensions.InitFromInstanceCreateInfo(
529 (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0), pCreateInfo);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700530#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600531 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700532#elif BUILD_THREAD_SAFETY
533 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "google_thread_checker");
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700534#else
535 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
536#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600537
538 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600539 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
540 }
541
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700542 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
543
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600544 return result;
545}
546
547VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
548 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600549 auto layer_data = GetLayerDataPtr(key, layer_data_map);
550 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700551 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600552 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700553 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600554 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600555 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700556 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600557 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700558 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600559 }
560
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600561 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600562
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600563 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700564 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600565 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700566 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600567 }
568 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600569 while (layer_data->logging_messenger.size() > 0) {
570 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
571 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
572 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600573 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600574 while (layer_data->logging_callback.size() > 0) {
575 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
576 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
577 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600578 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600579
580 layer_debug_utils_destroy_instance(layer_data->report_data);
581
582 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600583}
584
585VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
586 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600587 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600588
589 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
590
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600591 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
592 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600593 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
594 if (fpCreateDevice == NULL) {
595 return VK_ERROR_INITIALIZATION_FAILED;
596 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600597 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
598
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600599 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700600 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600601 intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700602 intercept->write_unlock();
603
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600604 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600605 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700606 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600607 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700608 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600609 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600610
611 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600612 if (result != VK_SUCCESS) {
613 return result;
614 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600615
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600616 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
617 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700618 // Save pCreateInfo device extension list for GetDeviceProcAddr()
619 for (uint32_t extn = 0; extn < pCreateInfo->enabledExtensionCount; extn++) {
620 device_interceptor->device_extension_set.insert(pCreateInfo->ppEnabledExtensionNames[extn]);
621 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600622 device_interceptor->device = *pDevice;
623 device_interceptor->physical_device = gpu;
624 device_interceptor->instance = instance_interceptor->instance;
625 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
626 device_interceptor->api_version = instance_interceptor->api_version;
627
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700628#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600629 // Create child layer objects for this key and add to dispatch vector
630 auto object_tracker = new ObjectLifetimes;
631 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
632 object_tracker->container_type = LayerObjectTypeObjectTracker;
633 object_tracker->physical_device = gpu;
634 object_tracker->instance = instance_interceptor->instance;
635 object_tracker->report_data = device_interceptor->report_data;
636 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
637 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700638#elif BUILD_THREAD_SAFETY
639 auto thread_safety = new ThreadSafety;
640 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
641 thread_safety->container_type = LayerObjectTypeThreading;
642 thread_safety->physical_device = gpu;
643 thread_safety->instance = instance_interceptor->instance;
644 thread_safety->report_data = device_interceptor->report_data;
645 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
646 device_interceptor->object_dispatch.emplace_back(thread_safety);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700647#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600648
649 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700650 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600651 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700652 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600653 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600654
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700655 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
656
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600657 return result;
658}
659
660VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
661 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600662 auto layer_data = GetLayerDataPtr(key, layer_data_map);
663 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700664 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600665 intercept->PreCallValidateDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700666 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600667 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600668 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700669 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600670 intercept->PreCallRecordDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700671 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600672 }
673 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600674
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600675 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600676
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600677 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700678 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600679 intercept->PostCallRecordDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700680 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600681 }
682
683 FreeLayerDataPtr(key, layer_data_map);
684}
685
686VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
687 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
688 const VkAllocationCallbacks *pAllocator,
689 VkDebugReportCallbackEXT *pCallback) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600690 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
691 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700692 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600693 intercept->PreCallValidateCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700694 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600695 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600696 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700697 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600698 intercept->PreCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700699 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600700 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700701 VkResult result = DispatchCreateDebugReportCallbackEXT(layer_data, instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600702 result = layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);
703 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700704 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600705 intercept->PostCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700706 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600707 }
708 return result;
709}
710
711VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
712 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600713 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
714 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700715 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600716 intercept->PreCallValidateDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700717 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600718 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600719 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700720 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600721 intercept->PreCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700722 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600723 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700724 DispatchDestroyDebugReportCallbackEXT(layer_data, instance, callback, pAllocator);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600725 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
726 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700727 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600728 intercept->PostCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700729 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600730 }
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700731}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600732
733 inline_custom_source_postamble = """
734// loader-layer interface v0, just wrappers since there is only a layer
735
736VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
737 VkExtensionProperties *pProperties) {
738 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
739}
740
741VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
742 VkLayerProperties *pProperties) {
743 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
744}
745
746VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
747 VkLayerProperties *pProperties) {
748 // the layer command handles VK_NULL_HANDLE just fine internally
749 assert(physicalDevice == VK_NULL_HANDLE);
750 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
751}
752
753VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
754 const char *pLayerName, uint32_t *pCount,
755 VkExtensionProperties *pProperties) {
756 // the layer command handles VK_NULL_HANDLE just fine internally
757 assert(physicalDevice == VK_NULL_HANDLE);
758 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
759}
760
761VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
762 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
763}
764
765VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
766 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
767}
768
769VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
770 const char *funcName) {
771 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
772}
773
774VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
775 assert(pVersionStruct != NULL);
776 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
777
778 // Fill in the function pointers if our version is at least capable of having the structure contain them.
779 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
780 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
781 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
782 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
783 }
784
785 return VK_SUCCESS;
786}"""
787
788
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600789 def __init__(self,
790 errFile = sys.stderr,
791 warnFile = sys.stderr,
792 diagFile = sys.stdout):
793 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
794 # Internal state - accumulators for different inner block text
795 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
796 self.intercepts = []
797 self.layer_factory = '' # String containing base layer factory class definition
798
799 # Check if the parameter passed in is a pointer to an array
800 def paramIsArray(self, param):
801 return param.attrib.get('len') is not None
802
803 # Check if the parameter passed in is a pointer
804 def paramIsPointer(self, param):
805 ispointer = False
806 for elem in param:
807 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
808 ispointer = True
809 return ispointer
810
811 # Check if an object is a non-dispatchable handle
812 def isHandleTypeNonDispatchable(self, handletype):
813 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
814 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
815 return True
816 else:
817 return False
818
819 # Check if an object is a dispatchable handle
820 def isHandleTypeDispatchable(self, handletype):
821 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
822 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
823 return True
824 else:
825 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700826 #
827 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600828 def beginFile(self, genOpts):
829 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700830 # Output Copyright
831 write(self.inline_copyright_message, file=self.outFile)
832 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600833 self.header = False
834 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
835 self.header = True
836 write('#pragma once', file=self.outFile)
837 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600838 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700839 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600840 else:
841 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700842 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700843 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600844 #
845 def endFile(self):
846 # Finish C++ namespace and multiple inclusion protection
847 self.newline()
848 if not self.header:
849 # Record intercepted procedures
850 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
851 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
852 write('\n'.join(self.intercepts), file=self.outFile)
853 write('};\n', file=self.outFile)
854 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600855 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600856 if self.header:
857 self.newline()
858 # Output Layer Factory Class Definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600859 self.layer_factory += '};\n\n'
860 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600861 write(self.layer_factory, file=self.outFile)
862 else:
863 write(self.inline_custom_source_postamble, file=self.outFile)
864 # Finish processing in superclass
865 OutputGenerator.endFile(self)
866
867 def beginFeature(self, interface, emit):
868 # Start processing in superclass
869 OutputGenerator.beginFeature(self, interface, emit)
870 # Get feature extra protect
871 self.featureExtraProtect = GetFeatureProtect(interface)
872 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
873 # feature. They're only printed in endFeature().
874 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
875
876 def endFeature(self):
877 # Actually write the interface to the output file.
878 if (self.emit):
879 self.newline()
880 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
881 # or move it below the 'for section...' loop.
882 if (self.featureExtraProtect != None):
883 write('#ifdef', self.featureExtraProtect, file=self.outFile)
884 for section in self.TYPE_SECTIONS:
885 contents = self.sections[section]
886 if contents:
887 write('\n'.join(contents), file=self.outFile)
888 self.newline()
889 if (self.sections['command']):
890 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
891 self.newline()
892 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600893 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600894 # Finish processing in superclass
895 OutputGenerator.endFeature(self)
896 #
897 # Append a definition to the specified section
898 def appendSection(self, section, text):
899 self.sections[section].append(text)
900 #
901 # Type generation
902 def genType(self, typeinfo, name, alias):
903 pass
904 #
905 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
906 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
907 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
908 # structs etc.)
909 def genStruct(self, typeinfo, typeName):
910 OutputGenerator.genStruct(self, typeinfo, typeName)
911 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
912 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
913 for member in typeinfo.elem.findall('.//member'):
914 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
915 body += ';\n'
916 body += '} ' + typeName + ';\n'
917 self.appendSection('struct', body)
918 #
919 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
920 def genGroup(self, groupinfo, groupName, alias):
921 pass
922 # Enumerant generation
923 # <enum> tags may specify their values in several ways, but are usually just integers.
924 def genEnum(self, enuminfo, name, alias):
925 pass
926 #
927 # Customize Cdecl for layer factory base class
928 def BaseClassCdecl(self, elem, name):
929 raw = self.makeCDecls(elem)[1]
930
931 # Toss everything before the undecorated name
932 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
933 prototype = prototype.replace(")", "", 1)
934 prototype = prototype.replace(";", " {};")
935
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600936 # Build up pre/post call virtual function declarations
937 pre_call_validate = 'virtual bool PreCallValidate' + prototype
938 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
939 pre_call_record = 'virtual void PreCallRecord' + prototype
940 post_call_record = 'virtual void PostCallRecord' + prototype
941 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
942 #
943 # Command generation
944 def genCmd(self, cmdinfo, name, alias):
945 ignore_functions = [
946 'vkEnumerateInstanceVersion'
947 ]
948
949 if name in ignore_functions:
950 return
951
952 if self.header: # In the header declare all intercepts
953 self.appendSection('command', '')
954 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
955 if (self.featureExtraProtect != None):
956 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
957 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
958 # Update base class with virtual function declarations
959 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
960 # Update function intercepts
961 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
962 if (self.featureExtraProtect != None):
963 self.intercepts += [ '#endif' ]
964 self.layer_factory += '#endif\n'
965 return
966
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700967 if name in self.manual_functions:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600968 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
969 return
970 # Record that the function will be intercepted
971 if (self.featureExtraProtect != None):
972 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
973 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
974 if (self.featureExtraProtect != None):
975 self.intercepts += [ '#endif' ]
976 OutputGenerator.genCmd(self, cmdinfo, name, alias)
977 #
978 decls = self.makeCDecls(cmdinfo.elem)
979 self.appendSection('command', '')
980 self.appendSection('command', '%s {' % decls[0][:-1])
981 # Setup common to call wrappers. First parameter is always dispatchable
982 dispatchable_type = cmdinfo.elem.find('param/type').text
983 dispatchable_name = cmdinfo.elem.find('param/name').text
984 # Default to device
985 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600986 dispatch_table_name = 'VkLayerDispatchTable'
987 # Set to instance as necessary
988 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
989 device_or_instance = 'instance'
990 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600991 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600992 api_function_name = cmdinfo.elem.attrib.get('name')
993 params = cmdinfo.elem.findall('param/name')
994 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700995 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600996
997 # Declare result variable, if any.
998 return_map = {
999 'void': 'return;',
1000 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1001 'PFN_vkVoidFunction': 'return nullptr;',
1002 'VkBool32': 'return VK_FALSE;',
1003 }
1004 resulttype = cmdinfo.elem.find('proto/type')
1005 assignresult = ''
1006 if (resulttype.text != 'void'):
1007 assignresult = resulttype.text + ' result = '
1008
1009 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001010 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001011
1012 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001013 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001014 self.appendSection('command', ' intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001015 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001016 self.appendSection('command', ' intercept->write_unlock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001017 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1018 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001019
1020 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001021 self.appendSection('command', ' %s' % self.precallrecord_loop)
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001022 self.appendSection('command', ' intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001023 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001024 self.appendSection('command', ' intercept->write_unlock();')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001025 self.appendSection('command', ' }')
1026
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001027 # Insert pre-dispatch debug utils function call
1028 if name in self.pre_dispatch_debug_utils_functions:
1029 self.appendSection('command', ' {')
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001030 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->validation_object_mutex);')
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001031 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
1032 self.appendSection('command', ' }')
1033
1034 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001035 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001036
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001037 # Insert post-dispatch debug utils function call
1038 if name in self.post_dispatch_debug_utils_functions:
1039 self.appendSection('command', ' {')
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001040 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->validation_object_mutex);')
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001041 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
1042 self.appendSection('command', ' }')
1043
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001044 # Generate post-call object processing source code
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001045 return_type_indent = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001046 if (resulttype.text == 'VkResult'):
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001047 return_type_indent = ' '
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001048 if name in self.alt_ret_codes:
Mark Lobodzinskib3c94842018-11-27 10:01:51 -07001049 self.appendSection('command', ' if ((VK_SUCCESS == result) || (VK_INCOMPLETE == result)) {')
1050 else:
1051 self.appendSection('command', ' if (VK_SUCCESS == result) {')
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001052
1053 self.appendSection('command', '%s %s' % (return_type_indent, self.postcallrecord_loop))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001054 self.appendSection('command', '%s intercept->write_lock();' % return_type_indent)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001055 self.appendSection('command', '%s intercept->PostCallRecord%s(%s);' % (return_type_indent,api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001056 self.appendSection('command', '%s intercept->write_unlock();' % return_type_indent)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001057 self.appendSection('command', '%s }' % return_type_indent)
1058 if (resulttype.text == 'VkResult'):
1059 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001060
1061 # Return result variable, if any.
1062 if (resulttype.text != 'void'):
1063 self.appendSection('command', ' return result;')
1064 self.appendSection('command', '}')
1065 #
1066 # Override makeProtoName to drop the "vk" prefix
1067 def makeProtoName(self, name, tail):
1068 return self.genOpts.apientry + name[2:] + tail