blob: c1c7f3dc582678d677c502493e3fda47ac4dfe13 [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,
Mike Schuchardt21638df2019-03-16 10:52:02 -070065 conventions = None,
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -060066 filename = None,
67 directory = '.',
68 apiname = None,
69 profile = None,
70 versions = '.*',
71 emitversions = '.*',
72 defaultExtensions = None,
73 addExtensions = None,
74 removeExtensions = None,
75 emitExtensions = None,
76 sortProcedure = regSortFeatures,
77 prefixText = "",
78 genFuncPointers = True,
79 protectFile = True,
80 protectFeature = True,
81 apicall = '',
82 apientry = '',
83 apientryp = '',
84 indentFuncProto = True,
85 indentFuncPointer = False,
86 alignFuncParam = 0,
87 helper_file_type = '',
88 expandEnumerants = True):
Mike Schuchardt21638df2019-03-16 10:52:02 -070089 GeneratorOptions.__init__(self, conventions, filename, directory, apiname, profile,
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -060090 versions, emitversions, defaultExtensions,
91 addExtensions, removeExtensions, emitExtensions, sortProcedure)
92 self.prefixText = prefixText
93 self.genFuncPointers = genFuncPointers
94 self.protectFile = protectFile
95 self.protectFeature = protectFeature
96 self.apicall = apicall
97 self.apientry = apientry
98 self.apientryp = apientryp
99 self.indentFuncProto = indentFuncProto
100 self.indentFuncPointer = indentFuncPointer
101 self.alignFuncParam = alignFuncParam
102
103# LayerChassisOutputGenerator - subclass of OutputGenerator.
104# Generates a LayerFactory layer that intercepts all API entrypoints
105# This is intended to be used as a starting point for creating custom layers
106#
107# ---- methods ----
108# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
109# OutputGenerator. Defines additional internal state.
110# ---- methods overriding base class ----
111# beginFile(genOpts)
112# endFile()
113# beginFeature(interface, emit)
114# endFeature()
115# genType(typeinfo,name)
116# genStruct(typeinfo,name)
117# genGroup(groupinfo,name)
118# genEnum(enuminfo, name)
119# genCmd(cmdinfo)
120class LayerChassisOutputGenerator(OutputGenerator):
121 """Generate specified API interfaces in a specific style, such as a C header"""
122 # This is an ordered list of sections in the header file.
123 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
124 'group', 'bitmask', 'funcpointer', 'struct']
125 ALL_SECTIONS = TYPE_SECTIONS + ['command']
126
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700127 manual_functions = [
128 # Include functions here to be interecpted w/ manually implemented function bodies
129 'vkGetDeviceProcAddr',
130 'vkGetInstanceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700131 '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 Lobodzinski56e88122019-03-26 10:21:48 -0600151 # We don't wanna hook this function
152 'vkGetPhysicalDeviceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700153 ]
154
155 alt_ret_codes = [
156 # Include functions here which must tolerate VK_INCOMPLETE as a return code
157 'vkEnumeratePhysicalDevices',
158 'vkEnumeratePhysicalDeviceGroupsKHR',
159 'vkGetValidationCacheDataEXT',
160 'vkGetPipelineCacheData',
161 'vkGetShaderInfoAMD',
162 'vkGetPhysicalDeviceDisplayPropertiesKHR',
163 'vkGetPhysicalDeviceDisplayProperties2KHR',
164 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
165 'vkGetDisplayPlaneSupportedDisplaysKHR',
166 'vkGetDisplayModePropertiesKHR',
167 'vkGetDisplayModeProperties2KHR',
168 'vkGetPhysicalDeviceSurfaceFormatsKHR',
169 'vkGetPhysicalDeviceSurfacePresentModesKHR',
170 'vkGetPhysicalDevicePresentRectanglesKHR',
171 'vkGetPastPresentationTimingGOOGLE',
172 'vkGetSwapchainImagesKHR',
173 'vkEnumerateInstanceLayerProperties',
174 'vkEnumerateDeviceLayerProperties',
175 'vkEnumerateInstanceExtensionProperties',
176 'vkEnumerateDeviceExtensionProperties',
177 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
178 ]
179
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700180 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700181 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
182 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700183 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
184 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700185 }
186
187 post_dispatch_debug_utils_functions = {
188 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700189 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
190 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
191 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
192 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700193 }
194
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600195 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
196 precallrecord_loop = precallvalidate_loop
197 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600198
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700199 inline_custom_header_preamble = """
200#define NOMINMAX
Jeff Bolz89b9a502019-08-20 08:58:51 -0500201#include <atomic>
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700202#include <mutex>
203#include <cinttypes>
204#include <stdio.h>
205#include <stdlib.h>
206#include <string.h>
207#include <unordered_map>
208#include <unordered_set>
209#include <algorithm>
210#include <memory>
211
212#include "vk_loader_platform.h"
213#include "vulkan/vulkan.h"
214#include "vk_layer_config.h"
215#include "vk_layer_data.h"
216#include "vk_layer_logging.h"
217#include "vk_object_types.h"
218#include "vulkan/vk_layer.h"
219#include "vk_enum_string_helper.h"
220#include "vk_layer_extension_utils.h"
221#include "vk_layer_utils.h"
222#include "vulkan/vk_layer.h"
223#include "vk_dispatch_table_helper.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700224#include "vk_extension_helper.h"
225#include "vk_safe_struct.h"
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700226#include "vk_typemap_helper.h"
227
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700228
Jeff Bolz89b9a502019-08-20 08:58:51 -0500229extern std::atomic<uint64_t> global_unique_id;
230extern vl_concurrent_unordered_map<uint64_t, uint64_t, 4> unique_id_mapping;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700231"""
232
233 inline_custom_header_class_definition = """
234
235// Layer object type identifiers
236enum LayerObjectTypeId {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700237 LayerObjectTypeInstance, // Container for an instance dispatch object
238 LayerObjectTypeDevice, // Container for a device dispatch object
239 LayerObjectTypeThreading, // Instance or device threading layer object
240 LayerObjectTypeParameterValidation, // Instance or device parameter validation layer object
241 LayerObjectTypeObjectTracker, // Instance or device object tracker layer object
242 LayerObjectTypeCoreValidation, // Instance or device core validation layer object
Camdeneaa86ea2019-07-26 11:00:09 -0600243 LayerObjectTypeBestPractices, // Instance or device best practices 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 {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600261 VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600262 VALIDATION_CHECK_DISABLE_OBJECT_IN_USE,
263 VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET,
264 VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE,
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600265 VALIDATION_CHECK_DISABLE_QUERY_VALIDATION,
Matthew Ruschd7ef5482019-07-16 22:01:54 -0700266 VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600267} ValidationCheckDisables;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600268
Camden3231dcc2019-08-05 11:28:57 -0600269typedef enum VkValidationFeatureEnable {
270 VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES,
271} VkValidationFeatureEnable;
272
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600273
274// CHECK_DISABLED struct is a container for bools that can block validation checks from being performed.
275// These bools are all "false" by default meaning that all checks are enabled. Enum values can be specified
276// via the vk_layer_setting.txt config file or at CreateInstance time via the VK_EXT_validation_features extension
277// that can selectively disable checks.
278struct CHECK_DISABLED {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600279 bool command_buffer_state; // Skip command buffer state validation
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600280 bool object_in_use; // Skip all object in_use checking
281 bool idle_descriptor_set; // Skip check to verify that descriptor set is not in-use
282 bool push_constant_range; // Skip push constant range checks
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600283 bool query_validation; // Disable all core validation query-related checks
Matthew Ruschd7ef5482019-07-16 22:01:54 -0700284 bool image_layout_validation; // Disable image layout validation
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600285 bool object_tracking; // Disable object lifetime validation
286 bool core_checks; // Disable core validation checks
287 bool thread_safety; // Disable thread safety validation
288 bool stateless_checks; // Disable stateless validation checks
289 bool handle_wrapping; // Disable unique handles/handle wrapping
290 bool shader_validation; // Skip validation for shaders
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700291
292 void SetAll(bool value) { std::fill(&command_buffer_state, &shader_validation + 1, value); }
293};
294
295struct CHECK_ENABLED {
296 bool gpu_validation;
297 bool gpu_validation_reserve_binding_slot;
Camdeneaa86ea2019-07-26 11:00:09 -0600298 bool best_practices;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700299
300 void SetAll(bool value) { std::fill(&gpu_validation, &gpu_validation_reserve_binding_slot + 1, value); }
301};
302
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700303// Layer chassis validation object base class definition
304class ValidationObject {
305 public:
306 uint32_t api_version;
307 debug_report_data* report_data = nullptr;
308 std::vector<VkDebugReportCallbackEXT> logging_callback;
309 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
310
311 VkLayerInstanceDispatchTable instance_dispatch_table;
312 VkLayerDispatchTable device_dispatch_table;
313
314 InstanceExtensions instance_extensions;
315 DeviceExtensions device_extensions = {};
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700316 CHECK_DISABLED disabled = {};
317 CHECK_ENABLED enabled = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700318
319 VkInstance instance = VK_NULL_HANDLE;
320 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
321 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700322 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700323
324 std::vector<ValidationObject*> object_dispatch;
325 LayerObjectTypeId container_type;
326
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700327 std::string layer_name = "CHASSIS";
328
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700329 // Constructor
330 ValidationObject(){};
331 // Destructor
332 virtual ~ValidationObject() {};
333
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700334 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700335 virtual std::unique_lock<std::mutex> write_lock() {
336 return std::unique_lock<std::mutex>(validation_object_mutex);
337 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700338
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700339 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
340 for (auto validation_object : object_dispatch) {
341 if (validation_object->container_type == object_type) {
342 return validation_object;
343 }
344 }
345 return nullptr;
346 };
347
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700348 // Handle Wrapping Data
349 // Reverse map display handles
Jeff Bolz89b9a502019-08-20 08:58:51 -0500350 vl_concurrent_unordered_map<VkDisplayKHR, uint64_t, 0> display_id_reverse_mapping;
Mark Lobodzinskidd28ee22019-06-04 14:20:56 -0600351 // Wrapping Descriptor Template Update structures requires access to the template createinfo structs
352 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_createinfo_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700353 struct SubpassesUsageStates {
354 std::unordered_set<uint32_t> subpasses_using_color_attachment;
355 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
356 };
357 // Uses unwrapped handles
358 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
359 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
360 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
361 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700362 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
363 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700364
365
Jeff Bolz89b9a502019-08-20 08:58:51 -0500366 // Unwrap a handle.
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700367 template <typename HandleType>
368 HandleType Unwrap(HandleType wrappedHandle) {
Jeff Bolz89b9a502019-08-20 08:58:51 -0500369 auto iter = unique_id_mapping.find(reinterpret_cast<uint64_t const &>(wrappedHandle));
370 if (iter == unique_id_mapping.end())
371 return (HandleType)0;
372 return (HandleType)iter->second;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700373 }
374
Jeff Bolz89b9a502019-08-20 08:58:51 -0500375 // Wrap a newly created handle with a new unique ID, and return the new ID.
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700376 template <typename HandleType>
377 HandleType WrapNew(HandleType newlyCreatedHandle) {
378 auto unique_id = global_unique_id++;
Jeff Bolz89b9a502019-08-20 08:58:51 -0500379 unique_id_mapping.insert_or_assign(unique_id, reinterpret_cast<uint64_t const &>(newlyCreatedHandle));
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700380 return (HandleType)unique_id;
381 }
382
Jeff Bolz89b9a502019-08-20 08:58:51 -0500383 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup.
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700384 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
385 auto unique_id = global_unique_id++;
Jeff Bolz89b9a502019-08-20 08:58:51 -0500386 unique_id_mapping.insert_or_assign(unique_id, reinterpret_cast<uint64_t const &>(newlyCreatedHandle));
387 map_data->display_id_reverse_mapping.insert_or_assign(newlyCreatedHandle, unique_id);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700388 return (VkDisplayKHR)unique_id;
389 }
390
391 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
Jeff Bolz89b9a502019-08-20 08:58:51 -0500392 // creating another.
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700393 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
394 // See if this display is already known
395 auto it = map_data->display_id_reverse_mapping.find(handle);
396 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
397 // Unknown, so wrap
398 return WrapDisplay(handle, map_data);
399 }
400
401 // Pre/post hook point declarations
402"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600403
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700404 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600405// This file is ***GENERATED***. Do Not Edit.
406// See layer_chassis_generator.py for modifications.
407
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700408/* Copyright (c) 2015-2019 The Khronos Group Inc.
409 * Copyright (c) 2015-2019 Valve Corporation
410 * Copyright (c) 2015-2019 LunarG, Inc.
411 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600412 *
413 * Licensed under the Apache License, Version 2.0 (the "License");
414 * you may not use this file except in compliance with the License.
415 * You may obtain a copy of the License at
416 *
417 * http://www.apache.org/licenses/LICENSE-2.0
418 *
419 * Unless required by applicable law or agreed to in writing, software
420 * distributed under the License is distributed on an "AS IS" BASIS,
421 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
422 * See the License for the specific language governing permissions and
423 * limitations under the License.
424 *
425 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700426 */"""
427
428 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600429
430#include <string.h>
431#include <mutex>
432
433#define VALIDATION_ERROR_MAP_IMPL
434
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600435#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700436#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600437
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600438std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600439
Jeff Bolz89b9a502019-08-20 08:58:51 -0500440// Global unique object identifier.
441std::atomic<uint64_t> global_unique_id(1ULL);
442// Map uniqueID to actual object handle. Accesses to the map itself are
443// internally synchronized.
444vl_concurrent_unordered_map<uint64_t, uint64_t, 4> unique_id_mapping;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700445
446// TODO: This variable controls handle wrapping -- in the future it should be hooked
447// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
448#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
449bool wrap_handles = true;
450#else
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600451bool wrap_handles = false;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700452#endif
453
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600454// Set layer name -- Khronos layer name overrides any other defined names
Mark Lobodzinskiaa6fd7b2019-03-19 09:26:48 -0600455#if BUILD_KHRONOS_VALIDATION
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600456#define OBJECT_LAYER_NAME "VK_LAYER_KHRONOS_validation"
457#define OBJECT_LAYER_DESCRIPTION "khronos_validation"
458#elif BUILD_OBJECT_TRACKER
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700459#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600460#define OBJECT_LAYER_DESCRIPTION "lunarg_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700461#elif BUILD_THREAD_SAFETY
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700462#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600463#define OBJECT_LAYER_DESCRIPTION "google_thread_checker"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700464#elif BUILD_PARAMETER_VALIDATION
465#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600466#define OBJECT_LAYER_DESCRIPTION "lunarg_parameter_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700467#elif BUILD_CORE_VALIDATION
468#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600469#define OBJECT_LAYER_DESCRIPTION "lunarg_core_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700470#else
471#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600472#define OBJECT_LAYER_DESCRIPTION "lunarg_unique_objects"
473#endif
474
475// Include layer validation object definitions
476#if BUILD_OBJECT_TRACKER
477#include "object_lifetime_validation.h"
478#endif
479#if BUILD_THREAD_SAFETY
480#include "thread_safety.h"
481#endif
482#if BUILD_PARAMETER_VALIDATION
483#include "stateless_validation.h"
484#endif
485#if BUILD_CORE_VALIDATION
486#include "core_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700487#endif
Camdeneaa86ea2019-07-26 11:00:09 -0600488#if BUILD_BEST_PRACTICES
489#include "best_practices.h"
490#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600491
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600492namespace vulkan_layer_chassis {
493
494using std::unordered_map;
495
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600496static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700497 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600498};
499
John Zulauf358462e2019-04-10 11:10:32 -0600500static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION},
501 {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION}};
Lenny Komow3627f6e2019-06-19 13:54:59 -0600502static const VkExtensionProperties device_extensions[] = {
503 {VK_EXT_VALIDATION_CACHE_EXTENSION_NAME, VK_EXT_VALIDATION_CACHE_SPEC_VERSION},
504 {VK_EXT_DEBUG_MARKER_EXTENSION_NAME, VK_EXT_DEBUG_MARKER_SPEC_VERSION},
505};
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600506
Mark Lobodzinski31395512019-06-18 16:25:01 -0600507typedef struct {
508 bool is_instance_api;
509 void* funcptr;
510} function_data;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600511
Mark Lobodzinski31395512019-06-18 16:25:01 -0600512extern const std::unordered_map<std::string, function_data> name_to_funcptr_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600513
514// Manually written functions
515
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700516// Check enabled instance extensions against supported instance extension whitelist
517static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
518 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
519 // Check for recognized instance extensions
520 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
Ricardo Garcia0072a572019-08-01 12:19:23 +0200521 log_msg(layer_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700522 kVUIDUndefined,
523 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
524 "results and/or produce undefined behavior.",
525 pCreateInfo->ppEnabledExtensionNames[i]);
526 }
527 }
528}
529
530// Check enabled device extensions against supported device extension whitelist
531static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
532 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
533 // Check for recognized device extensions
534 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
Ricardo Garcia0072a572019-08-01 12:19:23 +0200535 log_msg(layer_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700536 kVUIDUndefined,
537 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
538 "results and/or produce undefined behavior.",
539 pCreateInfo->ppEnabledExtensionNames[i]);
540 }
541 }
542}
543
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600544
545// Process validation features, flags and settings specified through extensions, a layer settings file, or environment variables
546
547static const std::unordered_map<std::string, VkValidationFeatureDisableEXT> VkValFeatureDisableLookup = {
548 {"VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT", VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT},
549 {"VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT", VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT},
550 {"VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT", VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT},
551 {"VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT", VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT},
552 {"VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT", VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT},
553 {"VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT", VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT},
554 {"VK_VALIDATION_FEATURE_DISABLE_ALL_EXT", VK_VALIDATION_FEATURE_DISABLE_ALL_EXT},
555};
556
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600557static const std::unordered_map<std::string, VkValidationFeatureEnableEXT> VkValFeatureEnableLookup = {
558 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT},
559 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT},
560};
561
Camden3231dcc2019-08-05 11:28:57 -0600562static const std::unordered_map<std::string, VkValidationFeatureEnable> VkValFeatureEnableLookup2 = {
563 {"VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES", VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES},
564};
565
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600566static const std::unordered_map<std::string, ValidationCheckDisables> ValidationDisableLookup = {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600567 {"VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE", VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600568 {"VALIDATION_CHECK_DISABLE_OBJECT_IN_USE", VALIDATION_CHECK_DISABLE_OBJECT_IN_USE},
569 {"VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET", VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET},
570 {"VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE", VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE},
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600571 {"VALIDATION_CHECK_DISABLE_QUERY_VALIDATION", VALIDATION_CHECK_DISABLE_QUERY_VALIDATION},
Matthew Ruschd7ef5482019-07-16 22:01:54 -0700572 {"VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION", VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600573};
574
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600575// Set the local disable flag for the appropriate VALIDATION_CHECK_DISABLE enum
576void SetValidationDisable(CHECK_DISABLED* disable_data, const ValidationCheckDisables disable_id) {
577 switch (disable_id) {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600578 case VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE:
579 disable_data->command_buffer_state = true;
580 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600581 case VALIDATION_CHECK_DISABLE_OBJECT_IN_USE:
582 disable_data->object_in_use = true;
583 break;
584 case VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET:
585 disable_data->idle_descriptor_set = true;
586 break;
587 case VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE:
588 disable_data->push_constant_range = true;
589 break;
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600590 case VALIDATION_CHECK_DISABLE_QUERY_VALIDATION:
591 disable_data->query_validation = true;
592 break;
Matthew Ruschd7ef5482019-07-16 22:01:54 -0700593 case VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION:
594 disable_data->image_layout_validation = true;
595 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600596 default:
597 assert(true);
598 }
599}
600
601// Set the local disable flag for a single VK_VALIDATION_FEATURE_DISABLE_* flag
602void SetValidationFeatureDisable(CHECK_DISABLED* disable_data, const VkValidationFeatureDisableEXT feature_disable) {
603 switch (feature_disable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700604 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600605 disable_data->shader_validation = true;
606 break;
607 case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
608 disable_data->thread_safety = true;
609 break;
610 case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
611 disable_data->stateless_checks = true;
612 break;
613 case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
614 disable_data->object_tracking = true;
615 break;
616 case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
617 disable_data->core_checks = true;
618 break;
619 case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
620 disable_data->handle_wrapping = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700621 break;
622 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
623 // Set all disabled flags to true
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600624 disable_data->SetAll(true);
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700625 break;
626 default:
627 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700628 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600629}
630
631// Set the local enable flag for a single VK_VALIDATION_FEATURE_ENABLE_* flag
632void SetValidationFeatureEnable(CHECK_ENABLED *enable_data, const VkValidationFeatureEnableEXT feature_enable) {
633 switch (feature_enable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700634 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600635 enable_data->gpu_validation = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700636 break;
637 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600638 enable_data->gpu_validation_reserve_binding_slot = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700639 break;
640 default:
641 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700642 }
643}
644
Camden3231dcc2019-08-05 11:28:57 -0600645void SetValidationFeatureEnable(CHECK_ENABLED *enable_data, const VkValidationFeatureEnable feature_enable) {
646 switch(feature_enable) {
647 case VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES:
648 enable_data->best_practices = true;
649 break;
650 default:
651 break;
652 }
653}
654
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600655// Set the local disable flag for settings specified through the VK_EXT_validation_flags extension
656void SetValidationFlags(CHECK_DISABLED* disables, const VkValidationFlagsEXT* val_flags_struct) {
657 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
658 switch (val_flags_struct->pDisabledValidationChecks[i]) {
659 case VK_VALIDATION_CHECK_SHADERS_EXT:
660 disables->shader_validation = true;
661 break;
662 case VK_VALIDATION_CHECK_ALL_EXT:
663 // Set all disabled flags to true
664 disables->SetAll(true);
665 break;
666 default:
667 break;
668 }
669 }
670}
671
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600672// Process Validation Features flags specified through the ValidationFeature extension
673void SetValidationFeatures(CHECK_DISABLED *disable_data, CHECK_ENABLED *enable_data,
674 const VkValidationFeaturesEXT *val_features_struct) {
675 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
676 SetValidationFeatureDisable(disable_data, val_features_struct->pDisabledValidationFeatures[i]);
677 }
678 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
679 SetValidationFeatureEnable(enable_data, val_features_struct->pEnabledValidationFeatures[i]);
680 }
681}
682
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600683// Given a string representation of a list of enable enum values, call the appropriate setter function
684void SetLocalEnableSetting(std::string list_of_enables, std::string delimiter, CHECK_ENABLED* enables) {
685 size_t pos = 0;
686 std::string token;
687 while (list_of_enables.length() != 0) {
688 pos = list_of_enables.find(delimiter);
689 if (pos != std::string::npos) {
690 token = list_of_enables.substr(0, pos);
691 } else {
692 pos = list_of_enables.length() - delimiter.length();
693 token = list_of_enables;
694 }
695 if (token.find("VK_VALIDATION_FEATURE_ENABLE_") != std::string::npos) {
696 auto result = VkValFeatureEnableLookup.find(token);
697 if (result != VkValFeatureEnableLookup.end()) {
698 SetValidationFeatureEnable(enables, result->second);
Camden3231dcc2019-08-05 11:28:57 -0600699 } else {
700 auto result2 = VkValFeatureEnableLookup2.find(token);
701 if (result2 != VkValFeatureEnableLookup2.end()) {
702 SetValidationFeatureEnable(enables, result2->second);
703 }
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600704 }
705 }
706 list_of_enables.erase(0, pos + delimiter.length());
707 }
708}
709
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600710// Given a string representation of a list of disable enum values, call the appropriate setter function
711void SetLocalDisableSetting(std::string list_of_disables, std::string delimiter, CHECK_DISABLED* disables) {
712 size_t pos = 0;
713 std::string token;
714 while (list_of_disables.length() != 0) {
715 pos = list_of_disables.find(delimiter);
716 if (pos != std::string::npos) {
717 token = list_of_disables.substr(0, pos);
718 } else {
719 pos = list_of_disables.length() - delimiter.length();
720 token = list_of_disables;
721 }
722 if (token.find("VK_VALIDATION_FEATURE_DISABLE_") != std::string::npos) {
723 auto result = VkValFeatureDisableLookup.find(token);
724 if (result != VkValFeatureDisableLookup.end()) {
725 SetValidationFeatureDisable(disables, result->second);
726 }
727 }
728 if (token.find("VALIDATION_CHECK_DISABLE_") != std::string::npos) {
729 auto result = ValidationDisableLookup.find(token);
730 if (result != ValidationDisableLookup.end()) {
731 SetValidationDisable(disables, result->second);
732 }
733 }
734 list_of_disables.erase(0, pos + delimiter.length());
735 }
736}
737
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600738// Process enables and disables set though the vk_layer_settings.txt config file or through an environment variable
739void ProcessConfigAndEnvSettings(const char* layer_description, CHECK_ENABLED* enables, CHECK_DISABLED* disables) {
740 std::string enable_key = layer_description;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600741 std::string disable_key = layer_description;
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600742 enable_key.append(".enables");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600743 disable_key.append(".disables");
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600744 std::string list_of_config_enables = getLayerOption(enable_key.c_str());
745 std::string list_of_env_enables = GetLayerEnvVar("VK_LAYER_ENABLES");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600746 std::string list_of_config_disables = getLayerOption(disable_key.c_str());
747 std::string list_of_env_disables = GetLayerEnvVar("VK_LAYER_DISABLES");
748#if defined(_WIN32)
749 std::string env_delimiter = ";";
750#else
751 std::string env_delimiter = ":";
752#endif
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600753 SetLocalEnableSetting(list_of_config_enables, ",", enables);
754 SetLocalEnableSetting(list_of_env_enables, env_delimiter, enables);
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600755 SetLocalDisableSetting(list_of_config_disables, ",", disables);
756 SetLocalDisableSetting(list_of_env_disables, env_delimiter, disables);
757}
758
759
760// Non-code-generated chassis API functions
761
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600762VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600763 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskif94196f2019-07-11 11:46:09 -0600764 if (!ApiParentExtensionEnabled(funcName, &layer_data->device_extensions)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700765 return nullptr;
766 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600767 const auto &item = name_to_funcptr_map.find(funcName);
768 if (item != name_to_funcptr_map.end()) {
Mark Lobodzinski31395512019-06-18 16:25:01 -0600769 if (item->second.is_instance_api) {
770 return nullptr;
771 } else {
772 return reinterpret_cast<PFN_vkVoidFunction>(item->second.funcptr);
773 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600774 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600775 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600776 if (!table.GetDeviceProcAddr) return nullptr;
777 return table.GetDeviceProcAddr(device, funcName);
778}
779
780VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600781 const auto &item = name_to_funcptr_map.find(funcName);
782 if (item != name_to_funcptr_map.end()) {
Mark Lobodzinski31395512019-06-18 16:25:01 -0600783 return reinterpret_cast<PFN_vkVoidFunction>(item->second.funcptr);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600784 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600785 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
786 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600787 if (!table.GetInstanceProcAddr) return nullptr;
788 return table.GetInstanceProcAddr(instance, funcName);
789}
790
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600791VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
792 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
793}
794
795VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
796 VkLayerProperties *pProperties) {
797 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
798}
799
800VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
801 VkExtensionProperties *pProperties) {
802 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
John Zulauf358462e2019-04-10 11:10:32 -0600803 return util_GetExtensionProperties(ARRAY_SIZE(instance_extensions), instance_extensions, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600804
805 return VK_ERROR_LAYER_NOT_PRESENT;
806}
807
808VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
809 uint32_t *pCount, VkExtensionProperties *pProperties) {
Lenny Komow3627f6e2019-06-19 13:54:59 -0600810 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(ARRAY_SIZE(device_extensions), device_extensions, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600811 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600812 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
Lenny Komow7b567f72019-06-10 16:49:43 -0600813 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600814}
815
816VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
817 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600818 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600819
820 assert(chain_info->u.pLayerInfo);
821 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
822 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
823 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
824 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700825 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
826 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
827
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600828 CHECK_ENABLED local_enables {};
829 CHECK_DISABLED local_disables {};
830 const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(pCreateInfo->pNext);
831 if (validation_features_ext) {
832 SetValidationFeatures(&local_disables, &local_enables, validation_features_ext);
833 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600834 const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
835 if (validation_flags_ext) {
836 SetValidationFlags(&local_disables, validation_flags_ext);
837 }
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600838 ProcessConfigAndEnvSettings(OBJECT_LAYER_DESCRIPTION, &local_enables, &local_disables);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600839
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600840 // Create temporary dispatch vector for pre-calls until instance is created
841 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600842 // Add VOs to dispatch vector. Order here will be the validation dispatch order!
843#if BUILD_THREAD_SAFETY
844 auto thread_checker = new ThreadSafety;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600845 if (!local_disables.thread_safety) {
846 local_object_dispatch.emplace_back(thread_checker);
847 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600848 thread_checker->container_type = LayerObjectTypeThreading;
849 thread_checker->api_version = api_version;
850#endif
851#if BUILD_PARAMETER_VALIDATION
852 auto parameter_validation = new StatelessValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600853 if (!local_disables.stateless_checks) {
854 local_object_dispatch.emplace_back(parameter_validation);
855 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600856 parameter_validation->container_type = LayerObjectTypeParameterValidation;
857 parameter_validation->api_version = api_version;
858#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700859#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600860 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600861 if (!local_disables.object_tracking) {
862 local_object_dispatch.emplace_back(object_tracker);
863 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600864 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700865 object_tracker->api_version = api_version;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600866#endif
867#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700868 auto core_checks = new CoreChecks;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600869 if (!local_disables.core_checks) {
870 local_object_dispatch.emplace_back(core_checks);
871 }
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700872 core_checks->container_type = LayerObjectTypeCoreValidation;
873 core_checks->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700874#endif
Camdeneaa86ea2019-07-26 11:00:09 -0600875#if BUILD_BEST_PRACTICES
876 auto best_practices = new BestPractices;
877 if (local_enables.best_practices) {
878 local_object_dispatch.emplace_back(best_practices);
879 }
880 best_practices->container_type = LayerObjectTypeBestPractices;
881 best_practices->api_version = api_version;
882#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600883
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600884 // If handle wrapping is disabled via the ValidationFeatures extension, override build flag
885 if (local_disables.handle_wrapping) {
886 wrap_handles = false;
887 }
888
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600889 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600890 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600891 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
892 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600893 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600894 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
895 }
896
897 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600898 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600899
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600900 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600901
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600902 framework->object_dispatch = local_object_dispatch;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700903 framework->container_type = LayerObjectTypeInstance;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600904 framework->disabled = local_disables;
905 framework->enabled = local_enables;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600906
907 framework->instance = *pInstance;
908 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
909 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
910 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700911 framework->api_version = api_version;
912 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
913
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600914 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, OBJECT_LAYER_DESCRIPTION);
915
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700916#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700917 object_tracker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600918 object_tracker->instance_dispatch_table = framework->instance_dispatch_table;
919 object_tracker->enabled = framework->enabled;
920 object_tracker->disabled = framework->disabled;
921#endif
922#if BUILD_THREAD_SAFETY
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700923 thread_checker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600924 thread_checker->instance_dispatch_table = framework->instance_dispatch_table;
925 thread_checker->enabled = framework->enabled;
926 thread_checker->disabled = framework->disabled;
927#endif
928#if BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700929 parameter_validation->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600930 parameter_validation->instance_dispatch_table = framework->instance_dispatch_table;
931 parameter_validation->enabled = framework->enabled;
932 parameter_validation->disabled = framework->disabled;
933#endif
934#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700935 core_checks->report_data = framework->report_data;
936 core_checks->instance_dispatch_table = framework->instance_dispatch_table;
937 core_checks->instance = *pInstance;
938 core_checks->enabled = framework->enabled;
939 core_checks->disabled = framework->disabled;
940 core_checks->instance_state = core_checks;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700941#endif
Camdeneaa86ea2019-07-26 11:00:09 -0600942#if BUILD_BEST_PRACTICES
943 best_practices->report_data = framework->report_data;
944 best_practices->instance_dispatch_table = framework->instance_dispatch_table;
945 best_practices->enabled = framework->enabled;
946 best_practices->disabled = framework->disabled;
947#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600948
949 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700950 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600951 }
952
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700953 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
954
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600955 return result;
956}
957
958VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
959 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600960 auto layer_data = GetLayerDataPtr(key, layer_data_map);
961 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700962 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600963 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
964 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600965 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700966 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600967 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
968 }
969
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600970 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600971
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600972 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700973 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600974 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
975 }
976 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600977 while (layer_data->logging_messenger.size() > 0) {
978 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
979 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
980 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600981 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600982 while (layer_data->logging_callback.size() > 0) {
983 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
984 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
985 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600986 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600987
988 layer_debug_utils_destroy_instance(layer_data->report_data);
989
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700990 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
991 delete *item;
992 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600993 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600994}
995
996VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
997 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600998 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600999
1000 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
1001
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001002 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
1003 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001004 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
1005 if (fpCreateDevice == NULL) {
1006 return VK_ERROR_INITIALIZATION_FAILED;
1007 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001008 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
1009
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001010 // Get physical device limits for device
1011 VkPhysicalDeviceProperties device_properties = {};
1012 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
1013
1014 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
1015 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
1016
1017 DeviceExtensions device_extensions = {};
1018 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
1019 for (auto item : instance_interceptor->object_dispatch) {
1020 item->device_extensions = device_extensions;
1021 }
1022
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001023 std::unique_ptr<safe_VkDeviceCreateInfo> modified_create_info(new safe_VkDeviceCreateInfo(pCreateInfo));
1024
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001025 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001026 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001027 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001028 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001029 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001030 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001031 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001032 auto lock = intercept->write_lock();
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001033 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, modified_create_info);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001034 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001035
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001036 VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(modified_create_info.get()), pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001037 if (result != VK_SUCCESS) {
1038 return result;
1039 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001040
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001041 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001042 device_interceptor->container_type = LayerObjectTypeDevice;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001043
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001044 // Save local info in device object
1045 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001046 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
1047 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001048 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001049
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001050 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001051
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001052 device_interceptor->device = *pDevice;
1053 device_interceptor->physical_device = gpu;
1054 device_interceptor->instance = instance_interceptor->instance;
1055 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001056
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001057 // Note that this defines the order in which the layer validation objects are called
1058#if BUILD_THREAD_SAFETY
1059 auto thread_safety = new ThreadSafety;
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001060 thread_safety->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001061 if (!instance_interceptor->disabled.thread_safety) {
1062 device_interceptor->object_dispatch.emplace_back(thread_safety);
1063 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001064#endif
1065#if BUILD_PARAMETER_VALIDATION
1066 auto stateless_validation = new StatelessValidation;
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001067 stateless_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001068 if (!instance_interceptor->disabled.stateless_checks) {
1069 device_interceptor->object_dispatch.emplace_back(stateless_validation);
1070 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001071#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001072#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001073 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001074 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001075 if (!instance_interceptor->disabled.object_tracking) {
1076 device_interceptor->object_dispatch.emplace_back(object_tracker);
1077 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001078#endif
1079#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001080 auto core_checks = new CoreChecks;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001081 core_checks->container_type = LayerObjectTypeCoreValidation;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001082 core_checks->instance_state = reinterpret_cast<CoreChecks *>(
1083 core_checks->GetValidationObject(instance_interceptor->object_dispatch, LayerObjectTypeCoreValidation));
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
Camdeneaa86ea2019-07-26 11:00:09 -06001088#if BUILD_BEST_PRACTICES
1089 auto best_practices = new BestPractices;
1090 best_practices->container_type = LayerObjectTypeBestPractices;
1091 if (instance_interceptor->enabled.best_practices) {
1092 device_interceptor->object_dispatch.emplace_back(best_practices);
1093 }
1094#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001095
Mark Lobodzinski7314bf42019-03-28 08:54:53 -06001096 // Set per-intercept common data items
1097 for (auto dev_intercept : device_interceptor->object_dispatch) {
1098 dev_intercept->device = *pDevice;
1099 dev_intercept->physical_device = gpu;
1100 dev_intercept->instance = instance_interceptor->instance;
1101 dev_intercept->report_data = device_interceptor->report_data;
1102 dev_intercept->device_dispatch_table = device_interceptor->device_dispatch_table;
1103 dev_intercept->api_version = device_interceptor->api_version;
1104 dev_intercept->disabled = instance_interceptor->disabled;
1105 dev_intercept->enabled = instance_interceptor->enabled;
1106 dev_intercept->instance_dispatch_table = instance_interceptor->instance_dispatch_table;
1107 dev_intercept->instance_extensions = instance_interceptor->instance_extensions;
1108 dev_intercept->device_extensions = device_interceptor->device_extensions;
1109 }
1110
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001111 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001112 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001113 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001114 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001115
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001116 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
1117
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001118 return result;
1119}
1120
1121VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
1122 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001123 auto layer_data = GetLayerDataPtr(key, layer_data_map);
1124 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001125 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001126 intercept->PreCallValidateDestroyDevice(device, pAllocator);
1127 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001128 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001129 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001130 intercept->PreCallRecordDestroyDevice(device, pAllocator);
1131 }
1132 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001133
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001134 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001135
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001136 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001137 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001138 intercept->PostCallRecordDestroyDevice(device, pAllocator);
1139 }
1140
Mark Lobodzinskic5003372018-12-17 16:36:01 -07001141 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
1142 delete *item;
1143 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001144 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001145}
1146
1147
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001148// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001149
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001150VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
1151 VkDevice device,
1152 VkPipelineCache pipelineCache,
1153 uint32_t createInfoCount,
1154 const VkGraphicsPipelineCreateInfo* pCreateInfos,
1155 const VkAllocationCallbacks* pAllocator,
1156 VkPipeline* pPipelines) {
1157 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1158 bool skip = false;
1159
1160#ifdef BUILD_CORE_VALIDATION
1161 create_graphics_pipeline_api_state cgpl_state{};
1162#else
1163 struct create_graphics_pipeline_api_state {
1164 const VkGraphicsPipelineCreateInfo* pCreateInfos;
1165 } cgpl_state;
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001166#endif
Mark Lobodzinskid08e16c2019-06-11 10:22:10 -06001167 cgpl_state.pCreateInfos = pCreateInfos;
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001168
1169 for (auto intercept : layer_data->object_dispatch) {
1170 auto lock = intercept->write_lock();
1171 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1172 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1173 }
1174 for (auto intercept : layer_data->object_dispatch) {
1175 auto lock = intercept->write_lock();
1176 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1177 }
1178
Tony-LunarG152a88b2019-03-20 15:42:24 -06001179 VkResult result = DispatchCreateGraphicsPipelines(device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001180
1181 for (auto intercept : layer_data->object_dispatch) {
1182 auto lock = intercept->write_lock();
1183 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
1184 }
1185 return result;
1186}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001187
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001188// This API saves some core_validation pipeline state state on the stack for performance purposes
1189VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
1190 VkDevice device,
1191 VkPipelineCache pipelineCache,
1192 uint32_t createInfoCount,
1193 const VkComputePipelineCreateInfo* pCreateInfos,
1194 const VkAllocationCallbacks* pAllocator,
1195 VkPipeline* pPipelines) {
1196 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1197 bool skip = false;
1198
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001199#ifdef BUILD_CORE_VALIDATION
1200 create_compute_pipeline_api_state ccpl_state{};
1201#else
1202 struct create_compute_pipeline_api_state {
1203 const VkComputePipelineCreateInfo* pCreateInfos;
1204 } ccpl_state;
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001205#endif
Mark Lobodzinskid08e16c2019-06-11 10:22:10 -06001206 ccpl_state.pCreateInfos = pCreateInfos;
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001207
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001208 for (auto intercept : layer_data->object_dispatch) {
1209 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001210 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001211 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1212 }
1213 for (auto intercept : layer_data->object_dispatch) {
1214 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001215 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001216 }
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001217 VkResult result = DispatchCreateComputePipelines(device, pipelineCache, createInfoCount, ccpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001218 for (auto intercept : layer_data->object_dispatch) {
1219 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001220 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001221 }
1222 return result;
1223}
1224
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001225VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
1226 VkDevice device,
1227 VkPipelineCache pipelineCache,
1228 uint32_t createInfoCount,
1229 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
1230 const VkAllocationCallbacks* pAllocator,
1231 VkPipeline* pPipelines) {
1232 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1233 bool skip = false;
1234
Jason Macnak67407e72019-07-11 11:05:09 -07001235#ifdef BUILD_CORE_VALIDATION
1236 create_ray_tracing_pipeline_api_state crtpl_state{};
1237#else
1238 struct create_ray_tracing_pipeline_api_state {
1239 const VkRayTracingPipelineCreateInfoNV* pCreateInfos;
1240 } crtpl_state;
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001241#endif
Jason Macnak67407e72019-07-11 11:05:09 -07001242 crtpl_state.pCreateInfos = pCreateInfos;
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001243
1244 for (auto intercept : layer_data->object_dispatch) {
1245 auto lock = intercept->write_lock();
Jason Macnak67407e72019-07-11 11:05:09 -07001246 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos,
1247 pAllocator, pPipelines, &crtpl_state);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001248 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1249 }
1250 for (auto intercept : layer_data->object_dispatch) {
1251 auto lock = intercept->write_lock();
Jason Macnak67407e72019-07-11 11:05:09 -07001252 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator,
1253 pPipelines, &crtpl_state);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001254 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001255 VkResult result = DispatchCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001256 for (auto intercept : layer_data->object_dispatch) {
1257 auto lock = intercept->write_lock();
Jason Macnak67407e72019-07-11 11:05:09 -07001258 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator,
1259 pPipelines, result, &crtpl_state);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001260 }
1261 return result;
1262}
1263
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001264// This API needs the ability to modify a down-chain parameter
1265VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
1266 VkDevice device,
1267 const VkPipelineLayoutCreateInfo* pCreateInfo,
1268 const VkAllocationCallbacks* pAllocator,
1269 VkPipelineLayout* pPipelineLayout) {
1270 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1271 bool skip = false;
1272
1273#ifndef BUILD_CORE_VALIDATION
1274 struct create_pipeline_layout_api_state {
1275 VkPipelineLayoutCreateInfo modified_create_info;
1276 };
1277#endif
1278 create_pipeline_layout_api_state cpl_state{};
1279 cpl_state.modified_create_info = *pCreateInfo;
1280
1281 for (auto intercept : layer_data->object_dispatch) {
1282 auto lock = intercept->write_lock();
1283 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1284 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1285 }
1286 for (auto intercept : layer_data->object_dispatch) {
1287 auto lock = intercept->write_lock();
1288 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1289 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001290 VkResult result = DispatchCreatePipelineLayout(device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001291 for (auto intercept : layer_data->object_dispatch) {
1292 auto lock = intercept->write_lock();
1293 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1294 }
1295 return result;
1296}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001297
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001298// This API needs some local stack data for performance reasons and also may modify a parameter
1299VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1300 VkDevice device,
1301 const VkShaderModuleCreateInfo* pCreateInfo,
1302 const VkAllocationCallbacks* pAllocator,
1303 VkShaderModule* pShaderModule) {
1304 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1305 bool skip = false;
1306
1307#ifndef BUILD_CORE_VALIDATION
1308 struct create_shader_module_api_state {
1309 VkShaderModuleCreateInfo instrumented_create_info;
1310 };
1311#endif
1312 create_shader_module_api_state csm_state{};
1313 csm_state.instrumented_create_info = *pCreateInfo;
1314
1315 for (auto intercept : layer_data->object_dispatch) {
1316 auto lock = intercept->write_lock();
1317 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1318 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1319 }
1320 for (auto intercept : layer_data->object_dispatch) {
1321 auto lock = intercept->write_lock();
1322 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1323 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001324 VkResult result = DispatchCreateShaderModule(device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001325 for (auto intercept : layer_data->object_dispatch) {
1326 auto lock = intercept->write_lock();
1327 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1328 }
1329 return result;
1330}
1331
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001332VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1333 VkDevice device,
1334 const VkDescriptorSetAllocateInfo* pAllocateInfo,
1335 VkDescriptorSet* pDescriptorSets) {
1336 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1337 bool skip = false;
1338
1339#ifdef BUILD_CORE_VALIDATION
1340 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1341#else
1342 struct ads_state {} ads_state;
1343#endif
1344
1345 for (auto intercept : layer_data->object_dispatch) {
1346 auto lock = intercept->write_lock();
1347 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1348 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1349 }
1350 for (auto intercept : layer_data->object_dispatch) {
1351 auto lock = intercept->write_lock();
1352 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1353 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001354 VkResult result = DispatchAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001355 for (auto intercept : layer_data->object_dispatch) {
1356 auto lock = intercept->write_lock();
1357 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1358 }
1359 return result;
1360}
1361
1362
1363
1364
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001365
1366// ValidationCache APIs do not dispatch
1367
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001368VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1369 VkDevice device,
1370 const VkValidationCacheCreateInfoEXT* pCreateInfo,
1371 const VkAllocationCallbacks* pAllocator,
1372 VkValidationCacheEXT* pValidationCache) {
1373 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1374 VkResult result = VK_SUCCESS;
1375
1376 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1377 if (validation_data) {
1378 auto lock = validation_data->write_lock();
1379 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1380 }
1381 return result;
1382}
1383
1384VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1385 VkDevice device,
1386 VkValidationCacheEXT validationCache,
1387 const VkAllocationCallbacks* pAllocator) {
1388 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
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 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1394 }
1395}
1396
1397VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1398 VkDevice device,
1399 VkValidationCacheEXT dstCache,
1400 uint32_t srcCacheCount,
1401 const VkValidationCacheEXT* pSrcCaches) {
1402 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1403 VkResult result = VK_SUCCESS;
1404
1405 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1406 if (validation_data) {
1407 auto lock = validation_data->write_lock();
1408 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1409 }
1410 return result;
1411}
1412
1413VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1414 VkDevice device,
1415 VkValidationCacheEXT validationCache,
1416 size_t* pDataSize,
1417 void* pData) {
1418 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1419 VkResult result = VK_SUCCESS;
1420
1421 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1422 if (validation_data) {
1423 auto lock = validation_data->write_lock();
1424 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1425 }
1426 return result;
1427
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001428}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001429
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001430 inline_custom_validation_class_definitions = """
1431 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1432 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1433 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1434 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001435
Jason Macnak67407e72019-07-11 11:05:09 -07001436 // Allow additional state parameter for CreateGraphicsPipelines
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001437 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1438 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1439 };
1440 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1441 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1442 };
1443 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1444 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1445 };
Jason Macnak67407e72019-07-11 11:05:09 -07001446
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001447 // Allow additional state parameter for CreateComputePipelines
1448 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1449 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1450 };
Jason Macnak67407e72019-07-11 11:05:09 -07001451 virtual void PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* ccpl_state) {
1452 PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1453 };
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001454 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1455 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1456 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001457
1458 // Allow additional state parameter for CreateRayTracingPipelinesNV
1459 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1460 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1461 };
Jason Macnak67407e72019-07-11 11:05:09 -07001462 virtual void PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* ccpl_state) {
1463 PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1464 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001465 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1466 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1467 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001468
1469 // Allow modification of a down-chain parameter for CreatePipelineLayout
1470 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1471 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1472 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001473
1474 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1475 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1476 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1477 };
1478 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1479 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1480 };
1481 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1482 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1483 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001484
1485 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1486 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1487 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1488 };
1489 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1490 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1491 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001492
1493 // Modify a parameter to CreateDevice
1494 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1495 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1496 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001497"""
1498
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001499 inline_custom_source_postamble = """
1500// loader-layer interface v0, just wrappers since there is only a layer
1501
1502VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1503 VkExtensionProperties *pProperties) {
1504 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1505}
1506
1507VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1508 VkLayerProperties *pProperties) {
1509 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1510}
1511
1512VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1513 VkLayerProperties *pProperties) {
1514 // the layer command handles VK_NULL_HANDLE just fine internally
1515 assert(physicalDevice == VK_NULL_HANDLE);
1516 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1517}
1518
1519VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1520 const char *pLayerName, uint32_t *pCount,
1521 VkExtensionProperties *pProperties) {
1522 // the layer command handles VK_NULL_HANDLE just fine internally
1523 assert(physicalDevice == VK_NULL_HANDLE);
1524 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1525}
1526
1527VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1528 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1529}
1530
1531VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1532 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1533}
1534
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001535VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1536 assert(pVersionStruct != NULL);
1537 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1538
1539 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1540 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1541 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1542 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
Mark Lobodzinski56e88122019-03-26 10:21:48 -06001543 pVersionStruct->pfnGetPhysicalDeviceProcAddr = nullptr;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001544 }
1545
1546 return VK_SUCCESS;
1547}"""
1548
1549
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001550 def __init__(self,
1551 errFile = sys.stderr,
1552 warnFile = sys.stderr,
1553 diagFile = sys.stdout):
1554 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1555 # Internal state - accumulators for different inner block text
1556 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1557 self.intercepts = []
1558 self.layer_factory = '' # String containing base layer factory class definition
1559
1560 # Check if the parameter passed in is a pointer to an array
1561 def paramIsArray(self, param):
1562 return param.attrib.get('len') is not None
1563
1564 # Check if the parameter passed in is a pointer
1565 def paramIsPointer(self, param):
1566 ispointer = False
1567 for elem in param:
Raul Tambre7b300182019-05-04 11:25:14 +03001568 if elem.tag == 'type' and elem.tail is not None and '*' in elem.tail:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001569 ispointer = True
1570 return ispointer
1571
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001572 #
1573 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001574 def beginFile(self, genOpts):
1575 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001576 # Output Copyright
1577 write(self.inline_copyright_message, file=self.outFile)
1578 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001579 self.header = False
1580 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1581 self.header = True
1582 write('#pragma once', file=self.outFile)
1583 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001584 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001585 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001586 else:
1587 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001588 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001589 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001590 #
1591 def endFile(self):
1592 # Finish C++ namespace and multiple inclusion protection
1593 self.newline()
1594 if not self.header:
1595 # Record intercepted procedures
Mark Lobodzinski31395512019-06-18 16:25:01 -06001596 write('// Map of intercepted ApiName to its associated function data', file=self.outFile)
1597 write('const std::unordered_map<std::string, function_data> name_to_funcptr_map = {', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001598 write('\n'.join(self.intercepts), file=self.outFile)
1599 write('};\n', file=self.outFile)
1600 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001601 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001602 if self.header:
1603 self.newline()
1604 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001605 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001606 self.layer_factory += '};\n\n'
1607 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001608 write(self.layer_factory, file=self.outFile)
1609 else:
1610 write(self.inline_custom_source_postamble, file=self.outFile)
1611 # Finish processing in superclass
1612 OutputGenerator.endFile(self)
1613
1614 def beginFeature(self, interface, emit):
1615 # Start processing in superclass
1616 OutputGenerator.beginFeature(self, interface, emit)
1617 # Get feature extra protect
1618 self.featureExtraProtect = GetFeatureProtect(interface)
1619 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1620 # feature. They're only printed in endFeature().
1621 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1622
1623 def endFeature(self):
1624 # Actually write the interface to the output file.
1625 if (self.emit):
1626 self.newline()
1627 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1628 # or move it below the 'for section...' loop.
1629 if (self.featureExtraProtect != None):
1630 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1631 for section in self.TYPE_SECTIONS:
1632 contents = self.sections[section]
1633 if contents:
1634 write('\n'.join(contents), file=self.outFile)
1635 self.newline()
1636 if (self.sections['command']):
1637 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1638 self.newline()
1639 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001640 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001641 # Finish processing in superclass
1642 OutputGenerator.endFeature(self)
1643 #
1644 # Append a definition to the specified section
1645 def appendSection(self, section, text):
1646 self.sections[section].append(text)
1647 #
1648 # Type generation
1649 def genType(self, typeinfo, name, alias):
1650 pass
1651 #
1652 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1653 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1654 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1655 # structs etc.)
1656 def genStruct(self, typeinfo, typeName):
1657 OutputGenerator.genStruct(self, typeinfo, typeName)
1658 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1659 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1660 for member in typeinfo.elem.findall('.//member'):
1661 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1662 body += ';\n'
1663 body += '} ' + typeName + ';\n'
1664 self.appendSection('struct', body)
1665 #
1666 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1667 def genGroup(self, groupinfo, groupName, alias):
1668 pass
1669 # Enumerant generation
1670 # <enum> tags may specify their values in several ways, but are usually just integers.
1671 def genEnum(self, enuminfo, name, alias):
1672 pass
1673 #
1674 # Customize Cdecl for layer factory base class
1675 def BaseClassCdecl(self, elem, name):
1676 raw = self.makeCDecls(elem)[1]
1677
1678 # Toss everything before the undecorated name
1679 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1680 prototype = prototype.replace(")", "", 1)
1681 prototype = prototype.replace(";", " {};")
1682
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001683 # Build up pre/post call virtual function declarations
1684 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1685 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1686 pre_call_record = 'virtual void PreCallRecord' + prototype
1687 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001688 resulttype = elem.find('proto/type')
1689 if resulttype.text == 'VkResult':
1690 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001691 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1692 #
1693 # Command generation
1694 def genCmd(self, cmdinfo, name, alias):
1695 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001696 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001697 ]
1698
1699 if name in ignore_functions:
1700 return
1701
1702 if self.header: # In the header declare all intercepts
1703 self.appendSection('command', '')
1704 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1705 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001706 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1707 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001708 if 'ValidationCache' not in name:
1709 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001710 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001711 self.layer_factory += '#endif\n'
1712 return
1713
Mark Lobodzinski31395512019-06-18 16:25:01 -06001714 is_instance = 'false'
1715 dispatchable_type = cmdinfo.elem.find('param/type').text
1716 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1717 is_instance = 'true'
1718
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001719 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001720 if 'ValidationCache' not in name:
Mark Lobodzinski31395512019-06-18 16:25:01 -06001721 self.intercepts += [ ' {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001722 else:
1723 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
Mark Lobodzinski31395512019-06-18 16:25:01 -06001724
1725 self.intercepts += [ ' {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001726 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001727 return
1728 # Record that the function will be intercepted
1729 if (self.featureExtraProtect != None):
1730 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
Mark Lobodzinski31395512019-06-18 16:25:01 -06001731 self.intercepts += [ ' {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001732 if (self.featureExtraProtect != None):
1733 self.intercepts += [ '#endif' ]
1734 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1735 #
1736 decls = self.makeCDecls(cmdinfo.elem)
1737 self.appendSection('command', '')
1738 self.appendSection('command', '%s {' % decls[0][:-1])
1739 # Setup common to call wrappers. First parameter is always dispatchable
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001740 dispatchable_name = cmdinfo.elem.find('param/name').text
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001741 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001742 api_function_name = cmdinfo.elem.attrib.get('name')
1743 params = cmdinfo.elem.findall('param/name')
1744 paramstext = ', '.join([str(param.text) for param in params])
Tony-LunarG152a88b2019-03-20 15:42:24 -06001745 API = api_function_name.replace('vk','Dispatch') + '('
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001746
1747 # Declare result variable, if any.
1748 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001749 'PFN_vkVoidFunction': 'return nullptr;',
1750 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001751 'VkDeviceAddress': 'return 0;',
1752 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1753 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001754 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001755 }
1756 resulttype = cmdinfo.elem.find('proto/type')
1757 assignresult = ''
1758 if (resulttype.text != 'void'):
1759 assignresult = resulttype.text + ' result = '
1760
1761 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001762 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001763
1764 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001765 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001766 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001767 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1768 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1769 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001770
1771 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001772 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001773 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001774 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001775 self.appendSection('command', ' }')
1776
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001777 # Insert pre-dispatch debug utils function call
1778 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001779 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001780
1781 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001782 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001783
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001784 # Insert post-dispatch debug utils function call
1785 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001786 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001787
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001788 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001789 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001790 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001791 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001792 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001793 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001794 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001795 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001796 # Return result variable, if any.
1797 if (resulttype.text != 'void'):
1798 self.appendSection('command', ' return result;')
1799 self.appendSection('command', '}')
1800 #
1801 # Override makeProtoName to drop the "vk" prefix
1802 def makeProtoName(self, name, tail):
1803 return self.genOpts.apientry + name[2:] + tail