blob: 1fc4e91441dbaebda8b26fa45448394c364b9aee [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
262 std::mutex layer_mutex;
263
264 std::string layer_name = "CHASSIS";
265
266 // Handle Wrapping Data
267 // Reverse map display handles
268 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
269 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
270 std::unordered_set<std::string> device_extension_set;
271 struct SubpassesUsageStates {
272 std::unordered_set<uint32_t> subpasses_using_color_attachment;
273 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
274 };
275 // Uses unwrapped handles
276 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
277 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
278 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
279 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700280 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
281 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700282
283
284 // Unwrap a handle. Must hold lock.
285 template <typename HandleType>
286 HandleType Unwrap(HandleType wrappedHandle) {
287 // TODO: don't use operator[] here.
288 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
289 }
290
291 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
292 template <typename HandleType>
293 HandleType WrapNew(HandleType newlyCreatedHandle) {
294 auto unique_id = global_unique_id++;
295 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
296 return (HandleType)unique_id;
297 }
298
299 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
300 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
301 auto unique_id = global_unique_id++;
302 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
303 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
304 return (VkDisplayKHR)unique_id;
305 }
306
307 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
308 // creating another. Must hold lock.
309 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
310 // See if this display is already known
311 auto it = map_data->display_id_reverse_mapping.find(handle);
312 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
313 // Unknown, so wrap
314 return WrapDisplay(handle, map_data);
315 }
316
317 // Pre/post hook point declarations
318"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600319
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700320 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600321// This file is ***GENERATED***. Do Not Edit.
322// See layer_chassis_generator.py for modifications.
323
324/* Copyright (c) 2015-2018 The Khronos Group Inc.
325 * Copyright (c) 2015-2018 Valve Corporation
326 * Copyright (c) 2015-2018 LunarG, Inc.
327 * Copyright (c) 2015-2018 Google Inc.
328 *
329 * Licensed under the Apache License, Version 2.0 (the "License");
330 * you may not use this file except in compliance with the License.
331 * You may obtain a copy of the License at
332 *
333 * http://www.apache.org/licenses/LICENSE-2.0
334 *
335 * Unless required by applicable law or agreed to in writing, software
336 * distributed under the License is distributed on an "AS IS" BASIS,
337 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
338 * See the License for the specific language governing permissions and
339 * limitations under the License.
340 *
341 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700342 */"""
343
344 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600345
346#include <string.h>
347#include <mutex>
348
349#define VALIDATION_ERROR_MAP_IMPL
350
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600351#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700352#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600353
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600354std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600355
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700356// Global unique object identifier. All increments must be guarded by a lock.
357uint64_t global_unique_id = 1;
358// Map uniqueID to actual object handle
359std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
360
361// TODO: This variable controls handle wrapping -- in the future it should be hooked
362// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
363#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
364bool wrap_handles = true;
365#else
366const bool wrap_handles = false;
367#endif
368
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600369// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700370#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600371#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700372#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
373#elif BUILD_THREAD_CHECKER
374#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
375#elif BUILD_PARAMETER_VALIDATION
376#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
377#elif BUILD_CORE_VALIDATION
378#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
379#else
380#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
381#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600382
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600383namespace vulkan_layer_chassis {
384
385using std::unordered_map;
386
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600387static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700388 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600389};
390
391static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
392
393extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
394
395
396// Manually written functions
397
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700398// Check enabled instance extensions against supported instance extension whitelist
399static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
400 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
401 // Check for recognized instance extensions
402 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
403 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
404 kVUIDUndefined,
405 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
406 "results and/or produce undefined behavior.",
407 pCreateInfo->ppEnabledExtensionNames[i]);
408 }
409 }
410}
411
412// Check enabled device extensions against supported device extension whitelist
413static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
414 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
415 // Check for recognized device extensions
416 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
417 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
418 kVUIDUndefined,
419 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
420 "results and/or produce undefined behavior.",
421 pCreateInfo->ppEnabledExtensionNames[i]);
422 }
423 }
424}
425
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600426VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600427 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700428 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extension_set)) {
429 return nullptr;
430 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600431 const auto &item = name_to_funcptr_map.find(funcName);
432 if (item != name_to_funcptr_map.end()) {
433 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
434 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600435 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600436 if (!table.GetDeviceProcAddr) return nullptr;
437 return table.GetDeviceProcAddr(device, funcName);
438}
439
440VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600441 const auto &item = name_to_funcptr_map.find(funcName);
442 if (item != name_to_funcptr_map.end()) {
443 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
444 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600445 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
446 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600447 if (!table.GetInstanceProcAddr) return nullptr;
448 return table.GetInstanceProcAddr(instance, funcName);
449}
450
451VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600452 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
453 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600454 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
455 return table.GetPhysicalDeviceProcAddr(instance, funcName);
456}
457
458VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
459 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
460}
461
462VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
463 VkLayerProperties *pProperties) {
464 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
465}
466
467VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
468 VkExtensionProperties *pProperties) {
469 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
470 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
471
472 return VK_ERROR_LAYER_NOT_PRESENT;
473}
474
475VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
476 uint32_t *pCount, VkExtensionProperties *pProperties) {
477 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600478 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600479 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
480 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600481}
482
483VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
484 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600485 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600486
487 assert(chain_info->u.pLayerInfo);
488 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
489 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
490 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
491 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
492
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600493 // Create temporary dispatch vector for pre-calls until instance is created
494 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700495#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600496 auto object_tracker = new ObjectLifetimes;
497 local_object_dispatch.emplace_back(object_tracker);
498 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700499#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600500
501
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600502 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600503 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600504 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
505 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600506 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600507 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
508 }
509
510 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600511 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600512
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600513 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600514
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600515 framework->object_dispatch = local_object_dispatch;
516
517 framework->instance = *pInstance;
518 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
519 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
520 pCreateInfo->ppEnabledExtensionNames);
521 framework->api_version = framework->instance_extensions.InitFromInstanceCreateInfo(
522 (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0), pCreateInfo);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700523#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600524 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700525#else
526 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
527#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600528
529 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600530 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
531 }
532
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700533 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
534
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600535 return result;
536}
537
538VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
539 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600540 auto layer_data = GetLayerDataPtr(key, layer_data_map);
541 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700542 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600543 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
544 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600545 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700546 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600547 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
548 }
549
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600550 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600551
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600552 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700553 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600554 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
555 }
556 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600557 while (layer_data->logging_messenger.size() > 0) {
558 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
559 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
560 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600561 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600562 while (layer_data->logging_callback.size() > 0) {
563 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
564 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
565 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600566 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600567
568 layer_debug_utils_destroy_instance(layer_data->report_data);
569
570 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600571}
572
573VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
574 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600575 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600576
577 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
578
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600579 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
580 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600581 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
582 if (fpCreateDevice == NULL) {
583 return VK_ERROR_INITIALIZATION_FAILED;
584 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600585 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
586
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600587 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700588 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600589 intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
590 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600591 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700592 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600593 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
594 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600595
596 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600597 if (result != VK_SUCCESS) {
598 return result;
599 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600600
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600601 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
602 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700603 // Save pCreateInfo device extension list for GetDeviceProcAddr()
604 for (uint32_t extn = 0; extn < pCreateInfo->enabledExtensionCount; extn++) {
605 device_interceptor->device_extension_set.insert(pCreateInfo->ppEnabledExtensionNames[extn]);
606 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600607 device_interceptor->device = *pDevice;
608 device_interceptor->physical_device = gpu;
609 device_interceptor->instance = instance_interceptor->instance;
610 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
611 device_interceptor->api_version = instance_interceptor->api_version;
612
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700613#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600614 // Create child layer objects for this key and add to dispatch vector
615 auto object_tracker = new ObjectLifetimes;
616 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
617 object_tracker->container_type = LayerObjectTypeObjectTracker;
618 object_tracker->physical_device = gpu;
619 object_tracker->instance = instance_interceptor->instance;
620 object_tracker->report_data = device_interceptor->report_data;
621 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
622 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700623#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600624
625 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700626 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600627 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
628 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600629
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700630 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
631
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600632 return result;
633}
634
635VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
636 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600637 auto layer_data = GetLayerDataPtr(key, layer_data_map);
638 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700639 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600640 intercept->PreCallValidateDestroyDevice(device, pAllocator);
641 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600642 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700643 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600644 intercept->PreCallRecordDestroyDevice(device, pAllocator);
645 }
646 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600647
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600648 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600649
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600650 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700651 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600652 intercept->PostCallRecordDestroyDevice(device, pAllocator);
653 }
654
655 FreeLayerDataPtr(key, layer_data_map);
656}
657
658VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
659 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
660 const VkAllocationCallbacks *pAllocator,
661 VkDebugReportCallbackEXT *pCallback) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600662 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
663 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700664 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600665 intercept->PreCallValidateCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
666 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600667 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700668 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600669 intercept->PreCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
670 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700671 VkResult result = DispatchCreateDebugReportCallbackEXT(layer_data, instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600672 result = layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);
673 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700674 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600675 intercept->PostCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
676 }
677 return result;
678}
679
680VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
681 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600682 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
683 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700684 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600685 intercept->PreCallValidateDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
686 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600687 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700688 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600689 intercept->PreCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
690 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700691 DispatchDestroyDebugReportCallbackEXT(layer_data, instance, callback, pAllocator);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600692 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
693 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700694 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600695 intercept->PostCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
696 }
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700697}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600698
699 inline_custom_source_postamble = """
700// loader-layer interface v0, just wrappers since there is only a layer
701
702VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
703 VkExtensionProperties *pProperties) {
704 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
705}
706
707VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
708 VkLayerProperties *pProperties) {
709 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
710}
711
712VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
713 VkLayerProperties *pProperties) {
714 // the layer command handles VK_NULL_HANDLE just fine internally
715 assert(physicalDevice == VK_NULL_HANDLE);
716 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
717}
718
719VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
720 const char *pLayerName, uint32_t *pCount,
721 VkExtensionProperties *pProperties) {
722 // the layer command handles VK_NULL_HANDLE just fine internally
723 assert(physicalDevice == VK_NULL_HANDLE);
724 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
725}
726
727VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
728 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
729}
730
731VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
732 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
733}
734
735VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
736 const char *funcName) {
737 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
738}
739
740VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
741 assert(pVersionStruct != NULL);
742 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
743
744 // Fill in the function pointers if our version is at least capable of having the structure contain them.
745 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
746 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
747 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
748 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
749 }
750
751 return VK_SUCCESS;
752}"""
753
754
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600755 def __init__(self,
756 errFile = sys.stderr,
757 warnFile = sys.stderr,
758 diagFile = sys.stdout):
759 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
760 # Internal state - accumulators for different inner block text
761 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
762 self.intercepts = []
763 self.layer_factory = '' # String containing base layer factory class definition
764
765 # Check if the parameter passed in is a pointer to an array
766 def paramIsArray(self, param):
767 return param.attrib.get('len') is not None
768
769 # Check if the parameter passed in is a pointer
770 def paramIsPointer(self, param):
771 ispointer = False
772 for elem in param:
773 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
774 ispointer = True
775 return ispointer
776
777 # Check if an object is a non-dispatchable handle
778 def isHandleTypeNonDispatchable(self, handletype):
779 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
780 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
781 return True
782 else:
783 return False
784
785 # Check if an object is a dispatchable handle
786 def isHandleTypeDispatchable(self, handletype):
787 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
788 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
789 return True
790 else:
791 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700792 #
793 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600794 def beginFile(self, genOpts):
795 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700796 # Output Copyright
797 write(self.inline_copyright_message, file=self.outFile)
798 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600799 self.header = False
800 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
801 self.header = True
802 write('#pragma once', file=self.outFile)
803 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600804 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700805 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600806 else:
807 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700808 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700809 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600810 #
811 def endFile(self):
812 # Finish C++ namespace and multiple inclusion protection
813 self.newline()
814 if not self.header:
815 # Record intercepted procedures
816 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
817 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
818 write('\n'.join(self.intercepts), file=self.outFile)
819 write('};\n', file=self.outFile)
820 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600821 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600822 if self.header:
823 self.newline()
824 # Output Layer Factory Class Definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600825 self.layer_factory += '};\n\n'
826 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600827 write(self.layer_factory, file=self.outFile)
828 else:
829 write(self.inline_custom_source_postamble, file=self.outFile)
830 # Finish processing in superclass
831 OutputGenerator.endFile(self)
832
833 def beginFeature(self, interface, emit):
834 # Start processing in superclass
835 OutputGenerator.beginFeature(self, interface, emit)
836 # Get feature extra protect
837 self.featureExtraProtect = GetFeatureProtect(interface)
838 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
839 # feature. They're only printed in endFeature().
840 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
841
842 def endFeature(self):
843 # Actually write the interface to the output file.
844 if (self.emit):
845 self.newline()
846 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
847 # or move it below the 'for section...' loop.
848 if (self.featureExtraProtect != None):
849 write('#ifdef', self.featureExtraProtect, file=self.outFile)
850 for section in self.TYPE_SECTIONS:
851 contents = self.sections[section]
852 if contents:
853 write('\n'.join(contents), file=self.outFile)
854 self.newline()
855 if (self.sections['command']):
856 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
857 self.newline()
858 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600859 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600860 # Finish processing in superclass
861 OutputGenerator.endFeature(self)
862 #
863 # Append a definition to the specified section
864 def appendSection(self, section, text):
865 self.sections[section].append(text)
866 #
867 # Type generation
868 def genType(self, typeinfo, name, alias):
869 pass
870 #
871 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
872 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
873 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
874 # structs etc.)
875 def genStruct(self, typeinfo, typeName):
876 OutputGenerator.genStruct(self, typeinfo, typeName)
877 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
878 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
879 for member in typeinfo.elem.findall('.//member'):
880 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
881 body += ';\n'
882 body += '} ' + typeName + ';\n'
883 self.appendSection('struct', body)
884 #
885 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
886 def genGroup(self, groupinfo, groupName, alias):
887 pass
888 # Enumerant generation
889 # <enum> tags may specify their values in several ways, but are usually just integers.
890 def genEnum(self, enuminfo, name, alias):
891 pass
892 #
893 # Customize Cdecl for layer factory base class
894 def BaseClassCdecl(self, elem, name):
895 raw = self.makeCDecls(elem)[1]
896
897 # Toss everything before the undecorated name
898 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
899 prototype = prototype.replace(")", "", 1)
900 prototype = prototype.replace(";", " {};")
901
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600902 # Build up pre/post call virtual function declarations
903 pre_call_validate = 'virtual bool PreCallValidate' + prototype
904 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
905 pre_call_record = 'virtual void PreCallRecord' + prototype
906 post_call_record = 'virtual void PostCallRecord' + prototype
907 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
908 #
909 # Command generation
910 def genCmd(self, cmdinfo, name, alias):
911 ignore_functions = [
912 'vkEnumerateInstanceVersion'
913 ]
914
915 if name in ignore_functions:
916 return
917
918 if self.header: # In the header declare all intercepts
919 self.appendSection('command', '')
920 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
921 if (self.featureExtraProtect != None):
922 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
923 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
924 # Update base class with virtual function declarations
925 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
926 # Update function intercepts
927 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
928 if (self.featureExtraProtect != None):
929 self.intercepts += [ '#endif' ]
930 self.layer_factory += '#endif\n'
931 return
932
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700933 if name in self.manual_functions:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600934 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
935 return
936 # Record that the function will be intercepted
937 if (self.featureExtraProtect != None):
938 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
939 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
940 if (self.featureExtraProtect != None):
941 self.intercepts += [ '#endif' ]
942 OutputGenerator.genCmd(self, cmdinfo, name, alias)
943 #
944 decls = self.makeCDecls(cmdinfo.elem)
945 self.appendSection('command', '')
946 self.appendSection('command', '%s {' % decls[0][:-1])
947 # Setup common to call wrappers. First parameter is always dispatchable
948 dispatchable_type = cmdinfo.elem.find('param/type').text
949 dispatchable_name = cmdinfo.elem.find('param/name').text
950 # Default to device
951 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600952 dispatch_table_name = 'VkLayerDispatchTable'
953 # Set to instance as necessary
954 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
955 device_or_instance = 'instance'
956 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600957 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600958 api_function_name = cmdinfo.elem.attrib.get('name')
959 params = cmdinfo.elem.findall('param/name')
960 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700961 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600962
963 # Declare result variable, if any.
964 return_map = {
965 'void': 'return;',
966 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
967 'PFN_vkVoidFunction': 'return nullptr;',
968 'VkBool32': 'return VK_FALSE;',
969 }
970 resulttype = cmdinfo.elem.find('proto/type')
971 assignresult = ''
972 if (resulttype.text != 'void'):
973 assignresult = resulttype.text + ' result = '
974
975 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700976 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600977
978 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600979 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700980 self.appendSection('command', ' std::lock_guard<std::mutex> lock(intercept->layer_mutex);')
981 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
982 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
983 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600984
985 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600986 self.appendSection('command', ' %s' % self.precallrecord_loop)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700987 self.appendSection('command', ' std::lock_guard<std::mutex> lock(intercept->layer_mutex);')
988 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600989 self.appendSection('command', ' }')
990
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700991 # Insert pre-dispatch debug utils function call
992 if name in self.pre_dispatch_debug_utils_functions:
993 self.appendSection('command', ' {')
994 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->layer_mutex);')
995 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
996 self.appendSection('command', ' }')
997
998 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700999 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001000
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001001 # Insert post-dispatch debug utils function call
1002 if name in self.post_dispatch_debug_utils_functions:
1003 self.appendSection('command', ' {')
1004 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->layer_mutex);')
1005 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
1006 self.appendSection('command', ' }')
1007
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001008 # Generate post-call object processing source code
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001009 return_type_indent = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001010 if (resulttype.text == 'VkResult'):
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001011 return_type_indent = ' '
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001012 if name in self.alt_ret_codes:
Mark Lobodzinskib3c94842018-11-27 10:01:51 -07001013 self.appendSection('command', ' if ((VK_SUCCESS == result) || (VK_INCOMPLETE == result)) {')
1014 else:
1015 self.appendSection('command', ' if (VK_SUCCESS == result) {')
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001016
1017 self.appendSection('command', '%s %s' % (return_type_indent, self.postcallrecord_loop))
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001018 self.appendSection('command', '%s std::lock_guard<std::mutex> lock(intercept->layer_mutex);' % return_type_indent)
1019 self.appendSection('command', '%s intercept->PostCallRecord%s(%s);' % (return_type_indent,api_function_name[2:], paramstext))
1020 self.appendSection('command', '%s }' % return_type_indent)
1021 if (resulttype.text == 'VkResult'):
1022 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001023
1024 # Return result variable, if any.
1025 if (resulttype.text != 'void'):
1026 self.appendSection('command', ' return result;')
1027 self.appendSection('command', '}')
1028 #
1029 # Override makeProtoName to drop the "vk" prefix
1030 def makeProtoName(self, name, tail):
1031 return self.genOpts.apientry + name[2:] + tail