xref: /aosp_15_r20/external/vulkan-validation-layers/scripts/layer_chassis_generator.py (revision b7893ccf7851cd6a48cc5a1e965257d8a5cdcc70)
1*b7893ccfSSadaf Ebrahimi#!/usr/bin/python3 -i
2*b7893ccfSSadaf Ebrahimi#
3*b7893ccfSSadaf Ebrahimi# Copyright (c) 2015-2019 Valve Corporation
4*b7893ccfSSadaf Ebrahimi# Copyright (c) 2015-2019 LunarG, Inc.
5*b7893ccfSSadaf Ebrahimi# Copyright (c) 2015-2019 Google Inc.
6*b7893ccfSSadaf Ebrahimi#
7*b7893ccfSSadaf Ebrahimi# Licensed under the Apache License, Version 2.0 (the "License");
8*b7893ccfSSadaf Ebrahimi# you may not use this file except in compliance with the License.
9*b7893ccfSSadaf Ebrahimi# You may obtain a copy of the License at
10*b7893ccfSSadaf Ebrahimi#
11*b7893ccfSSadaf Ebrahimi#     http://www.apache.org/licenses/LICENSE-2.0
12*b7893ccfSSadaf Ebrahimi#
13*b7893ccfSSadaf Ebrahimi# Unless required by applicable law or agreed to in writing, software
14*b7893ccfSSadaf Ebrahimi# distributed under the License is distributed on an "AS IS" BASIS,
15*b7893ccfSSadaf Ebrahimi# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*b7893ccfSSadaf Ebrahimi# See the License for the specific language governing permissions and
17*b7893ccfSSadaf Ebrahimi# limitations under the License.
18*b7893ccfSSadaf Ebrahimi#
19*b7893ccfSSadaf Ebrahimi# Author: Tobin Ehlis <[email protected]>
20*b7893ccfSSadaf Ebrahimi# Author: Mark Lobodzinski <[email protected]>
21*b7893ccfSSadaf Ebrahimi#
22*b7893ccfSSadaf Ebrahimi# This script generates the dispatch portion of a factory layer which intercepts
23*b7893ccfSSadaf Ebrahimi# all Vulkan  functions. The resultant factory layer allows rapid development of
24*b7893ccfSSadaf Ebrahimi# layers and interceptors.
25*b7893ccfSSadaf Ebrahimi
26*b7893ccfSSadaf Ebrahimiimport os,re,sys
27*b7893ccfSSadaf Ebrahimifrom generator import *
28*b7893ccfSSadaf Ebrahimifrom common_codegen import *
29*b7893ccfSSadaf Ebrahimi
30*b7893ccfSSadaf Ebrahimi# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31*b7893ccfSSadaf Ebrahimi#
32*b7893ccfSSadaf Ebrahimi# Adds options used by LayerFactoryOutputGenerator objects during factory
33*b7893ccfSSadaf Ebrahimi# layer generation.
34*b7893ccfSSadaf Ebrahimi#
35*b7893ccfSSadaf Ebrahimi# Additional members
36*b7893ccfSSadaf Ebrahimi#   prefixText - list of strings to prefix generated header with
37*b7893ccfSSadaf Ebrahimi#     (usually a copyright statement + calling convention macros).
38*b7893ccfSSadaf Ebrahimi#   protectFile - True if multiple inclusion protection should be
39*b7893ccfSSadaf Ebrahimi#     generated (based on the filename) around the entire header.
40*b7893ccfSSadaf Ebrahimi#   protectFeature - True if #ifndef..#endif protection should be
41*b7893ccfSSadaf Ebrahimi#     generated around a feature interface in the header file.
42*b7893ccfSSadaf Ebrahimi#   genFuncPointers - True if function pointer typedefs should be
43*b7893ccfSSadaf Ebrahimi#     generated
44*b7893ccfSSadaf Ebrahimi#   protectProto - If conditional protection should be generated
45*b7893ccfSSadaf Ebrahimi#     around prototype declarations, set to either '#ifdef'
46*b7893ccfSSadaf Ebrahimi#     to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47*b7893ccfSSadaf Ebrahimi#     to require opt-out (#ifndef protectProtoStr). Otherwise
48*b7893ccfSSadaf Ebrahimi#     set to None.
49*b7893ccfSSadaf Ebrahimi#   protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50*b7893ccfSSadaf Ebrahimi#     declarations, if protectProto is set
51*b7893ccfSSadaf Ebrahimi#   apicall - string to use for the function declaration prefix,
52*b7893ccfSSadaf Ebrahimi#     such as APICALL on Windows.
53*b7893ccfSSadaf Ebrahimi#   apientry - string to use for the calling convention macro,
54*b7893ccfSSadaf Ebrahimi#     in typedefs, such as APIENTRY.
55*b7893ccfSSadaf Ebrahimi#   apientryp - string to use for the calling convention macro
56*b7893ccfSSadaf Ebrahimi#     in function pointer typedefs, such as APIENTRYP.
57*b7893ccfSSadaf Ebrahimi#   indentFuncProto - True if prototype declarations should put each
58*b7893ccfSSadaf Ebrahimi#     parameter on a separate line
59*b7893ccfSSadaf Ebrahimi#   indentFuncPointer - True if typedefed function pointers should put each
60*b7893ccfSSadaf Ebrahimi#     parameter on a separate line
61*b7893ccfSSadaf Ebrahimi#   alignFuncParam - if nonzero and parameters are being put on a
62*b7893ccfSSadaf Ebrahimi#     separate line, align parameter names at the specified column
63*b7893ccfSSadaf Ebrahimiclass LayerChassisGeneratorOptions(GeneratorOptions):
64*b7893ccfSSadaf Ebrahimi    def __init__(self,
65*b7893ccfSSadaf Ebrahimi                 conventions = None,
66*b7893ccfSSadaf Ebrahimi                 filename = None,
67*b7893ccfSSadaf Ebrahimi                 directory = '.',
68*b7893ccfSSadaf Ebrahimi                 apiname = None,
69*b7893ccfSSadaf Ebrahimi                 profile = None,
70*b7893ccfSSadaf Ebrahimi                 versions = '.*',
71*b7893ccfSSadaf Ebrahimi                 emitversions = '.*',
72*b7893ccfSSadaf Ebrahimi                 defaultExtensions = None,
73*b7893ccfSSadaf Ebrahimi                 addExtensions = None,
74*b7893ccfSSadaf Ebrahimi                 removeExtensions = None,
75*b7893ccfSSadaf Ebrahimi                 emitExtensions = None,
76*b7893ccfSSadaf Ebrahimi                 sortProcedure = regSortFeatures,
77*b7893ccfSSadaf Ebrahimi                 prefixText = "",
78*b7893ccfSSadaf Ebrahimi                 genFuncPointers = True,
79*b7893ccfSSadaf Ebrahimi                 protectFile = True,
80*b7893ccfSSadaf Ebrahimi                 protectFeature = True,
81*b7893ccfSSadaf Ebrahimi                 apicall = '',
82*b7893ccfSSadaf Ebrahimi                 apientry = '',
83*b7893ccfSSadaf Ebrahimi                 apientryp = '',
84*b7893ccfSSadaf Ebrahimi                 indentFuncProto = True,
85*b7893ccfSSadaf Ebrahimi                 indentFuncPointer = False,
86*b7893ccfSSadaf Ebrahimi                 alignFuncParam = 0,
87*b7893ccfSSadaf Ebrahimi                 helper_file_type = '',
88*b7893ccfSSadaf Ebrahimi                 expandEnumerants = True):
89*b7893ccfSSadaf Ebrahimi        GeneratorOptions.__init__(self, conventions, filename, directory, apiname, profile,
90*b7893ccfSSadaf Ebrahimi                                  versions, emitversions, defaultExtensions,
91*b7893ccfSSadaf Ebrahimi                                  addExtensions, removeExtensions, emitExtensions, sortProcedure)
92*b7893ccfSSadaf Ebrahimi        self.prefixText      = prefixText
93*b7893ccfSSadaf Ebrahimi        self.genFuncPointers = genFuncPointers
94*b7893ccfSSadaf Ebrahimi        self.protectFile     = protectFile
95*b7893ccfSSadaf Ebrahimi        self.protectFeature  = protectFeature
96*b7893ccfSSadaf Ebrahimi        self.apicall         = apicall
97*b7893ccfSSadaf Ebrahimi        self.apientry        = apientry
98*b7893ccfSSadaf Ebrahimi        self.apientryp       = apientryp
99*b7893ccfSSadaf Ebrahimi        self.indentFuncProto = indentFuncProto
100*b7893ccfSSadaf Ebrahimi        self.indentFuncPointer = indentFuncPointer
101*b7893ccfSSadaf Ebrahimi        self.alignFuncParam  = alignFuncParam
102*b7893ccfSSadaf Ebrahimi
103*b7893ccfSSadaf Ebrahimi# LayerChassisOutputGenerator - subclass of OutputGenerator.
104*b7893ccfSSadaf Ebrahimi# Generates a LayerFactory layer that intercepts all API entrypoints
105*b7893ccfSSadaf Ebrahimi#  This is intended to be used as a starting point for creating custom layers
106*b7893ccfSSadaf Ebrahimi#
107*b7893ccfSSadaf Ebrahimi# ---- methods ----
108*b7893ccfSSadaf Ebrahimi# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
109*b7893ccfSSadaf Ebrahimi#   OutputGenerator. Defines additional internal state.
110*b7893ccfSSadaf Ebrahimi# ---- methods overriding base class ----
111*b7893ccfSSadaf Ebrahimi# beginFile(genOpts)
112*b7893ccfSSadaf Ebrahimi# endFile()
113*b7893ccfSSadaf Ebrahimi# beginFeature(interface, emit)
114*b7893ccfSSadaf Ebrahimi# endFeature()
115*b7893ccfSSadaf Ebrahimi# genType(typeinfo,name)
116*b7893ccfSSadaf Ebrahimi# genStruct(typeinfo,name)
117*b7893ccfSSadaf Ebrahimi# genGroup(groupinfo,name)
118*b7893ccfSSadaf Ebrahimi# genEnum(enuminfo, name)
119*b7893ccfSSadaf Ebrahimi# genCmd(cmdinfo)
120*b7893ccfSSadaf Ebrahimiclass LayerChassisOutputGenerator(OutputGenerator):
121*b7893ccfSSadaf Ebrahimi    """Generate specified API interfaces in a specific style, such as a C header"""
122*b7893ccfSSadaf Ebrahimi    # This is an ordered list of sections in the header file.
123*b7893ccfSSadaf Ebrahimi    TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
124*b7893ccfSSadaf Ebrahimi                     'group', 'bitmask', 'funcpointer', 'struct']
125*b7893ccfSSadaf Ebrahimi    ALL_SECTIONS = TYPE_SECTIONS + ['command']
126*b7893ccfSSadaf Ebrahimi
127*b7893ccfSSadaf Ebrahimi    manual_functions = [
128*b7893ccfSSadaf Ebrahimi        # Include functions here to be interecpted w/ manually implemented function bodies
129*b7893ccfSSadaf Ebrahimi        'vkGetDeviceProcAddr',
130*b7893ccfSSadaf Ebrahimi        'vkGetInstanceProcAddr',
131*b7893ccfSSadaf Ebrahimi        'vkCreateDevice',
132*b7893ccfSSadaf Ebrahimi        'vkDestroyDevice',
133*b7893ccfSSadaf Ebrahimi        'vkCreateInstance',
134*b7893ccfSSadaf Ebrahimi        'vkDestroyInstance',
135*b7893ccfSSadaf Ebrahimi        'vkEnumerateInstanceLayerProperties',
136*b7893ccfSSadaf Ebrahimi        'vkEnumerateInstanceExtensionProperties',
137*b7893ccfSSadaf Ebrahimi        'vkEnumerateDeviceLayerProperties',
138*b7893ccfSSadaf Ebrahimi        'vkEnumerateDeviceExtensionProperties',
139*b7893ccfSSadaf Ebrahimi        # Functions that are handled explicitly due to chassis architecture violations
140*b7893ccfSSadaf Ebrahimi        'vkCreateGraphicsPipelines',
141*b7893ccfSSadaf Ebrahimi        'vkCreateComputePipelines',
142*b7893ccfSSadaf Ebrahimi        'vkCreateRayTracingPipelinesNV',
143*b7893ccfSSadaf Ebrahimi        'vkCreatePipelineLayout',
144*b7893ccfSSadaf Ebrahimi        'vkCreateShaderModule',
145*b7893ccfSSadaf Ebrahimi        'vkAllocateDescriptorSets',
146*b7893ccfSSadaf Ebrahimi        # ValidationCache functions do not get dispatched
147*b7893ccfSSadaf Ebrahimi        'vkCreateValidationCacheEXT',
148*b7893ccfSSadaf Ebrahimi        'vkDestroyValidationCacheEXT',
149*b7893ccfSSadaf Ebrahimi        'vkMergeValidationCachesEXT',
150*b7893ccfSSadaf Ebrahimi        'vkGetValidationCacheDataEXT',
151*b7893ccfSSadaf Ebrahimi        # We don't wanna hook this function
152*b7893ccfSSadaf Ebrahimi        'vkGetPhysicalDeviceProcAddr',
153*b7893ccfSSadaf Ebrahimi        ]
154*b7893ccfSSadaf Ebrahimi
155*b7893ccfSSadaf Ebrahimi    alt_ret_codes = [
156*b7893ccfSSadaf Ebrahimi        # Include functions here which must tolerate VK_INCOMPLETE as a return code
157*b7893ccfSSadaf Ebrahimi        'vkEnumeratePhysicalDevices',
158*b7893ccfSSadaf Ebrahimi        'vkEnumeratePhysicalDeviceGroupsKHR',
159*b7893ccfSSadaf Ebrahimi        'vkGetValidationCacheDataEXT',
160*b7893ccfSSadaf Ebrahimi        'vkGetPipelineCacheData',
161*b7893ccfSSadaf Ebrahimi        'vkGetShaderInfoAMD',
162*b7893ccfSSadaf Ebrahimi        'vkGetPhysicalDeviceDisplayPropertiesKHR',
163*b7893ccfSSadaf Ebrahimi        'vkGetPhysicalDeviceDisplayProperties2KHR',
164*b7893ccfSSadaf Ebrahimi        'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
165*b7893ccfSSadaf Ebrahimi        'vkGetDisplayPlaneSupportedDisplaysKHR',
166*b7893ccfSSadaf Ebrahimi        'vkGetDisplayModePropertiesKHR',
167*b7893ccfSSadaf Ebrahimi        'vkGetDisplayModeProperties2KHR',
168*b7893ccfSSadaf Ebrahimi        'vkGetPhysicalDeviceSurfaceFormatsKHR',
169*b7893ccfSSadaf Ebrahimi        'vkGetPhysicalDeviceSurfacePresentModesKHR',
170*b7893ccfSSadaf Ebrahimi        'vkGetPhysicalDevicePresentRectanglesKHR',
171*b7893ccfSSadaf Ebrahimi        'vkGetPastPresentationTimingGOOGLE',
172*b7893ccfSSadaf Ebrahimi        'vkGetSwapchainImagesKHR',
173*b7893ccfSSadaf Ebrahimi        'vkEnumerateInstanceLayerProperties',
174*b7893ccfSSadaf Ebrahimi        'vkEnumerateDeviceLayerProperties',
175*b7893ccfSSadaf Ebrahimi        'vkEnumerateInstanceExtensionProperties',
176*b7893ccfSSadaf Ebrahimi        'vkEnumerateDeviceExtensionProperties',
177*b7893ccfSSadaf Ebrahimi        'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
178*b7893ccfSSadaf Ebrahimi    ]
179*b7893ccfSSadaf Ebrahimi
180*b7893ccfSSadaf Ebrahimi    pre_dispatch_debug_utils_functions = {
181*b7893ccfSSadaf Ebrahimi        'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
182*b7893ccfSSadaf Ebrahimi        'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
183*b7893ccfSSadaf Ebrahimi        'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
184*b7893ccfSSadaf Ebrahimi        'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
185*b7893ccfSSadaf Ebrahimi        }
186*b7893ccfSSadaf Ebrahimi
187*b7893ccfSSadaf Ebrahimi    post_dispatch_debug_utils_functions = {
188*b7893ccfSSadaf Ebrahimi        'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
189*b7893ccfSSadaf Ebrahimi        'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
190*b7893ccfSSadaf Ebrahimi        'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
191*b7893ccfSSadaf Ebrahimi        'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
192*b7893ccfSSadaf Ebrahimi        'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
193*b7893ccfSSadaf Ebrahimi        }
194*b7893ccfSSadaf Ebrahimi
195*b7893ccfSSadaf Ebrahimi    precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
196*b7893ccfSSadaf Ebrahimi    precallrecord_loop = precallvalidate_loop
197*b7893ccfSSadaf Ebrahimi    postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
198*b7893ccfSSadaf Ebrahimi
199*b7893ccfSSadaf Ebrahimi    inline_custom_header_preamble = """
200*b7893ccfSSadaf Ebrahimi#define NOMINMAX
201*b7893ccfSSadaf Ebrahimi#include <atomic>
202*b7893ccfSSadaf Ebrahimi#include <mutex>
203*b7893ccfSSadaf Ebrahimi#include <cinttypes>
204*b7893ccfSSadaf Ebrahimi#include <stdio.h>
205*b7893ccfSSadaf Ebrahimi#include <stdlib.h>
206*b7893ccfSSadaf Ebrahimi#include <string.h>
207*b7893ccfSSadaf Ebrahimi#include <unordered_map>
208*b7893ccfSSadaf Ebrahimi#include <unordered_set>
209*b7893ccfSSadaf Ebrahimi#include <algorithm>
210*b7893ccfSSadaf Ebrahimi#include <memory>
211*b7893ccfSSadaf Ebrahimi
212*b7893ccfSSadaf Ebrahimi#include "vk_loader_platform.h"
213*b7893ccfSSadaf Ebrahimi#include "vulkan/vulkan.h"
214*b7893ccfSSadaf Ebrahimi#include "vk_layer_config.h"
215*b7893ccfSSadaf Ebrahimi#include "vk_layer_data.h"
216*b7893ccfSSadaf Ebrahimi#include "vk_layer_logging.h"
217*b7893ccfSSadaf Ebrahimi#include "vk_object_types.h"
218*b7893ccfSSadaf Ebrahimi#include "vulkan/vk_layer.h"
219*b7893ccfSSadaf Ebrahimi#include "vk_enum_string_helper.h"
220*b7893ccfSSadaf Ebrahimi#include "vk_layer_extension_utils.h"
221*b7893ccfSSadaf Ebrahimi#include "vk_layer_utils.h"
222*b7893ccfSSadaf Ebrahimi#include "vulkan/vk_layer.h"
223*b7893ccfSSadaf Ebrahimi#include "vk_dispatch_table_helper.h"
224*b7893ccfSSadaf Ebrahimi#include "vk_extension_helper.h"
225*b7893ccfSSadaf Ebrahimi#include "vk_safe_struct.h"
226*b7893ccfSSadaf Ebrahimi#include "vk_typemap_helper.h"
227*b7893ccfSSadaf Ebrahimi
228*b7893ccfSSadaf Ebrahimi
229*b7893ccfSSadaf Ebrahimiextern std::atomic<uint64_t> global_unique_id;
230*b7893ccfSSadaf Ebrahimiextern vl_concurrent_unordered_map<uint64_t, uint64_t, 4> unique_id_mapping;
231*b7893ccfSSadaf Ebrahimi"""
232*b7893ccfSSadaf Ebrahimi
233*b7893ccfSSadaf Ebrahimi    inline_custom_header_class_definition = """
234*b7893ccfSSadaf Ebrahimi
235*b7893ccfSSadaf Ebrahimi// Layer object type identifiers
236*b7893ccfSSadaf Ebrahimienum LayerObjectTypeId {
237*b7893ccfSSadaf Ebrahimi    LayerObjectTypeInstance,                    // Container for an instance dispatch object
238*b7893ccfSSadaf Ebrahimi    LayerObjectTypeDevice,                      // Container for a device dispatch object
239*b7893ccfSSadaf Ebrahimi    LayerObjectTypeThreading,                   // Instance or device threading layer object
240*b7893ccfSSadaf Ebrahimi    LayerObjectTypeParameterValidation,         // Instance or device parameter validation layer object
241*b7893ccfSSadaf Ebrahimi    LayerObjectTypeObjectTracker,               // Instance or device object tracker layer object
242*b7893ccfSSadaf Ebrahimi    LayerObjectTypeCoreValidation,              // Instance or device core validation layer object
243*b7893ccfSSadaf Ebrahimi    LayerObjectTypeBestPractices,               // Instance or device best practices layer object
244*b7893ccfSSadaf Ebrahimi};
245*b7893ccfSSadaf Ebrahimi
246*b7893ccfSSadaf Ebrahimistruct TEMPLATE_STATE {
247*b7893ccfSSadaf Ebrahimi    VkDescriptorUpdateTemplateKHR desc_update_template;
248*b7893ccfSSadaf Ebrahimi    safe_VkDescriptorUpdateTemplateCreateInfo create_info;
249*b7893ccfSSadaf Ebrahimi
250*b7893ccfSSadaf Ebrahimi    TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
251*b7893ccfSSadaf Ebrahimi        : desc_update_template(update_template), create_info(*pCreateInfo) {}
252*b7893ccfSSadaf Ebrahimi};
253*b7893ccfSSadaf Ebrahimi
254*b7893ccfSSadaf Ebrahimiclass LAYER_PHYS_DEV_PROPERTIES {
255*b7893ccfSSadaf Ebrahimipublic:
256*b7893ccfSSadaf Ebrahimi    VkPhysicalDeviceProperties properties;
257*b7893ccfSSadaf Ebrahimi    std::vector<VkQueueFamilyProperties> queue_family_properties;
258*b7893ccfSSadaf Ebrahimi};
259*b7893ccfSSadaf Ebrahimi
260*b7893ccfSSadaf Ebrahimitypedef enum ValidationCheckDisables {
261*b7893ccfSSadaf Ebrahimi    VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE,
262*b7893ccfSSadaf Ebrahimi    VALIDATION_CHECK_DISABLE_OBJECT_IN_USE,
263*b7893ccfSSadaf Ebrahimi    VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET,
264*b7893ccfSSadaf Ebrahimi    VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE,
265*b7893ccfSSadaf Ebrahimi    VALIDATION_CHECK_DISABLE_QUERY_VALIDATION,
266*b7893ccfSSadaf Ebrahimi    VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION,
267*b7893ccfSSadaf Ebrahimi} ValidationCheckDisables;
268*b7893ccfSSadaf Ebrahimi
269*b7893ccfSSadaf Ebrahimitypedef enum VkValidationFeatureEnable {
270*b7893ccfSSadaf Ebrahimi    VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES,
271*b7893ccfSSadaf Ebrahimi} VkValidationFeatureEnable;
272*b7893ccfSSadaf Ebrahimi
273*b7893ccfSSadaf Ebrahimi
274*b7893ccfSSadaf Ebrahimi// CHECK_DISABLED struct is a container for bools that can block validation checks from being performed.
275*b7893ccfSSadaf Ebrahimi// These bools are all "false" by default meaning that all checks are enabled. Enum values can be specified
276*b7893ccfSSadaf Ebrahimi// via the vk_layer_setting.txt config file or at CreateInstance time via the VK_EXT_validation_features extension
277*b7893ccfSSadaf Ebrahimi// that can selectively disable checks.
278*b7893ccfSSadaf Ebrahimistruct CHECK_DISABLED {
279*b7893ccfSSadaf Ebrahimi    bool command_buffer_state;                      // Skip command buffer state validation
280*b7893ccfSSadaf Ebrahimi    bool object_in_use;                             // Skip all object in_use checking
281*b7893ccfSSadaf Ebrahimi    bool idle_descriptor_set;                       // Skip check to verify that descriptor set is not in-use
282*b7893ccfSSadaf Ebrahimi    bool push_constant_range;                       // Skip push constant range checks
283*b7893ccfSSadaf Ebrahimi    bool query_validation;                          // Disable all core validation query-related checks
284*b7893ccfSSadaf Ebrahimi    bool image_layout_validation;                   // Disable image layout validation
285*b7893ccfSSadaf Ebrahimi    bool object_tracking;                           // Disable object lifetime validation
286*b7893ccfSSadaf Ebrahimi    bool core_checks;                               // Disable core validation checks
287*b7893ccfSSadaf Ebrahimi    bool thread_safety;                             // Disable thread safety validation
288*b7893ccfSSadaf Ebrahimi    bool stateless_checks;                          // Disable stateless validation checks
289*b7893ccfSSadaf Ebrahimi    bool handle_wrapping;                           // Disable unique handles/handle wrapping
290*b7893ccfSSadaf Ebrahimi    bool shader_validation;                         // Skip validation for shaders
291*b7893ccfSSadaf Ebrahimi
292*b7893ccfSSadaf Ebrahimi    void SetAll(bool value) { std::fill(&command_buffer_state, &shader_validation + 1, value); }
293*b7893ccfSSadaf Ebrahimi};
294*b7893ccfSSadaf Ebrahimi
295*b7893ccfSSadaf Ebrahimistruct CHECK_ENABLED {
296*b7893ccfSSadaf Ebrahimi    bool gpu_validation;
297*b7893ccfSSadaf Ebrahimi    bool gpu_validation_reserve_binding_slot;
298*b7893ccfSSadaf Ebrahimi    bool best_practices;
299*b7893ccfSSadaf Ebrahimi
300*b7893ccfSSadaf Ebrahimi    void SetAll(bool value) { std::fill(&gpu_validation, &gpu_validation_reserve_binding_slot + 1, value); }
301*b7893ccfSSadaf Ebrahimi};
302*b7893ccfSSadaf Ebrahimi
303*b7893ccfSSadaf Ebrahimi// Layer chassis validation object base class definition
304*b7893ccfSSadaf Ebrahimiclass ValidationObject {
305*b7893ccfSSadaf Ebrahimi    public:
306*b7893ccfSSadaf Ebrahimi        uint32_t api_version;
307*b7893ccfSSadaf Ebrahimi        debug_report_data* report_data = nullptr;
308*b7893ccfSSadaf Ebrahimi        std::vector<VkDebugReportCallbackEXT> logging_callback;
309*b7893ccfSSadaf Ebrahimi        std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
310*b7893ccfSSadaf Ebrahimi
311*b7893ccfSSadaf Ebrahimi        VkLayerInstanceDispatchTable instance_dispatch_table;
312*b7893ccfSSadaf Ebrahimi        VkLayerDispatchTable device_dispatch_table;
313*b7893ccfSSadaf Ebrahimi
314*b7893ccfSSadaf Ebrahimi        InstanceExtensions instance_extensions;
315*b7893ccfSSadaf Ebrahimi        DeviceExtensions device_extensions = {};
316*b7893ccfSSadaf Ebrahimi        CHECK_DISABLED disabled = {};
317*b7893ccfSSadaf Ebrahimi        CHECK_ENABLED enabled = {};
318*b7893ccfSSadaf Ebrahimi
319*b7893ccfSSadaf Ebrahimi        VkInstance instance = VK_NULL_HANDLE;
320*b7893ccfSSadaf Ebrahimi        VkPhysicalDevice physical_device = VK_NULL_HANDLE;
321*b7893ccfSSadaf Ebrahimi        VkDevice device = VK_NULL_HANDLE;
322*b7893ccfSSadaf Ebrahimi        LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
323*b7893ccfSSadaf Ebrahimi
324*b7893ccfSSadaf Ebrahimi        std::vector<ValidationObject*> object_dispatch;
325*b7893ccfSSadaf Ebrahimi        LayerObjectTypeId container_type;
326*b7893ccfSSadaf Ebrahimi
327*b7893ccfSSadaf Ebrahimi        std::string layer_name = "CHASSIS";
328*b7893ccfSSadaf Ebrahimi
329*b7893ccfSSadaf Ebrahimi        // Constructor
330*b7893ccfSSadaf Ebrahimi        ValidationObject(){};
331*b7893ccfSSadaf Ebrahimi        // Destructor
332*b7893ccfSSadaf Ebrahimi        virtual ~ValidationObject() {};
333*b7893ccfSSadaf Ebrahimi
334*b7893ccfSSadaf Ebrahimi        std::mutex validation_object_mutex;
335*b7893ccfSSadaf Ebrahimi        virtual std::unique_lock<std::mutex> write_lock() {
336*b7893ccfSSadaf Ebrahimi            return std::unique_lock<std::mutex>(validation_object_mutex);
337*b7893ccfSSadaf Ebrahimi        }
338*b7893ccfSSadaf Ebrahimi
339*b7893ccfSSadaf Ebrahimi        ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
340*b7893ccfSSadaf Ebrahimi            for (auto validation_object : object_dispatch) {
341*b7893ccfSSadaf Ebrahimi                if (validation_object->container_type == object_type) {
342*b7893ccfSSadaf Ebrahimi                    return validation_object;
343*b7893ccfSSadaf Ebrahimi                }
344*b7893ccfSSadaf Ebrahimi            }
345*b7893ccfSSadaf Ebrahimi            return nullptr;
346*b7893ccfSSadaf Ebrahimi        };
347*b7893ccfSSadaf Ebrahimi
348*b7893ccfSSadaf Ebrahimi        // Handle Wrapping Data
349*b7893ccfSSadaf Ebrahimi        // Reverse map display handles
350*b7893ccfSSadaf Ebrahimi        vl_concurrent_unordered_map<VkDisplayKHR, uint64_t, 0> display_id_reverse_mapping;
351*b7893ccfSSadaf Ebrahimi        // Wrapping Descriptor Template Update structures requires access to the template createinfo structs
352*b7893ccfSSadaf Ebrahimi        std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_createinfo_map;
353*b7893ccfSSadaf Ebrahimi        struct SubpassesUsageStates {
354*b7893ccfSSadaf Ebrahimi            std::unordered_set<uint32_t> subpasses_using_color_attachment;
355*b7893ccfSSadaf Ebrahimi            std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
356*b7893ccfSSadaf Ebrahimi        };
357*b7893ccfSSadaf Ebrahimi        // Uses unwrapped handles
358*b7893ccfSSadaf Ebrahimi        std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
359*b7893ccfSSadaf Ebrahimi        // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
360*b7893ccfSSadaf Ebrahimi        // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
361*b7893ccfSSadaf Ebrahimi        std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
362*b7893ccfSSadaf Ebrahimi        // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
363*b7893ccfSSadaf Ebrahimi        std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
364*b7893ccfSSadaf Ebrahimi
365*b7893ccfSSadaf Ebrahimi
366*b7893ccfSSadaf Ebrahimi        // Unwrap a handle.
367*b7893ccfSSadaf Ebrahimi        template <typename HandleType>
368*b7893ccfSSadaf Ebrahimi        HandleType Unwrap(HandleType wrappedHandle) {
369*b7893ccfSSadaf Ebrahimi            auto iter = unique_id_mapping.find(reinterpret_cast<uint64_t const &>(wrappedHandle));
370*b7893ccfSSadaf Ebrahimi            if (iter == unique_id_mapping.end())
371*b7893ccfSSadaf Ebrahimi                return (HandleType)0;
372*b7893ccfSSadaf Ebrahimi            return (HandleType)iter->second;
373*b7893ccfSSadaf Ebrahimi        }
374*b7893ccfSSadaf Ebrahimi
375*b7893ccfSSadaf Ebrahimi        // Wrap a newly created handle with a new unique ID, and return the new ID.
376*b7893ccfSSadaf Ebrahimi        template <typename HandleType>
377*b7893ccfSSadaf Ebrahimi        HandleType WrapNew(HandleType newlyCreatedHandle) {
378*b7893ccfSSadaf Ebrahimi            auto unique_id = global_unique_id++;
379*b7893ccfSSadaf Ebrahimi            unique_id_mapping.insert_or_assign(unique_id, reinterpret_cast<uint64_t const &>(newlyCreatedHandle));
380*b7893ccfSSadaf Ebrahimi            return (HandleType)unique_id;
381*b7893ccfSSadaf Ebrahimi        }
382*b7893ccfSSadaf Ebrahimi
383*b7893ccfSSadaf Ebrahimi        // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup.
384*b7893ccfSSadaf Ebrahimi        VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
385*b7893ccfSSadaf Ebrahimi            auto unique_id = global_unique_id++;
386*b7893ccfSSadaf Ebrahimi            unique_id_mapping.insert_or_assign(unique_id, reinterpret_cast<uint64_t const &>(newlyCreatedHandle));
387*b7893ccfSSadaf Ebrahimi            map_data->display_id_reverse_mapping.insert_or_assign(newlyCreatedHandle, unique_id);
388*b7893ccfSSadaf Ebrahimi            return (VkDisplayKHR)unique_id;
389*b7893ccfSSadaf Ebrahimi        }
390*b7893ccfSSadaf Ebrahimi
391*b7893ccfSSadaf Ebrahimi        // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
392*b7893ccfSSadaf Ebrahimi        // creating another.
393*b7893ccfSSadaf Ebrahimi        VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
394*b7893ccfSSadaf Ebrahimi            // See if this display is already known
395*b7893ccfSSadaf Ebrahimi            auto it = map_data->display_id_reverse_mapping.find(handle);
396*b7893ccfSSadaf Ebrahimi            if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
397*b7893ccfSSadaf Ebrahimi            // Unknown, so wrap
398*b7893ccfSSadaf Ebrahimi            return WrapDisplay(handle, map_data);
399*b7893ccfSSadaf Ebrahimi        }
400*b7893ccfSSadaf Ebrahimi
401*b7893ccfSSadaf Ebrahimi        // Pre/post hook point declarations
402*b7893ccfSSadaf Ebrahimi"""
403*b7893ccfSSadaf Ebrahimi
404*b7893ccfSSadaf Ebrahimi    inline_copyright_message = """
405*b7893ccfSSadaf Ebrahimi// This file is ***GENERATED***.  Do Not Edit.
406*b7893ccfSSadaf Ebrahimi// See layer_chassis_generator.py for modifications.
407*b7893ccfSSadaf Ebrahimi
408*b7893ccfSSadaf Ebrahimi/* Copyright (c) 2015-2019 The Khronos Group Inc.
409*b7893ccfSSadaf Ebrahimi * Copyright (c) 2015-2019 Valve Corporation
410*b7893ccfSSadaf Ebrahimi * Copyright (c) 2015-2019 LunarG, Inc.
411*b7893ccfSSadaf Ebrahimi * Copyright (c) 2015-2019 Google Inc.
412*b7893ccfSSadaf Ebrahimi *
413*b7893ccfSSadaf Ebrahimi * Licensed under the Apache License, Version 2.0 (the "License");
414*b7893ccfSSadaf Ebrahimi * you may not use this file except in compliance with the License.
415*b7893ccfSSadaf Ebrahimi * You may obtain a copy of the License at
416*b7893ccfSSadaf Ebrahimi *
417*b7893ccfSSadaf Ebrahimi *     http://www.apache.org/licenses/LICENSE-2.0
418*b7893ccfSSadaf Ebrahimi *
419*b7893ccfSSadaf Ebrahimi * Unless required by applicable law or agreed to in writing, software
420*b7893ccfSSadaf Ebrahimi * distributed under the License is distributed on an "AS IS" BASIS,
421*b7893ccfSSadaf Ebrahimi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
422*b7893ccfSSadaf Ebrahimi * See the License for the specific language governing permissions and
423*b7893ccfSSadaf Ebrahimi * limitations under the License.
424*b7893ccfSSadaf Ebrahimi *
425*b7893ccfSSadaf Ebrahimi * Author: Mark Lobodzinski <[email protected]>
426*b7893ccfSSadaf Ebrahimi */"""
427*b7893ccfSSadaf Ebrahimi
428*b7893ccfSSadaf Ebrahimi    inline_custom_source_preamble = """
429*b7893ccfSSadaf Ebrahimi
430*b7893ccfSSadaf Ebrahimi#include <string.h>
431*b7893ccfSSadaf Ebrahimi#include <mutex>
432*b7893ccfSSadaf Ebrahimi
433*b7893ccfSSadaf Ebrahimi#define VALIDATION_ERROR_MAP_IMPL
434*b7893ccfSSadaf Ebrahimi
435*b7893ccfSSadaf Ebrahimi#include "chassis.h"
436*b7893ccfSSadaf Ebrahimi#include "layer_chassis_dispatch.h"
437*b7893ccfSSadaf Ebrahimi
438*b7893ccfSSadaf Ebrahimistd::unordered_map<void*, ValidationObject*> layer_data_map;
439*b7893ccfSSadaf Ebrahimi
440*b7893ccfSSadaf Ebrahimi// Global unique object identifier.
441*b7893ccfSSadaf Ebrahimistd::atomic<uint64_t> global_unique_id(1ULL);
442*b7893ccfSSadaf Ebrahimi// Map uniqueID to actual object handle. Accesses to the map itself are
443*b7893ccfSSadaf Ebrahimi// internally synchronized.
444*b7893ccfSSadaf Ebrahimivl_concurrent_unordered_map<uint64_t, uint64_t, 4> unique_id_mapping;
445*b7893ccfSSadaf Ebrahimi
446*b7893ccfSSadaf Ebrahimi// TODO: This variable controls handle wrapping -- in the future it should be hooked
447*b7893ccfSSadaf Ebrahimi//       up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
448*b7893ccfSSadaf Ebrahimi#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
449*b7893ccfSSadaf Ebrahimibool wrap_handles = true;
450*b7893ccfSSadaf Ebrahimi#else
451*b7893ccfSSadaf Ebrahimibool wrap_handles = false;
452*b7893ccfSSadaf Ebrahimi#endif
453*b7893ccfSSadaf Ebrahimi
454*b7893ccfSSadaf Ebrahimi// Set layer name -- Khronos layer name overrides any other defined names
455*b7893ccfSSadaf Ebrahimi#if BUILD_KHRONOS_VALIDATION
456*b7893ccfSSadaf Ebrahimi#define OBJECT_LAYER_NAME "VK_LAYER_KHRONOS_validation"
457*b7893ccfSSadaf Ebrahimi#define OBJECT_LAYER_DESCRIPTION "khronos_validation"
458*b7893ccfSSadaf Ebrahimi#elif BUILD_OBJECT_TRACKER
459*b7893ccfSSadaf Ebrahimi#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
460*b7893ccfSSadaf Ebrahimi#define OBJECT_LAYER_DESCRIPTION "lunarg_object_tracker"
461*b7893ccfSSadaf Ebrahimi#elif BUILD_THREAD_SAFETY
462*b7893ccfSSadaf Ebrahimi#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
463*b7893ccfSSadaf Ebrahimi#define OBJECT_LAYER_DESCRIPTION "google_thread_checker"
464*b7893ccfSSadaf Ebrahimi#elif BUILD_PARAMETER_VALIDATION
465*b7893ccfSSadaf Ebrahimi#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
466*b7893ccfSSadaf Ebrahimi#define OBJECT_LAYER_DESCRIPTION "lunarg_parameter_validation"
467*b7893ccfSSadaf Ebrahimi#elif BUILD_CORE_VALIDATION
468*b7893ccfSSadaf Ebrahimi#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
469*b7893ccfSSadaf Ebrahimi#define OBJECT_LAYER_DESCRIPTION "lunarg_core_validation"
470*b7893ccfSSadaf Ebrahimi#else
471*b7893ccfSSadaf Ebrahimi#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
472*b7893ccfSSadaf Ebrahimi#define OBJECT_LAYER_DESCRIPTION "lunarg_unique_objects"
473*b7893ccfSSadaf Ebrahimi#endif
474*b7893ccfSSadaf Ebrahimi
475*b7893ccfSSadaf Ebrahimi// Include layer validation object definitions
476*b7893ccfSSadaf Ebrahimi#if BUILD_OBJECT_TRACKER
477*b7893ccfSSadaf Ebrahimi#include "object_lifetime_validation.h"
478*b7893ccfSSadaf Ebrahimi#endif
479*b7893ccfSSadaf Ebrahimi#if BUILD_THREAD_SAFETY
480*b7893ccfSSadaf Ebrahimi#include "thread_safety.h"
481*b7893ccfSSadaf Ebrahimi#endif
482*b7893ccfSSadaf Ebrahimi#if BUILD_PARAMETER_VALIDATION
483*b7893ccfSSadaf Ebrahimi#include "stateless_validation.h"
484*b7893ccfSSadaf Ebrahimi#endif
485*b7893ccfSSadaf Ebrahimi#if BUILD_CORE_VALIDATION
486*b7893ccfSSadaf Ebrahimi#include "core_validation.h"
487*b7893ccfSSadaf Ebrahimi#endif
488*b7893ccfSSadaf Ebrahimi#if BUILD_BEST_PRACTICES
489*b7893ccfSSadaf Ebrahimi#include "best_practices.h"
490*b7893ccfSSadaf Ebrahimi#endif
491*b7893ccfSSadaf Ebrahimi
492*b7893ccfSSadaf Ebrahiminamespace vulkan_layer_chassis {
493*b7893ccfSSadaf Ebrahimi
494*b7893ccfSSadaf Ebrahimiusing std::unordered_map;
495*b7893ccfSSadaf Ebrahimi
496*b7893ccfSSadaf Ebrahimistatic const VkLayerProperties global_layer = {
497*b7893ccfSSadaf Ebrahimi    OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
498*b7893ccfSSadaf Ebrahimi};
499*b7893ccfSSadaf Ebrahimi
500*b7893ccfSSadaf Ebrahimistatic const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION},
501*b7893ccfSSadaf Ebrahimi                                                            {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION}};
502*b7893ccfSSadaf Ebrahimistatic const VkExtensionProperties device_extensions[] = {
503*b7893ccfSSadaf Ebrahimi    {VK_EXT_VALIDATION_CACHE_EXTENSION_NAME, VK_EXT_VALIDATION_CACHE_SPEC_VERSION},
504*b7893ccfSSadaf Ebrahimi    {VK_EXT_DEBUG_MARKER_EXTENSION_NAME, VK_EXT_DEBUG_MARKER_SPEC_VERSION},
505*b7893ccfSSadaf Ebrahimi};
506*b7893ccfSSadaf Ebrahimi
507*b7893ccfSSadaf Ebrahimitypedef struct {
508*b7893ccfSSadaf Ebrahimi    bool is_instance_api;
509*b7893ccfSSadaf Ebrahimi    void* funcptr;
510*b7893ccfSSadaf Ebrahimi} function_data;
511*b7893ccfSSadaf Ebrahimi
512*b7893ccfSSadaf Ebrahimiextern const std::unordered_map<std::string, function_data> name_to_funcptr_map;
513*b7893ccfSSadaf Ebrahimi
514*b7893ccfSSadaf Ebrahimi// Manually written functions
515*b7893ccfSSadaf Ebrahimi
516*b7893ccfSSadaf Ebrahimi// Check enabled instance extensions against supported instance extension whitelist
517*b7893ccfSSadaf Ebrahimistatic void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
518*b7893ccfSSadaf Ebrahimi    for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
519*b7893ccfSSadaf Ebrahimi        // Check for recognized instance extensions
520*b7893ccfSSadaf Ebrahimi        if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
521*b7893ccfSSadaf Ebrahimi            log_msg(layer_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
522*b7893ccfSSadaf Ebrahimi                    kVUIDUndefined,
523*b7893ccfSSadaf Ebrahimi                    "Instance Extension %s is not supported by this layer.  Using this extension may adversely affect validation "
524*b7893ccfSSadaf Ebrahimi                    "results and/or produce undefined behavior.",
525*b7893ccfSSadaf Ebrahimi                    pCreateInfo->ppEnabledExtensionNames[i]);
526*b7893ccfSSadaf Ebrahimi        }
527*b7893ccfSSadaf Ebrahimi    }
528*b7893ccfSSadaf Ebrahimi}
529*b7893ccfSSadaf Ebrahimi
530*b7893ccfSSadaf Ebrahimi// Check enabled device extensions against supported device extension whitelist
531*b7893ccfSSadaf Ebrahimistatic void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
532*b7893ccfSSadaf Ebrahimi    for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
533*b7893ccfSSadaf Ebrahimi        // Check for recognized device extensions
534*b7893ccfSSadaf Ebrahimi        if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
535*b7893ccfSSadaf Ebrahimi            log_msg(layer_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
536*b7893ccfSSadaf Ebrahimi                    kVUIDUndefined,
537*b7893ccfSSadaf Ebrahimi                    "Device Extension %s is not supported by this layer.  Using this extension may adversely affect validation "
538*b7893ccfSSadaf Ebrahimi                    "results and/or produce undefined behavior.",
539*b7893ccfSSadaf Ebrahimi                    pCreateInfo->ppEnabledExtensionNames[i]);
540*b7893ccfSSadaf Ebrahimi        }
541*b7893ccfSSadaf Ebrahimi    }
542*b7893ccfSSadaf Ebrahimi}
543*b7893ccfSSadaf Ebrahimi
544*b7893ccfSSadaf Ebrahimi
545*b7893ccfSSadaf Ebrahimi// Process validation features, flags and settings specified through extensions, a layer settings file, or environment variables
546*b7893ccfSSadaf Ebrahimi
547*b7893ccfSSadaf Ebrahimistatic const std::unordered_map<std::string, VkValidationFeatureDisableEXT> VkValFeatureDisableLookup = {
548*b7893ccfSSadaf Ebrahimi    {"VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT", VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT},
549*b7893ccfSSadaf Ebrahimi    {"VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT", VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT},
550*b7893ccfSSadaf Ebrahimi    {"VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT", VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT},
551*b7893ccfSSadaf Ebrahimi    {"VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT", VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT},
552*b7893ccfSSadaf Ebrahimi    {"VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT", VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT},
553*b7893ccfSSadaf Ebrahimi    {"VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT", VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT},
554*b7893ccfSSadaf Ebrahimi    {"VK_VALIDATION_FEATURE_DISABLE_ALL_EXT", VK_VALIDATION_FEATURE_DISABLE_ALL_EXT},
555*b7893ccfSSadaf Ebrahimi};
556*b7893ccfSSadaf Ebrahimi
557*b7893ccfSSadaf Ebrahimistatic const std::unordered_map<std::string, VkValidationFeatureEnableEXT> VkValFeatureEnableLookup = {
558*b7893ccfSSadaf Ebrahimi    {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT},
559*b7893ccfSSadaf Ebrahimi    {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT},
560*b7893ccfSSadaf Ebrahimi};
561*b7893ccfSSadaf Ebrahimi
562*b7893ccfSSadaf Ebrahimistatic const std::unordered_map<std::string, VkValidationFeatureEnable> VkValFeatureEnableLookup2 = {
563*b7893ccfSSadaf Ebrahimi    {"VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES", VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES},
564*b7893ccfSSadaf Ebrahimi};
565*b7893ccfSSadaf Ebrahimi
566*b7893ccfSSadaf Ebrahimistatic const std::unordered_map<std::string, ValidationCheckDisables> ValidationDisableLookup = {
567*b7893ccfSSadaf Ebrahimi    {"VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE", VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE},
568*b7893ccfSSadaf Ebrahimi    {"VALIDATION_CHECK_DISABLE_OBJECT_IN_USE", VALIDATION_CHECK_DISABLE_OBJECT_IN_USE},
569*b7893ccfSSadaf Ebrahimi    {"VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET", VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET},
570*b7893ccfSSadaf Ebrahimi    {"VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE", VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE},
571*b7893ccfSSadaf Ebrahimi    {"VALIDATION_CHECK_DISABLE_QUERY_VALIDATION", VALIDATION_CHECK_DISABLE_QUERY_VALIDATION},
572*b7893ccfSSadaf Ebrahimi    {"VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION", VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION},
573*b7893ccfSSadaf Ebrahimi};
574*b7893ccfSSadaf Ebrahimi
575*b7893ccfSSadaf Ebrahimi// Set the local disable flag for the appropriate VALIDATION_CHECK_DISABLE enum
576*b7893ccfSSadaf Ebrahimivoid SetValidationDisable(CHECK_DISABLED* disable_data, const ValidationCheckDisables disable_id) {
577*b7893ccfSSadaf Ebrahimi    switch (disable_id) {
578*b7893ccfSSadaf Ebrahimi        case VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE:
579*b7893ccfSSadaf Ebrahimi            disable_data->command_buffer_state = true;
580*b7893ccfSSadaf Ebrahimi            break;
581*b7893ccfSSadaf Ebrahimi        case VALIDATION_CHECK_DISABLE_OBJECT_IN_USE:
582*b7893ccfSSadaf Ebrahimi            disable_data->object_in_use = true;
583*b7893ccfSSadaf Ebrahimi            break;
584*b7893ccfSSadaf Ebrahimi        case VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET:
585*b7893ccfSSadaf Ebrahimi            disable_data->idle_descriptor_set = true;
586*b7893ccfSSadaf Ebrahimi            break;
587*b7893ccfSSadaf Ebrahimi        case VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE:
588*b7893ccfSSadaf Ebrahimi            disable_data->push_constant_range = true;
589*b7893ccfSSadaf Ebrahimi            break;
590*b7893ccfSSadaf Ebrahimi        case VALIDATION_CHECK_DISABLE_QUERY_VALIDATION:
591*b7893ccfSSadaf Ebrahimi            disable_data->query_validation = true;
592*b7893ccfSSadaf Ebrahimi            break;
593*b7893ccfSSadaf Ebrahimi        case VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION:
594*b7893ccfSSadaf Ebrahimi            disable_data->image_layout_validation = true;
595*b7893ccfSSadaf Ebrahimi            break;
596*b7893ccfSSadaf Ebrahimi        default:
597*b7893ccfSSadaf Ebrahimi            assert(true);
598*b7893ccfSSadaf Ebrahimi    }
599*b7893ccfSSadaf Ebrahimi}
600*b7893ccfSSadaf Ebrahimi
601*b7893ccfSSadaf Ebrahimi// Set the local disable flag for a single VK_VALIDATION_FEATURE_DISABLE_* flag
602*b7893ccfSSadaf Ebrahimivoid SetValidationFeatureDisable(CHECK_DISABLED* disable_data, const VkValidationFeatureDisableEXT feature_disable) {
603*b7893ccfSSadaf Ebrahimi    switch (feature_disable) {
604*b7893ccfSSadaf Ebrahimi        case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
605*b7893ccfSSadaf Ebrahimi            disable_data->shader_validation = true;
606*b7893ccfSSadaf Ebrahimi            break;
607*b7893ccfSSadaf Ebrahimi        case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
608*b7893ccfSSadaf Ebrahimi            disable_data->thread_safety = true;
609*b7893ccfSSadaf Ebrahimi            break;
610*b7893ccfSSadaf Ebrahimi        case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
611*b7893ccfSSadaf Ebrahimi            disable_data->stateless_checks = true;
612*b7893ccfSSadaf Ebrahimi            break;
613*b7893ccfSSadaf Ebrahimi        case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
614*b7893ccfSSadaf Ebrahimi            disable_data->object_tracking = true;
615*b7893ccfSSadaf Ebrahimi            break;
616*b7893ccfSSadaf Ebrahimi        case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
617*b7893ccfSSadaf Ebrahimi            disable_data->core_checks = true;
618*b7893ccfSSadaf Ebrahimi            break;
619*b7893ccfSSadaf Ebrahimi        case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
620*b7893ccfSSadaf Ebrahimi            disable_data->handle_wrapping = true;
621*b7893ccfSSadaf Ebrahimi            break;
622*b7893ccfSSadaf Ebrahimi        case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
623*b7893ccfSSadaf Ebrahimi            // Set all disabled flags to true
624*b7893ccfSSadaf Ebrahimi            disable_data->SetAll(true);
625*b7893ccfSSadaf Ebrahimi            break;
626*b7893ccfSSadaf Ebrahimi        default:
627*b7893ccfSSadaf Ebrahimi            break;
628*b7893ccfSSadaf Ebrahimi    }
629*b7893ccfSSadaf Ebrahimi}
630*b7893ccfSSadaf Ebrahimi
631*b7893ccfSSadaf Ebrahimi// Set the local enable flag for a single VK_VALIDATION_FEATURE_ENABLE_* flag
632*b7893ccfSSadaf Ebrahimivoid SetValidationFeatureEnable(CHECK_ENABLED *enable_data, const VkValidationFeatureEnableEXT feature_enable) {
633*b7893ccfSSadaf Ebrahimi    switch (feature_enable) {
634*b7893ccfSSadaf Ebrahimi        case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
635*b7893ccfSSadaf Ebrahimi            enable_data->gpu_validation = true;
636*b7893ccfSSadaf Ebrahimi            break;
637*b7893ccfSSadaf Ebrahimi        case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
638*b7893ccfSSadaf Ebrahimi            enable_data->gpu_validation_reserve_binding_slot = true;
639*b7893ccfSSadaf Ebrahimi            break;
640*b7893ccfSSadaf Ebrahimi        default:
641*b7893ccfSSadaf Ebrahimi            break;
642*b7893ccfSSadaf Ebrahimi    }
643*b7893ccfSSadaf Ebrahimi}
644*b7893ccfSSadaf Ebrahimi
645*b7893ccfSSadaf Ebrahimivoid SetValidationFeatureEnable(CHECK_ENABLED *enable_data, const VkValidationFeatureEnable feature_enable) {
646*b7893ccfSSadaf Ebrahimi    switch(feature_enable) {
647*b7893ccfSSadaf Ebrahimi        case VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES:
648*b7893ccfSSadaf Ebrahimi            enable_data->best_practices = true;
649*b7893ccfSSadaf Ebrahimi            break;
650*b7893ccfSSadaf Ebrahimi        default:
651*b7893ccfSSadaf Ebrahimi            break;
652*b7893ccfSSadaf Ebrahimi    }
653*b7893ccfSSadaf Ebrahimi}
654*b7893ccfSSadaf Ebrahimi
655*b7893ccfSSadaf Ebrahimi// Set the local disable flag for settings specified through the VK_EXT_validation_flags extension
656*b7893ccfSSadaf Ebrahimivoid SetValidationFlags(CHECK_DISABLED* disables, const VkValidationFlagsEXT* val_flags_struct) {
657*b7893ccfSSadaf Ebrahimi    for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
658*b7893ccfSSadaf Ebrahimi        switch (val_flags_struct->pDisabledValidationChecks[i]) {
659*b7893ccfSSadaf Ebrahimi            case VK_VALIDATION_CHECK_SHADERS_EXT:
660*b7893ccfSSadaf Ebrahimi                disables->shader_validation = true;
661*b7893ccfSSadaf Ebrahimi                break;
662*b7893ccfSSadaf Ebrahimi            case VK_VALIDATION_CHECK_ALL_EXT:
663*b7893ccfSSadaf Ebrahimi                // Set all disabled flags to true
664*b7893ccfSSadaf Ebrahimi                disables->SetAll(true);
665*b7893ccfSSadaf Ebrahimi                break;
666*b7893ccfSSadaf Ebrahimi            default:
667*b7893ccfSSadaf Ebrahimi                break;
668*b7893ccfSSadaf Ebrahimi        }
669*b7893ccfSSadaf Ebrahimi    }
670*b7893ccfSSadaf Ebrahimi}
671*b7893ccfSSadaf Ebrahimi
672*b7893ccfSSadaf Ebrahimi// Process Validation Features flags specified through the ValidationFeature extension
673*b7893ccfSSadaf Ebrahimivoid SetValidationFeatures(CHECK_DISABLED *disable_data, CHECK_ENABLED *enable_data,
674*b7893ccfSSadaf Ebrahimi                           const VkValidationFeaturesEXT *val_features_struct) {
675*b7893ccfSSadaf Ebrahimi    for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
676*b7893ccfSSadaf Ebrahimi        SetValidationFeatureDisable(disable_data, val_features_struct->pDisabledValidationFeatures[i]);
677*b7893ccfSSadaf Ebrahimi    }
678*b7893ccfSSadaf Ebrahimi    for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
679*b7893ccfSSadaf Ebrahimi        SetValidationFeatureEnable(enable_data, val_features_struct->pEnabledValidationFeatures[i]);
680*b7893ccfSSadaf Ebrahimi    }
681*b7893ccfSSadaf Ebrahimi}
682*b7893ccfSSadaf Ebrahimi
683*b7893ccfSSadaf Ebrahimi// Given a string representation of a list of enable enum values, call the appropriate setter function
684*b7893ccfSSadaf Ebrahimivoid SetLocalEnableSetting(std::string list_of_enables, std::string delimiter, CHECK_ENABLED* enables) {
685*b7893ccfSSadaf Ebrahimi    size_t pos = 0;
686*b7893ccfSSadaf Ebrahimi    std::string token;
687*b7893ccfSSadaf Ebrahimi    while (list_of_enables.length() != 0) {
688*b7893ccfSSadaf Ebrahimi        pos = list_of_enables.find(delimiter);
689*b7893ccfSSadaf Ebrahimi        if (pos != std::string::npos) {
690*b7893ccfSSadaf Ebrahimi            token = list_of_enables.substr(0, pos);
691*b7893ccfSSadaf Ebrahimi        } else {
692*b7893ccfSSadaf Ebrahimi            pos = list_of_enables.length() - delimiter.length();
693*b7893ccfSSadaf Ebrahimi            token = list_of_enables;
694*b7893ccfSSadaf Ebrahimi        }
695*b7893ccfSSadaf Ebrahimi        if (token.find("VK_VALIDATION_FEATURE_ENABLE_") != std::string::npos) {
696*b7893ccfSSadaf Ebrahimi            auto result = VkValFeatureEnableLookup.find(token);
697*b7893ccfSSadaf Ebrahimi            if (result != VkValFeatureEnableLookup.end()) {
698*b7893ccfSSadaf Ebrahimi                SetValidationFeatureEnable(enables, result->second);
699*b7893ccfSSadaf Ebrahimi            } else {
700*b7893ccfSSadaf Ebrahimi                auto result2 = VkValFeatureEnableLookup2.find(token);
701*b7893ccfSSadaf Ebrahimi                if (result2 != VkValFeatureEnableLookup2.end()) {
702*b7893ccfSSadaf Ebrahimi                    SetValidationFeatureEnable(enables, result2->second);
703*b7893ccfSSadaf Ebrahimi                }
704*b7893ccfSSadaf Ebrahimi            }
705*b7893ccfSSadaf Ebrahimi        }
706*b7893ccfSSadaf Ebrahimi        list_of_enables.erase(0, pos + delimiter.length());
707*b7893ccfSSadaf Ebrahimi    }
708*b7893ccfSSadaf Ebrahimi}
709*b7893ccfSSadaf Ebrahimi
710*b7893ccfSSadaf Ebrahimi// Given a string representation of a list of disable enum values, call the appropriate setter function
711*b7893ccfSSadaf Ebrahimivoid SetLocalDisableSetting(std::string list_of_disables, std::string delimiter, CHECK_DISABLED* disables) {
712*b7893ccfSSadaf Ebrahimi    size_t pos = 0;
713*b7893ccfSSadaf Ebrahimi    std::string token;
714*b7893ccfSSadaf Ebrahimi    while (list_of_disables.length() != 0) {
715*b7893ccfSSadaf Ebrahimi        pos = list_of_disables.find(delimiter);
716*b7893ccfSSadaf Ebrahimi        if (pos != std::string::npos) {
717*b7893ccfSSadaf Ebrahimi            token = list_of_disables.substr(0, pos);
718*b7893ccfSSadaf Ebrahimi        } else {
719*b7893ccfSSadaf Ebrahimi            pos = list_of_disables.length() - delimiter.length();
720*b7893ccfSSadaf Ebrahimi            token = list_of_disables;
721*b7893ccfSSadaf Ebrahimi        }
722*b7893ccfSSadaf Ebrahimi        if (token.find("VK_VALIDATION_FEATURE_DISABLE_") != std::string::npos) {
723*b7893ccfSSadaf Ebrahimi            auto result = VkValFeatureDisableLookup.find(token);
724*b7893ccfSSadaf Ebrahimi            if (result != VkValFeatureDisableLookup.end()) {
725*b7893ccfSSadaf Ebrahimi                SetValidationFeatureDisable(disables, result->second);
726*b7893ccfSSadaf Ebrahimi            }
727*b7893ccfSSadaf Ebrahimi        }
728*b7893ccfSSadaf Ebrahimi        if (token.find("VALIDATION_CHECK_DISABLE_") != std::string::npos) {
729*b7893ccfSSadaf Ebrahimi            auto result = ValidationDisableLookup.find(token);
730*b7893ccfSSadaf Ebrahimi            if (result != ValidationDisableLookup.end()) {
731*b7893ccfSSadaf Ebrahimi                SetValidationDisable(disables, result->second);
732*b7893ccfSSadaf Ebrahimi            }
733*b7893ccfSSadaf Ebrahimi        }
734*b7893ccfSSadaf Ebrahimi        list_of_disables.erase(0, pos + delimiter.length());
735*b7893ccfSSadaf Ebrahimi    }
736*b7893ccfSSadaf Ebrahimi}
737*b7893ccfSSadaf Ebrahimi
738*b7893ccfSSadaf Ebrahimi// Process enables and disables set though the vk_layer_settings.txt config file or through an environment variable
739*b7893ccfSSadaf Ebrahimivoid ProcessConfigAndEnvSettings(const char* layer_description, CHECK_ENABLED* enables, CHECK_DISABLED* disables) {
740*b7893ccfSSadaf Ebrahimi    std::string enable_key = layer_description;
741*b7893ccfSSadaf Ebrahimi    std::string disable_key = layer_description;
742*b7893ccfSSadaf Ebrahimi    enable_key.append(".enables");
743*b7893ccfSSadaf Ebrahimi    disable_key.append(".disables");
744*b7893ccfSSadaf Ebrahimi    std::string list_of_config_enables = getLayerOption(enable_key.c_str());
745*b7893ccfSSadaf Ebrahimi    std::string list_of_env_enables = GetLayerEnvVar("VK_LAYER_ENABLES");
746*b7893ccfSSadaf Ebrahimi    std::string list_of_config_disables = getLayerOption(disable_key.c_str());
747*b7893ccfSSadaf Ebrahimi    std::string list_of_env_disables = GetLayerEnvVar("VK_LAYER_DISABLES");
748*b7893ccfSSadaf Ebrahimi#if defined(_WIN32)
749*b7893ccfSSadaf Ebrahimi    std::string env_delimiter = ";";
750*b7893ccfSSadaf Ebrahimi#else
751*b7893ccfSSadaf Ebrahimi    std::string env_delimiter = ":";
752*b7893ccfSSadaf Ebrahimi#endif
753*b7893ccfSSadaf Ebrahimi    SetLocalEnableSetting(list_of_config_enables, ",", enables);
754*b7893ccfSSadaf Ebrahimi    SetLocalEnableSetting(list_of_env_enables, env_delimiter, enables);
755*b7893ccfSSadaf Ebrahimi    SetLocalDisableSetting(list_of_config_disables, ",", disables);
756*b7893ccfSSadaf Ebrahimi    SetLocalDisableSetting(list_of_env_disables, env_delimiter, disables);
757*b7893ccfSSadaf Ebrahimi}
758*b7893ccfSSadaf Ebrahimi
759*b7893ccfSSadaf Ebrahimi
760*b7893ccfSSadaf Ebrahimi// Non-code-generated chassis API functions
761*b7893ccfSSadaf Ebrahimi
762*b7893ccfSSadaf EbrahimiVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
763*b7893ccfSSadaf Ebrahimi    auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
764*b7893ccfSSadaf Ebrahimi    if (!ApiParentExtensionEnabled(funcName, &layer_data->device_extensions)) {
765*b7893ccfSSadaf Ebrahimi        return nullptr;
766*b7893ccfSSadaf Ebrahimi    }
767*b7893ccfSSadaf Ebrahimi    const auto &item = name_to_funcptr_map.find(funcName);
768*b7893ccfSSadaf Ebrahimi    if (item != name_to_funcptr_map.end()) {
769*b7893ccfSSadaf Ebrahimi        if (item->second.is_instance_api) {
770*b7893ccfSSadaf Ebrahimi            return nullptr;
771*b7893ccfSSadaf Ebrahimi        } else {
772*b7893ccfSSadaf Ebrahimi            return reinterpret_cast<PFN_vkVoidFunction>(item->second.funcptr);
773*b7893ccfSSadaf Ebrahimi        }
774*b7893ccfSSadaf Ebrahimi    }
775*b7893ccfSSadaf Ebrahimi    auto &table = layer_data->device_dispatch_table;
776*b7893ccfSSadaf Ebrahimi    if (!table.GetDeviceProcAddr) return nullptr;
777*b7893ccfSSadaf Ebrahimi    return table.GetDeviceProcAddr(device, funcName);
778*b7893ccfSSadaf Ebrahimi}
779*b7893ccfSSadaf Ebrahimi
780*b7893ccfSSadaf EbrahimiVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
781*b7893ccfSSadaf Ebrahimi    const auto &item = name_to_funcptr_map.find(funcName);
782*b7893ccfSSadaf Ebrahimi    if (item != name_to_funcptr_map.end()) {
783*b7893ccfSSadaf Ebrahimi        return reinterpret_cast<PFN_vkVoidFunction>(item->second.funcptr);
784*b7893ccfSSadaf Ebrahimi    }
785*b7893ccfSSadaf Ebrahimi    auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
786*b7893ccfSSadaf Ebrahimi    auto &table = layer_data->instance_dispatch_table;
787*b7893ccfSSadaf Ebrahimi    if (!table.GetInstanceProcAddr) return nullptr;
788*b7893ccfSSadaf Ebrahimi    return table.GetInstanceProcAddr(instance, funcName);
789*b7893ccfSSadaf Ebrahimi}
790*b7893ccfSSadaf Ebrahimi
791*b7893ccfSSadaf EbrahimiVKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
792*b7893ccfSSadaf Ebrahimi    return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
793*b7893ccfSSadaf Ebrahimi}
794*b7893ccfSSadaf Ebrahimi
795*b7893ccfSSadaf EbrahimiVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
796*b7893ccfSSadaf Ebrahimi                                                              VkLayerProperties *pProperties) {
797*b7893ccfSSadaf Ebrahimi    return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
798*b7893ccfSSadaf Ebrahimi}
799*b7893ccfSSadaf Ebrahimi
800*b7893ccfSSadaf EbrahimiVKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
801*b7893ccfSSadaf Ebrahimi                                                                    VkExtensionProperties *pProperties) {
802*b7893ccfSSadaf Ebrahimi    if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
803*b7893ccfSSadaf Ebrahimi        return util_GetExtensionProperties(ARRAY_SIZE(instance_extensions), instance_extensions, pCount, pProperties);
804*b7893ccfSSadaf Ebrahimi
805*b7893ccfSSadaf Ebrahimi    return VK_ERROR_LAYER_NOT_PRESENT;
806*b7893ccfSSadaf Ebrahimi}
807*b7893ccfSSadaf Ebrahimi
808*b7893ccfSSadaf EbrahimiVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
809*b7893ccfSSadaf Ebrahimi                                                                  uint32_t *pCount, VkExtensionProperties *pProperties) {
810*b7893ccfSSadaf Ebrahimi    if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(ARRAY_SIZE(device_extensions), device_extensions, pCount, pProperties);
811*b7893ccfSSadaf Ebrahimi    assert(physicalDevice);
812*b7893ccfSSadaf Ebrahimi    auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
813*b7893ccfSSadaf Ebrahimi    return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pCount, pProperties);
814*b7893ccfSSadaf Ebrahimi}
815*b7893ccfSSadaf Ebrahimi
816*b7893ccfSSadaf EbrahimiVKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
817*b7893ccfSSadaf Ebrahimi                                              VkInstance *pInstance) {
818*b7893ccfSSadaf Ebrahimi    VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
819*b7893ccfSSadaf Ebrahimi
820*b7893ccfSSadaf Ebrahimi    assert(chain_info->u.pLayerInfo);
821*b7893ccfSSadaf Ebrahimi    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
822*b7893ccfSSadaf Ebrahimi    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
823*b7893ccfSSadaf Ebrahimi    if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
824*b7893ccfSSadaf Ebrahimi    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
825*b7893ccfSSadaf Ebrahimi    uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
826*b7893ccfSSadaf Ebrahimi    uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
827*b7893ccfSSadaf Ebrahimi
828*b7893ccfSSadaf Ebrahimi    CHECK_ENABLED local_enables {};
829*b7893ccfSSadaf Ebrahimi    CHECK_DISABLED local_disables {};
830*b7893ccfSSadaf Ebrahimi    const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(pCreateInfo->pNext);
831*b7893ccfSSadaf Ebrahimi    if (validation_features_ext) {
832*b7893ccfSSadaf Ebrahimi        SetValidationFeatures(&local_disables, &local_enables, validation_features_ext);
833*b7893ccfSSadaf Ebrahimi    }
834*b7893ccfSSadaf Ebrahimi    const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
835*b7893ccfSSadaf Ebrahimi    if (validation_flags_ext) {
836*b7893ccfSSadaf Ebrahimi        SetValidationFlags(&local_disables, validation_flags_ext);
837*b7893ccfSSadaf Ebrahimi    }
838*b7893ccfSSadaf Ebrahimi    ProcessConfigAndEnvSettings(OBJECT_LAYER_DESCRIPTION, &local_enables, &local_disables);
839*b7893ccfSSadaf Ebrahimi
840*b7893ccfSSadaf Ebrahimi    // Create temporary dispatch vector for pre-calls until instance is created
841*b7893ccfSSadaf Ebrahimi    std::vector<ValidationObject*> local_object_dispatch;
842*b7893ccfSSadaf Ebrahimi    // Add VOs to dispatch vector. Order here will be the validation dispatch order!
843*b7893ccfSSadaf Ebrahimi#if BUILD_THREAD_SAFETY
844*b7893ccfSSadaf Ebrahimi    auto thread_checker = new ThreadSafety;
845*b7893ccfSSadaf Ebrahimi    if (!local_disables.thread_safety) {
846*b7893ccfSSadaf Ebrahimi        local_object_dispatch.emplace_back(thread_checker);
847*b7893ccfSSadaf Ebrahimi    }
848*b7893ccfSSadaf Ebrahimi    thread_checker->container_type = LayerObjectTypeThreading;
849*b7893ccfSSadaf Ebrahimi    thread_checker->api_version = api_version;
850*b7893ccfSSadaf Ebrahimi#endif
851*b7893ccfSSadaf Ebrahimi#if BUILD_PARAMETER_VALIDATION
852*b7893ccfSSadaf Ebrahimi    auto parameter_validation = new StatelessValidation;
853*b7893ccfSSadaf Ebrahimi    if (!local_disables.stateless_checks) {
854*b7893ccfSSadaf Ebrahimi        local_object_dispatch.emplace_back(parameter_validation);
855*b7893ccfSSadaf Ebrahimi    }
856*b7893ccfSSadaf Ebrahimi    parameter_validation->container_type = LayerObjectTypeParameterValidation;
857*b7893ccfSSadaf Ebrahimi    parameter_validation->api_version = api_version;
858*b7893ccfSSadaf Ebrahimi#endif
859*b7893ccfSSadaf Ebrahimi#if BUILD_OBJECT_TRACKER
860*b7893ccfSSadaf Ebrahimi    auto object_tracker = new ObjectLifetimes;
861*b7893ccfSSadaf Ebrahimi    if (!local_disables.object_tracking) {
862*b7893ccfSSadaf Ebrahimi        local_object_dispatch.emplace_back(object_tracker);
863*b7893ccfSSadaf Ebrahimi    }
864*b7893ccfSSadaf Ebrahimi    object_tracker->container_type = LayerObjectTypeObjectTracker;
865*b7893ccfSSadaf Ebrahimi    object_tracker->api_version = api_version;
866*b7893ccfSSadaf Ebrahimi#endif
867*b7893ccfSSadaf Ebrahimi#if BUILD_CORE_VALIDATION
868*b7893ccfSSadaf Ebrahimi    auto core_checks = new CoreChecks;
869*b7893ccfSSadaf Ebrahimi    if (!local_disables.core_checks) {
870*b7893ccfSSadaf Ebrahimi        local_object_dispatch.emplace_back(core_checks);
871*b7893ccfSSadaf Ebrahimi    }
872*b7893ccfSSadaf Ebrahimi    core_checks->container_type = LayerObjectTypeCoreValidation;
873*b7893ccfSSadaf Ebrahimi    core_checks->api_version = api_version;
874*b7893ccfSSadaf Ebrahimi#endif
875*b7893ccfSSadaf Ebrahimi#if BUILD_BEST_PRACTICES
876*b7893ccfSSadaf Ebrahimi    auto best_practices = new BestPractices;
877*b7893ccfSSadaf Ebrahimi    if (local_enables.best_practices) {
878*b7893ccfSSadaf Ebrahimi        local_object_dispatch.emplace_back(best_practices);
879*b7893ccfSSadaf Ebrahimi    }
880*b7893ccfSSadaf Ebrahimi    best_practices->container_type = LayerObjectTypeBestPractices;
881*b7893ccfSSadaf Ebrahimi    best_practices->api_version = api_version;
882*b7893ccfSSadaf Ebrahimi#endif
883*b7893ccfSSadaf Ebrahimi
884*b7893ccfSSadaf Ebrahimi    // If handle wrapping is disabled via the ValidationFeatures extension, override build flag
885*b7893ccfSSadaf Ebrahimi    if (local_disables.handle_wrapping) {
886*b7893ccfSSadaf Ebrahimi        wrap_handles = false;
887*b7893ccfSSadaf Ebrahimi    }
888*b7893ccfSSadaf Ebrahimi
889*b7893ccfSSadaf Ebrahimi    // Init dispatch array and call registration functions
890*b7893ccfSSadaf Ebrahimi    for (auto intercept : local_object_dispatch) {
891*b7893ccfSSadaf Ebrahimi        intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
892*b7893ccfSSadaf Ebrahimi    }
893*b7893ccfSSadaf Ebrahimi    for (auto intercept : local_object_dispatch) {
894*b7893ccfSSadaf Ebrahimi        intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
895*b7893ccfSSadaf Ebrahimi    }
896*b7893ccfSSadaf Ebrahimi
897*b7893ccfSSadaf Ebrahimi    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
898*b7893ccfSSadaf Ebrahimi    if (result != VK_SUCCESS) return result;
899*b7893ccfSSadaf Ebrahimi
900*b7893ccfSSadaf Ebrahimi    auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
901*b7893ccfSSadaf Ebrahimi
902*b7893ccfSSadaf Ebrahimi    framework->object_dispatch = local_object_dispatch;
903*b7893ccfSSadaf Ebrahimi    framework->container_type = LayerObjectTypeInstance;
904*b7893ccfSSadaf Ebrahimi    framework->disabled = local_disables;
905*b7893ccfSSadaf Ebrahimi    framework->enabled = local_enables;
906*b7893ccfSSadaf Ebrahimi
907*b7893ccfSSadaf Ebrahimi    framework->instance = *pInstance;
908*b7893ccfSSadaf Ebrahimi    layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
909*b7893ccfSSadaf Ebrahimi    framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
910*b7893ccfSSadaf Ebrahimi                                                         pCreateInfo->ppEnabledExtensionNames);
911*b7893ccfSSadaf Ebrahimi    framework->api_version = api_version;
912*b7893ccfSSadaf Ebrahimi    framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
913*b7893ccfSSadaf Ebrahimi
914*b7893ccfSSadaf Ebrahimi    layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, OBJECT_LAYER_DESCRIPTION);
915*b7893ccfSSadaf Ebrahimi
916*b7893ccfSSadaf Ebrahimi#if BUILD_OBJECT_TRACKER
917*b7893ccfSSadaf Ebrahimi    object_tracker->report_data = framework->report_data;
918*b7893ccfSSadaf Ebrahimi    object_tracker->instance_dispatch_table = framework->instance_dispatch_table;
919*b7893ccfSSadaf Ebrahimi    object_tracker->enabled = framework->enabled;
920*b7893ccfSSadaf Ebrahimi    object_tracker->disabled = framework->disabled;
921*b7893ccfSSadaf Ebrahimi#endif
922*b7893ccfSSadaf Ebrahimi#if BUILD_THREAD_SAFETY
923*b7893ccfSSadaf Ebrahimi    thread_checker->report_data = framework->report_data;
924*b7893ccfSSadaf Ebrahimi    thread_checker->instance_dispatch_table = framework->instance_dispatch_table;
925*b7893ccfSSadaf Ebrahimi    thread_checker->enabled = framework->enabled;
926*b7893ccfSSadaf Ebrahimi    thread_checker->disabled = framework->disabled;
927*b7893ccfSSadaf Ebrahimi#endif
928*b7893ccfSSadaf Ebrahimi#if BUILD_PARAMETER_VALIDATION
929*b7893ccfSSadaf Ebrahimi    parameter_validation->report_data = framework->report_data;
930*b7893ccfSSadaf Ebrahimi    parameter_validation->instance_dispatch_table = framework->instance_dispatch_table;
931*b7893ccfSSadaf Ebrahimi    parameter_validation->enabled = framework->enabled;
932*b7893ccfSSadaf Ebrahimi    parameter_validation->disabled = framework->disabled;
933*b7893ccfSSadaf Ebrahimi#endif
934*b7893ccfSSadaf Ebrahimi#if BUILD_CORE_VALIDATION
935*b7893ccfSSadaf Ebrahimi    core_checks->report_data = framework->report_data;
936*b7893ccfSSadaf Ebrahimi    core_checks->instance_dispatch_table = framework->instance_dispatch_table;
937*b7893ccfSSadaf Ebrahimi    core_checks->instance = *pInstance;
938*b7893ccfSSadaf Ebrahimi    core_checks->enabled = framework->enabled;
939*b7893ccfSSadaf Ebrahimi    core_checks->disabled = framework->disabled;
940*b7893ccfSSadaf Ebrahimi    core_checks->instance_state = core_checks;
941*b7893ccfSSadaf Ebrahimi#endif
942*b7893ccfSSadaf Ebrahimi#if BUILD_BEST_PRACTICES
943*b7893ccfSSadaf Ebrahimi    best_practices->report_data = framework->report_data;
944*b7893ccfSSadaf Ebrahimi    best_practices->instance_dispatch_table = framework->instance_dispatch_table;
945*b7893ccfSSadaf Ebrahimi    best_practices->enabled = framework->enabled;
946*b7893ccfSSadaf Ebrahimi    best_practices->disabled = framework->disabled;
947*b7893ccfSSadaf Ebrahimi#endif
948*b7893ccfSSadaf Ebrahimi
949*b7893ccfSSadaf Ebrahimi    for (auto intercept : framework->object_dispatch) {
950*b7893ccfSSadaf Ebrahimi        intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
951*b7893ccfSSadaf Ebrahimi    }
952*b7893ccfSSadaf Ebrahimi
953*b7893ccfSSadaf Ebrahimi    InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
954*b7893ccfSSadaf Ebrahimi
955*b7893ccfSSadaf Ebrahimi    return result;
956*b7893ccfSSadaf Ebrahimi}
957*b7893ccfSSadaf Ebrahimi
958*b7893ccfSSadaf EbrahimiVKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
959*b7893ccfSSadaf Ebrahimi    dispatch_key key = get_dispatch_key(instance);
960*b7893ccfSSadaf Ebrahimi    auto layer_data = GetLayerDataPtr(key, layer_data_map);
961*b7893ccfSSadaf Ebrahimi    """ + precallvalidate_loop + """
962*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
963*b7893ccfSSadaf Ebrahimi        intercept->PreCallValidateDestroyInstance(instance, pAllocator);
964*b7893ccfSSadaf Ebrahimi    }
965*b7893ccfSSadaf Ebrahimi    """ + precallrecord_loop + """
966*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
967*b7893ccfSSadaf Ebrahimi        intercept->PreCallRecordDestroyInstance(instance, pAllocator);
968*b7893ccfSSadaf Ebrahimi    }
969*b7893ccfSSadaf Ebrahimi
970*b7893ccfSSadaf Ebrahimi    layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
971*b7893ccfSSadaf Ebrahimi
972*b7893ccfSSadaf Ebrahimi    """ + postcallrecord_loop + """
973*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
974*b7893ccfSSadaf Ebrahimi        intercept->PostCallRecordDestroyInstance(instance, pAllocator);
975*b7893ccfSSadaf Ebrahimi    }
976*b7893ccfSSadaf Ebrahimi    // Clean up logging callback, if any
977*b7893ccfSSadaf Ebrahimi    while (layer_data->logging_messenger.size() > 0) {
978*b7893ccfSSadaf Ebrahimi        VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
979*b7893ccfSSadaf Ebrahimi        layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
980*b7893ccfSSadaf Ebrahimi        layer_data->logging_messenger.pop_back();
981*b7893ccfSSadaf Ebrahimi    }
982*b7893ccfSSadaf Ebrahimi    while (layer_data->logging_callback.size() > 0) {
983*b7893ccfSSadaf Ebrahimi        VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
984*b7893ccfSSadaf Ebrahimi        layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
985*b7893ccfSSadaf Ebrahimi        layer_data->logging_callback.pop_back();
986*b7893ccfSSadaf Ebrahimi    }
987*b7893ccfSSadaf Ebrahimi
988*b7893ccfSSadaf Ebrahimi    layer_debug_utils_destroy_instance(layer_data->report_data);
989*b7893ccfSSadaf Ebrahimi
990*b7893ccfSSadaf Ebrahimi    for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
991*b7893ccfSSadaf Ebrahimi        delete *item;
992*b7893ccfSSadaf Ebrahimi    }
993*b7893ccfSSadaf Ebrahimi    FreeLayerDataPtr(key, layer_data_map);
994*b7893ccfSSadaf Ebrahimi}
995*b7893ccfSSadaf Ebrahimi
996*b7893ccfSSadaf EbrahimiVKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
997*b7893ccfSSadaf Ebrahimi                                            const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
998*b7893ccfSSadaf Ebrahimi    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
999*b7893ccfSSadaf Ebrahimi
1000*b7893ccfSSadaf Ebrahimi    auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
1001*b7893ccfSSadaf Ebrahimi
1002*b7893ccfSSadaf Ebrahimi    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
1003*b7893ccfSSadaf Ebrahimi    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
1004*b7893ccfSSadaf Ebrahimi    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
1005*b7893ccfSSadaf Ebrahimi    if (fpCreateDevice == NULL) {
1006*b7893ccfSSadaf Ebrahimi        return VK_ERROR_INITIALIZATION_FAILED;
1007*b7893ccfSSadaf Ebrahimi    }
1008*b7893ccfSSadaf Ebrahimi    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
1009*b7893ccfSSadaf Ebrahimi
1010*b7893ccfSSadaf Ebrahimi    // Get physical device limits for device
1011*b7893ccfSSadaf Ebrahimi    VkPhysicalDeviceProperties device_properties = {};
1012*b7893ccfSSadaf Ebrahimi    instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
1013*b7893ccfSSadaf Ebrahimi
1014*b7893ccfSSadaf Ebrahimi    // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
1015*b7893ccfSSadaf Ebrahimi    uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
1016*b7893ccfSSadaf Ebrahimi
1017*b7893ccfSSadaf Ebrahimi    DeviceExtensions device_extensions = {};
1018*b7893ccfSSadaf Ebrahimi    device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
1019*b7893ccfSSadaf Ebrahimi    for (auto item : instance_interceptor->object_dispatch) {
1020*b7893ccfSSadaf Ebrahimi        item->device_extensions = device_extensions;
1021*b7893ccfSSadaf Ebrahimi    }
1022*b7893ccfSSadaf Ebrahimi
1023*b7893ccfSSadaf Ebrahimi    safe_VkDeviceCreateInfo modified_create_info(pCreateInfo);
1024*b7893ccfSSadaf Ebrahimi
1025*b7893ccfSSadaf Ebrahimi    bool skip = false;
1026*b7893ccfSSadaf Ebrahimi    for (auto intercept : instance_interceptor->object_dispatch) {
1027*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1028*b7893ccfSSadaf Ebrahimi        skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
1029*b7893ccfSSadaf Ebrahimi        if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1030*b7893ccfSSadaf Ebrahimi    }
1031*b7893ccfSSadaf Ebrahimi    for (auto intercept : instance_interceptor->object_dispatch) {
1032*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1033*b7893ccfSSadaf Ebrahimi        intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, &modified_create_info);
1034*b7893ccfSSadaf Ebrahimi    }
1035*b7893ccfSSadaf Ebrahimi
1036*b7893ccfSSadaf Ebrahimi    VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(&modified_create_info), pAllocator, pDevice);
1037*b7893ccfSSadaf Ebrahimi    if (result != VK_SUCCESS) {
1038*b7893ccfSSadaf Ebrahimi        return result;
1039*b7893ccfSSadaf Ebrahimi    }
1040*b7893ccfSSadaf Ebrahimi
1041*b7893ccfSSadaf Ebrahimi    auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
1042*b7893ccfSSadaf Ebrahimi    device_interceptor->container_type = LayerObjectTypeDevice;
1043*b7893ccfSSadaf Ebrahimi
1044*b7893ccfSSadaf Ebrahimi    // Save local info in device object
1045*b7893ccfSSadaf Ebrahimi    device_interceptor->phys_dev_properties.properties = device_properties;
1046*b7893ccfSSadaf Ebrahimi    device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
1047*b7893ccfSSadaf Ebrahimi        &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
1048*b7893ccfSSadaf Ebrahimi    device_interceptor->device_extensions = device_extensions;
1049*b7893ccfSSadaf Ebrahimi
1050*b7893ccfSSadaf Ebrahimi    layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
1051*b7893ccfSSadaf Ebrahimi
1052*b7893ccfSSadaf Ebrahimi    device_interceptor->device = *pDevice;
1053*b7893ccfSSadaf Ebrahimi    device_interceptor->physical_device = gpu;
1054*b7893ccfSSadaf Ebrahimi    device_interceptor->instance = instance_interceptor->instance;
1055*b7893ccfSSadaf Ebrahimi    device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
1056*b7893ccfSSadaf Ebrahimi
1057*b7893ccfSSadaf Ebrahimi    // Note that this defines the order in which the layer validation objects are called
1058*b7893ccfSSadaf Ebrahimi#if BUILD_THREAD_SAFETY
1059*b7893ccfSSadaf Ebrahimi    auto thread_safety = new ThreadSafety;
1060*b7893ccfSSadaf Ebrahimi    thread_safety->container_type = LayerObjectTypeThreading;
1061*b7893ccfSSadaf Ebrahimi    if (!instance_interceptor->disabled.thread_safety) {
1062*b7893ccfSSadaf Ebrahimi        device_interceptor->object_dispatch.emplace_back(thread_safety);
1063*b7893ccfSSadaf Ebrahimi    }
1064*b7893ccfSSadaf Ebrahimi#endif
1065*b7893ccfSSadaf Ebrahimi#if BUILD_PARAMETER_VALIDATION
1066*b7893ccfSSadaf Ebrahimi    auto stateless_validation = new StatelessValidation;
1067*b7893ccfSSadaf Ebrahimi    stateless_validation->container_type = LayerObjectTypeParameterValidation;
1068*b7893ccfSSadaf Ebrahimi    if (!instance_interceptor->disabled.stateless_checks) {
1069*b7893ccfSSadaf Ebrahimi        device_interceptor->object_dispatch.emplace_back(stateless_validation);
1070*b7893ccfSSadaf Ebrahimi    }
1071*b7893ccfSSadaf Ebrahimi#endif
1072*b7893ccfSSadaf Ebrahimi#if BUILD_OBJECT_TRACKER
1073*b7893ccfSSadaf Ebrahimi    auto object_tracker = new ObjectLifetimes;
1074*b7893ccfSSadaf Ebrahimi    object_tracker->container_type = LayerObjectTypeObjectTracker;
1075*b7893ccfSSadaf Ebrahimi    if (!instance_interceptor->disabled.object_tracking) {
1076*b7893ccfSSadaf Ebrahimi        device_interceptor->object_dispatch.emplace_back(object_tracker);
1077*b7893ccfSSadaf Ebrahimi    }
1078*b7893ccfSSadaf Ebrahimi#endif
1079*b7893ccfSSadaf Ebrahimi#if BUILD_CORE_VALIDATION
1080*b7893ccfSSadaf Ebrahimi    auto core_checks = new CoreChecks;
1081*b7893ccfSSadaf Ebrahimi    core_checks->container_type = LayerObjectTypeCoreValidation;
1082*b7893ccfSSadaf Ebrahimi    core_checks->instance_state = reinterpret_cast<CoreChecks *>(
1083*b7893ccfSSadaf Ebrahimi        core_checks->GetValidationObject(instance_interceptor->object_dispatch, LayerObjectTypeCoreValidation));
1084*b7893ccfSSadaf Ebrahimi    if (!instance_interceptor->disabled.core_checks) {
1085*b7893ccfSSadaf Ebrahimi        device_interceptor->object_dispatch.emplace_back(core_checks);
1086*b7893ccfSSadaf Ebrahimi    }
1087*b7893ccfSSadaf Ebrahimi#endif
1088*b7893ccfSSadaf Ebrahimi#if BUILD_BEST_PRACTICES
1089*b7893ccfSSadaf Ebrahimi    auto best_practices = new BestPractices;
1090*b7893ccfSSadaf Ebrahimi    best_practices->container_type = LayerObjectTypeBestPractices;
1091*b7893ccfSSadaf Ebrahimi    if (instance_interceptor->enabled.best_practices) {
1092*b7893ccfSSadaf Ebrahimi        device_interceptor->object_dispatch.emplace_back(best_practices);
1093*b7893ccfSSadaf Ebrahimi    }
1094*b7893ccfSSadaf Ebrahimi#endif
1095*b7893ccfSSadaf Ebrahimi
1096*b7893ccfSSadaf Ebrahimi    // Set per-intercept common data items
1097*b7893ccfSSadaf Ebrahimi    for (auto dev_intercept : device_interceptor->object_dispatch) {
1098*b7893ccfSSadaf Ebrahimi        dev_intercept->device = *pDevice;
1099*b7893ccfSSadaf Ebrahimi        dev_intercept->physical_device = gpu;
1100*b7893ccfSSadaf Ebrahimi        dev_intercept->instance = instance_interceptor->instance;
1101*b7893ccfSSadaf Ebrahimi        dev_intercept->report_data = device_interceptor->report_data;
1102*b7893ccfSSadaf Ebrahimi        dev_intercept->device_dispatch_table = device_interceptor->device_dispatch_table;
1103*b7893ccfSSadaf Ebrahimi        dev_intercept->api_version = device_interceptor->api_version;
1104*b7893ccfSSadaf Ebrahimi        dev_intercept->disabled = instance_interceptor->disabled;
1105*b7893ccfSSadaf Ebrahimi        dev_intercept->enabled = instance_interceptor->enabled;
1106*b7893ccfSSadaf Ebrahimi        dev_intercept->instance_dispatch_table = instance_interceptor->instance_dispatch_table;
1107*b7893ccfSSadaf Ebrahimi        dev_intercept->instance_extensions = instance_interceptor->instance_extensions;
1108*b7893ccfSSadaf Ebrahimi        dev_intercept->device_extensions = device_interceptor->device_extensions;
1109*b7893ccfSSadaf Ebrahimi    }
1110*b7893ccfSSadaf Ebrahimi
1111*b7893ccfSSadaf Ebrahimi    for (auto intercept : instance_interceptor->object_dispatch) {
1112*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1113*b7893ccfSSadaf Ebrahimi        intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
1114*b7893ccfSSadaf Ebrahimi    }
1115*b7893ccfSSadaf Ebrahimi
1116*b7893ccfSSadaf Ebrahimi    DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
1117*b7893ccfSSadaf Ebrahimi
1118*b7893ccfSSadaf Ebrahimi    return result;
1119*b7893ccfSSadaf Ebrahimi}
1120*b7893ccfSSadaf Ebrahimi
1121*b7893ccfSSadaf EbrahimiVKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
1122*b7893ccfSSadaf Ebrahimi    dispatch_key key = get_dispatch_key(device);
1123*b7893ccfSSadaf Ebrahimi    auto layer_data = GetLayerDataPtr(key, layer_data_map);
1124*b7893ccfSSadaf Ebrahimi    """ + precallvalidate_loop + """
1125*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1126*b7893ccfSSadaf Ebrahimi        intercept->PreCallValidateDestroyDevice(device, pAllocator);
1127*b7893ccfSSadaf Ebrahimi    }
1128*b7893ccfSSadaf Ebrahimi    """ + precallrecord_loop + """
1129*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1130*b7893ccfSSadaf Ebrahimi        intercept->PreCallRecordDestroyDevice(device, pAllocator);
1131*b7893ccfSSadaf Ebrahimi    }
1132*b7893ccfSSadaf Ebrahimi    layer_debug_utils_destroy_device(device);
1133*b7893ccfSSadaf Ebrahimi
1134*b7893ccfSSadaf Ebrahimi    layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
1135*b7893ccfSSadaf Ebrahimi
1136*b7893ccfSSadaf Ebrahimi    """ + postcallrecord_loop + """
1137*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1138*b7893ccfSSadaf Ebrahimi        intercept->PostCallRecordDestroyDevice(device, pAllocator);
1139*b7893ccfSSadaf Ebrahimi    }
1140*b7893ccfSSadaf Ebrahimi
1141*b7893ccfSSadaf Ebrahimi    for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
1142*b7893ccfSSadaf Ebrahimi        delete *item;
1143*b7893ccfSSadaf Ebrahimi    }
1144*b7893ccfSSadaf Ebrahimi    FreeLayerDataPtr(key, layer_data_map);
1145*b7893ccfSSadaf Ebrahimi}
1146*b7893ccfSSadaf Ebrahimi
1147*b7893ccfSSadaf Ebrahimi
1148*b7893ccfSSadaf Ebrahimi// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
1149*b7893ccfSSadaf Ebrahimi
1150*b7893ccfSSadaf EbrahimiVKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
1151*b7893ccfSSadaf Ebrahimi    VkDevice                                    device,
1152*b7893ccfSSadaf Ebrahimi    VkPipelineCache                             pipelineCache,
1153*b7893ccfSSadaf Ebrahimi    uint32_t                                    createInfoCount,
1154*b7893ccfSSadaf Ebrahimi    const VkGraphicsPipelineCreateInfo*         pCreateInfos,
1155*b7893ccfSSadaf Ebrahimi    const VkAllocationCallbacks*                pAllocator,
1156*b7893ccfSSadaf Ebrahimi    VkPipeline*                                 pPipelines) {
1157*b7893ccfSSadaf Ebrahimi    auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1158*b7893ccfSSadaf Ebrahimi    bool skip = false;
1159*b7893ccfSSadaf Ebrahimi
1160*b7893ccfSSadaf Ebrahimi#ifdef BUILD_CORE_VALIDATION
1161*b7893ccfSSadaf Ebrahimi        create_graphics_pipeline_api_state cgpl_state{};
1162*b7893ccfSSadaf Ebrahimi#else
1163*b7893ccfSSadaf Ebrahimi        struct create_graphics_pipeline_api_state {
1164*b7893ccfSSadaf Ebrahimi            const VkGraphicsPipelineCreateInfo* pCreateInfos;
1165*b7893ccfSSadaf Ebrahimi        } cgpl_state;
1166*b7893ccfSSadaf Ebrahimi#endif
1167*b7893ccfSSadaf Ebrahimi    cgpl_state.pCreateInfos = pCreateInfos;
1168*b7893ccfSSadaf Ebrahimi
1169*b7893ccfSSadaf Ebrahimi    for (auto intercept : layer_data->object_dispatch) {
1170*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1171*b7893ccfSSadaf Ebrahimi        skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1172*b7893ccfSSadaf Ebrahimi        if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1173*b7893ccfSSadaf Ebrahimi    }
1174*b7893ccfSSadaf Ebrahimi    for (auto intercept : layer_data->object_dispatch) {
1175*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1176*b7893ccfSSadaf Ebrahimi        intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1177*b7893ccfSSadaf Ebrahimi    }
1178*b7893ccfSSadaf Ebrahimi
1179*b7893ccfSSadaf Ebrahimi    VkResult result = DispatchCreateGraphicsPipelines(device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
1180*b7893ccfSSadaf Ebrahimi
1181*b7893ccfSSadaf Ebrahimi    for (auto intercept : layer_data->object_dispatch) {
1182*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1183*b7893ccfSSadaf Ebrahimi        intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
1184*b7893ccfSSadaf Ebrahimi    }
1185*b7893ccfSSadaf Ebrahimi    return result;
1186*b7893ccfSSadaf Ebrahimi}
1187*b7893ccfSSadaf Ebrahimi
1188*b7893ccfSSadaf Ebrahimi// This API saves some core_validation pipeline state state on the stack for performance purposes
1189*b7893ccfSSadaf EbrahimiVKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
1190*b7893ccfSSadaf Ebrahimi    VkDevice                                    device,
1191*b7893ccfSSadaf Ebrahimi    VkPipelineCache                             pipelineCache,
1192*b7893ccfSSadaf Ebrahimi    uint32_t                                    createInfoCount,
1193*b7893ccfSSadaf Ebrahimi    const VkComputePipelineCreateInfo*          pCreateInfos,
1194*b7893ccfSSadaf Ebrahimi    const VkAllocationCallbacks*                pAllocator,
1195*b7893ccfSSadaf Ebrahimi    VkPipeline*                                 pPipelines) {
1196*b7893ccfSSadaf Ebrahimi    auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1197*b7893ccfSSadaf Ebrahimi    bool skip = false;
1198*b7893ccfSSadaf Ebrahimi
1199*b7893ccfSSadaf Ebrahimi#ifdef BUILD_CORE_VALIDATION
1200*b7893ccfSSadaf Ebrahimi    create_compute_pipeline_api_state ccpl_state{};
1201*b7893ccfSSadaf Ebrahimi#else
1202*b7893ccfSSadaf Ebrahimi    struct create_compute_pipeline_api_state {
1203*b7893ccfSSadaf Ebrahimi        const VkComputePipelineCreateInfo* pCreateInfos;
1204*b7893ccfSSadaf Ebrahimi    } ccpl_state;
1205*b7893ccfSSadaf Ebrahimi#endif
1206*b7893ccfSSadaf Ebrahimi    ccpl_state.pCreateInfos = pCreateInfos;
1207*b7893ccfSSadaf Ebrahimi
1208*b7893ccfSSadaf Ebrahimi    for (auto intercept : layer_data->object_dispatch) {
1209*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1210*b7893ccfSSadaf Ebrahimi        skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &ccpl_state);
1211*b7893ccfSSadaf Ebrahimi        if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1212*b7893ccfSSadaf Ebrahimi    }
1213*b7893ccfSSadaf Ebrahimi    for (auto intercept : layer_data->object_dispatch) {
1214*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1215*b7893ccfSSadaf Ebrahimi        intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &ccpl_state);
1216*b7893ccfSSadaf Ebrahimi    }
1217*b7893ccfSSadaf Ebrahimi    VkResult result = DispatchCreateComputePipelines(device, pipelineCache, createInfoCount, ccpl_state.pCreateInfos, pAllocator, pPipelines);
1218*b7893ccfSSadaf Ebrahimi    for (auto intercept : layer_data->object_dispatch) {
1219*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1220*b7893ccfSSadaf Ebrahimi        intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &ccpl_state);
1221*b7893ccfSSadaf Ebrahimi    }
1222*b7893ccfSSadaf Ebrahimi    return result;
1223*b7893ccfSSadaf Ebrahimi}
1224*b7893ccfSSadaf Ebrahimi
1225*b7893ccfSSadaf EbrahimiVKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
1226*b7893ccfSSadaf Ebrahimi    VkDevice                                    device,
1227*b7893ccfSSadaf Ebrahimi    VkPipelineCache                             pipelineCache,
1228*b7893ccfSSadaf Ebrahimi    uint32_t                                    createInfoCount,
1229*b7893ccfSSadaf Ebrahimi    const VkRayTracingPipelineCreateInfoNV*     pCreateInfos,
1230*b7893ccfSSadaf Ebrahimi    const VkAllocationCallbacks*                pAllocator,
1231*b7893ccfSSadaf Ebrahimi    VkPipeline*                                 pPipelines) {
1232*b7893ccfSSadaf Ebrahimi    auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1233*b7893ccfSSadaf Ebrahimi    bool skip = false;
1234*b7893ccfSSadaf Ebrahimi
1235*b7893ccfSSadaf Ebrahimi#ifdef BUILD_CORE_VALIDATION
1236*b7893ccfSSadaf Ebrahimi    create_ray_tracing_pipeline_api_state crtpl_state{};
1237*b7893ccfSSadaf Ebrahimi#else
1238*b7893ccfSSadaf Ebrahimi    struct create_ray_tracing_pipeline_api_state {
1239*b7893ccfSSadaf Ebrahimi        const VkRayTracingPipelineCreateInfoNV* pCreateInfos;
1240*b7893ccfSSadaf Ebrahimi    } crtpl_state;
1241*b7893ccfSSadaf Ebrahimi#endif
1242*b7893ccfSSadaf Ebrahimi    crtpl_state.pCreateInfos = pCreateInfos;
1243*b7893ccfSSadaf Ebrahimi
1244*b7893ccfSSadaf Ebrahimi    for (auto intercept : layer_data->object_dispatch) {
1245*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1246*b7893ccfSSadaf Ebrahimi        skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos,
1247*b7893ccfSSadaf Ebrahimi                                                                      pAllocator, pPipelines, &crtpl_state);
1248*b7893ccfSSadaf Ebrahimi        if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1249*b7893ccfSSadaf Ebrahimi    }
1250*b7893ccfSSadaf Ebrahimi    for (auto intercept : layer_data->object_dispatch) {
1251*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1252*b7893ccfSSadaf Ebrahimi        intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator,
1253*b7893ccfSSadaf Ebrahimi                                                            pPipelines, &crtpl_state);
1254*b7893ccfSSadaf Ebrahimi    }
1255*b7893ccfSSadaf Ebrahimi    VkResult result = DispatchCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1256*b7893ccfSSadaf Ebrahimi    for (auto intercept : layer_data->object_dispatch) {
1257*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1258*b7893ccfSSadaf Ebrahimi        intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator,
1259*b7893ccfSSadaf Ebrahimi                                                             pPipelines, result, &crtpl_state);
1260*b7893ccfSSadaf Ebrahimi    }
1261*b7893ccfSSadaf Ebrahimi    return result;
1262*b7893ccfSSadaf Ebrahimi}
1263*b7893ccfSSadaf Ebrahimi
1264*b7893ccfSSadaf Ebrahimi// This API needs the ability to modify a down-chain parameter
1265*b7893ccfSSadaf EbrahimiVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
1266*b7893ccfSSadaf Ebrahimi    VkDevice                                    device,
1267*b7893ccfSSadaf Ebrahimi    const VkPipelineLayoutCreateInfo*           pCreateInfo,
1268*b7893ccfSSadaf Ebrahimi    const VkAllocationCallbacks*                pAllocator,
1269*b7893ccfSSadaf Ebrahimi    VkPipelineLayout*                           pPipelineLayout) {
1270*b7893ccfSSadaf Ebrahimi    auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1271*b7893ccfSSadaf Ebrahimi    bool skip = false;
1272*b7893ccfSSadaf Ebrahimi
1273*b7893ccfSSadaf Ebrahimi#ifndef BUILD_CORE_VALIDATION
1274*b7893ccfSSadaf Ebrahimi    struct create_pipeline_layout_api_state {
1275*b7893ccfSSadaf Ebrahimi        VkPipelineLayoutCreateInfo modified_create_info;
1276*b7893ccfSSadaf Ebrahimi    };
1277*b7893ccfSSadaf Ebrahimi#endif
1278*b7893ccfSSadaf Ebrahimi    create_pipeline_layout_api_state cpl_state{};
1279*b7893ccfSSadaf Ebrahimi    cpl_state.modified_create_info = *pCreateInfo;
1280*b7893ccfSSadaf Ebrahimi
1281*b7893ccfSSadaf Ebrahimi    for (auto intercept : layer_data->object_dispatch) {
1282*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1283*b7893ccfSSadaf Ebrahimi        skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1284*b7893ccfSSadaf Ebrahimi        if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1285*b7893ccfSSadaf Ebrahimi    }
1286*b7893ccfSSadaf Ebrahimi    for (auto intercept : layer_data->object_dispatch) {
1287*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1288*b7893ccfSSadaf Ebrahimi        intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1289*b7893ccfSSadaf Ebrahimi    }
1290*b7893ccfSSadaf Ebrahimi    VkResult result = DispatchCreatePipelineLayout(device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
1291*b7893ccfSSadaf Ebrahimi    for (auto intercept : layer_data->object_dispatch) {
1292*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1293*b7893ccfSSadaf Ebrahimi        intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1294*b7893ccfSSadaf Ebrahimi    }
1295*b7893ccfSSadaf Ebrahimi    return result;
1296*b7893ccfSSadaf Ebrahimi}
1297*b7893ccfSSadaf Ebrahimi
1298*b7893ccfSSadaf Ebrahimi// This API needs some local stack data for performance reasons and also may modify a parameter
1299*b7893ccfSSadaf EbrahimiVKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1300*b7893ccfSSadaf Ebrahimi    VkDevice                                    device,
1301*b7893ccfSSadaf Ebrahimi    const VkShaderModuleCreateInfo*             pCreateInfo,
1302*b7893ccfSSadaf Ebrahimi    const VkAllocationCallbacks*                pAllocator,
1303*b7893ccfSSadaf Ebrahimi    VkShaderModule*                             pShaderModule) {
1304*b7893ccfSSadaf Ebrahimi    auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1305*b7893ccfSSadaf Ebrahimi    bool skip = false;
1306*b7893ccfSSadaf Ebrahimi
1307*b7893ccfSSadaf Ebrahimi#ifndef BUILD_CORE_VALIDATION
1308*b7893ccfSSadaf Ebrahimi    struct create_shader_module_api_state {
1309*b7893ccfSSadaf Ebrahimi        VkShaderModuleCreateInfo instrumented_create_info;
1310*b7893ccfSSadaf Ebrahimi    };
1311*b7893ccfSSadaf Ebrahimi#endif
1312*b7893ccfSSadaf Ebrahimi    create_shader_module_api_state csm_state{};
1313*b7893ccfSSadaf Ebrahimi    csm_state.instrumented_create_info = *pCreateInfo;
1314*b7893ccfSSadaf Ebrahimi
1315*b7893ccfSSadaf Ebrahimi    for (auto intercept : layer_data->object_dispatch) {
1316*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1317*b7893ccfSSadaf Ebrahimi        skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1318*b7893ccfSSadaf Ebrahimi        if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1319*b7893ccfSSadaf Ebrahimi    }
1320*b7893ccfSSadaf Ebrahimi    for (auto intercept : layer_data->object_dispatch) {
1321*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1322*b7893ccfSSadaf Ebrahimi        intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1323*b7893ccfSSadaf Ebrahimi    }
1324*b7893ccfSSadaf Ebrahimi    VkResult result = DispatchCreateShaderModule(device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
1325*b7893ccfSSadaf Ebrahimi    for (auto intercept : layer_data->object_dispatch) {
1326*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1327*b7893ccfSSadaf Ebrahimi        intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1328*b7893ccfSSadaf Ebrahimi    }
1329*b7893ccfSSadaf Ebrahimi    return result;
1330*b7893ccfSSadaf Ebrahimi}
1331*b7893ccfSSadaf Ebrahimi
1332*b7893ccfSSadaf EbrahimiVKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1333*b7893ccfSSadaf Ebrahimi    VkDevice                                    device,
1334*b7893ccfSSadaf Ebrahimi    const VkDescriptorSetAllocateInfo*          pAllocateInfo,
1335*b7893ccfSSadaf Ebrahimi    VkDescriptorSet*                            pDescriptorSets) {
1336*b7893ccfSSadaf Ebrahimi    auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1337*b7893ccfSSadaf Ebrahimi    bool skip = false;
1338*b7893ccfSSadaf Ebrahimi
1339*b7893ccfSSadaf Ebrahimi#ifdef BUILD_CORE_VALIDATION
1340*b7893ccfSSadaf Ebrahimi    cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1341*b7893ccfSSadaf Ebrahimi#else
1342*b7893ccfSSadaf Ebrahimi    struct ads_state {} ads_state;
1343*b7893ccfSSadaf Ebrahimi#endif
1344*b7893ccfSSadaf Ebrahimi
1345*b7893ccfSSadaf Ebrahimi    for (auto intercept : layer_data->object_dispatch) {
1346*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1347*b7893ccfSSadaf Ebrahimi        skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1348*b7893ccfSSadaf Ebrahimi        if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1349*b7893ccfSSadaf Ebrahimi    }
1350*b7893ccfSSadaf Ebrahimi    for (auto intercept : layer_data->object_dispatch) {
1351*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1352*b7893ccfSSadaf Ebrahimi        intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1353*b7893ccfSSadaf Ebrahimi    }
1354*b7893ccfSSadaf Ebrahimi    VkResult result = DispatchAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1355*b7893ccfSSadaf Ebrahimi    for (auto intercept : layer_data->object_dispatch) {
1356*b7893ccfSSadaf Ebrahimi        auto lock = intercept->write_lock();
1357*b7893ccfSSadaf Ebrahimi        intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1358*b7893ccfSSadaf Ebrahimi    }
1359*b7893ccfSSadaf Ebrahimi    return result;
1360*b7893ccfSSadaf Ebrahimi}
1361*b7893ccfSSadaf Ebrahimi
1362*b7893ccfSSadaf Ebrahimi
1363*b7893ccfSSadaf Ebrahimi
1364*b7893ccfSSadaf Ebrahimi
1365*b7893ccfSSadaf Ebrahimi
1366*b7893ccfSSadaf Ebrahimi// ValidationCache APIs do not dispatch
1367*b7893ccfSSadaf Ebrahimi
1368*b7893ccfSSadaf EbrahimiVKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1369*b7893ccfSSadaf Ebrahimi    VkDevice                                    device,
1370*b7893ccfSSadaf Ebrahimi    const VkValidationCacheCreateInfoEXT*       pCreateInfo,
1371*b7893ccfSSadaf Ebrahimi    const VkAllocationCallbacks*                pAllocator,
1372*b7893ccfSSadaf Ebrahimi    VkValidationCacheEXT*                       pValidationCache) {
1373*b7893ccfSSadaf Ebrahimi    auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1374*b7893ccfSSadaf Ebrahimi    VkResult result = VK_SUCCESS;
1375*b7893ccfSSadaf Ebrahimi
1376*b7893ccfSSadaf Ebrahimi    ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1377*b7893ccfSSadaf Ebrahimi    if (validation_data) {
1378*b7893ccfSSadaf Ebrahimi        auto lock = validation_data->write_lock();
1379*b7893ccfSSadaf Ebrahimi        result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1380*b7893ccfSSadaf Ebrahimi    }
1381*b7893ccfSSadaf Ebrahimi    return result;
1382*b7893ccfSSadaf Ebrahimi}
1383*b7893ccfSSadaf Ebrahimi
1384*b7893ccfSSadaf EbrahimiVKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1385*b7893ccfSSadaf Ebrahimi    VkDevice                                    device,
1386*b7893ccfSSadaf Ebrahimi    VkValidationCacheEXT                        validationCache,
1387*b7893ccfSSadaf Ebrahimi    const VkAllocationCallbacks*                pAllocator) {
1388*b7893ccfSSadaf Ebrahimi    auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1389*b7893ccfSSadaf Ebrahimi
1390*b7893ccfSSadaf Ebrahimi    ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1391*b7893ccfSSadaf Ebrahimi    if (validation_data) {
1392*b7893ccfSSadaf Ebrahimi        auto lock = validation_data->write_lock();
1393*b7893ccfSSadaf Ebrahimi        validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1394*b7893ccfSSadaf Ebrahimi    }
1395*b7893ccfSSadaf Ebrahimi}
1396*b7893ccfSSadaf Ebrahimi
1397*b7893ccfSSadaf EbrahimiVKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1398*b7893ccfSSadaf Ebrahimi    VkDevice                                    device,
1399*b7893ccfSSadaf Ebrahimi    VkValidationCacheEXT                        dstCache,
1400*b7893ccfSSadaf Ebrahimi    uint32_t                                    srcCacheCount,
1401*b7893ccfSSadaf Ebrahimi    const VkValidationCacheEXT*                 pSrcCaches) {
1402*b7893ccfSSadaf Ebrahimi    auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1403*b7893ccfSSadaf Ebrahimi    VkResult result = VK_SUCCESS;
1404*b7893ccfSSadaf Ebrahimi
1405*b7893ccfSSadaf Ebrahimi    ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1406*b7893ccfSSadaf Ebrahimi    if (validation_data) {
1407*b7893ccfSSadaf Ebrahimi        auto lock = validation_data->write_lock();
1408*b7893ccfSSadaf Ebrahimi        result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1409*b7893ccfSSadaf Ebrahimi    }
1410*b7893ccfSSadaf Ebrahimi    return result;
1411*b7893ccfSSadaf Ebrahimi}
1412*b7893ccfSSadaf Ebrahimi
1413*b7893ccfSSadaf EbrahimiVKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1414*b7893ccfSSadaf Ebrahimi    VkDevice                                    device,
1415*b7893ccfSSadaf Ebrahimi    VkValidationCacheEXT                        validationCache,
1416*b7893ccfSSadaf Ebrahimi    size_t*                                     pDataSize,
1417*b7893ccfSSadaf Ebrahimi    void*                                       pData) {
1418*b7893ccfSSadaf Ebrahimi    auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1419*b7893ccfSSadaf Ebrahimi    VkResult result = VK_SUCCESS;
1420*b7893ccfSSadaf Ebrahimi
1421*b7893ccfSSadaf Ebrahimi    ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1422*b7893ccfSSadaf Ebrahimi    if (validation_data) {
1423*b7893ccfSSadaf Ebrahimi        auto lock = validation_data->write_lock();
1424*b7893ccfSSadaf Ebrahimi        result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1425*b7893ccfSSadaf Ebrahimi    }
1426*b7893ccfSSadaf Ebrahimi    return result;
1427*b7893ccfSSadaf Ebrahimi
1428*b7893ccfSSadaf Ebrahimi}"""
1429*b7893ccfSSadaf Ebrahimi
1430*b7893ccfSSadaf Ebrahimi    inline_custom_validation_class_definitions = """
1431*b7893ccfSSadaf Ebrahimi        virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1432*b7893ccfSSadaf Ebrahimi        virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1433*b7893ccfSSadaf Ebrahimi        virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches)  { return VK_SUCCESS; };
1434*b7893ccfSSadaf Ebrahimi        virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData)  { return VK_SUCCESS; };
1435*b7893ccfSSadaf Ebrahimi
1436*b7893ccfSSadaf Ebrahimi        // Allow additional state parameter for CreateGraphicsPipelines
1437*b7893ccfSSadaf Ebrahimi        virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1438*b7893ccfSSadaf Ebrahimi            return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1439*b7893ccfSSadaf Ebrahimi        };
1440*b7893ccfSSadaf Ebrahimi        virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1441*b7893ccfSSadaf Ebrahimi            PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1442*b7893ccfSSadaf Ebrahimi        };
1443*b7893ccfSSadaf Ebrahimi        virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1444*b7893ccfSSadaf Ebrahimi            PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1445*b7893ccfSSadaf Ebrahimi        };
1446*b7893ccfSSadaf Ebrahimi
1447*b7893ccfSSadaf Ebrahimi        // Allow additional state parameter for CreateComputePipelines
1448*b7893ccfSSadaf Ebrahimi        virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state)  {
1449*b7893ccfSSadaf Ebrahimi            return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1450*b7893ccfSSadaf Ebrahimi        };
1451*b7893ccfSSadaf Ebrahimi        virtual void PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* ccpl_state) {
1452*b7893ccfSSadaf Ebrahimi            PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1453*b7893ccfSSadaf Ebrahimi        };
1454*b7893ccfSSadaf Ebrahimi        virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1455*b7893ccfSSadaf Ebrahimi            PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1456*b7893ccfSSadaf Ebrahimi        };
1457*b7893ccfSSadaf Ebrahimi
1458*b7893ccfSSadaf Ebrahimi        // Allow additional state parameter for CreateRayTracingPipelinesNV
1459*b7893ccfSSadaf Ebrahimi        virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state)  {
1460*b7893ccfSSadaf Ebrahimi            return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1461*b7893ccfSSadaf Ebrahimi        };
1462*b7893ccfSSadaf Ebrahimi        virtual void PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* ccpl_state) {
1463*b7893ccfSSadaf Ebrahimi            PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1464*b7893ccfSSadaf Ebrahimi        };
1465*b7893ccfSSadaf Ebrahimi        virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1466*b7893ccfSSadaf Ebrahimi            PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1467*b7893ccfSSadaf Ebrahimi        };
1468*b7893ccfSSadaf Ebrahimi
1469*b7893ccfSSadaf Ebrahimi        // Allow modification of a down-chain parameter for CreatePipelineLayout
1470*b7893ccfSSadaf Ebrahimi        virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1471*b7893ccfSSadaf Ebrahimi            PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1472*b7893ccfSSadaf Ebrahimi        };
1473*b7893ccfSSadaf Ebrahimi
1474*b7893ccfSSadaf Ebrahimi        // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1475*b7893ccfSSadaf Ebrahimi        virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state)  {
1476*b7893ccfSSadaf Ebrahimi            return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1477*b7893ccfSSadaf Ebrahimi        };
1478*b7893ccfSSadaf Ebrahimi        virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1479*b7893ccfSSadaf Ebrahimi            PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1480*b7893ccfSSadaf Ebrahimi        };
1481*b7893ccfSSadaf Ebrahimi        virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1482*b7893ccfSSadaf Ebrahimi            PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1483*b7893ccfSSadaf Ebrahimi        };
1484*b7893ccfSSadaf Ebrahimi
1485*b7893ccfSSadaf Ebrahimi        // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1486*b7893ccfSSadaf Ebrahimi        virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state)  {
1487*b7893ccfSSadaf Ebrahimi            return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1488*b7893ccfSSadaf Ebrahimi        };
1489*b7893ccfSSadaf Ebrahimi        virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state)  {
1490*b7893ccfSSadaf Ebrahimi            PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1491*b7893ccfSSadaf Ebrahimi        };
1492*b7893ccfSSadaf Ebrahimi
1493*b7893ccfSSadaf Ebrahimi        // Modify a parameter to CreateDevice
1494*b7893ccfSSadaf Ebrahimi        virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, safe_VkDeviceCreateInfo *modified_create_info) {
1495*b7893ccfSSadaf Ebrahimi            PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1496*b7893ccfSSadaf Ebrahimi        };
1497*b7893ccfSSadaf Ebrahimi"""
1498*b7893ccfSSadaf Ebrahimi
1499*b7893ccfSSadaf Ebrahimi    inline_custom_source_postamble = """
1500*b7893ccfSSadaf Ebrahimi// loader-layer interface v0, just wrappers since there is only a layer
1501*b7893ccfSSadaf Ebrahimi
1502*b7893ccfSSadaf EbrahimiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1503*b7893ccfSSadaf Ebrahimi                                                                                      VkExtensionProperties *pProperties) {
1504*b7893ccfSSadaf Ebrahimi    return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1505*b7893ccfSSadaf Ebrahimi}
1506*b7893ccfSSadaf Ebrahimi
1507*b7893ccfSSadaf EbrahimiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1508*b7893ccfSSadaf Ebrahimi                                                                                  VkLayerProperties *pProperties) {
1509*b7893ccfSSadaf Ebrahimi    return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1510*b7893ccfSSadaf Ebrahimi}
1511*b7893ccfSSadaf Ebrahimi
1512*b7893ccfSSadaf EbrahimiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1513*b7893ccfSSadaf Ebrahimi                                                                                VkLayerProperties *pProperties) {
1514*b7893ccfSSadaf Ebrahimi    // the layer command handles VK_NULL_HANDLE just fine internally
1515*b7893ccfSSadaf Ebrahimi    assert(physicalDevice == VK_NULL_HANDLE);
1516*b7893ccfSSadaf Ebrahimi    return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1517*b7893ccfSSadaf Ebrahimi}
1518*b7893ccfSSadaf Ebrahimi
1519*b7893ccfSSadaf EbrahimiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1520*b7893ccfSSadaf Ebrahimi                                                                                    const char *pLayerName, uint32_t *pCount,
1521*b7893ccfSSadaf Ebrahimi                                                                                    VkExtensionProperties *pProperties) {
1522*b7893ccfSSadaf Ebrahimi    // the layer command handles VK_NULL_HANDLE just fine internally
1523*b7893ccfSSadaf Ebrahimi    assert(physicalDevice == VK_NULL_HANDLE);
1524*b7893ccfSSadaf Ebrahimi    return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1525*b7893ccfSSadaf Ebrahimi}
1526*b7893ccfSSadaf Ebrahimi
1527*b7893ccfSSadaf EbrahimiVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1528*b7893ccfSSadaf Ebrahimi    return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1529*b7893ccfSSadaf Ebrahimi}
1530*b7893ccfSSadaf Ebrahimi
1531*b7893ccfSSadaf EbrahimiVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1532*b7893ccfSSadaf Ebrahimi    return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1533*b7893ccfSSadaf Ebrahimi}
1534*b7893ccfSSadaf Ebrahimi
1535*b7893ccfSSadaf EbrahimiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1536*b7893ccfSSadaf Ebrahimi    assert(pVersionStruct != NULL);
1537*b7893ccfSSadaf Ebrahimi    assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1538*b7893ccfSSadaf Ebrahimi
1539*b7893ccfSSadaf Ebrahimi    // Fill in the function pointers if our version is at least capable of having the structure contain them.
1540*b7893ccfSSadaf Ebrahimi    if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1541*b7893ccfSSadaf Ebrahimi        pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1542*b7893ccfSSadaf Ebrahimi        pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
1543*b7893ccfSSadaf Ebrahimi        pVersionStruct->pfnGetPhysicalDeviceProcAddr = nullptr;
1544*b7893ccfSSadaf Ebrahimi    }
1545*b7893ccfSSadaf Ebrahimi
1546*b7893ccfSSadaf Ebrahimi    return VK_SUCCESS;
1547*b7893ccfSSadaf Ebrahimi}"""
1548*b7893ccfSSadaf Ebrahimi
1549*b7893ccfSSadaf Ebrahimi
1550*b7893ccfSSadaf Ebrahimi    def __init__(self,
1551*b7893ccfSSadaf Ebrahimi                 errFile = sys.stderr,
1552*b7893ccfSSadaf Ebrahimi                 warnFile = sys.stderr,
1553*b7893ccfSSadaf Ebrahimi                 diagFile = sys.stdout):
1554*b7893ccfSSadaf Ebrahimi        OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1555*b7893ccfSSadaf Ebrahimi        # Internal state - accumulators for different inner block text
1556*b7893ccfSSadaf Ebrahimi        self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1557*b7893ccfSSadaf Ebrahimi        self.intercepts = []
1558*b7893ccfSSadaf Ebrahimi        self.layer_factory = ''                     # String containing base layer factory class definition
1559*b7893ccfSSadaf Ebrahimi
1560*b7893ccfSSadaf Ebrahimi    # Check if the parameter passed in is a pointer to an array
1561*b7893ccfSSadaf Ebrahimi    def paramIsArray(self, param):
1562*b7893ccfSSadaf Ebrahimi        return param.attrib.get('len') is not None
1563*b7893ccfSSadaf Ebrahimi
1564*b7893ccfSSadaf Ebrahimi    # Check if the parameter passed in is a pointer
1565*b7893ccfSSadaf Ebrahimi    def paramIsPointer(self, param):
1566*b7893ccfSSadaf Ebrahimi        ispointer = False
1567*b7893ccfSSadaf Ebrahimi        for elem in param:
1568*b7893ccfSSadaf Ebrahimi            if elem.tag == 'type' and elem.tail is not None and '*' in elem.tail:
1569*b7893ccfSSadaf Ebrahimi                ispointer = True
1570*b7893ccfSSadaf Ebrahimi        return ispointer
1571*b7893ccfSSadaf Ebrahimi
1572*b7893ccfSSadaf Ebrahimi    #
1573*b7893ccfSSadaf Ebrahimi    #
1574*b7893ccfSSadaf Ebrahimi    def beginFile(self, genOpts):
1575*b7893ccfSSadaf Ebrahimi        OutputGenerator.beginFile(self, genOpts)
1576*b7893ccfSSadaf Ebrahimi        # Output Copyright
1577*b7893ccfSSadaf Ebrahimi        write(self.inline_copyright_message, file=self.outFile)
1578*b7893ccfSSadaf Ebrahimi        # Multiple inclusion protection
1579*b7893ccfSSadaf Ebrahimi        self.header = False
1580*b7893ccfSSadaf Ebrahimi        if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1581*b7893ccfSSadaf Ebrahimi            self.header = True
1582*b7893ccfSSadaf Ebrahimi            write('#pragma once', file=self.outFile)
1583*b7893ccfSSadaf Ebrahimi            self.newline()
1584*b7893ccfSSadaf Ebrahimi        if self.header:
1585*b7893ccfSSadaf Ebrahimi            write(self.inline_custom_header_preamble, file=self.outFile)
1586*b7893ccfSSadaf Ebrahimi        else:
1587*b7893ccfSSadaf Ebrahimi            write(self.inline_custom_source_preamble, file=self.outFile)
1588*b7893ccfSSadaf Ebrahimi        self.layer_factory += self.inline_custom_header_class_definition
1589*b7893ccfSSadaf Ebrahimi    #
1590*b7893ccfSSadaf Ebrahimi    #
1591*b7893ccfSSadaf Ebrahimi    def endFile(self):
1592*b7893ccfSSadaf Ebrahimi        # Finish C++ namespace and multiple inclusion protection
1593*b7893ccfSSadaf Ebrahimi        self.newline()
1594*b7893ccfSSadaf Ebrahimi        if not self.header:
1595*b7893ccfSSadaf Ebrahimi            # Record intercepted procedures
1596*b7893ccfSSadaf Ebrahimi            write('// Map of intercepted ApiName to its associated function data', file=self.outFile)
1597*b7893ccfSSadaf Ebrahimi            write('const std::unordered_map<std::string, function_data> name_to_funcptr_map = {', file=self.outFile)
1598*b7893ccfSSadaf Ebrahimi            write('\n'.join(self.intercepts), file=self.outFile)
1599*b7893ccfSSadaf Ebrahimi            write('};\n', file=self.outFile)
1600*b7893ccfSSadaf Ebrahimi            self.newline()
1601*b7893ccfSSadaf Ebrahimi            write('} // namespace vulkan_layer_chassis', file=self.outFile)
1602*b7893ccfSSadaf Ebrahimi        if self.header:
1603*b7893ccfSSadaf Ebrahimi            self.newline()
1604*b7893ccfSSadaf Ebrahimi            # Output Layer Factory Class Definitions
1605*b7893ccfSSadaf Ebrahimi            self.layer_factory += self.inline_custom_validation_class_definitions
1606*b7893ccfSSadaf Ebrahimi            self.layer_factory += '};\n\n'
1607*b7893ccfSSadaf Ebrahimi            self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
1608*b7893ccfSSadaf Ebrahimi            write(self.layer_factory, file=self.outFile)
1609*b7893ccfSSadaf Ebrahimi        else:
1610*b7893ccfSSadaf Ebrahimi            write(self.inline_custom_source_postamble, file=self.outFile)
1611*b7893ccfSSadaf Ebrahimi        # Finish processing in superclass
1612*b7893ccfSSadaf Ebrahimi        OutputGenerator.endFile(self)
1613*b7893ccfSSadaf Ebrahimi
1614*b7893ccfSSadaf Ebrahimi    def beginFeature(self, interface, emit):
1615*b7893ccfSSadaf Ebrahimi        # Start processing in superclass
1616*b7893ccfSSadaf Ebrahimi        OutputGenerator.beginFeature(self, interface, emit)
1617*b7893ccfSSadaf Ebrahimi        # Get feature extra protect
1618*b7893ccfSSadaf Ebrahimi        self.featureExtraProtect = GetFeatureProtect(interface)
1619*b7893ccfSSadaf Ebrahimi        # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1620*b7893ccfSSadaf Ebrahimi        # feature. They're only printed in endFeature().
1621*b7893ccfSSadaf Ebrahimi        self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1622*b7893ccfSSadaf Ebrahimi
1623*b7893ccfSSadaf Ebrahimi    def endFeature(self):
1624*b7893ccfSSadaf Ebrahimi        # Actually write the interface to the output file.
1625*b7893ccfSSadaf Ebrahimi        if (self.emit):
1626*b7893ccfSSadaf Ebrahimi            self.newline()
1627*b7893ccfSSadaf Ebrahimi            # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1628*b7893ccfSSadaf Ebrahimi            # or move it below the 'for section...' loop.
1629*b7893ccfSSadaf Ebrahimi            if (self.featureExtraProtect != None):
1630*b7893ccfSSadaf Ebrahimi                write('#ifdef', self.featureExtraProtect, file=self.outFile)
1631*b7893ccfSSadaf Ebrahimi            for section in self.TYPE_SECTIONS:
1632*b7893ccfSSadaf Ebrahimi                contents = self.sections[section]
1633*b7893ccfSSadaf Ebrahimi                if contents:
1634*b7893ccfSSadaf Ebrahimi                    write('\n'.join(contents), file=self.outFile)
1635*b7893ccfSSadaf Ebrahimi                    self.newline()
1636*b7893ccfSSadaf Ebrahimi            if (self.sections['command']):
1637*b7893ccfSSadaf Ebrahimi                write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1638*b7893ccfSSadaf Ebrahimi                self.newline()
1639*b7893ccfSSadaf Ebrahimi            if (self.featureExtraProtect != None):
1640*b7893ccfSSadaf Ebrahimi                write('#endif //', self.featureExtraProtect, file=self.outFile)
1641*b7893ccfSSadaf Ebrahimi        # Finish processing in superclass
1642*b7893ccfSSadaf Ebrahimi        OutputGenerator.endFeature(self)
1643*b7893ccfSSadaf Ebrahimi    #
1644*b7893ccfSSadaf Ebrahimi    # Append a definition to the specified section
1645*b7893ccfSSadaf Ebrahimi    def appendSection(self, section, text):
1646*b7893ccfSSadaf Ebrahimi        self.sections[section].append(text)
1647*b7893ccfSSadaf Ebrahimi    #
1648*b7893ccfSSadaf Ebrahimi    # Type generation
1649*b7893ccfSSadaf Ebrahimi    def genType(self, typeinfo, name, alias):
1650*b7893ccfSSadaf Ebrahimi        pass
1651*b7893ccfSSadaf Ebrahimi    #
1652*b7893ccfSSadaf Ebrahimi    # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1653*b7893ccfSSadaf Ebrahimi    # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1654*b7893ccfSSadaf Ebrahimi    # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1655*b7893ccfSSadaf Ebrahimi    # structs etc.)
1656*b7893ccfSSadaf Ebrahimi    def genStruct(self, typeinfo, typeName):
1657*b7893ccfSSadaf Ebrahimi        OutputGenerator.genStruct(self, typeinfo, typeName)
1658*b7893ccfSSadaf Ebrahimi        body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1659*b7893ccfSSadaf Ebrahimi        # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1660*b7893ccfSSadaf Ebrahimi        for member in typeinfo.elem.findall('.//member'):
1661*b7893ccfSSadaf Ebrahimi            body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1662*b7893ccfSSadaf Ebrahimi            body += ';\n'
1663*b7893ccfSSadaf Ebrahimi        body += '} ' + typeName + ';\n'
1664*b7893ccfSSadaf Ebrahimi        self.appendSection('struct', body)
1665*b7893ccfSSadaf Ebrahimi    #
1666*b7893ccfSSadaf Ebrahimi    # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1667*b7893ccfSSadaf Ebrahimi    def genGroup(self, groupinfo, groupName, alias):
1668*b7893ccfSSadaf Ebrahimi        pass
1669*b7893ccfSSadaf Ebrahimi    # Enumerant generation
1670*b7893ccfSSadaf Ebrahimi    # <enum> tags may specify their values in several ways, but are usually just integers.
1671*b7893ccfSSadaf Ebrahimi    def genEnum(self, enuminfo, name, alias):
1672*b7893ccfSSadaf Ebrahimi        pass
1673*b7893ccfSSadaf Ebrahimi    #
1674*b7893ccfSSadaf Ebrahimi    # Customize Cdecl for layer factory base class
1675*b7893ccfSSadaf Ebrahimi    def BaseClassCdecl(self, elem, name):
1676*b7893ccfSSadaf Ebrahimi        raw = self.makeCDecls(elem)[1]
1677*b7893ccfSSadaf Ebrahimi
1678*b7893ccfSSadaf Ebrahimi        # Toss everything before the undecorated name
1679*b7893ccfSSadaf Ebrahimi        prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1680*b7893ccfSSadaf Ebrahimi        prototype = prototype.replace(")", "", 1)
1681*b7893ccfSSadaf Ebrahimi        prototype = prototype.replace(";", " {};")
1682*b7893ccfSSadaf Ebrahimi
1683*b7893ccfSSadaf Ebrahimi        # Build up pre/post call virtual function declarations
1684*b7893ccfSSadaf Ebrahimi        pre_call_validate = 'virtual bool PreCallValidate' + prototype
1685*b7893ccfSSadaf Ebrahimi        pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1686*b7893ccfSSadaf Ebrahimi        pre_call_record = 'virtual void PreCallRecord' + prototype
1687*b7893ccfSSadaf Ebrahimi        post_call_record = 'virtual void PostCallRecord' + prototype
1688*b7893ccfSSadaf Ebrahimi        resulttype = elem.find('proto/type')
1689*b7893ccfSSadaf Ebrahimi        if resulttype.text == 'VkResult':
1690*b7893ccfSSadaf Ebrahimi            post_call_record = post_call_record.replace(')', ', VkResult result)')
1691*b7893ccfSSadaf Ebrahimi        return '        %s\n        %s\n        %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1692*b7893ccfSSadaf Ebrahimi    #
1693*b7893ccfSSadaf Ebrahimi    # Command generation
1694*b7893ccfSSadaf Ebrahimi    def genCmd(self, cmdinfo, name, alias):
1695*b7893ccfSSadaf Ebrahimi        ignore_functions = [
1696*b7893ccfSSadaf Ebrahimi        'vkEnumerateInstanceVersion',
1697*b7893ccfSSadaf Ebrahimi        ]
1698*b7893ccfSSadaf Ebrahimi
1699*b7893ccfSSadaf Ebrahimi        if name in ignore_functions:
1700*b7893ccfSSadaf Ebrahimi            return
1701*b7893ccfSSadaf Ebrahimi
1702*b7893ccfSSadaf Ebrahimi        if self.header: # In the header declare all intercepts
1703*b7893ccfSSadaf Ebrahimi            self.appendSection('command', '')
1704*b7893ccfSSadaf Ebrahimi            self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1705*b7893ccfSSadaf Ebrahimi            if (self.featureExtraProtect != None):
1706*b7893ccfSSadaf Ebrahimi                self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1707*b7893ccfSSadaf Ebrahimi            # Update base class with virtual function declarations
1708*b7893ccfSSadaf Ebrahimi            if 'ValidationCache' not in name:
1709*b7893ccfSSadaf Ebrahimi                self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
1710*b7893ccfSSadaf Ebrahimi            if (self.featureExtraProtect != None):
1711*b7893ccfSSadaf Ebrahimi                self.layer_factory += '#endif\n'
1712*b7893ccfSSadaf Ebrahimi            return
1713*b7893ccfSSadaf Ebrahimi
1714*b7893ccfSSadaf Ebrahimi        is_instance = 'false'
1715*b7893ccfSSadaf Ebrahimi        dispatchable_type = cmdinfo.elem.find('param/type').text
1716*b7893ccfSSadaf Ebrahimi        if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1717*b7893ccfSSadaf Ebrahimi            is_instance = 'true'
1718*b7893ccfSSadaf Ebrahimi
1719*b7893ccfSSadaf Ebrahimi        if name in self.manual_functions:
1720*b7893ccfSSadaf Ebrahimi            if 'ValidationCache' not in name:
1721*b7893ccfSSadaf Ebrahimi                self.intercepts += [ '    {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
1722*b7893ccfSSadaf Ebrahimi            else:
1723*b7893ccfSSadaf Ebrahimi                self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1724*b7893ccfSSadaf Ebrahimi
1725*b7893ccfSSadaf Ebrahimi                self.intercepts += [ '    {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
1726*b7893ccfSSadaf Ebrahimi                self.intercepts += [ '#endif' ]
1727*b7893ccfSSadaf Ebrahimi            return
1728*b7893ccfSSadaf Ebrahimi        # Record that the function will be intercepted
1729*b7893ccfSSadaf Ebrahimi        if (self.featureExtraProtect != None):
1730*b7893ccfSSadaf Ebrahimi            self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1731*b7893ccfSSadaf Ebrahimi        self.intercepts += [ '    {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
1732*b7893ccfSSadaf Ebrahimi        if (self.featureExtraProtect != None):
1733*b7893ccfSSadaf Ebrahimi            self.intercepts += [ '#endif' ]
1734*b7893ccfSSadaf Ebrahimi        OutputGenerator.genCmd(self, cmdinfo, name, alias)
1735*b7893ccfSSadaf Ebrahimi        #
1736*b7893ccfSSadaf Ebrahimi        decls = self.makeCDecls(cmdinfo.elem)
1737*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '')
1738*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '%s {' % decls[0][:-1])
1739*b7893ccfSSadaf Ebrahimi        # Setup common to call wrappers. First parameter is always dispatchable
1740*b7893ccfSSadaf Ebrahimi        dispatchable_name = cmdinfo.elem.find('param/name').text
1741*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '    auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
1742*b7893ccfSSadaf Ebrahimi        api_function_name = cmdinfo.elem.attrib.get('name')
1743*b7893ccfSSadaf Ebrahimi        params = cmdinfo.elem.findall('param/name')
1744*b7893ccfSSadaf Ebrahimi        paramstext = ', '.join([str(param.text) for param in params])
1745*b7893ccfSSadaf Ebrahimi        API = api_function_name.replace('vk','Dispatch') + '('
1746*b7893ccfSSadaf Ebrahimi
1747*b7893ccfSSadaf Ebrahimi        # Declare result variable, if any.
1748*b7893ccfSSadaf Ebrahimi        return_map = {
1749*b7893ccfSSadaf Ebrahimi            'PFN_vkVoidFunction': 'return nullptr;',
1750*b7893ccfSSadaf Ebrahimi            'VkBool32': 'return VK_FALSE;',
1751*b7893ccfSSadaf Ebrahimi            'VkDeviceAddress': 'return 0;',
1752*b7893ccfSSadaf Ebrahimi            'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1753*b7893ccfSSadaf Ebrahimi            'void': 'return;',
1754*b7893ccfSSadaf Ebrahimi            'uint32_t': 'return 0;'
1755*b7893ccfSSadaf Ebrahimi            }
1756*b7893ccfSSadaf Ebrahimi        resulttype = cmdinfo.elem.find('proto/type')
1757*b7893ccfSSadaf Ebrahimi        assignresult = ''
1758*b7893ccfSSadaf Ebrahimi        if (resulttype.text != 'void'):
1759*b7893ccfSSadaf Ebrahimi            assignresult = resulttype.text + ' result = '
1760*b7893ccfSSadaf Ebrahimi
1761*b7893ccfSSadaf Ebrahimi        # Set up skip and locking
1762*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '    bool skip = false;')
1763*b7893ccfSSadaf Ebrahimi
1764*b7893ccfSSadaf Ebrahimi        # Generate pre-call validation source code
1765*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '    %s' % self.precallvalidate_loop)
1766*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '        auto lock = intercept->write_lock();')
1767*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '        skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1768*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '        if (skip) %s' % return_map[resulttype.text])
1769*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '    }')
1770*b7893ccfSSadaf Ebrahimi
1771*b7893ccfSSadaf Ebrahimi        # Generate pre-call state recording source code
1772*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '    %s' % self.precallrecord_loop)
1773*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '        auto lock = intercept->write_lock();')
1774*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '        intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
1775*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '    }')
1776*b7893ccfSSadaf Ebrahimi
1777*b7893ccfSSadaf Ebrahimi        # Insert pre-dispatch debug utils function call
1778*b7893ccfSSadaf Ebrahimi        if name in self.pre_dispatch_debug_utils_functions:
1779*b7893ccfSSadaf Ebrahimi            self.appendSection('command', '    %s' % self.pre_dispatch_debug_utils_functions[name])
1780*b7893ccfSSadaf Ebrahimi
1781*b7893ccfSSadaf Ebrahimi        # Output dispatch (down-chain) function call
1782*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '    ' + assignresult + API + paramstext + ');')
1783*b7893ccfSSadaf Ebrahimi
1784*b7893ccfSSadaf Ebrahimi        # Insert post-dispatch debug utils function call
1785*b7893ccfSSadaf Ebrahimi        if name in self.post_dispatch_debug_utils_functions:
1786*b7893ccfSSadaf Ebrahimi            self.appendSection('command', '    %s' % self.post_dispatch_debug_utils_functions[name])
1787*b7893ccfSSadaf Ebrahimi
1788*b7893ccfSSadaf Ebrahimi        # Generate post-call object processing source code
1789*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '    %s' % self.postcallrecord_loop)
1790*b7893ccfSSadaf Ebrahimi        returnparam = ''
1791*b7893ccfSSadaf Ebrahimi        if (resulttype.text == 'VkResult'):
1792*b7893ccfSSadaf Ebrahimi            returnparam = ', result'
1793*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '        auto lock = intercept->write_lock();')
1794*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '        intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
1795*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '    }')
1796*b7893ccfSSadaf Ebrahimi        # Return result variable, if any.
1797*b7893ccfSSadaf Ebrahimi        if (resulttype.text != 'void'):
1798*b7893ccfSSadaf Ebrahimi            self.appendSection('command', '    return result;')
1799*b7893ccfSSadaf Ebrahimi        self.appendSection('command', '}')
1800*b7893ccfSSadaf Ebrahimi    #
1801*b7893ccfSSadaf Ebrahimi    # Override makeProtoName to drop the "vk" prefix
1802*b7893ccfSSadaf Ebrahimi    def makeProtoName(self, name, tail):
1803*b7893ccfSSadaf Ebrahimi        return self.genOpts.apientry + name[2:] + tail
1804