blob: 41bd5b8d6d3939a905560e04a716a784c85627c6 [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 Lobodzinski9b6522d2018-09-26 11:07:45 -0600428 const auto &item = name_to_funcptr_map.find(funcName);
429 if (item != name_to_funcptr_map.end()) {
430 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
431 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600432 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600433 if (!table.GetDeviceProcAddr) return nullptr;
434 return table.GetDeviceProcAddr(device, funcName);
435}
436
437VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600438 const auto &item = name_to_funcptr_map.find(funcName);
439 if (item != name_to_funcptr_map.end()) {
440 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
441 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600442 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
443 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600444 if (!table.GetInstanceProcAddr) return nullptr;
445 return table.GetInstanceProcAddr(instance, funcName);
446}
447
448VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600449 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
450 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600451 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
452 return table.GetPhysicalDeviceProcAddr(instance, funcName);
453}
454
455VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
456 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
457}
458
459VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
460 VkLayerProperties *pProperties) {
461 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
462}
463
464VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
465 VkExtensionProperties *pProperties) {
466 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
467 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
468
469 return VK_ERROR_LAYER_NOT_PRESENT;
470}
471
472VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
473 uint32_t *pCount, VkExtensionProperties *pProperties) {
474 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600475 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600476 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
477 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600478}
479
480VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
481 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600482 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600483
484 assert(chain_info->u.pLayerInfo);
485 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
486 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
487 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
488 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
489
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600490 // Create temporary dispatch vector for pre-calls until instance is created
491 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700492#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600493 auto object_tracker = new ObjectLifetimes;
494 local_object_dispatch.emplace_back(object_tracker);
495 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700496#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600497
498
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600499 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600500 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600501 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
502 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600503 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600504 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
505 }
506
507 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600508 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600509
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600510 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600511
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600512 framework->object_dispatch = local_object_dispatch;
513
514 framework->instance = *pInstance;
515 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
516 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
517 pCreateInfo->ppEnabledExtensionNames);
518 framework->api_version = framework->instance_extensions.InitFromInstanceCreateInfo(
519 (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0), pCreateInfo);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700520#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600521 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700522#else
523 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
524#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600525
526 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600527 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
528 }
529
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700530 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
531
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600532 return result;
533}
534
535VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
536 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600537 auto layer_data = GetLayerDataPtr(key, layer_data_map);
538 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700539 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600540 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
541 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600542 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700543 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600544 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
545 }
546
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600547 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600548
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600549 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700550 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600551 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
552 }
553 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600554 while (layer_data->logging_messenger.size() > 0) {
555 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
556 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
557 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600558 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600559 while (layer_data->logging_callback.size() > 0) {
560 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
561 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
562 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600563 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600564
565 layer_debug_utils_destroy_instance(layer_data->report_data);
566
567 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600568}
569
570VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
571 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600572 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600573
574 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
575
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600576 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
577 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600578 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
579 if (fpCreateDevice == NULL) {
580 return VK_ERROR_INITIALIZATION_FAILED;
581 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600582 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
583
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600584 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700585 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600586 intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
587 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600588 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700589 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600590 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
591 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600592
593 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600594 if (result != VK_SUCCESS) {
595 return result;
596 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600597
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600598 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
599 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
600 device_interceptor->device = *pDevice;
601 device_interceptor->physical_device = gpu;
602 device_interceptor->instance = instance_interceptor->instance;
603 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
604 device_interceptor->api_version = instance_interceptor->api_version;
605
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700606#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600607 // Create child layer objects for this key and add to dispatch vector
608 auto object_tracker = new ObjectLifetimes;
609 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
610 object_tracker->container_type = LayerObjectTypeObjectTracker;
611 object_tracker->physical_device = gpu;
612 object_tracker->instance = instance_interceptor->instance;
613 object_tracker->report_data = device_interceptor->report_data;
614 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
615 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700616#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600617
618 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700619 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600620 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
621 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600622
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700623 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
624
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600625 return result;
626}
627
628VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
629 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600630 auto layer_data = GetLayerDataPtr(key, layer_data_map);
631 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700632 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600633 intercept->PreCallValidateDestroyDevice(device, pAllocator);
634 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600635 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700636 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600637 intercept->PreCallRecordDestroyDevice(device, pAllocator);
638 }
639 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600640
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600641 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600642
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600643 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700644 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600645 intercept->PostCallRecordDestroyDevice(device, pAllocator);
646 }
647
648 FreeLayerDataPtr(key, layer_data_map);
649}
650
651VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
652 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
653 const VkAllocationCallbacks *pAllocator,
654 VkDebugReportCallbackEXT *pCallback) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600655 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
656 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700657 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600658 intercept->PreCallValidateCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
659 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600660 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700661 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600662 intercept->PreCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
663 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700664 VkResult result = DispatchCreateDebugReportCallbackEXT(layer_data, instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600665 result = layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);
666 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700667 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600668 intercept->PostCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
669 }
670 return result;
671}
672
673VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
674 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600675 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
676 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700677 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600678 intercept->PreCallValidateDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
679 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600680 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700681 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600682 intercept->PreCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
683 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700684 DispatchDestroyDebugReportCallbackEXT(layer_data, instance, callback, pAllocator);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600685 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
686 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700687 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600688 intercept->PostCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
689 }
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700690}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600691
692 inline_custom_source_postamble = """
693// loader-layer interface v0, just wrappers since there is only a layer
694
695VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
696 VkExtensionProperties *pProperties) {
697 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
698}
699
700VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
701 VkLayerProperties *pProperties) {
702 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
703}
704
705VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
706 VkLayerProperties *pProperties) {
707 // the layer command handles VK_NULL_HANDLE just fine internally
708 assert(physicalDevice == VK_NULL_HANDLE);
709 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
710}
711
712VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
713 const char *pLayerName, uint32_t *pCount,
714 VkExtensionProperties *pProperties) {
715 // the layer command handles VK_NULL_HANDLE just fine internally
716 assert(physicalDevice == VK_NULL_HANDLE);
717 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
718}
719
720VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
721 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
722}
723
724VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
725 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
726}
727
728VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
729 const char *funcName) {
730 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
731}
732
733VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
734 assert(pVersionStruct != NULL);
735 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
736
737 // Fill in the function pointers if our version is at least capable of having the structure contain them.
738 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
739 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
740 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
741 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
742 }
743
744 return VK_SUCCESS;
745}"""
746
747
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600748 def __init__(self,
749 errFile = sys.stderr,
750 warnFile = sys.stderr,
751 diagFile = sys.stdout):
752 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
753 # Internal state - accumulators for different inner block text
754 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
755 self.intercepts = []
756 self.layer_factory = '' # String containing base layer factory class definition
757
758 # Check if the parameter passed in is a pointer to an array
759 def paramIsArray(self, param):
760 return param.attrib.get('len') is not None
761
762 # Check if the parameter passed in is a pointer
763 def paramIsPointer(self, param):
764 ispointer = False
765 for elem in param:
766 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
767 ispointer = True
768 return ispointer
769
770 # Check if an object is a non-dispatchable handle
771 def isHandleTypeNonDispatchable(self, handletype):
772 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
773 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
774 return True
775 else:
776 return False
777
778 # Check if an object is a dispatchable handle
779 def isHandleTypeDispatchable(self, handletype):
780 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
781 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
782 return True
783 else:
784 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700785 #
786 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600787 def beginFile(self, genOpts):
788 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700789 # Output Copyright
790 write(self.inline_copyright_message, file=self.outFile)
791 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600792 self.header = False
793 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
794 self.header = True
795 write('#pragma once', file=self.outFile)
796 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600797 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700798 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600799 else:
800 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700801 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700802 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600803 #
804 def endFile(self):
805 # Finish C++ namespace and multiple inclusion protection
806 self.newline()
807 if not self.header:
808 # Record intercepted procedures
809 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
810 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
811 write('\n'.join(self.intercepts), file=self.outFile)
812 write('};\n', file=self.outFile)
813 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600814 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600815 if self.header:
816 self.newline()
817 # Output Layer Factory Class Definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600818 self.layer_factory += '};\n\n'
819 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600820 write(self.layer_factory, file=self.outFile)
821 else:
822 write(self.inline_custom_source_postamble, file=self.outFile)
823 # Finish processing in superclass
824 OutputGenerator.endFile(self)
825
826 def beginFeature(self, interface, emit):
827 # Start processing in superclass
828 OutputGenerator.beginFeature(self, interface, emit)
829 # Get feature extra protect
830 self.featureExtraProtect = GetFeatureProtect(interface)
831 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
832 # feature. They're only printed in endFeature().
833 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
834
835 def endFeature(self):
836 # Actually write the interface to the output file.
837 if (self.emit):
838 self.newline()
839 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
840 # or move it below the 'for section...' loop.
841 if (self.featureExtraProtect != None):
842 write('#ifdef', self.featureExtraProtect, file=self.outFile)
843 for section in self.TYPE_SECTIONS:
844 contents = self.sections[section]
845 if contents:
846 write('\n'.join(contents), file=self.outFile)
847 self.newline()
848 if (self.sections['command']):
849 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
850 self.newline()
851 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600852 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600853 # Finish processing in superclass
854 OutputGenerator.endFeature(self)
855 #
856 # Append a definition to the specified section
857 def appendSection(self, section, text):
858 self.sections[section].append(text)
859 #
860 # Type generation
861 def genType(self, typeinfo, name, alias):
862 pass
863 #
864 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
865 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
866 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
867 # structs etc.)
868 def genStruct(self, typeinfo, typeName):
869 OutputGenerator.genStruct(self, typeinfo, typeName)
870 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
871 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
872 for member in typeinfo.elem.findall('.//member'):
873 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
874 body += ';\n'
875 body += '} ' + typeName + ';\n'
876 self.appendSection('struct', body)
877 #
878 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
879 def genGroup(self, groupinfo, groupName, alias):
880 pass
881 # Enumerant generation
882 # <enum> tags may specify their values in several ways, but are usually just integers.
883 def genEnum(self, enuminfo, name, alias):
884 pass
885 #
886 # Customize Cdecl for layer factory base class
887 def BaseClassCdecl(self, elem, name):
888 raw = self.makeCDecls(elem)[1]
889
890 # Toss everything before the undecorated name
891 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
892 prototype = prototype.replace(")", "", 1)
893 prototype = prototype.replace(";", " {};")
894
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600895 # Build up pre/post call virtual function declarations
896 pre_call_validate = 'virtual bool PreCallValidate' + prototype
897 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
898 pre_call_record = 'virtual void PreCallRecord' + prototype
899 post_call_record = 'virtual void PostCallRecord' + prototype
900 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
901 #
902 # Command generation
903 def genCmd(self, cmdinfo, name, alias):
904 ignore_functions = [
905 'vkEnumerateInstanceVersion'
906 ]
907
908 if name in ignore_functions:
909 return
910
911 if self.header: # In the header declare all intercepts
912 self.appendSection('command', '')
913 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
914 if (self.featureExtraProtect != None):
915 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
916 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
917 # Update base class with virtual function declarations
918 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
919 # Update function intercepts
920 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
921 if (self.featureExtraProtect != None):
922 self.intercepts += [ '#endif' ]
923 self.layer_factory += '#endif\n'
924 return
925
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700926 if name in self.manual_functions:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600927 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
928 return
929 # Record that the function will be intercepted
930 if (self.featureExtraProtect != None):
931 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
932 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
933 if (self.featureExtraProtect != None):
934 self.intercepts += [ '#endif' ]
935 OutputGenerator.genCmd(self, cmdinfo, name, alias)
936 #
937 decls = self.makeCDecls(cmdinfo.elem)
938 self.appendSection('command', '')
939 self.appendSection('command', '%s {' % decls[0][:-1])
940 # Setup common to call wrappers. First parameter is always dispatchable
941 dispatchable_type = cmdinfo.elem.find('param/type').text
942 dispatchable_name = cmdinfo.elem.find('param/name').text
943 # Default to device
944 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600945 dispatch_table_name = 'VkLayerDispatchTable'
946 # Set to instance as necessary
947 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
948 device_or_instance = 'instance'
949 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600950 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600951 api_function_name = cmdinfo.elem.attrib.get('name')
952 params = cmdinfo.elem.findall('param/name')
953 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700954 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600955
956 # Declare result variable, if any.
957 return_map = {
958 'void': 'return;',
959 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
960 'PFN_vkVoidFunction': 'return nullptr;',
961 'VkBool32': 'return VK_FALSE;',
962 }
963 resulttype = cmdinfo.elem.find('proto/type')
964 assignresult = ''
965 if (resulttype.text != 'void'):
966 assignresult = resulttype.text + ' result = '
967
968 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700969 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600970
971 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600972 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700973 self.appendSection('command', ' std::lock_guard<std::mutex> lock(intercept->layer_mutex);')
974 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
975 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
976 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600977
978 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600979 self.appendSection('command', ' %s' % self.precallrecord_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', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600982 self.appendSection('command', ' }')
983
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700984 # Insert pre-dispatch debug utils function call
985 if name in self.pre_dispatch_debug_utils_functions:
986 self.appendSection('command', ' {')
987 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->layer_mutex);')
988 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
989 self.appendSection('command', ' }')
990
991 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700992 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600993
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700994 # Insert post-dispatch debug utils function call
995 if name in self.post_dispatch_debug_utils_functions:
996 self.appendSection('command', ' {')
997 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->layer_mutex);')
998 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
999 self.appendSection('command', ' }')
1000
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001001 # Generate post-call object processing source code
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001002 return_type_indent = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001003 if (resulttype.text == 'VkResult'):
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001004 return_type_indent = ' '
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001005 if name in self.alt_ret_codes:
Mark Lobodzinskib3c94842018-11-27 10:01:51 -07001006 self.appendSection('command', ' if ((VK_SUCCESS == result) || (VK_INCOMPLETE == result)) {')
1007 else:
1008 self.appendSection('command', ' if (VK_SUCCESS == result) {')
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001009
1010 self.appendSection('command', '%s %s' % (return_type_indent, self.postcallrecord_loop))
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001011 self.appendSection('command', '%s std::lock_guard<std::mutex> lock(intercept->layer_mutex);' % return_type_indent)
1012 self.appendSection('command', '%s intercept->PostCallRecord%s(%s);' % (return_type_indent,api_function_name[2:], paramstext))
1013 self.appendSection('command', '%s }' % return_type_indent)
1014 if (resulttype.text == 'VkResult'):
1015 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001016
1017 # Return result variable, if any.
1018 if (resulttype.text != 'void'):
1019 self.appendSection('command', ' return result;')
1020 self.appendSection('command', '}')
1021 #
1022 # Override makeProtoName to drop the "vk" prefix
1023 def makeProtoName(self, name, tail):
1024 return self.genOpts.apientry + name[2:] + tail