blob: b7196ed942822cb9ce260171233eea50a68ac2c7 [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07003# Copyright (c) 2015-2019 Valve Corporation
4# Copyright (c) 2015-2019 LunarG, Inc.
5# Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06006#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
20# Author: Mark Lobodzinski <mark@lunarg.com>
21#
22# This script generates the dispatch portion of a factory layer which intercepts
23# all Vulkan functions. The resultant factory layer allows rapid development of
24# layers and interceptors.
25
26import os,re,sys
27from generator import *
28from common_codegen import *
29
30# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31#
32# Adds options used by LayerFactoryOutputGenerator objects during factory
33# layer generation.
34#
35# Additional members
36# prefixText - list of strings to prefix generated header with
37# (usually a copyright statement + calling convention macros).
38# protectFile - True if multiple inclusion protection should be
39# generated (based on the filename) around the entire header.
40# protectFeature - True if #ifndef..#endif protection should be
41# generated around a feature interface in the header file.
42# genFuncPointers - True if function pointer typedefs should be
43# generated
44# protectProto - If conditional protection should be generated
45# around prototype declarations, set to either '#ifdef'
46# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47# to require opt-out (#ifndef protectProtoStr). Otherwise
48# set to None.
49# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50# declarations, if protectProto is set
51# apicall - string to use for the function declaration prefix,
52# such as APICALL on Windows.
53# apientry - string to use for the calling convention macro,
54# in typedefs, such as APIENTRY.
55# apientryp - string to use for the calling convention macro
56# in function pointer typedefs, such as APIENTRYP.
57# indentFuncProto - True if prototype declarations should put each
58# parameter on a separate line
59# indentFuncPointer - True if typedefed function pointers should put each
60# parameter on a separate line
61# alignFuncParam - if nonzero and parameters are being put on a
62# separate line, align parameter names at the specified column
63class LayerChassisGeneratorOptions(GeneratorOptions):
64 def __init__(self,
65 filename = None,
66 directory = '.',
67 apiname = None,
68 profile = None,
69 versions = '.*',
70 emitversions = '.*',
71 defaultExtensions = None,
72 addExtensions = None,
73 removeExtensions = None,
74 emitExtensions = None,
75 sortProcedure = regSortFeatures,
76 prefixText = "",
77 genFuncPointers = True,
78 protectFile = True,
79 protectFeature = True,
80 apicall = '',
81 apientry = '',
82 apientryp = '',
83 indentFuncProto = True,
84 indentFuncPointer = False,
85 alignFuncParam = 0,
86 helper_file_type = '',
87 expandEnumerants = True):
88 GeneratorOptions.__init__(self, filename, directory, apiname, profile,
89 versions, emitversions, defaultExtensions,
90 addExtensions, removeExtensions, emitExtensions, sortProcedure)
91 self.prefixText = prefixText
92 self.genFuncPointers = genFuncPointers
93 self.protectFile = protectFile
94 self.protectFeature = protectFeature
95 self.apicall = apicall
96 self.apientry = apientry
97 self.apientryp = apientryp
98 self.indentFuncProto = indentFuncProto
99 self.indentFuncPointer = indentFuncPointer
100 self.alignFuncParam = alignFuncParam
101
102# LayerChassisOutputGenerator - subclass of OutputGenerator.
103# Generates a LayerFactory layer that intercepts all API entrypoints
104# This is intended to be used as a starting point for creating custom layers
105#
106# ---- methods ----
107# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
108# OutputGenerator. Defines additional internal state.
109# ---- methods overriding base class ----
110# beginFile(genOpts)
111# endFile()
112# beginFeature(interface, emit)
113# endFeature()
114# genType(typeinfo,name)
115# genStruct(typeinfo,name)
116# genGroup(groupinfo,name)
117# genEnum(enuminfo, name)
118# genCmd(cmdinfo)
119class LayerChassisOutputGenerator(OutputGenerator):
120 """Generate specified API interfaces in a specific style, such as a C header"""
121 # This is an ordered list of sections in the header file.
122 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
123 'group', 'bitmask', 'funcpointer', 'struct']
124 ALL_SECTIONS = TYPE_SECTIONS + ['command']
125
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700126 manual_functions = [
127 # Include functions here to be interecpted w/ manually implemented function bodies
128 'vkGetDeviceProcAddr',
129 'vkGetInstanceProcAddr',
130 'vkGetPhysicalDeviceProcAddr',
131 'vkCreateDevice',
132 'vkDestroyDevice',
133 'vkCreateInstance',
134 'vkDestroyInstance',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700135 'vkEnumerateInstanceLayerProperties',
136 'vkEnumerateInstanceExtensionProperties',
137 'vkEnumerateDeviceLayerProperties',
138 'vkEnumerateDeviceExtensionProperties',
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700139 # Functions that are handled explicitly due to chassis architecture violations
140 'vkCreateGraphicsPipelines',
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700141 'vkCreateComputePipelines',
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700142 'vkCreateRayTracingPipelinesNV',
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -0700143 'vkCreatePipelineLayout',
Mark Lobodzinski1db77e82019-03-01 10:02:54 -0700144 'vkCreateShaderModule',
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -0700145 'vkAllocateDescriptorSets',
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700146 # ValidationCache functions do not get dispatched
147 'vkCreateValidationCacheEXT',
148 'vkDestroyValidationCacheEXT',
149 'vkMergeValidationCachesEXT',
150 'vkGetValidationCacheDataEXT',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700151 ]
152
153 alt_ret_codes = [
154 # Include functions here which must tolerate VK_INCOMPLETE as a return code
155 'vkEnumeratePhysicalDevices',
156 'vkEnumeratePhysicalDeviceGroupsKHR',
157 'vkGetValidationCacheDataEXT',
158 'vkGetPipelineCacheData',
159 'vkGetShaderInfoAMD',
160 'vkGetPhysicalDeviceDisplayPropertiesKHR',
161 'vkGetPhysicalDeviceDisplayProperties2KHR',
162 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
163 'vkGetDisplayPlaneSupportedDisplaysKHR',
164 'vkGetDisplayModePropertiesKHR',
165 'vkGetDisplayModeProperties2KHR',
166 'vkGetPhysicalDeviceSurfaceFormatsKHR',
167 'vkGetPhysicalDeviceSurfacePresentModesKHR',
168 'vkGetPhysicalDevicePresentRectanglesKHR',
169 'vkGetPastPresentationTimingGOOGLE',
170 'vkGetSwapchainImagesKHR',
171 'vkEnumerateInstanceLayerProperties',
172 'vkEnumerateDeviceLayerProperties',
173 'vkEnumerateInstanceExtensionProperties',
174 'vkEnumerateDeviceExtensionProperties',
175 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
176 ]
177
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700178 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700179 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
180 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700181 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
182 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
183 'vkCmdBeginDebugUtilsLabelEXT' : 'BeginCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
184 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
185 }
186
187 post_dispatch_debug_utils_functions = {
188 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
189 'vkCmdEndDebugUtilsLabelEXT' : 'EndCmdDebugUtilsLabel(layer_data->report_data, commandBuffer);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700190 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
191 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
192 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
193 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
194 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700195 }
196
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600197 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
198 precallrecord_loop = precallvalidate_loop
199 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600200
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700201 inline_custom_header_preamble = """
202#define NOMINMAX
203#include <mutex>
204#include <cinttypes>
205#include <stdio.h>
206#include <stdlib.h>
207#include <string.h>
208#include <unordered_map>
209#include <unordered_set>
210#include <algorithm>
211#include <memory>
212
213#include "vk_loader_platform.h"
214#include "vulkan/vulkan.h"
215#include "vk_layer_config.h"
216#include "vk_layer_data.h"
217#include "vk_layer_logging.h"
218#include "vk_object_types.h"
219#include "vulkan/vk_layer.h"
220#include "vk_enum_string_helper.h"
221#include "vk_layer_extension_utils.h"
222#include "vk_layer_utils.h"
223#include "vulkan/vk_layer.h"
224#include "vk_dispatch_table_helper.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700225#include "vk_extension_helper.h"
226#include "vk_safe_struct.h"
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700227#include "vk_typemap_helper.h"
228
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700229
230extern uint64_t global_unique_id;
231extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
232"""
233
234 inline_custom_header_class_definition = """
235
236// Layer object type identifiers
237enum LayerObjectTypeId {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700238 LayerObjectTypeInstance, // Container for an instance dispatch object
239 LayerObjectTypeDevice, // Container for a device dispatch object
240 LayerObjectTypeThreading, // Instance or device threading layer object
241 LayerObjectTypeParameterValidation, // Instance or device parameter validation layer object
242 LayerObjectTypeObjectTracker, // Instance or device object tracker layer object
243 LayerObjectTypeCoreValidation, // Instance or device core validation layer object
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700244};
245
246struct TEMPLATE_STATE {
247 VkDescriptorUpdateTemplateKHR desc_update_template;
248 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
249
250 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
251 : desc_update_template(update_template), create_info(*pCreateInfo) {}
252};
253
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700254class LAYER_PHYS_DEV_PROPERTIES {
255public:
256 VkPhysicalDeviceProperties properties;
257 std::vector<VkQueueFamilyProperties> queue_family_properties;
258};
259
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600260typedef enum ValidationCheckDisables {
261 VALIDATION_CHECK_DISABLE_DESTROY_PIPELINE,
262 VALIDATION_CHECK_DISABLE_DESTROY_SAMPLER,
263 VALIDATION_CHECK_DISABLE_DESTROY_COMMAND_POOL,
264 VALIDATION_CHECK_DISABLE_DESTROY_SEMAPHORE,
265 VALIDATION_CHECK_DISABLE_DESTROY_DESCRIPTOR_POOL,
266 VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE,
267 VALIDATION_CHECK_DISABLE_CREATE_DESCRIPTOR_SET_LAYOUT,
268 VALIDATION_CHECK_DISABLE_OBJECT_IN_USE,
269 VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET,
270 VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE,
271 VALIDATION_CHECK_DISABLE_ALLOCATE_DESCRIPTOR_SETS,
272 VALIDATION_CHECK_DISABLE_UPDATE_DESCRIPTOR_SETS,
273 VALIDATION_CHECK_DISABLE_WAIT_FOR_FENCES,
274 VALIDATION_CHECK_DISABLE_QUEUE_WAIT_IDLE,
275 VALIDATION_CHECK_DISABLE_DEVICE_WAIT_IDLE,
276} ValidationCheckDisables;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600277
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600278
279// CHECK_DISABLED struct is a container for bools that can block validation checks from being performed.
280// These bools are all "false" by default meaning that all checks are enabled. Enum values can be specified
281// via the vk_layer_setting.txt config file or at CreateInstance time via the VK_EXT_validation_features extension
282// that can selectively disable checks.
283struct CHECK_DISABLED {
284 bool destroy_pipeline; // Skip validation at DestroyPipeline time
285 bool destroy_sampler; // Skip validation at DestroySampler time
286 bool destroy_command_pool; // Skip validation at DestroyCommandPool time
287 bool destroy_semaphore; // Skip validation at DestroySemaphore time
288 bool destroy_descriptor_pool; // Skip validation at DestroyDescriptorPool time
289 bool command_buffer_state; // Skip command buffer state validation
290 bool create_descriptor_set_layout; // Skip validation at CreateDescSetLayout time
291 bool object_in_use; // Skip all object in_use checking
292 bool idle_descriptor_set; // Skip check to verify that descriptor set is not in-use
293 bool push_constant_range; // Skip push constant range checks
294 bool allocate_descriptor_sets; // Skip validation prior to vkAllocateDescriptorSets()
295 bool update_descriptor_sets; // Skip validation prior to vkUpdateDescriptorSets()
296 bool wait_for_fences; // Skip validation at WaitForFences time
297 bool queue_wait_idle; // Skip validation at QueueWaitIdle time
298 bool device_wait_idle; // Skip validation at DeviceWaitIdle time
299 bool object_tracking; // Disable object lifetime validation
300 bool core_checks; // Disable core validation checks
301 bool thread_safety; // Disable thread safety validation
302 bool stateless_checks; // Disable stateless validation checks
303 bool handle_wrapping; // Disable unique handles/handle wrapping
304 bool shader_validation; // Skip validation for shaders
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700305
306 void SetAll(bool value) { std::fill(&command_buffer_state, &shader_validation + 1, value); }
307};
308
309struct CHECK_ENABLED {
310 bool gpu_validation;
311 bool gpu_validation_reserve_binding_slot;
312
313 void SetAll(bool value) { std::fill(&gpu_validation, &gpu_validation_reserve_binding_slot + 1, value); }
314};
315
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700316// Layer chassis validation object base class definition
317class ValidationObject {
318 public:
319 uint32_t api_version;
320 debug_report_data* report_data = nullptr;
321 std::vector<VkDebugReportCallbackEXT> logging_callback;
322 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
323
324 VkLayerInstanceDispatchTable instance_dispatch_table;
325 VkLayerDispatchTable device_dispatch_table;
326
327 InstanceExtensions instance_extensions;
328 DeviceExtensions device_extensions = {};
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700329 CHECK_DISABLED disabled = {};
330 CHECK_ENABLED enabled = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700331
332 VkInstance instance = VK_NULL_HANDLE;
333 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
334 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700335 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700336
337 std::vector<ValidationObject*> object_dispatch;
338 LayerObjectTypeId container_type;
339
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700340 std::string layer_name = "CHASSIS";
341
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700342 // Constructor
343 ValidationObject(){};
344 // Destructor
345 virtual ~ValidationObject() {};
346
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700347 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700348 virtual std::unique_lock<std::mutex> write_lock() {
349 return std::unique_lock<std::mutex>(validation_object_mutex);
350 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700351
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700352 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
353 for (auto validation_object : object_dispatch) {
354 if (validation_object->container_type == object_type) {
355 return validation_object;
356 }
357 }
358 return nullptr;
359 };
360
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700361 // Handle Wrapping Data
362 // Reverse map display handles
363 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
364 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700365 struct SubpassesUsageStates {
366 std::unordered_set<uint32_t> subpasses_using_color_attachment;
367 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
368 };
369 // Uses unwrapped handles
370 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
371 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
372 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
373 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700374 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
375 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700376
377
378 // Unwrap a handle. Must hold lock.
379 template <typename HandleType>
380 HandleType Unwrap(HandleType wrappedHandle) {
381 // TODO: don't use operator[] here.
382 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
383 }
384
385 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
386 template <typename HandleType>
387 HandleType WrapNew(HandleType newlyCreatedHandle) {
388 auto unique_id = global_unique_id++;
389 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
390 return (HandleType)unique_id;
391 }
392
393 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
394 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
395 auto unique_id = global_unique_id++;
396 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
397 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
398 return (VkDisplayKHR)unique_id;
399 }
400
401 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
402 // creating another. Must hold lock.
403 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
404 // See if this display is already known
405 auto it = map_data->display_id_reverse_mapping.find(handle);
406 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
407 // Unknown, so wrap
408 return WrapDisplay(handle, map_data);
409 }
410
411 // Pre/post hook point declarations
412"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600413
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700414 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600415// This file is ***GENERATED***. Do Not Edit.
416// See layer_chassis_generator.py for modifications.
417
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700418/* Copyright (c) 2015-2019 The Khronos Group Inc.
419 * Copyright (c) 2015-2019 Valve Corporation
420 * Copyright (c) 2015-2019 LunarG, Inc.
421 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600422 *
423 * Licensed under the Apache License, Version 2.0 (the "License");
424 * you may not use this file except in compliance with the License.
425 * You may obtain a copy of the License at
426 *
427 * http://www.apache.org/licenses/LICENSE-2.0
428 *
429 * Unless required by applicable law or agreed to in writing, software
430 * distributed under the License is distributed on an "AS IS" BASIS,
431 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
432 * See the License for the specific language governing permissions and
433 * limitations under the License.
434 *
435 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700436 */"""
437
438 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600439
440#include <string.h>
441#include <mutex>
442
443#define VALIDATION_ERROR_MAP_IMPL
444
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600445#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700446#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600447
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600448std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600449
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700450// Global unique object identifier. All increments must be guarded by a lock.
451uint64_t global_unique_id = 1;
452// Map uniqueID to actual object handle
453std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
454
455// TODO: This variable controls handle wrapping -- in the future it should be hooked
456// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
457#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
458bool wrap_handles = true;
459#else
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600460bool wrap_handles = false;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700461#endif
462
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600463// Set layer name -- Khronos layer name overrides any other defined names
Mark Lobodzinskiaa6fd7b2019-03-19 09:26:48 -0600464#if BUILD_KHRONOS_VALIDATION
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600465#define OBJECT_LAYER_NAME "VK_LAYER_KHRONOS_validation"
466#define OBJECT_LAYER_DESCRIPTION "khronos_validation"
467#elif BUILD_OBJECT_TRACKER
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700468#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600469#define OBJECT_LAYER_DESCRIPTION "lunarg_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700470#elif BUILD_THREAD_SAFETY
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700471#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600472#define OBJECT_LAYER_DESCRIPTION "google_thread_checker"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700473#elif BUILD_PARAMETER_VALIDATION
474#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600475#define OBJECT_LAYER_DESCRIPTION "lunarg_parameter_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700476#elif BUILD_CORE_VALIDATION
477#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600478#define OBJECT_LAYER_DESCRIPTION "lunarg_core_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700479#else
480#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600481#define OBJECT_LAYER_DESCRIPTION "lunarg_unique_objects"
482#endif
483
484// Include layer validation object definitions
485#if BUILD_OBJECT_TRACKER
486#include "object_lifetime_validation.h"
487#endif
488#if BUILD_THREAD_SAFETY
489#include "thread_safety.h"
490#endif
491#if BUILD_PARAMETER_VALIDATION
492#include "stateless_validation.h"
493#endif
494#if BUILD_CORE_VALIDATION
495#include "core_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700496#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600497
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600498namespace vulkan_layer_chassis {
499
500using std::unordered_map;
501
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600502static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700503 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600504};
505
506static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
507
508extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
509
510
511// Manually written functions
512
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700513// Check enabled instance extensions against supported instance extension whitelist
514static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
515 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
516 // Check for recognized instance extensions
517 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
518 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
519 kVUIDUndefined,
520 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
521 "results and/or produce undefined behavior.",
522 pCreateInfo->ppEnabledExtensionNames[i]);
523 }
524 }
525}
526
527// Check enabled device extensions against supported device extension whitelist
528static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
529 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
530 // Check for recognized device extensions
531 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
532 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
533 kVUIDUndefined,
534 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
535 "results and/or produce undefined behavior.",
536 pCreateInfo->ppEnabledExtensionNames[i]);
537 }
538 }
539}
540
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600541
542// Process validation features, flags and settings specified through extensions, a layer settings file, or environment variables
543
544static const std::unordered_map<std::string, VkValidationFeatureDisableEXT> VkValFeatureDisableLookup = {
545 {"VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT", VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT},
546 {"VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT", VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT},
547 {"VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT", VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT},
548 {"VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT", VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT},
549 {"VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT", VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT},
550 {"VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT", VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT},
551 {"VK_VALIDATION_FEATURE_DISABLE_ALL_EXT", VK_VALIDATION_FEATURE_DISABLE_ALL_EXT},
552};
553
554static const std::unordered_map<std::string, ValidationCheckDisables> ValidationDisableLookup = {
555 {"VALIDATION_CHECK_DISABLE_DESTROY_PIPELINE", VALIDATION_CHECK_DISABLE_DESTROY_PIPELINE},
556 {"VALIDATION_CHECK_DISABLE_DESTROY_SAMPLER", VALIDATION_CHECK_DISABLE_DESTROY_SAMPLER},
557 {"VALIDATION_CHECK_DISABLE_DESTROY_COMMAND_POOL", VALIDATION_CHECK_DISABLE_DESTROY_COMMAND_POOL},
558 {"VALIDATION_CHECK_DISABLE_DESTROY_SEMAPHORE", VALIDATION_CHECK_DISABLE_DESTROY_SEMAPHORE},
559 {"VALIDATION_CHECK_DISABLE_DESTROY_DESCRIPTOR_POOL", VALIDATION_CHECK_DISABLE_DESTROY_DESCRIPTOR_POOL},
560 {"VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE", VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE},
561 {"VALIDATION_CHECK_DISABLE_CREATE_DESCRIPTOR_SET_LAYOUT", VALIDATION_CHECK_DISABLE_CREATE_DESCRIPTOR_SET_LAYOUT},
562 {"VALIDATION_CHECK_DISABLE_OBJECT_IN_USE", VALIDATION_CHECK_DISABLE_OBJECT_IN_USE},
563 {"VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET", VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET},
564 {"VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE", VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE},
565 {"VALIDATION_CHECK_DISABLE_ALLOCATE_DESCRIPTOR_SETS", VALIDATION_CHECK_DISABLE_ALLOCATE_DESCRIPTOR_SETS},
566 {"VALIDATION_CHECK_DISABLE_UPDATE_DESCRIPTOR_SETS", VALIDATION_CHECK_DISABLE_UPDATE_DESCRIPTOR_SETS},
567 {"VALIDATION_CHECK_DISABLE_WAIT_FOR_FENCES", VALIDATION_CHECK_DISABLE_WAIT_FOR_FENCES},
568 {"VALIDATION_CHECK_DISABLE_QUEUE_WAIT_IDLE", VALIDATION_CHECK_DISABLE_QUEUE_WAIT_IDLE},
569 {"VALIDATION_CHECK_DISABLE_DEVICE_WAIT_IDLE", VALIDATION_CHECK_DISABLE_DEVICE_WAIT_IDLE},
570};
571
572// Set the local disable flag for settings specified through the VK_EXT_validation_flags extension
573void SetValidationFlags(CHECK_DISABLED* disables, const VkValidationFlagsEXT* val_flags_struct) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700574 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
575 switch (val_flags_struct->pDisabledValidationChecks[i]) {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600576 case VK_VALIDATION_CHECK_SHADERS_EXT:
577 disables->shader_validation = true;
578 break;
579 case VK_VALIDATION_CHECK_ALL_EXT:
580 // Set all disabled flags to true
581 disables->SetAll(true);
582 break;
583 default:
584 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700585 }
586 }
587}
588
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600589// Set the local disable flag for the appropriate VALIDATION_CHECK_DISABLE enum
590void SetValidationDisable(CHECK_DISABLED* disable_data, const ValidationCheckDisables disable_id) {
591 switch (disable_id) {
592 case VALIDATION_CHECK_DISABLE_DESTROY_PIPELINE:
593 disable_data->destroy_pipeline = true;
594 break;
595 case VALIDATION_CHECK_DISABLE_DESTROY_SAMPLER:
596 disable_data->destroy_sampler = true;
597 break;
598 case VALIDATION_CHECK_DISABLE_DESTROY_COMMAND_POOL:
599 disable_data->destroy_command_pool = true;
600 break;
601 case VALIDATION_CHECK_DISABLE_DESTROY_SEMAPHORE:
602 disable_data->destroy_semaphore = true;
603 break;
604 case VALIDATION_CHECK_DISABLE_DESTROY_DESCRIPTOR_POOL:
605 disable_data->destroy_descriptor_pool = true;
606 break;
607 case VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE:
608 disable_data->command_buffer_state = true;
609 break;
610 case VALIDATION_CHECK_DISABLE_CREATE_DESCRIPTOR_SET_LAYOUT:
611 disable_data->create_descriptor_set_layout = true;
612 break;
613 case VALIDATION_CHECK_DISABLE_OBJECT_IN_USE:
614 disable_data->object_in_use = true;
615 break;
616 case VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET:
617 disable_data->idle_descriptor_set = true;
618 break;
619 case VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE:
620 disable_data->push_constant_range = true;
621 break;
622 case VALIDATION_CHECK_DISABLE_ALLOCATE_DESCRIPTOR_SETS:
623 disable_data->allocate_descriptor_sets = true;
624 break;
625 case VALIDATION_CHECK_DISABLE_UPDATE_DESCRIPTOR_SETS:
626 disable_data->update_descriptor_sets = true;
627 break;
628 case VALIDATION_CHECK_DISABLE_WAIT_FOR_FENCES:
629 disable_data->wait_for_fences = true;
630 break;
631 case VALIDATION_CHECK_DISABLE_QUEUE_WAIT_IDLE:
632 disable_data->queue_wait_idle = true;
633 break;
634 case VALIDATION_CHECK_DISABLE_DEVICE_WAIT_IDLE:
635 disable_data->device_wait_idle = true;
636 break;
637 default:
638 assert(true);
639 }
640}
641
642// Set the local disable flag for a single VK_VALIDATION_FEATURE_DISABLE_* flag
643void SetValidationFeatureDisable(CHECK_DISABLED* disable_data, const VkValidationFeatureDisableEXT feature_disable) {
644 switch (feature_disable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700645 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600646 disable_data->shader_validation = true;
647 break;
648 case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
649 disable_data->thread_safety = true;
650 break;
651 case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
652 disable_data->stateless_checks = true;
653 break;
654 case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
655 disable_data->object_tracking = true;
656 break;
657 case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
658 disable_data->core_checks = true;
659 break;
660 case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
661 disable_data->handle_wrapping = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700662 break;
663 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
664 // Set all disabled flags to true
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600665 disable_data->SetAll(true);
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700666 break;
667 default:
668 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700669 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600670}
671
672// Set the local enable flag for a single VK_VALIDATION_FEATURE_ENABLE_* flag
673void SetValidationFeatureEnable(CHECK_ENABLED *enable_data, const VkValidationFeatureEnableEXT feature_enable) {
674 switch (feature_enable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700675 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600676 enable_data->gpu_validation = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700677 break;
678 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600679 enable_data->gpu_validation_reserve_binding_slot = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700680 break;
681 default:
682 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700683 }
684}
685
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600686// Process Validation Features flags specified through the ValidationFeature extension
687void SetValidationFeatures(CHECK_DISABLED *disable_data, CHECK_ENABLED *enable_data,
688 const VkValidationFeaturesEXT *val_features_struct) {
689 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
690 SetValidationFeatureDisable(disable_data, val_features_struct->pDisabledValidationFeatures[i]);
691 }
692 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
693 SetValidationFeatureEnable(enable_data, val_features_struct->pEnabledValidationFeatures[i]);
694 }
695}
696
697// Given a string representation of a list of disable enum values, call the appropriate setter function
698void SetLocalDisableSetting(std::string list_of_disables, std::string delimiter, CHECK_DISABLED* disables) {
699 size_t pos = 0;
700 std::string token;
701 while (list_of_disables.length() != 0) {
702 pos = list_of_disables.find(delimiter);
703 if (pos != std::string::npos) {
704 token = list_of_disables.substr(0, pos);
705 } else {
706 pos = list_of_disables.length() - delimiter.length();
707 token = list_of_disables;
708 }
709 if (token.find("VK_VALIDATION_FEATURE_DISABLE_") != std::string::npos) {
710 auto result = VkValFeatureDisableLookup.find(token);
711 if (result != VkValFeatureDisableLookup.end()) {
712 SetValidationFeatureDisable(disables, result->second);
713 }
714 }
715 if (token.find("VALIDATION_CHECK_DISABLE_") != std::string::npos) {
716 auto result = ValidationDisableLookup.find(token);
717 if (result != ValidationDisableLookup.end()) {
718 SetValidationDisable(disables, result->second);
719 }
720 }
721 list_of_disables.erase(0, pos + delimiter.length());
722 }
723}
724
725// Obtain and process disables set via the vk_layer_settings.txt config file or the VK_LAYER_DISABLES environment variable
726void ProcessLocalDisableSettings(const char* layer_description, CHECK_DISABLED* disables) {
727 std::string disable_key = layer_description;
728 disable_key.append(".disables");
729 std::string list_of_config_disables = getLayerOption(disable_key.c_str());
730 std::string list_of_env_disables = GetLayerEnvVar("VK_LAYER_DISABLES");
731#if defined(_WIN32)
732 std::string env_delimiter = ";";
733#else
734 std::string env_delimiter = ":";
735#endif
736 SetLocalDisableSetting(list_of_config_disables, ",", disables);
737 SetLocalDisableSetting(list_of_env_disables, env_delimiter, disables);
738}
739
740
741// Non-code-generated chassis API functions
742
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600743VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600744 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700745 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700746 return nullptr;
747 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600748 const auto &item = name_to_funcptr_map.find(funcName);
749 if (item != name_to_funcptr_map.end()) {
750 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
751 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600752 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600753 if (!table.GetDeviceProcAddr) return nullptr;
754 return table.GetDeviceProcAddr(device, funcName);
755}
756
757VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600758 const auto &item = name_to_funcptr_map.find(funcName);
759 if (item != name_to_funcptr_map.end()) {
760 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
761 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600762 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
763 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600764 if (!table.GetInstanceProcAddr) return nullptr;
765 return table.GetInstanceProcAddr(instance, funcName);
766}
767
768VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600769 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
770 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600771 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
772 return table.GetPhysicalDeviceProcAddr(instance, funcName);
773}
774
775VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
776 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
777}
778
779VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
780 VkLayerProperties *pProperties) {
781 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
782}
783
784VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
785 VkExtensionProperties *pProperties) {
786 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
787 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
788
789 return VK_ERROR_LAYER_NOT_PRESENT;
790}
791
792VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
793 uint32_t *pCount, VkExtensionProperties *pProperties) {
794 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600795 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600796 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
797 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600798}
799
800VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
801 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600802 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600803
804 assert(chain_info->u.pLayerInfo);
805 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
806 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
807 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
808 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700809 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
810 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
811
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600812 CHECK_ENABLED local_enables {};
813 CHECK_DISABLED local_disables {};
814 const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(pCreateInfo->pNext);
815 if (validation_features_ext) {
816 SetValidationFeatures(&local_disables, &local_enables, validation_features_ext);
817 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600818 const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
819 if (validation_flags_ext) {
820 SetValidationFlags(&local_disables, validation_flags_ext);
821 }
822
823 ProcessLocalDisableSettings(OBJECT_LAYER_DESCRIPTION, &local_disables);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600824
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600825 // Create temporary dispatch vector for pre-calls until instance is created
826 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600827 // Add VOs to dispatch vector. Order here will be the validation dispatch order!
828#if BUILD_THREAD_SAFETY
829 auto thread_checker = new ThreadSafety;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600830 if (!local_disables.thread_safety) {
831 local_object_dispatch.emplace_back(thread_checker);
832 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600833 thread_checker->container_type = LayerObjectTypeThreading;
834 thread_checker->api_version = api_version;
835#endif
836#if BUILD_PARAMETER_VALIDATION
837 auto parameter_validation = new StatelessValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600838 if (!local_disables.stateless_checks) {
839 local_object_dispatch.emplace_back(parameter_validation);
840 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600841 parameter_validation->container_type = LayerObjectTypeParameterValidation;
842 parameter_validation->api_version = api_version;
843#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700844#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600845 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600846 if (!local_disables.object_tracking) {
847 local_object_dispatch.emplace_back(object_tracker);
848 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600849 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700850 object_tracker->api_version = api_version;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600851#endif
852#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700853 auto core_checks = new CoreChecks;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600854 if (!local_disables.core_checks) {
855 local_object_dispatch.emplace_back(core_checks);
856 }
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700857 core_checks->container_type = LayerObjectTypeCoreValidation;
858 core_checks->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700859#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600860
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600861 // If handle wrapping is disabled via the ValidationFeatures extension, override build flag
862 if (local_disables.handle_wrapping) {
863 wrap_handles = false;
864 }
865
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600866 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600867 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600868 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
869 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600870 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600871 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
872 }
873
874 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600875 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600876
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600877 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600878
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600879 framework->object_dispatch = local_object_dispatch;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700880 framework->container_type = LayerObjectTypeInstance;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600881 framework->disabled = local_disables;
882 framework->enabled = local_enables;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600883
884 framework->instance = *pInstance;
885 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
886 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
887 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700888 framework->api_version = api_version;
889 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
890
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600891 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, OBJECT_LAYER_DESCRIPTION);
892
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700893#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700894 object_tracker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600895 object_tracker->instance_dispatch_table = framework->instance_dispatch_table;
896 object_tracker->enabled = framework->enabled;
897 object_tracker->disabled = framework->disabled;
898#endif
899#if BUILD_THREAD_SAFETY
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700900 thread_checker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600901 thread_checker->instance_dispatch_table = framework->instance_dispatch_table;
902 thread_checker->enabled = framework->enabled;
903 thread_checker->disabled = framework->disabled;
904#endif
905#if BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700906 parameter_validation->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600907 parameter_validation->instance_dispatch_table = framework->instance_dispatch_table;
908 parameter_validation->enabled = framework->enabled;
909 parameter_validation->disabled = framework->disabled;
910#endif
911#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700912 core_checks->report_data = framework->report_data;
913 core_checks->instance_dispatch_table = framework->instance_dispatch_table;
914 core_checks->instance = *pInstance;
915 core_checks->enabled = framework->enabled;
916 core_checks->disabled = framework->disabled;
917 core_checks->instance_state = core_checks;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700918#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600919
920 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700921 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600922 }
923
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700924 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
925
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600926 return result;
927}
928
929VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
930 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600931 auto layer_data = GetLayerDataPtr(key, layer_data_map);
932 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700933 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600934 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
935 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600936 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700937 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600938 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
939 }
940
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600941 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600942
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600943 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700944 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600945 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
946 }
947 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600948 while (layer_data->logging_messenger.size() > 0) {
949 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
950 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
951 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600952 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600953 while (layer_data->logging_callback.size() > 0) {
954 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
955 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
956 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600957 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600958
959 layer_debug_utils_destroy_instance(layer_data->report_data);
960
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700961 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
962 delete *item;
963 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600964 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600965}
966
967VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
968 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600969 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600970
971 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
972
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600973 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
974 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600975 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
976 if (fpCreateDevice == NULL) {
977 return VK_ERROR_INITIALIZATION_FAILED;
978 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600979 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
980
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700981 // Get physical device limits for device
982 VkPhysicalDeviceProperties device_properties = {};
983 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
984
985 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
986 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
987
988 DeviceExtensions device_extensions = {};
989 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
990 for (auto item : instance_interceptor->object_dispatch) {
991 item->device_extensions = device_extensions;
992 }
993
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700994 std::unique_ptr<safe_VkDeviceCreateInfo> modified_create_info(new safe_VkDeviceCreateInfo(pCreateInfo));
995
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700996 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600997 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700998 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700999 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001000 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001001 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001002 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001003 auto lock = intercept->write_lock();
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001004 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, modified_create_info);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001005 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001006
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001007 VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(modified_create_info.get()), pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001008 if (result != VK_SUCCESS) {
1009 return result;
1010 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001011
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001012 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001013 device_interceptor->container_type = LayerObjectTypeDevice;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001014
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001015 // Save local info in device object
1016 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001017 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
1018 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001019 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001020
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001021 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001022
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001023 device_interceptor->device = *pDevice;
1024 device_interceptor->physical_device = gpu;
1025 device_interceptor->instance = instance_interceptor->instance;
1026 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001027
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001028 // Note that this defines the order in which the layer validation objects are called
1029#if BUILD_THREAD_SAFETY
1030 auto thread_safety = new ThreadSafety;
1031 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
1032 thread_safety->container_type = LayerObjectTypeThreading;
1033 thread_safety->physical_device = gpu;
1034 thread_safety->instance = instance_interceptor->instance;
1035 thread_safety->report_data = device_interceptor->report_data;
1036 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
1037 thread_safety->api_version = device_interceptor->api_version;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001038 if (!instance_interceptor->disabled.thread_safety) {
1039 device_interceptor->object_dispatch.emplace_back(thread_safety);
1040 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001041#endif
1042#if BUILD_PARAMETER_VALIDATION
1043 auto stateless_validation = new StatelessValidation;
1044 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
1045 stateless_validation->container_type = LayerObjectTypeParameterValidation;
1046 stateless_validation->physical_device = gpu;
1047 stateless_validation->instance = instance_interceptor->instance;
1048 stateless_validation->report_data = device_interceptor->report_data;
1049 stateless_validation->device_dispatch_table = device_interceptor->device_dispatch_table;
1050 stateless_validation->api_version = device_interceptor->api_version;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001051 if (!instance_interceptor->disabled.stateless_checks) {
1052 device_interceptor->object_dispatch.emplace_back(stateless_validation);
1053 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001054#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001055#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001056 // Create child layer objects for this key and add to dispatch vector
1057 auto object_tracker = new ObjectLifetimes;
1058 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
1059 object_tracker->container_type = LayerObjectTypeObjectTracker;
1060 object_tracker->physical_device = gpu;
1061 object_tracker->instance = instance_interceptor->instance;
1062 object_tracker->report_data = device_interceptor->report_data;
1063 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -07001064 object_tracker->api_version = device_interceptor->api_version;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001065 if (!instance_interceptor->disabled.object_tracking) {
1066 device_interceptor->object_dispatch.emplace_back(object_tracker);
1067 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001068#endif
1069#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001070 auto core_checks = new CoreChecks;
1071 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
1072 core_checks->container_type = LayerObjectTypeCoreValidation;
1073 core_checks->physical_device = gpu;
1074 core_checks->instance = instance_interceptor->instance;
1075 core_checks->report_data = device_interceptor->report_data;
1076 core_checks->device_dispatch_table = device_interceptor->device_dispatch_table;
1077 core_checks->instance_dispatch_table = instance_interceptor->instance_dispatch_table;
1078 core_checks->api_version = device_interceptor->api_version;
1079 core_checks->instance_extensions = instance_interceptor->instance_extensions;
1080 core_checks->device_extensions = device_interceptor->device_extensions;
1081 core_checks->instance_state = reinterpret_cast<CoreChecks *>(
1082 core_checks->GetValidationObject(instance_interceptor->object_dispatch, LayerObjectTypeCoreValidation));
1083 core_checks->device = *pDevice;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001084 if (!instance_interceptor->disabled.core_checks) {
1085 device_interceptor->object_dispatch.emplace_back(core_checks);
1086 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001087#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001088
1089 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001090 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001091 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001092 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001093
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001094 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
1095
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001096 return result;
1097}
1098
1099VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
1100 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001101 auto layer_data = GetLayerDataPtr(key, layer_data_map);
1102 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001103 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001104 intercept->PreCallValidateDestroyDevice(device, pAllocator);
1105 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001106 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001107 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001108 intercept->PreCallRecordDestroyDevice(device, pAllocator);
1109 }
1110 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001111
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001112 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001113
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001114 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001115 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001116 intercept->PostCallRecordDestroyDevice(device, pAllocator);
1117 }
1118
Mark Lobodzinskic5003372018-12-17 16:36:01 -07001119 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
1120 delete *item;
1121 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001122 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001123}
1124
1125
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001126// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001127
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001128VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
1129 VkDevice device,
1130 VkPipelineCache pipelineCache,
1131 uint32_t createInfoCount,
1132 const VkGraphicsPipelineCreateInfo* pCreateInfos,
1133 const VkAllocationCallbacks* pAllocator,
1134 VkPipeline* pPipelines) {
1135 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1136 bool skip = false;
1137
1138#ifdef BUILD_CORE_VALIDATION
1139 create_graphics_pipeline_api_state cgpl_state{};
1140#else
1141 struct create_graphics_pipeline_api_state {
1142 const VkGraphicsPipelineCreateInfo* pCreateInfos;
1143 } cgpl_state;
1144 cgpl_state.pCreateInfos = pCreateInfos;
1145#endif
1146
1147 for (auto intercept : layer_data->object_dispatch) {
1148 auto lock = intercept->write_lock();
1149 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1150 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1151 }
1152 for (auto intercept : layer_data->object_dispatch) {
1153 auto lock = intercept->write_lock();
1154 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1155 }
1156
Tony-LunarG152a88b2019-03-20 15:42:24 -06001157 VkResult result = DispatchCreateGraphicsPipelines(device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001158
1159 for (auto intercept : layer_data->object_dispatch) {
1160 auto lock = intercept->write_lock();
1161 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
1162 }
1163 return result;
1164}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001165
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001166// This API saves some core_validation pipeline state state on the stack for performance purposes
1167VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
1168 VkDevice device,
1169 VkPipelineCache pipelineCache,
1170 uint32_t createInfoCount,
1171 const VkComputePipelineCreateInfo* pCreateInfos,
1172 const VkAllocationCallbacks* pAllocator,
1173 VkPipeline* pPipelines) {
1174 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1175 bool skip = false;
1176
1177#ifndef BUILD_CORE_VALIDATION
1178 struct PIPELINE_STATE {};
1179#endif
1180
1181 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
1182
1183 for (auto intercept : layer_data->object_dispatch) {
1184 auto lock = intercept->write_lock();
1185 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
1186 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1187 }
1188 for (auto intercept : layer_data->object_dispatch) {
1189 auto lock = intercept->write_lock();
1190 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1191 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001192 VkResult result = DispatchCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001193 for (auto intercept : layer_data->object_dispatch) {
1194 auto lock = intercept->write_lock();
1195 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1196 }
1197 return result;
1198}
1199
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001200VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
1201 VkDevice device,
1202 VkPipelineCache pipelineCache,
1203 uint32_t createInfoCount,
1204 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
1205 const VkAllocationCallbacks* pAllocator,
1206 VkPipeline* pPipelines) {
1207 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1208 bool skip = false;
1209
1210#ifndef BUILD_CORE_VALIDATION
1211 struct PIPELINE_STATE {};
1212#endif
1213
1214 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
1215
1216 for (auto intercept : layer_data->object_dispatch) {
1217 auto lock = intercept->write_lock();
1218 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
1219 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1220 }
1221 for (auto intercept : layer_data->object_dispatch) {
1222 auto lock = intercept->write_lock();
1223 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1224 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001225 VkResult result = DispatchCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001226 for (auto intercept : layer_data->object_dispatch) {
1227 auto lock = intercept->write_lock();
1228 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1229 }
1230 return result;
1231}
1232
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001233// This API needs the ability to modify a down-chain parameter
1234VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
1235 VkDevice device,
1236 const VkPipelineLayoutCreateInfo* pCreateInfo,
1237 const VkAllocationCallbacks* pAllocator,
1238 VkPipelineLayout* pPipelineLayout) {
1239 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1240 bool skip = false;
1241
1242#ifndef BUILD_CORE_VALIDATION
1243 struct create_pipeline_layout_api_state {
1244 VkPipelineLayoutCreateInfo modified_create_info;
1245 };
1246#endif
1247 create_pipeline_layout_api_state cpl_state{};
1248 cpl_state.modified_create_info = *pCreateInfo;
1249
1250 for (auto intercept : layer_data->object_dispatch) {
1251 auto lock = intercept->write_lock();
1252 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1253 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1254 }
1255 for (auto intercept : layer_data->object_dispatch) {
1256 auto lock = intercept->write_lock();
1257 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1258 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001259 VkResult result = DispatchCreatePipelineLayout(device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001260 for (auto intercept : layer_data->object_dispatch) {
1261 auto lock = intercept->write_lock();
1262 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1263 }
1264 return result;
1265}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001266
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001267// This API needs some local stack data for performance reasons and also may modify a parameter
1268VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1269 VkDevice device,
1270 const VkShaderModuleCreateInfo* pCreateInfo,
1271 const VkAllocationCallbacks* pAllocator,
1272 VkShaderModule* pShaderModule) {
1273 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1274 bool skip = false;
1275
1276#ifndef BUILD_CORE_VALIDATION
1277 struct create_shader_module_api_state {
1278 VkShaderModuleCreateInfo instrumented_create_info;
1279 };
1280#endif
1281 create_shader_module_api_state csm_state{};
1282 csm_state.instrumented_create_info = *pCreateInfo;
1283
1284 for (auto intercept : layer_data->object_dispatch) {
1285 auto lock = intercept->write_lock();
1286 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1287 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1288 }
1289 for (auto intercept : layer_data->object_dispatch) {
1290 auto lock = intercept->write_lock();
1291 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1292 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001293 VkResult result = DispatchCreateShaderModule(device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001294 for (auto intercept : layer_data->object_dispatch) {
1295 auto lock = intercept->write_lock();
1296 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1297 }
1298 return result;
1299}
1300
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001301VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1302 VkDevice device,
1303 const VkDescriptorSetAllocateInfo* pAllocateInfo,
1304 VkDescriptorSet* pDescriptorSets) {
1305 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1306 bool skip = false;
1307
1308#ifdef BUILD_CORE_VALIDATION
1309 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1310#else
1311 struct ads_state {} ads_state;
1312#endif
1313
1314 for (auto intercept : layer_data->object_dispatch) {
1315 auto lock = intercept->write_lock();
1316 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1317 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1318 }
1319 for (auto intercept : layer_data->object_dispatch) {
1320 auto lock = intercept->write_lock();
1321 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1322 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001323 VkResult result = DispatchAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001324 for (auto intercept : layer_data->object_dispatch) {
1325 auto lock = intercept->write_lock();
1326 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1327 }
1328 return result;
1329}
1330
1331
1332
1333
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001334
1335// ValidationCache APIs do not dispatch
1336
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001337VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1338 VkDevice device,
1339 const VkValidationCacheCreateInfoEXT* pCreateInfo,
1340 const VkAllocationCallbacks* pAllocator,
1341 VkValidationCacheEXT* pValidationCache) {
1342 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1343 VkResult result = VK_SUCCESS;
1344
1345 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1346 if (validation_data) {
1347 auto lock = validation_data->write_lock();
1348 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1349 }
1350 return result;
1351}
1352
1353VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1354 VkDevice device,
1355 VkValidationCacheEXT validationCache,
1356 const VkAllocationCallbacks* pAllocator) {
1357 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1358
1359 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1360 if (validation_data) {
1361 auto lock = validation_data->write_lock();
1362 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1363 }
1364}
1365
1366VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1367 VkDevice device,
1368 VkValidationCacheEXT dstCache,
1369 uint32_t srcCacheCount,
1370 const VkValidationCacheEXT* pSrcCaches) {
1371 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1372 VkResult result = VK_SUCCESS;
1373
1374 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1375 if (validation_data) {
1376 auto lock = validation_data->write_lock();
1377 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1378 }
1379 return result;
1380}
1381
1382VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1383 VkDevice device,
1384 VkValidationCacheEXT validationCache,
1385 size_t* pDataSize,
1386 void* pData) {
1387 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1388 VkResult result = VK_SUCCESS;
1389
1390 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1391 if (validation_data) {
1392 auto lock = validation_data->write_lock();
1393 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1394 }
1395 return result;
1396
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001397}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001398
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001399 inline_custom_validation_class_definitions = """
1400 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1401 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1402 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1403 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001404
1405 // Allow additional parameter for CreateGraphicsPipelines
1406 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1407 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1408 };
1409 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1410 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1411 };
1412 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1413 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1414 };
1415
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001416 // Allow additional state parameter for CreateComputePipelines
1417 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1418 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1419 };
1420 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1421 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1422 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001423
1424 // Allow additional state parameter for CreateRayTracingPipelinesNV
1425 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1426 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1427 };
1428 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1429 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1430 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001431
1432 // Allow modification of a down-chain parameter for CreatePipelineLayout
1433 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1434 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1435 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001436
1437 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1438 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1439 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1440 };
1441 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1442 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1443 };
1444 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1445 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1446 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001447
1448 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1449 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1450 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1451 };
1452 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1453 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1454 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001455
1456 // Modify a parameter to CreateDevice
1457 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1458 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1459 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001460"""
1461
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001462 inline_custom_source_postamble = """
1463// loader-layer interface v0, just wrappers since there is only a layer
1464
1465VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1466 VkExtensionProperties *pProperties) {
1467 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1468}
1469
1470VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1471 VkLayerProperties *pProperties) {
1472 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1473}
1474
1475VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1476 VkLayerProperties *pProperties) {
1477 // the layer command handles VK_NULL_HANDLE just fine internally
1478 assert(physicalDevice == VK_NULL_HANDLE);
1479 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1480}
1481
1482VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1483 const char *pLayerName, uint32_t *pCount,
1484 VkExtensionProperties *pProperties) {
1485 // the layer command handles VK_NULL_HANDLE just fine internally
1486 assert(physicalDevice == VK_NULL_HANDLE);
1487 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1488}
1489
1490VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1491 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1492}
1493
1494VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1495 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1496}
1497
1498VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
1499 const char *funcName) {
1500 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
1501}
1502
1503VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1504 assert(pVersionStruct != NULL);
1505 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1506
1507 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1508 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1509 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1510 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
1511 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
1512 }
1513
1514 return VK_SUCCESS;
1515}"""
1516
1517
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001518 def __init__(self,
1519 errFile = sys.stderr,
1520 warnFile = sys.stderr,
1521 diagFile = sys.stdout):
1522 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1523 # Internal state - accumulators for different inner block text
1524 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1525 self.intercepts = []
1526 self.layer_factory = '' # String containing base layer factory class definition
1527
1528 # Check if the parameter passed in is a pointer to an array
1529 def paramIsArray(self, param):
1530 return param.attrib.get('len') is not None
1531
1532 # Check if the parameter passed in is a pointer
1533 def paramIsPointer(self, param):
1534 ispointer = False
1535 for elem in param:
1536 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
1537 ispointer = True
1538 return ispointer
1539
1540 # Check if an object is a non-dispatchable handle
1541 def isHandleTypeNonDispatchable(self, handletype):
1542 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1543 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1544 return True
1545 else:
1546 return False
1547
1548 # Check if an object is a dispatchable handle
1549 def isHandleTypeDispatchable(self, handletype):
1550 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1551 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
1552 return True
1553 else:
1554 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001555 #
1556 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001557 def beginFile(self, genOpts):
1558 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001559 # Output Copyright
1560 write(self.inline_copyright_message, file=self.outFile)
1561 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001562 self.header = False
1563 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1564 self.header = True
1565 write('#pragma once', file=self.outFile)
1566 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001567 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001568 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001569 else:
1570 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001571 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001572 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001573 #
1574 def endFile(self):
1575 # Finish C++ namespace and multiple inclusion protection
1576 self.newline()
1577 if not self.header:
1578 # Record intercepted procedures
1579 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
1580 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
1581 write('\n'.join(self.intercepts), file=self.outFile)
1582 write('};\n', file=self.outFile)
1583 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001584 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001585 if self.header:
1586 self.newline()
1587 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001588 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001589 self.layer_factory += '};\n\n'
1590 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001591 write(self.layer_factory, file=self.outFile)
1592 else:
1593 write(self.inline_custom_source_postamble, file=self.outFile)
1594 # Finish processing in superclass
1595 OutputGenerator.endFile(self)
1596
1597 def beginFeature(self, interface, emit):
1598 # Start processing in superclass
1599 OutputGenerator.beginFeature(self, interface, emit)
1600 # Get feature extra protect
1601 self.featureExtraProtect = GetFeatureProtect(interface)
1602 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1603 # feature. They're only printed in endFeature().
1604 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1605
1606 def endFeature(self):
1607 # Actually write the interface to the output file.
1608 if (self.emit):
1609 self.newline()
1610 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1611 # or move it below the 'for section...' loop.
1612 if (self.featureExtraProtect != None):
1613 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1614 for section in self.TYPE_SECTIONS:
1615 contents = self.sections[section]
1616 if contents:
1617 write('\n'.join(contents), file=self.outFile)
1618 self.newline()
1619 if (self.sections['command']):
1620 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1621 self.newline()
1622 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001623 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001624 # Finish processing in superclass
1625 OutputGenerator.endFeature(self)
1626 #
1627 # Append a definition to the specified section
1628 def appendSection(self, section, text):
1629 self.sections[section].append(text)
1630 #
1631 # Type generation
1632 def genType(self, typeinfo, name, alias):
1633 pass
1634 #
1635 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1636 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1637 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1638 # structs etc.)
1639 def genStruct(self, typeinfo, typeName):
1640 OutputGenerator.genStruct(self, typeinfo, typeName)
1641 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1642 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1643 for member in typeinfo.elem.findall('.//member'):
1644 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1645 body += ';\n'
1646 body += '} ' + typeName + ';\n'
1647 self.appendSection('struct', body)
1648 #
1649 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1650 def genGroup(self, groupinfo, groupName, alias):
1651 pass
1652 # Enumerant generation
1653 # <enum> tags may specify their values in several ways, but are usually just integers.
1654 def genEnum(self, enuminfo, name, alias):
1655 pass
1656 #
1657 # Customize Cdecl for layer factory base class
1658 def BaseClassCdecl(self, elem, name):
1659 raw = self.makeCDecls(elem)[1]
1660
1661 # Toss everything before the undecorated name
1662 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1663 prototype = prototype.replace(")", "", 1)
1664 prototype = prototype.replace(";", " {};")
1665
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001666 # Build up pre/post call virtual function declarations
1667 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1668 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1669 pre_call_record = 'virtual void PreCallRecord' + prototype
1670 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001671 resulttype = elem.find('proto/type')
1672 if resulttype.text == 'VkResult':
1673 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001674 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1675 #
1676 # Command generation
1677 def genCmd(self, cmdinfo, name, alias):
1678 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001679 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001680 ]
1681
1682 if name in ignore_functions:
1683 return
1684
1685 if self.header: # In the header declare all intercepts
1686 self.appendSection('command', '')
1687 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1688 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001689 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1690 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001691 if 'ValidationCache' not in name:
1692 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001693 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001694 self.layer_factory += '#endif\n'
1695 return
1696
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001697 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001698 if 'ValidationCache' not in name:
1699 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1700 else:
1701 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1702 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1703 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001704 return
1705 # Record that the function will be intercepted
1706 if (self.featureExtraProtect != None):
1707 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1708 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1709 if (self.featureExtraProtect != None):
1710 self.intercepts += [ '#endif' ]
1711 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1712 #
1713 decls = self.makeCDecls(cmdinfo.elem)
1714 self.appendSection('command', '')
1715 self.appendSection('command', '%s {' % decls[0][:-1])
1716 # Setup common to call wrappers. First parameter is always dispatchable
1717 dispatchable_type = cmdinfo.elem.find('param/type').text
1718 dispatchable_name = cmdinfo.elem.find('param/name').text
1719 # Default to device
1720 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001721 dispatch_table_name = 'VkLayerDispatchTable'
1722 # Set to instance as necessary
1723 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1724 device_or_instance = 'instance'
1725 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001726 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001727 api_function_name = cmdinfo.elem.attrib.get('name')
1728 params = cmdinfo.elem.findall('param/name')
1729 paramstext = ', '.join([str(param.text) for param in params])
Tony-LunarG152a88b2019-03-20 15:42:24 -06001730 API = api_function_name.replace('vk','Dispatch') + '('
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001731
1732 # Declare result variable, if any.
1733 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001734 'PFN_vkVoidFunction': 'return nullptr;',
1735 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001736 'VkDeviceAddress': 'return 0;',
1737 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1738 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001739 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001740 }
1741 resulttype = cmdinfo.elem.find('proto/type')
1742 assignresult = ''
1743 if (resulttype.text != 'void'):
1744 assignresult = resulttype.text + ' result = '
1745
1746 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001747 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001748
1749 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001750 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001751 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001752 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1753 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1754 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001755
1756 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001757 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001758 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001759 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001760 self.appendSection('command', ' }')
1761
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001762 # Insert pre-dispatch debug utils function call
1763 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001764 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001765
1766 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001767 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001768
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001769 # Insert post-dispatch debug utils function call
1770 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001771 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001772
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001773 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001774 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001775 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001776 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001777 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001778 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001779 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001780 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001781 # Return result variable, if any.
1782 if (resulttype.text != 'void'):
1783 self.appendSection('command', ' return result;')
1784 self.appendSection('command', '}')
1785 #
1786 # Override makeProtoName to drop the "vk" prefix
1787 def makeProtoName(self, name, tail):
1788 return self.genOpts.apientry + name[2:] + tail