blob: 9b149d08e167d808123620f19685eb23af1cb430 [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07003# Copyright (c) 2015-2019 Valve Corporation
4# Copyright (c) 2015-2019 LunarG, Inc.
5# Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06006#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
20# Author: Mark Lobodzinski <mark@lunarg.com>
21#
22# This script generates the dispatch portion of a factory layer which intercepts
23# all Vulkan functions. The resultant factory layer allows rapid development of
24# layers and interceptors.
25
26import os,re,sys
27from generator import *
28from common_codegen import *
29
30# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31#
32# Adds options used by LayerFactoryOutputGenerator objects during factory
33# layer generation.
34#
35# Additional members
36# prefixText - list of strings to prefix generated header with
37# (usually a copyright statement + calling convention macros).
38# protectFile - True if multiple inclusion protection should be
39# generated (based on the filename) around the entire header.
40# protectFeature - True if #ifndef..#endif protection should be
41# generated around a feature interface in the header file.
42# genFuncPointers - True if function pointer typedefs should be
43# generated
44# protectProto - If conditional protection should be generated
45# around prototype declarations, set to either '#ifdef'
46# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47# to require opt-out (#ifndef protectProtoStr). Otherwise
48# set to None.
49# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50# declarations, if protectProto is set
51# apicall - string to use for the function declaration prefix,
52# such as APICALL on Windows.
53# apientry - string to use for the calling convention macro,
54# in typedefs, such as APIENTRY.
55# apientryp - string to use for the calling convention macro
56# in function pointer typedefs, such as APIENTRYP.
57# indentFuncProto - True if prototype declarations should put each
58# parameter on a separate line
59# indentFuncPointer - True if typedefed function pointers should put each
60# parameter on a separate line
61# alignFuncParam - if nonzero and parameters are being put on a
62# separate line, align parameter names at the specified column
63class LayerChassisGeneratorOptions(GeneratorOptions):
64 def __init__(self,
Mike Schuchardt21638df2019-03-16 10:52:02 -070065 conventions = None,
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -060066 filename = None,
67 directory = '.',
68 apiname = None,
69 profile = None,
70 versions = '.*',
71 emitversions = '.*',
72 defaultExtensions = None,
73 addExtensions = None,
74 removeExtensions = None,
75 emitExtensions = None,
76 sortProcedure = regSortFeatures,
77 prefixText = "",
78 genFuncPointers = True,
79 protectFile = True,
80 protectFeature = True,
81 apicall = '',
82 apientry = '',
83 apientryp = '',
84 indentFuncProto = True,
85 indentFuncPointer = False,
86 alignFuncParam = 0,
87 helper_file_type = '',
88 expandEnumerants = True):
Mike Schuchardt21638df2019-03-16 10:52:02 -070089 GeneratorOptions.__init__(self, conventions, filename, directory, apiname, profile,
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -060090 versions, emitversions, defaultExtensions,
91 addExtensions, removeExtensions, emitExtensions, sortProcedure)
92 self.prefixText = prefixText
93 self.genFuncPointers = genFuncPointers
94 self.protectFile = protectFile
95 self.protectFeature = protectFeature
96 self.apicall = apicall
97 self.apientry = apientry
98 self.apientryp = apientryp
99 self.indentFuncProto = indentFuncProto
100 self.indentFuncPointer = indentFuncPointer
101 self.alignFuncParam = alignFuncParam
102
103# LayerChassisOutputGenerator - subclass of OutputGenerator.
104# Generates a LayerFactory layer that intercepts all API entrypoints
105# This is intended to be used as a starting point for creating custom layers
106#
107# ---- methods ----
108# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
109# OutputGenerator. Defines additional internal state.
110# ---- methods overriding base class ----
111# beginFile(genOpts)
112# endFile()
113# beginFeature(interface, emit)
114# endFeature()
115# genType(typeinfo,name)
116# genStruct(typeinfo,name)
117# genGroup(groupinfo,name)
118# genEnum(enuminfo, name)
119# genCmd(cmdinfo)
120class LayerChassisOutputGenerator(OutputGenerator):
121 """Generate specified API interfaces in a specific style, such as a C header"""
122 # This is an ordered list of sections in the header file.
123 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
124 'group', 'bitmask', 'funcpointer', 'struct']
125 ALL_SECTIONS = TYPE_SECTIONS + ['command']
126
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700127 manual_functions = [
128 # Include functions here to be interecpted w/ manually implemented function bodies
129 'vkGetDeviceProcAddr',
130 'vkGetInstanceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700131 'vkCreateDevice',
132 'vkDestroyDevice',
133 'vkCreateInstance',
134 'vkDestroyInstance',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700135 'vkEnumerateInstanceLayerProperties',
136 'vkEnumerateInstanceExtensionProperties',
137 'vkEnumerateDeviceLayerProperties',
138 'vkEnumerateDeviceExtensionProperties',
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700139 # Functions that are handled explicitly due to chassis architecture violations
140 'vkCreateGraphicsPipelines',
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700141 'vkCreateComputePipelines',
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700142 'vkCreateRayTracingPipelinesNV',
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -0700143 'vkCreatePipelineLayout',
Mark Lobodzinski1db77e82019-03-01 10:02:54 -0700144 'vkCreateShaderModule',
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -0700145 'vkAllocateDescriptorSets',
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700146 # ValidationCache functions do not get dispatched
147 'vkCreateValidationCacheEXT',
148 'vkDestroyValidationCacheEXT',
149 'vkMergeValidationCachesEXT',
150 'vkGetValidationCacheDataEXT',
Mark Lobodzinski56e88122019-03-26 10:21:48 -0600151 # We don't wanna hook this function
152 'vkGetPhysicalDeviceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700153 ]
154
155 alt_ret_codes = [
156 # Include functions here which must tolerate VK_INCOMPLETE as a return code
157 'vkEnumeratePhysicalDevices',
158 'vkEnumeratePhysicalDeviceGroupsKHR',
159 'vkGetValidationCacheDataEXT',
160 'vkGetPipelineCacheData',
161 'vkGetShaderInfoAMD',
162 'vkGetPhysicalDeviceDisplayPropertiesKHR',
163 'vkGetPhysicalDeviceDisplayProperties2KHR',
164 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
165 'vkGetDisplayPlaneSupportedDisplaysKHR',
166 'vkGetDisplayModePropertiesKHR',
167 'vkGetDisplayModeProperties2KHR',
168 'vkGetPhysicalDeviceSurfaceFormatsKHR',
169 'vkGetPhysicalDeviceSurfacePresentModesKHR',
170 'vkGetPhysicalDevicePresentRectanglesKHR',
171 'vkGetPastPresentationTimingGOOGLE',
172 'vkGetSwapchainImagesKHR',
173 'vkEnumerateInstanceLayerProperties',
174 'vkEnumerateDeviceLayerProperties',
175 'vkEnumerateInstanceExtensionProperties',
176 'vkEnumerateDeviceExtensionProperties',
177 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
178 ]
179
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700180 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700181 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
182 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700183 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
184 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
185 'vkCmdBeginDebugUtilsLabelEXT' : 'BeginCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
186 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
187 }
188
189 post_dispatch_debug_utils_functions = {
190 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
191 'vkCmdEndDebugUtilsLabelEXT' : 'EndCmdDebugUtilsLabel(layer_data->report_data, commandBuffer);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700192 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
193 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
194 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
195 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
196 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700197 }
198
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600199 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
200 precallrecord_loop = precallvalidate_loop
201 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600202
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700203 inline_custom_header_preamble = """
204#define NOMINMAX
205#include <mutex>
206#include <cinttypes>
207#include <stdio.h>
208#include <stdlib.h>
209#include <string.h>
210#include <unordered_map>
211#include <unordered_set>
212#include <algorithm>
213#include <memory>
214
215#include "vk_loader_platform.h"
216#include "vulkan/vulkan.h"
217#include "vk_layer_config.h"
218#include "vk_layer_data.h"
219#include "vk_layer_logging.h"
220#include "vk_object_types.h"
221#include "vulkan/vk_layer.h"
222#include "vk_enum_string_helper.h"
223#include "vk_layer_extension_utils.h"
224#include "vk_layer_utils.h"
225#include "vulkan/vk_layer.h"
226#include "vk_dispatch_table_helper.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700227#include "vk_extension_helper.h"
228#include "vk_safe_struct.h"
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700229#include "vk_typemap_helper.h"
230
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700231
232extern uint64_t global_unique_id;
233extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
234"""
235
236 inline_custom_header_class_definition = """
237
238// Layer object type identifiers
239enum LayerObjectTypeId {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700240 LayerObjectTypeInstance, // Container for an instance dispatch object
241 LayerObjectTypeDevice, // Container for a device dispatch object
242 LayerObjectTypeThreading, // Instance or device threading layer object
243 LayerObjectTypeParameterValidation, // Instance or device parameter validation layer object
244 LayerObjectTypeObjectTracker, // Instance or device object tracker layer object
245 LayerObjectTypeCoreValidation, // Instance or device core validation layer object
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700246};
247
248struct TEMPLATE_STATE {
249 VkDescriptorUpdateTemplateKHR desc_update_template;
250 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
251
252 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
253 : desc_update_template(update_template), create_info(*pCreateInfo) {}
254};
255
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700256class LAYER_PHYS_DEV_PROPERTIES {
257public:
258 VkPhysicalDeviceProperties properties;
259 std::vector<VkQueueFamilyProperties> queue_family_properties;
260};
261
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600262typedef enum ValidationCheckDisables {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600263 VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600264 VALIDATION_CHECK_DISABLE_OBJECT_IN_USE,
265 VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET,
266 VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE,
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600267 VALIDATION_CHECK_DISABLE_QUERY_VALIDATION,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600268} ValidationCheckDisables;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600269
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600270
271// CHECK_DISABLED struct is a container for bools that can block validation checks from being performed.
272// These bools are all "false" by default meaning that all checks are enabled. Enum values can be specified
273// via the vk_layer_setting.txt config file or at CreateInstance time via the VK_EXT_validation_features extension
274// that can selectively disable checks.
275struct CHECK_DISABLED {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600276 bool command_buffer_state; // Skip command buffer state validation
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600277 bool object_in_use; // Skip all object in_use checking
278 bool idle_descriptor_set; // Skip check to verify that descriptor set is not in-use
279 bool push_constant_range; // Skip push constant range checks
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600280 bool query_validation; // Disable all core validation query-related checks
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600281 bool object_tracking; // Disable object lifetime validation
282 bool core_checks; // Disable core validation checks
283 bool thread_safety; // Disable thread safety validation
284 bool stateless_checks; // Disable stateless validation checks
285 bool handle_wrapping; // Disable unique handles/handle wrapping
286 bool shader_validation; // Skip validation for shaders
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700287
288 void SetAll(bool value) { std::fill(&command_buffer_state, &shader_validation + 1, value); }
289};
290
291struct CHECK_ENABLED {
292 bool gpu_validation;
293 bool gpu_validation_reserve_binding_slot;
294
295 void SetAll(bool value) { std::fill(&gpu_validation, &gpu_validation_reserve_binding_slot + 1, value); }
296};
297
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700298// Layer chassis validation object base class definition
299class ValidationObject {
300 public:
301 uint32_t api_version;
302 debug_report_data* report_data = nullptr;
303 std::vector<VkDebugReportCallbackEXT> logging_callback;
304 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
305
306 VkLayerInstanceDispatchTable instance_dispatch_table;
307 VkLayerDispatchTable device_dispatch_table;
308
309 InstanceExtensions instance_extensions;
310 DeviceExtensions device_extensions = {};
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700311 CHECK_DISABLED disabled = {};
312 CHECK_ENABLED enabled = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700313
314 VkInstance instance = VK_NULL_HANDLE;
315 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
316 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700317 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700318
319 std::vector<ValidationObject*> object_dispatch;
320 LayerObjectTypeId container_type;
321
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700322 std::string layer_name = "CHASSIS";
323
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700324 // Constructor
325 ValidationObject(){};
326 // Destructor
327 virtual ~ValidationObject() {};
328
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700329 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700330 virtual std::unique_lock<std::mutex> write_lock() {
331 return std::unique_lock<std::mutex>(validation_object_mutex);
332 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700333
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700334 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
335 for (auto validation_object : object_dispatch) {
336 if (validation_object->container_type == object_type) {
337 return validation_object;
338 }
339 }
340 return nullptr;
341 };
342
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700343 // Handle Wrapping Data
344 // Reverse map display handles
345 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
346 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700347 struct SubpassesUsageStates {
348 std::unordered_set<uint32_t> subpasses_using_color_attachment;
349 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
350 };
351 // Uses unwrapped handles
352 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
353 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
354 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
355 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700356 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
357 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700358
359
360 // Unwrap a handle. Must hold lock.
361 template <typename HandleType>
362 HandleType Unwrap(HandleType wrappedHandle) {
363 // TODO: don't use operator[] here.
364 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
365 }
366
367 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
368 template <typename HandleType>
369 HandleType WrapNew(HandleType newlyCreatedHandle) {
370 auto unique_id = global_unique_id++;
371 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
372 return (HandleType)unique_id;
373 }
374
375 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
376 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
377 auto unique_id = global_unique_id++;
378 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
379 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
380 return (VkDisplayKHR)unique_id;
381 }
382
383 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
384 // creating another. Must hold lock.
385 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
386 // See if this display is already known
387 auto it = map_data->display_id_reverse_mapping.find(handle);
388 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
389 // Unknown, so wrap
390 return WrapDisplay(handle, map_data);
391 }
392
393 // Pre/post hook point declarations
394"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600395
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700396 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600397// This file is ***GENERATED***. Do Not Edit.
398// See layer_chassis_generator.py for modifications.
399
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700400/* Copyright (c) 2015-2019 The Khronos Group Inc.
401 * Copyright (c) 2015-2019 Valve Corporation
402 * Copyright (c) 2015-2019 LunarG, Inc.
403 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600404 *
405 * Licensed under the Apache License, Version 2.0 (the "License");
406 * you may not use this file except in compliance with the License.
407 * You may obtain a copy of the License at
408 *
409 * http://www.apache.org/licenses/LICENSE-2.0
410 *
411 * Unless required by applicable law or agreed to in writing, software
412 * distributed under the License is distributed on an "AS IS" BASIS,
413 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
414 * See the License for the specific language governing permissions and
415 * limitations under the License.
416 *
417 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700418 */"""
419
420 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600421
422#include <string.h>
423#include <mutex>
424
425#define VALIDATION_ERROR_MAP_IMPL
426
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600427#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700428#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600429
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600430std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600431
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700432// Global unique object identifier. All increments must be guarded by a lock.
433uint64_t global_unique_id = 1;
434// Map uniqueID to actual object handle
435std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
436
437// TODO: This variable controls handle wrapping -- in the future it should be hooked
438// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
439#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
440bool wrap_handles = true;
441#else
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600442bool wrap_handles = false;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700443#endif
444
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600445// Set layer name -- Khronos layer name overrides any other defined names
Mark Lobodzinskiaa6fd7b2019-03-19 09:26:48 -0600446#if BUILD_KHRONOS_VALIDATION
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600447#define OBJECT_LAYER_NAME "VK_LAYER_KHRONOS_validation"
448#define OBJECT_LAYER_DESCRIPTION "khronos_validation"
449#elif BUILD_OBJECT_TRACKER
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700450#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600451#define OBJECT_LAYER_DESCRIPTION "lunarg_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700452#elif BUILD_THREAD_SAFETY
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700453#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600454#define OBJECT_LAYER_DESCRIPTION "google_thread_checker"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700455#elif BUILD_PARAMETER_VALIDATION
456#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600457#define OBJECT_LAYER_DESCRIPTION "lunarg_parameter_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700458#elif BUILD_CORE_VALIDATION
459#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600460#define OBJECT_LAYER_DESCRIPTION "lunarg_core_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700461#else
462#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600463#define OBJECT_LAYER_DESCRIPTION "lunarg_unique_objects"
464#endif
465
466// Include layer validation object definitions
467#if BUILD_OBJECT_TRACKER
468#include "object_lifetime_validation.h"
469#endif
470#if BUILD_THREAD_SAFETY
471#include "thread_safety.h"
472#endif
473#if BUILD_PARAMETER_VALIDATION
474#include "stateless_validation.h"
475#endif
476#if BUILD_CORE_VALIDATION
477#include "core_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700478#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600479
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600480namespace vulkan_layer_chassis {
481
482using std::unordered_map;
483
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600484static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700485 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600486};
487
488static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
489
490extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
491
492
493// Manually written functions
494
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700495// Check enabled instance extensions against supported instance extension whitelist
496static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
497 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
498 // Check for recognized instance extensions
499 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
500 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
501 kVUIDUndefined,
502 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
503 "results and/or produce undefined behavior.",
504 pCreateInfo->ppEnabledExtensionNames[i]);
505 }
506 }
507}
508
509// Check enabled device extensions against supported device extension whitelist
510static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
511 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
512 // Check for recognized device extensions
513 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
514 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
515 kVUIDUndefined,
516 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
517 "results and/or produce undefined behavior.",
518 pCreateInfo->ppEnabledExtensionNames[i]);
519 }
520 }
521}
522
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600523
524// Process validation features, flags and settings specified through extensions, a layer settings file, or environment variables
525
526static const std::unordered_map<std::string, VkValidationFeatureDisableEXT> VkValFeatureDisableLookup = {
527 {"VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT", VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT},
528 {"VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT", VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT},
529 {"VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT", VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT},
530 {"VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT", VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT},
531 {"VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT", VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT},
532 {"VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT", VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT},
533 {"VK_VALIDATION_FEATURE_DISABLE_ALL_EXT", VK_VALIDATION_FEATURE_DISABLE_ALL_EXT},
534};
535
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600536static const std::unordered_map<std::string, VkValidationFeatureEnableEXT> VkValFeatureEnableLookup = {
537 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT},
538 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT},
539};
540
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600541static const std::unordered_map<std::string, ValidationCheckDisables> ValidationDisableLookup = {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600542 {"VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE", VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600543 {"VALIDATION_CHECK_DISABLE_OBJECT_IN_USE", VALIDATION_CHECK_DISABLE_OBJECT_IN_USE},
544 {"VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET", VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET},
545 {"VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE", VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE},
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600546 {"VALIDATION_CHECK_DISABLE_QUERY_VALIDATION", VALIDATION_CHECK_DISABLE_QUERY_VALIDATION},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600547};
548
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600549// Set the local disable flag for the appropriate VALIDATION_CHECK_DISABLE enum
550void SetValidationDisable(CHECK_DISABLED* disable_data, const ValidationCheckDisables disable_id) {
551 switch (disable_id) {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600552 case VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE:
553 disable_data->command_buffer_state = true;
554 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600555 case VALIDATION_CHECK_DISABLE_OBJECT_IN_USE:
556 disable_data->object_in_use = true;
557 break;
558 case VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET:
559 disable_data->idle_descriptor_set = true;
560 break;
561 case VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE:
562 disable_data->push_constant_range = true;
563 break;
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600564 case VALIDATION_CHECK_DISABLE_QUERY_VALIDATION:
565 disable_data->query_validation = true;
566 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600567 default:
568 assert(true);
569 }
570}
571
572// Set the local disable flag for a single VK_VALIDATION_FEATURE_DISABLE_* flag
573void SetValidationFeatureDisable(CHECK_DISABLED* disable_data, const VkValidationFeatureDisableEXT feature_disable) {
574 switch (feature_disable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700575 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600576 disable_data->shader_validation = true;
577 break;
578 case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
579 disable_data->thread_safety = true;
580 break;
581 case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
582 disable_data->stateless_checks = true;
583 break;
584 case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
585 disable_data->object_tracking = true;
586 break;
587 case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
588 disable_data->core_checks = true;
589 break;
590 case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
591 disable_data->handle_wrapping = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700592 break;
593 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
594 // Set all disabled flags to true
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600595 disable_data->SetAll(true);
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700596 break;
597 default:
598 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700599 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600600}
601
602// Set the local enable flag for a single VK_VALIDATION_FEATURE_ENABLE_* flag
603void SetValidationFeatureEnable(CHECK_ENABLED *enable_data, const VkValidationFeatureEnableEXT feature_enable) {
604 switch (feature_enable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700605 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600606 enable_data->gpu_validation = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700607 break;
608 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600609 enable_data->gpu_validation_reserve_binding_slot = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700610 break;
611 default:
612 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700613 }
614}
615
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600616// Set the local disable flag for settings specified through the VK_EXT_validation_flags extension
617void SetValidationFlags(CHECK_DISABLED* disables, const VkValidationFlagsEXT* val_flags_struct) {
618 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
619 switch (val_flags_struct->pDisabledValidationChecks[i]) {
620 case VK_VALIDATION_CHECK_SHADERS_EXT:
621 disables->shader_validation = true;
622 break;
623 case VK_VALIDATION_CHECK_ALL_EXT:
624 // Set all disabled flags to true
625 disables->SetAll(true);
626 break;
627 default:
628 break;
629 }
630 }
631}
632
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600633// Process Validation Features flags specified through the ValidationFeature extension
634void SetValidationFeatures(CHECK_DISABLED *disable_data, CHECK_ENABLED *enable_data,
635 const VkValidationFeaturesEXT *val_features_struct) {
636 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
637 SetValidationFeatureDisable(disable_data, val_features_struct->pDisabledValidationFeatures[i]);
638 }
639 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
640 SetValidationFeatureEnable(enable_data, val_features_struct->pEnabledValidationFeatures[i]);
641 }
642}
643
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600644// Given a string representation of a list of enable enum values, call the appropriate setter function
645void SetLocalEnableSetting(std::string list_of_enables, std::string delimiter, CHECK_ENABLED* enables) {
646 size_t pos = 0;
647 std::string token;
648 while (list_of_enables.length() != 0) {
649 pos = list_of_enables.find(delimiter);
650 if (pos != std::string::npos) {
651 token = list_of_enables.substr(0, pos);
652 } else {
653 pos = list_of_enables.length() - delimiter.length();
654 token = list_of_enables;
655 }
656 if (token.find("VK_VALIDATION_FEATURE_ENABLE_") != std::string::npos) {
657 auto result = VkValFeatureEnableLookup.find(token);
658 if (result != VkValFeatureEnableLookup.end()) {
659 SetValidationFeatureEnable(enables, result->second);
660 }
661 }
662 list_of_enables.erase(0, pos + delimiter.length());
663 }
664}
665
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600666// Given a string representation of a list of disable enum values, call the appropriate setter function
667void SetLocalDisableSetting(std::string list_of_disables, std::string delimiter, CHECK_DISABLED* disables) {
668 size_t pos = 0;
669 std::string token;
670 while (list_of_disables.length() != 0) {
671 pos = list_of_disables.find(delimiter);
672 if (pos != std::string::npos) {
673 token = list_of_disables.substr(0, pos);
674 } else {
675 pos = list_of_disables.length() - delimiter.length();
676 token = list_of_disables;
677 }
678 if (token.find("VK_VALIDATION_FEATURE_DISABLE_") != std::string::npos) {
679 auto result = VkValFeatureDisableLookup.find(token);
680 if (result != VkValFeatureDisableLookup.end()) {
681 SetValidationFeatureDisable(disables, result->second);
682 }
683 }
684 if (token.find("VALIDATION_CHECK_DISABLE_") != std::string::npos) {
685 auto result = ValidationDisableLookup.find(token);
686 if (result != ValidationDisableLookup.end()) {
687 SetValidationDisable(disables, result->second);
688 }
689 }
690 list_of_disables.erase(0, pos + delimiter.length());
691 }
692}
693
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600694// Process enables and disables set though the vk_layer_settings.txt config file or through an environment variable
695void ProcessConfigAndEnvSettings(const char* layer_description, CHECK_ENABLED* enables, CHECK_DISABLED* disables) {
696 std::string enable_key = layer_description;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600697 std::string disable_key = layer_description;
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600698 enable_key.append(".enables");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600699 disable_key.append(".disables");
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600700 std::string list_of_config_enables = getLayerOption(enable_key.c_str());
701 std::string list_of_env_enables = GetLayerEnvVar("VK_LAYER_ENABLES");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600702 std::string list_of_config_disables = getLayerOption(disable_key.c_str());
703 std::string list_of_env_disables = GetLayerEnvVar("VK_LAYER_DISABLES");
704#if defined(_WIN32)
705 std::string env_delimiter = ";";
706#else
707 std::string env_delimiter = ":";
708#endif
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600709 SetLocalEnableSetting(list_of_config_enables, ",", enables);
710 SetLocalEnableSetting(list_of_env_enables, env_delimiter, enables);
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600711 SetLocalDisableSetting(list_of_config_disables, ",", disables);
712 SetLocalDisableSetting(list_of_env_disables, env_delimiter, disables);
713}
714
715
716// Non-code-generated chassis API functions
717
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600718VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600719 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700720 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700721 return nullptr;
722 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600723 const auto &item = name_to_funcptr_map.find(funcName);
724 if (item != name_to_funcptr_map.end()) {
725 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
726 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600727 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600728 if (!table.GetDeviceProcAddr) return nullptr;
729 return table.GetDeviceProcAddr(device, funcName);
730}
731
732VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600733 const auto &item = name_to_funcptr_map.find(funcName);
734 if (item != name_to_funcptr_map.end()) {
735 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
736 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600737 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
738 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600739 if (!table.GetInstanceProcAddr) return nullptr;
740 return table.GetInstanceProcAddr(instance, funcName);
741}
742
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600743VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
744 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
745}
746
747VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
748 VkLayerProperties *pProperties) {
749 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
750}
751
752VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
753 VkExtensionProperties *pProperties) {
754 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
755 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
756
757 return VK_ERROR_LAYER_NOT_PRESENT;
758}
759
760VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
761 uint32_t *pCount, VkExtensionProperties *pProperties) {
762 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600763 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600764 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
765 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600766}
767
768VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
769 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600770 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600771
772 assert(chain_info->u.pLayerInfo);
773 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
774 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
775 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
776 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700777 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
778 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
779
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600780 CHECK_ENABLED local_enables {};
781 CHECK_DISABLED local_disables {};
782 const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(pCreateInfo->pNext);
783 if (validation_features_ext) {
784 SetValidationFeatures(&local_disables, &local_enables, validation_features_ext);
785 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600786 const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
787 if (validation_flags_ext) {
788 SetValidationFlags(&local_disables, validation_flags_ext);
789 }
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600790 ProcessConfigAndEnvSettings(OBJECT_LAYER_DESCRIPTION, &local_enables, &local_disables);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600791
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600792 // Create temporary dispatch vector for pre-calls until instance is created
793 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600794 // Add VOs to dispatch vector. Order here will be the validation dispatch order!
795#if BUILD_THREAD_SAFETY
796 auto thread_checker = new ThreadSafety;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600797 if (!local_disables.thread_safety) {
798 local_object_dispatch.emplace_back(thread_checker);
799 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600800 thread_checker->container_type = LayerObjectTypeThreading;
801 thread_checker->api_version = api_version;
802#endif
803#if BUILD_PARAMETER_VALIDATION
804 auto parameter_validation = new StatelessValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600805 if (!local_disables.stateless_checks) {
806 local_object_dispatch.emplace_back(parameter_validation);
807 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600808 parameter_validation->container_type = LayerObjectTypeParameterValidation;
809 parameter_validation->api_version = api_version;
810#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700811#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600812 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600813 if (!local_disables.object_tracking) {
814 local_object_dispatch.emplace_back(object_tracker);
815 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600816 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700817 object_tracker->api_version = api_version;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600818#endif
819#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700820 auto core_checks = new CoreChecks;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600821 if (!local_disables.core_checks) {
822 local_object_dispatch.emplace_back(core_checks);
823 }
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700824 core_checks->container_type = LayerObjectTypeCoreValidation;
825 core_checks->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700826#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600827
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600828 // If handle wrapping is disabled via the ValidationFeatures extension, override build flag
829 if (local_disables.handle_wrapping) {
830 wrap_handles = false;
831 }
832
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600833 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600834 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600835 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
836 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600837 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600838 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
839 }
840
841 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600842 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600843
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600844 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600845
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600846 framework->object_dispatch = local_object_dispatch;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700847 framework->container_type = LayerObjectTypeInstance;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600848 framework->disabled = local_disables;
849 framework->enabled = local_enables;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600850
851 framework->instance = *pInstance;
852 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
853 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
854 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700855 framework->api_version = api_version;
856 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
857
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600858 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, OBJECT_LAYER_DESCRIPTION);
859
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700860#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700861 object_tracker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600862 object_tracker->instance_dispatch_table = framework->instance_dispatch_table;
863 object_tracker->enabled = framework->enabled;
864 object_tracker->disabled = framework->disabled;
865#endif
866#if BUILD_THREAD_SAFETY
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700867 thread_checker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600868 thread_checker->instance_dispatch_table = framework->instance_dispatch_table;
869 thread_checker->enabled = framework->enabled;
870 thread_checker->disabled = framework->disabled;
871#endif
872#if BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700873 parameter_validation->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600874 parameter_validation->instance_dispatch_table = framework->instance_dispatch_table;
875 parameter_validation->enabled = framework->enabled;
876 parameter_validation->disabled = framework->disabled;
877#endif
878#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700879 core_checks->report_data = framework->report_data;
880 core_checks->instance_dispatch_table = framework->instance_dispatch_table;
881 core_checks->instance = *pInstance;
882 core_checks->enabled = framework->enabled;
883 core_checks->disabled = framework->disabled;
884 core_checks->instance_state = core_checks;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700885#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600886
887 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700888 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600889 }
890
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700891 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
892
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600893 return result;
894}
895
896VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
897 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600898 auto layer_data = GetLayerDataPtr(key, layer_data_map);
899 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700900 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600901 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
902 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600903 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700904 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600905 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
906 }
907
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600908 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600909
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600910 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700911 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600912 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
913 }
914 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600915 while (layer_data->logging_messenger.size() > 0) {
916 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
917 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
918 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600919 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600920 while (layer_data->logging_callback.size() > 0) {
921 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
922 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
923 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600924 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600925
926 layer_debug_utils_destroy_instance(layer_data->report_data);
927
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700928 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
929 delete *item;
930 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600931 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600932}
933
934VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
935 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600936 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600937
938 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
939
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600940 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
941 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600942 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
943 if (fpCreateDevice == NULL) {
944 return VK_ERROR_INITIALIZATION_FAILED;
945 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600946 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
947
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700948 // Get physical device limits for device
949 VkPhysicalDeviceProperties device_properties = {};
950 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
951
952 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
953 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
954
955 DeviceExtensions device_extensions = {};
956 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
957 for (auto item : instance_interceptor->object_dispatch) {
958 item->device_extensions = device_extensions;
959 }
960
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700961 std::unique_ptr<safe_VkDeviceCreateInfo> modified_create_info(new safe_VkDeviceCreateInfo(pCreateInfo));
962
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700963 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600964 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700965 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700966 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700967 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600968 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600969 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700970 auto lock = intercept->write_lock();
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700971 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, modified_create_info);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600972 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600973
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700974 VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(modified_create_info.get()), pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600975 if (result != VK_SUCCESS) {
976 return result;
977 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600978
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600979 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700980 device_interceptor->container_type = LayerObjectTypeDevice;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700981
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700982 // Save local info in device object
983 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700984 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
985 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700986 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700987
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600988 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700989
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600990 device_interceptor->device = *pDevice;
991 device_interceptor->physical_device = gpu;
992 device_interceptor->instance = instance_interceptor->instance;
993 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600994
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600995 // Note that this defines the order in which the layer validation objects are called
996#if BUILD_THREAD_SAFETY
997 auto thread_safety = new ThreadSafety;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600998 thread_safety->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600999 if (!instance_interceptor->disabled.thread_safety) {
1000 device_interceptor->object_dispatch.emplace_back(thread_safety);
1001 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001002#endif
1003#if BUILD_PARAMETER_VALIDATION
1004 auto stateless_validation = new StatelessValidation;
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001005 stateless_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001006 if (!instance_interceptor->disabled.stateless_checks) {
1007 device_interceptor->object_dispatch.emplace_back(stateless_validation);
1008 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001009#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001010#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001011 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001012 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001013 if (!instance_interceptor->disabled.object_tracking) {
1014 device_interceptor->object_dispatch.emplace_back(object_tracker);
1015 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001016#endif
1017#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001018 auto core_checks = new CoreChecks;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001019 core_checks->container_type = LayerObjectTypeCoreValidation;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001020 core_checks->instance_state = reinterpret_cast<CoreChecks *>(
1021 core_checks->GetValidationObject(instance_interceptor->object_dispatch, LayerObjectTypeCoreValidation));
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001022 if (!instance_interceptor->disabled.core_checks) {
1023 device_interceptor->object_dispatch.emplace_back(core_checks);
1024 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001025#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001026
Mark Lobodzinski7314bf42019-03-28 08:54:53 -06001027 // Set per-intercept common data items
1028 for (auto dev_intercept : device_interceptor->object_dispatch) {
1029 dev_intercept->device = *pDevice;
1030 dev_intercept->physical_device = gpu;
1031 dev_intercept->instance = instance_interceptor->instance;
1032 dev_intercept->report_data = device_interceptor->report_data;
1033 dev_intercept->device_dispatch_table = device_interceptor->device_dispatch_table;
1034 dev_intercept->api_version = device_interceptor->api_version;
1035 dev_intercept->disabled = instance_interceptor->disabled;
1036 dev_intercept->enabled = instance_interceptor->enabled;
1037 dev_intercept->instance_dispatch_table = instance_interceptor->instance_dispatch_table;
1038 dev_intercept->instance_extensions = instance_interceptor->instance_extensions;
1039 dev_intercept->device_extensions = device_interceptor->device_extensions;
1040 }
1041
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001042 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001043 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001044 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001045 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001046
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001047 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
1048
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001049 return result;
1050}
1051
1052VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
1053 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001054 auto layer_data = GetLayerDataPtr(key, layer_data_map);
1055 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001056 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001057 intercept->PreCallValidateDestroyDevice(device, pAllocator);
1058 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001059 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001060 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001061 intercept->PreCallRecordDestroyDevice(device, pAllocator);
1062 }
1063 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001064
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001065 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001066
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001067 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001068 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001069 intercept->PostCallRecordDestroyDevice(device, pAllocator);
1070 }
1071
Mark Lobodzinskic5003372018-12-17 16:36:01 -07001072 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
1073 delete *item;
1074 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001075 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001076}
1077
1078
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001079// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001080
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001081VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
1082 VkDevice device,
1083 VkPipelineCache pipelineCache,
1084 uint32_t createInfoCount,
1085 const VkGraphicsPipelineCreateInfo* pCreateInfos,
1086 const VkAllocationCallbacks* pAllocator,
1087 VkPipeline* pPipelines) {
1088 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1089 bool skip = false;
1090
1091#ifdef BUILD_CORE_VALIDATION
1092 create_graphics_pipeline_api_state cgpl_state{};
1093#else
1094 struct create_graphics_pipeline_api_state {
1095 const VkGraphicsPipelineCreateInfo* pCreateInfos;
1096 } cgpl_state;
1097 cgpl_state.pCreateInfos = pCreateInfos;
1098#endif
1099
1100 for (auto intercept : layer_data->object_dispatch) {
1101 auto lock = intercept->write_lock();
1102 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1103 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1104 }
1105 for (auto intercept : layer_data->object_dispatch) {
1106 auto lock = intercept->write_lock();
1107 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1108 }
1109
Tony-LunarG152a88b2019-03-20 15:42:24 -06001110 VkResult result = DispatchCreateGraphicsPipelines(device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001111
1112 for (auto intercept : layer_data->object_dispatch) {
1113 auto lock = intercept->write_lock();
1114 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
1115 }
1116 return result;
1117}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001118
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001119// This API saves some core_validation pipeline state state on the stack for performance purposes
1120VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
1121 VkDevice device,
1122 VkPipelineCache pipelineCache,
1123 uint32_t createInfoCount,
1124 const VkComputePipelineCreateInfo* pCreateInfos,
1125 const VkAllocationCallbacks* pAllocator,
1126 VkPipeline* pPipelines) {
1127 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1128 bool skip = false;
1129
1130#ifndef BUILD_CORE_VALIDATION
1131 struct PIPELINE_STATE {};
1132#endif
1133
1134 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
1135
1136 for (auto intercept : layer_data->object_dispatch) {
1137 auto lock = intercept->write_lock();
1138 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
1139 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1140 }
1141 for (auto intercept : layer_data->object_dispatch) {
1142 auto lock = intercept->write_lock();
1143 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1144 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001145 VkResult result = DispatchCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001146 for (auto intercept : layer_data->object_dispatch) {
1147 auto lock = intercept->write_lock();
1148 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1149 }
1150 return result;
1151}
1152
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001153VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
1154 VkDevice device,
1155 VkPipelineCache pipelineCache,
1156 uint32_t createInfoCount,
1157 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
1158 const VkAllocationCallbacks* pAllocator,
1159 VkPipeline* pPipelines) {
1160 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1161 bool skip = false;
1162
1163#ifndef BUILD_CORE_VALIDATION
1164 struct PIPELINE_STATE {};
1165#endif
1166
1167 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
1168
1169 for (auto intercept : layer_data->object_dispatch) {
1170 auto lock = intercept->write_lock();
1171 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
1172 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1173 }
1174 for (auto intercept : layer_data->object_dispatch) {
1175 auto lock = intercept->write_lock();
1176 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1177 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001178 VkResult result = DispatchCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001179 for (auto intercept : layer_data->object_dispatch) {
1180 auto lock = intercept->write_lock();
1181 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1182 }
1183 return result;
1184}
1185
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001186// This API needs the ability to modify a down-chain parameter
1187VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
1188 VkDevice device,
1189 const VkPipelineLayoutCreateInfo* pCreateInfo,
1190 const VkAllocationCallbacks* pAllocator,
1191 VkPipelineLayout* pPipelineLayout) {
1192 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1193 bool skip = false;
1194
1195#ifndef BUILD_CORE_VALIDATION
1196 struct create_pipeline_layout_api_state {
1197 VkPipelineLayoutCreateInfo modified_create_info;
1198 };
1199#endif
1200 create_pipeline_layout_api_state cpl_state{};
1201 cpl_state.modified_create_info = *pCreateInfo;
1202
1203 for (auto intercept : layer_data->object_dispatch) {
1204 auto lock = intercept->write_lock();
1205 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1206 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1207 }
1208 for (auto intercept : layer_data->object_dispatch) {
1209 auto lock = intercept->write_lock();
1210 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1211 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001212 VkResult result = DispatchCreatePipelineLayout(device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001213 for (auto intercept : layer_data->object_dispatch) {
1214 auto lock = intercept->write_lock();
1215 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1216 }
1217 return result;
1218}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001219
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001220// This API needs some local stack data for performance reasons and also may modify a parameter
1221VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1222 VkDevice device,
1223 const VkShaderModuleCreateInfo* pCreateInfo,
1224 const VkAllocationCallbacks* pAllocator,
1225 VkShaderModule* pShaderModule) {
1226 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1227 bool skip = false;
1228
1229#ifndef BUILD_CORE_VALIDATION
1230 struct create_shader_module_api_state {
1231 VkShaderModuleCreateInfo instrumented_create_info;
1232 };
1233#endif
1234 create_shader_module_api_state csm_state{};
1235 csm_state.instrumented_create_info = *pCreateInfo;
1236
1237 for (auto intercept : layer_data->object_dispatch) {
1238 auto lock = intercept->write_lock();
1239 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1240 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1241 }
1242 for (auto intercept : layer_data->object_dispatch) {
1243 auto lock = intercept->write_lock();
1244 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1245 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001246 VkResult result = DispatchCreateShaderModule(device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001247 for (auto intercept : layer_data->object_dispatch) {
1248 auto lock = intercept->write_lock();
1249 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1250 }
1251 return result;
1252}
1253
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001254VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1255 VkDevice device,
1256 const VkDescriptorSetAllocateInfo* pAllocateInfo,
1257 VkDescriptorSet* pDescriptorSets) {
1258 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1259 bool skip = false;
1260
1261#ifdef BUILD_CORE_VALIDATION
1262 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1263#else
1264 struct ads_state {} ads_state;
1265#endif
1266
1267 for (auto intercept : layer_data->object_dispatch) {
1268 auto lock = intercept->write_lock();
1269 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1270 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1271 }
1272 for (auto intercept : layer_data->object_dispatch) {
1273 auto lock = intercept->write_lock();
1274 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1275 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001276 VkResult result = DispatchAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001277 for (auto intercept : layer_data->object_dispatch) {
1278 auto lock = intercept->write_lock();
1279 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1280 }
1281 return result;
1282}
1283
1284
1285
1286
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001287
1288// ValidationCache APIs do not dispatch
1289
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001290VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1291 VkDevice device,
1292 const VkValidationCacheCreateInfoEXT* pCreateInfo,
1293 const VkAllocationCallbacks* pAllocator,
1294 VkValidationCacheEXT* pValidationCache) {
1295 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1296 VkResult result = VK_SUCCESS;
1297
1298 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1299 if (validation_data) {
1300 auto lock = validation_data->write_lock();
1301 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1302 }
1303 return result;
1304}
1305
1306VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1307 VkDevice device,
1308 VkValidationCacheEXT validationCache,
1309 const VkAllocationCallbacks* pAllocator) {
1310 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1311
1312 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1313 if (validation_data) {
1314 auto lock = validation_data->write_lock();
1315 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1316 }
1317}
1318
1319VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1320 VkDevice device,
1321 VkValidationCacheEXT dstCache,
1322 uint32_t srcCacheCount,
1323 const VkValidationCacheEXT* pSrcCaches) {
1324 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1325 VkResult result = VK_SUCCESS;
1326
1327 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1328 if (validation_data) {
1329 auto lock = validation_data->write_lock();
1330 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1331 }
1332 return result;
1333}
1334
1335VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1336 VkDevice device,
1337 VkValidationCacheEXT validationCache,
1338 size_t* pDataSize,
1339 void* pData) {
1340 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1341 VkResult result = VK_SUCCESS;
1342
1343 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1344 if (validation_data) {
1345 auto lock = validation_data->write_lock();
1346 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1347 }
1348 return result;
1349
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001350}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001351
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001352 inline_custom_validation_class_definitions = """
1353 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1354 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1355 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1356 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001357
1358 // Allow additional parameter for CreateGraphicsPipelines
1359 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1360 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1361 };
1362 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1363 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1364 };
1365 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1366 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1367 };
1368
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001369 // Allow additional state parameter for CreateComputePipelines
1370 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1371 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1372 };
1373 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1374 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1375 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001376
1377 // Allow additional state parameter for CreateRayTracingPipelinesNV
1378 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1379 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1380 };
1381 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1382 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1383 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001384
1385 // Allow modification of a down-chain parameter for CreatePipelineLayout
1386 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1387 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1388 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001389
1390 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1391 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1392 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1393 };
1394 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1395 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1396 };
1397 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1398 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1399 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001400
1401 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1402 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1403 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1404 };
1405 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1406 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1407 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001408
1409 // Modify a parameter to CreateDevice
1410 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1411 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1412 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001413"""
1414
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001415 inline_custom_source_postamble = """
1416// loader-layer interface v0, just wrappers since there is only a layer
1417
1418VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1419 VkExtensionProperties *pProperties) {
1420 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1421}
1422
1423VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1424 VkLayerProperties *pProperties) {
1425 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1426}
1427
1428VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1429 VkLayerProperties *pProperties) {
1430 // the layer command handles VK_NULL_HANDLE just fine internally
1431 assert(physicalDevice == VK_NULL_HANDLE);
1432 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1433}
1434
1435VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1436 const char *pLayerName, uint32_t *pCount,
1437 VkExtensionProperties *pProperties) {
1438 // the layer command handles VK_NULL_HANDLE just fine internally
1439 assert(physicalDevice == VK_NULL_HANDLE);
1440 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1441}
1442
1443VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1444 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1445}
1446
1447VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1448 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1449}
1450
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001451VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1452 assert(pVersionStruct != NULL);
1453 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1454
1455 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1456 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1457 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1458 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
Mark Lobodzinski56e88122019-03-26 10:21:48 -06001459 pVersionStruct->pfnGetPhysicalDeviceProcAddr = nullptr;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001460 }
1461
1462 return VK_SUCCESS;
1463}"""
1464
1465
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001466 def __init__(self,
1467 errFile = sys.stderr,
1468 warnFile = sys.stderr,
1469 diagFile = sys.stdout):
1470 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1471 # Internal state - accumulators for different inner block text
1472 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1473 self.intercepts = []
1474 self.layer_factory = '' # String containing base layer factory class definition
1475
1476 # Check if the parameter passed in is a pointer to an array
1477 def paramIsArray(self, param):
1478 return param.attrib.get('len') is not None
1479
1480 # Check if the parameter passed in is a pointer
1481 def paramIsPointer(self, param):
1482 ispointer = False
1483 for elem in param:
1484 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
1485 ispointer = True
1486 return ispointer
1487
1488 # Check if an object is a non-dispatchable handle
1489 def isHandleTypeNonDispatchable(self, handletype):
1490 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1491 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1492 return True
1493 else:
1494 return False
1495
1496 # Check if an object is a dispatchable handle
1497 def isHandleTypeDispatchable(self, handletype):
1498 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1499 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
1500 return True
1501 else:
1502 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001503 #
1504 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001505 def beginFile(self, genOpts):
1506 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001507 # Output Copyright
1508 write(self.inline_copyright_message, file=self.outFile)
1509 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001510 self.header = False
1511 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1512 self.header = True
1513 write('#pragma once', file=self.outFile)
1514 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001515 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001516 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001517 else:
1518 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001519 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001520 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001521 #
1522 def endFile(self):
1523 # Finish C++ namespace and multiple inclusion protection
1524 self.newline()
1525 if not self.header:
1526 # Record intercepted procedures
1527 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
1528 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
1529 write('\n'.join(self.intercepts), file=self.outFile)
1530 write('};\n', file=self.outFile)
1531 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001532 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001533 if self.header:
1534 self.newline()
1535 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001536 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001537 self.layer_factory += '};\n\n'
1538 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001539 write(self.layer_factory, file=self.outFile)
1540 else:
1541 write(self.inline_custom_source_postamble, file=self.outFile)
1542 # Finish processing in superclass
1543 OutputGenerator.endFile(self)
1544
1545 def beginFeature(self, interface, emit):
1546 # Start processing in superclass
1547 OutputGenerator.beginFeature(self, interface, emit)
1548 # Get feature extra protect
1549 self.featureExtraProtect = GetFeatureProtect(interface)
1550 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1551 # feature. They're only printed in endFeature().
1552 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1553
1554 def endFeature(self):
1555 # Actually write the interface to the output file.
1556 if (self.emit):
1557 self.newline()
1558 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1559 # or move it below the 'for section...' loop.
1560 if (self.featureExtraProtect != None):
1561 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1562 for section in self.TYPE_SECTIONS:
1563 contents = self.sections[section]
1564 if contents:
1565 write('\n'.join(contents), file=self.outFile)
1566 self.newline()
1567 if (self.sections['command']):
1568 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1569 self.newline()
1570 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001571 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001572 # Finish processing in superclass
1573 OutputGenerator.endFeature(self)
1574 #
1575 # Append a definition to the specified section
1576 def appendSection(self, section, text):
1577 self.sections[section].append(text)
1578 #
1579 # Type generation
1580 def genType(self, typeinfo, name, alias):
1581 pass
1582 #
1583 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1584 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1585 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1586 # structs etc.)
1587 def genStruct(self, typeinfo, typeName):
1588 OutputGenerator.genStruct(self, typeinfo, typeName)
1589 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1590 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1591 for member in typeinfo.elem.findall('.//member'):
1592 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1593 body += ';\n'
1594 body += '} ' + typeName + ';\n'
1595 self.appendSection('struct', body)
1596 #
1597 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1598 def genGroup(self, groupinfo, groupName, alias):
1599 pass
1600 # Enumerant generation
1601 # <enum> tags may specify their values in several ways, but are usually just integers.
1602 def genEnum(self, enuminfo, name, alias):
1603 pass
1604 #
1605 # Customize Cdecl for layer factory base class
1606 def BaseClassCdecl(self, elem, name):
1607 raw = self.makeCDecls(elem)[1]
1608
1609 # Toss everything before the undecorated name
1610 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1611 prototype = prototype.replace(")", "", 1)
1612 prototype = prototype.replace(";", " {};")
1613
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001614 # Build up pre/post call virtual function declarations
1615 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1616 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1617 pre_call_record = 'virtual void PreCallRecord' + prototype
1618 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001619 resulttype = elem.find('proto/type')
1620 if resulttype.text == 'VkResult':
1621 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001622 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1623 #
1624 # Command generation
1625 def genCmd(self, cmdinfo, name, alias):
1626 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001627 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001628 ]
1629
1630 if name in ignore_functions:
1631 return
1632
1633 if self.header: # In the header declare all intercepts
1634 self.appendSection('command', '')
1635 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1636 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001637 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1638 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001639 if 'ValidationCache' not in name:
1640 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001641 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001642 self.layer_factory += '#endif\n'
1643 return
1644
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001645 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001646 if 'ValidationCache' not in name:
1647 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1648 else:
1649 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1650 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1651 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001652 return
1653 # Record that the function will be intercepted
1654 if (self.featureExtraProtect != None):
1655 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1656 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1657 if (self.featureExtraProtect != None):
1658 self.intercepts += [ '#endif' ]
1659 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1660 #
1661 decls = self.makeCDecls(cmdinfo.elem)
1662 self.appendSection('command', '')
1663 self.appendSection('command', '%s {' % decls[0][:-1])
1664 # Setup common to call wrappers. First parameter is always dispatchable
1665 dispatchable_type = cmdinfo.elem.find('param/type').text
1666 dispatchable_name = cmdinfo.elem.find('param/name').text
1667 # Default to device
1668 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001669 dispatch_table_name = 'VkLayerDispatchTable'
1670 # Set to instance as necessary
1671 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1672 device_or_instance = 'instance'
1673 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001674 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001675 api_function_name = cmdinfo.elem.attrib.get('name')
1676 params = cmdinfo.elem.findall('param/name')
1677 paramstext = ', '.join([str(param.text) for param in params])
Tony-LunarG152a88b2019-03-20 15:42:24 -06001678 API = api_function_name.replace('vk','Dispatch') + '('
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001679
1680 # Declare result variable, if any.
1681 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001682 'PFN_vkVoidFunction': 'return nullptr;',
1683 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001684 'VkDeviceAddress': 'return 0;',
1685 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1686 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001687 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001688 }
1689 resulttype = cmdinfo.elem.find('proto/type')
1690 assignresult = ''
1691 if (resulttype.text != 'void'):
1692 assignresult = resulttype.text + ' result = '
1693
1694 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001695 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001696
1697 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001698 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001699 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001700 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1701 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1702 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001703
1704 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001705 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001706 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001707 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001708 self.appendSection('command', ' }')
1709
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001710 # Insert pre-dispatch debug utils function call
1711 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001712 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001713
1714 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001715 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001716
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001717 # Insert post-dispatch debug utils function call
1718 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001719 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001720
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001721 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001722 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001723 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001724 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001725 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001726 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001727 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001728 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001729 # Return result variable, if any.
1730 if (resulttype.text != 'void'):
1731 self.appendSection('command', ' return result;')
1732 self.appendSection('command', '}')
1733 #
1734 # Override makeProtoName to drop the "vk" prefix
1735 def makeProtoName(self, name, tail):
1736 return self.genOpts.apientry + name[2:] + tail