blob: f581b981a58a91d352f41d373fc8a534055ae25f [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07003# Copyright (c) 2015-2019 Valve Corporation
4# Copyright (c) 2015-2019 LunarG, Inc.
5# Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06006#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
20# Author: Mark Lobodzinski <mark@lunarg.com>
21#
22# This script generates the dispatch portion of a factory layer which intercepts
23# all Vulkan functions. The resultant factory layer allows rapid development of
24# layers and interceptors.
25
26import os,re,sys
27from generator import *
28from common_codegen import *
29
30# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31#
32# Adds options used by LayerFactoryOutputGenerator objects during factory
33# layer generation.
34#
35# Additional members
36# prefixText - list of strings to prefix generated header with
37# (usually a copyright statement + calling convention macros).
38# protectFile - True if multiple inclusion protection should be
39# generated (based on the filename) around the entire header.
40# protectFeature - True if #ifndef..#endif protection should be
41# generated around a feature interface in the header file.
42# genFuncPointers - True if function pointer typedefs should be
43# generated
44# protectProto - If conditional protection should be generated
45# around prototype declarations, set to either '#ifdef'
46# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47# to require opt-out (#ifndef protectProtoStr). Otherwise
48# set to None.
49# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50# declarations, if protectProto is set
51# apicall - string to use for the function declaration prefix,
52# such as APICALL on Windows.
53# apientry - string to use for the calling convention macro,
54# in typedefs, such as APIENTRY.
55# apientryp - string to use for the calling convention macro
56# in function pointer typedefs, such as APIENTRYP.
57# indentFuncProto - True if prototype declarations should put each
58# parameter on a separate line
59# indentFuncPointer - True if typedefed function pointers should put each
60# parameter on a separate line
61# alignFuncParam - if nonzero and parameters are being put on a
62# separate line, align parameter names at the specified column
63class LayerChassisGeneratorOptions(GeneratorOptions):
64 def __init__(self,
Mike Schuchardt21638df2019-03-16 10:52:02 -070065 conventions = None,
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -060066 filename = None,
67 directory = '.',
68 apiname = None,
69 profile = None,
70 versions = '.*',
71 emitversions = '.*',
72 defaultExtensions = None,
73 addExtensions = None,
74 removeExtensions = None,
75 emitExtensions = None,
76 sortProcedure = regSortFeatures,
77 prefixText = "",
78 genFuncPointers = True,
79 protectFile = True,
80 protectFeature = True,
81 apicall = '',
82 apientry = '',
83 apientryp = '',
84 indentFuncProto = True,
85 indentFuncPointer = False,
86 alignFuncParam = 0,
87 helper_file_type = '',
88 expandEnumerants = True):
Mike Schuchardt21638df2019-03-16 10:52:02 -070089 GeneratorOptions.__init__(self, conventions, filename, directory, apiname, profile,
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -060090 versions, emitversions, defaultExtensions,
91 addExtensions, removeExtensions, emitExtensions, sortProcedure)
92 self.prefixText = prefixText
93 self.genFuncPointers = genFuncPointers
94 self.protectFile = protectFile
95 self.protectFeature = protectFeature
96 self.apicall = apicall
97 self.apientry = apientry
98 self.apientryp = apientryp
99 self.indentFuncProto = indentFuncProto
100 self.indentFuncPointer = indentFuncPointer
101 self.alignFuncParam = alignFuncParam
102
103# LayerChassisOutputGenerator - subclass of OutputGenerator.
104# Generates a LayerFactory layer that intercepts all API entrypoints
105# This is intended to be used as a starting point for creating custom layers
106#
107# ---- methods ----
108# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
109# OutputGenerator. Defines additional internal state.
110# ---- methods overriding base class ----
111# beginFile(genOpts)
112# endFile()
113# beginFeature(interface, emit)
114# endFeature()
115# genType(typeinfo,name)
116# genStruct(typeinfo,name)
117# genGroup(groupinfo,name)
118# genEnum(enuminfo, name)
119# genCmd(cmdinfo)
120class LayerChassisOutputGenerator(OutputGenerator):
121 """Generate specified API interfaces in a specific style, such as a C header"""
122 # This is an ordered list of sections in the header file.
123 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
124 'group', 'bitmask', 'funcpointer', 'struct']
125 ALL_SECTIONS = TYPE_SECTIONS + ['command']
126
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700127 manual_functions = [
128 # Include functions here to be interecpted w/ manually implemented function bodies
129 'vkGetDeviceProcAddr',
130 'vkGetInstanceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700131 'vkCreateDevice',
132 'vkDestroyDevice',
133 'vkCreateInstance',
134 'vkDestroyInstance',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700135 'vkEnumerateInstanceLayerProperties',
136 'vkEnumerateInstanceExtensionProperties',
137 'vkEnumerateDeviceLayerProperties',
138 'vkEnumerateDeviceExtensionProperties',
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700139 # Functions that are handled explicitly due to chassis architecture violations
140 'vkCreateGraphicsPipelines',
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700141 'vkCreateComputePipelines',
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700142 'vkCreateRayTracingPipelinesNV',
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -0700143 'vkCreatePipelineLayout',
Mark Lobodzinski1db77e82019-03-01 10:02:54 -0700144 'vkCreateShaderModule',
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -0700145 'vkAllocateDescriptorSets',
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700146 # ValidationCache functions do not get dispatched
147 'vkCreateValidationCacheEXT',
148 'vkDestroyValidationCacheEXT',
149 'vkMergeValidationCachesEXT',
150 'vkGetValidationCacheDataEXT',
Mark Lobodzinski56e88122019-03-26 10:21:48 -0600151 # We don't wanna hook this function
152 'vkGetPhysicalDeviceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700153 ]
154
155 alt_ret_codes = [
156 # Include functions here which must tolerate VK_INCOMPLETE as a return code
157 'vkEnumeratePhysicalDevices',
158 'vkEnumeratePhysicalDeviceGroupsKHR',
159 'vkGetValidationCacheDataEXT',
160 'vkGetPipelineCacheData',
161 'vkGetShaderInfoAMD',
162 'vkGetPhysicalDeviceDisplayPropertiesKHR',
163 'vkGetPhysicalDeviceDisplayProperties2KHR',
164 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
165 'vkGetDisplayPlaneSupportedDisplaysKHR',
166 'vkGetDisplayModePropertiesKHR',
167 'vkGetDisplayModeProperties2KHR',
168 'vkGetPhysicalDeviceSurfaceFormatsKHR',
169 'vkGetPhysicalDeviceSurfacePresentModesKHR',
170 'vkGetPhysicalDevicePresentRectanglesKHR',
171 'vkGetPastPresentationTimingGOOGLE',
172 'vkGetSwapchainImagesKHR',
173 'vkEnumerateInstanceLayerProperties',
174 'vkEnumerateDeviceLayerProperties',
175 'vkEnumerateInstanceExtensionProperties',
176 'vkEnumerateDeviceExtensionProperties',
177 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
178 ]
179
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700180 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700181 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
182 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700183 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
184 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700185 }
186
187 post_dispatch_debug_utils_functions = {
188 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700189 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
190 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
191 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
192 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700193 }
194
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600195 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
196 precallrecord_loop = precallvalidate_loop
197 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600198
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700199 inline_custom_header_preamble = """
200#define NOMINMAX
201#include <mutex>
202#include <cinttypes>
203#include <stdio.h>
204#include <stdlib.h>
205#include <string.h>
206#include <unordered_map>
207#include <unordered_set>
208#include <algorithm>
209#include <memory>
210
211#include "vk_loader_platform.h"
212#include "vulkan/vulkan.h"
213#include "vk_layer_config.h"
214#include "vk_layer_data.h"
215#include "vk_layer_logging.h"
216#include "vk_object_types.h"
217#include "vulkan/vk_layer.h"
218#include "vk_enum_string_helper.h"
219#include "vk_layer_extension_utils.h"
220#include "vk_layer_utils.h"
221#include "vulkan/vk_layer.h"
222#include "vk_dispatch_table_helper.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700223#include "vk_extension_helper.h"
224#include "vk_safe_struct.h"
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700225#include "vk_typemap_helper.h"
226
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700227
228extern uint64_t global_unique_id;
229extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
230"""
231
232 inline_custom_header_class_definition = """
233
234// Layer object type identifiers
235enum LayerObjectTypeId {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700236 LayerObjectTypeInstance, // Container for an instance dispatch object
237 LayerObjectTypeDevice, // Container for a device dispatch object
238 LayerObjectTypeThreading, // Instance or device threading layer object
239 LayerObjectTypeParameterValidation, // Instance or device parameter validation layer object
240 LayerObjectTypeObjectTracker, // Instance or device object tracker layer object
241 LayerObjectTypeCoreValidation, // Instance or device core validation layer object
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700242};
243
244struct TEMPLATE_STATE {
245 VkDescriptorUpdateTemplateKHR desc_update_template;
246 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
247
248 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
249 : desc_update_template(update_template), create_info(*pCreateInfo) {}
250};
251
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700252class LAYER_PHYS_DEV_PROPERTIES {
253public:
254 VkPhysicalDeviceProperties properties;
255 std::vector<VkQueueFamilyProperties> queue_family_properties;
256};
257
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600258typedef enum ValidationCheckDisables {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600259 VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600260 VALIDATION_CHECK_DISABLE_OBJECT_IN_USE,
261 VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET,
262 VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE,
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600263 VALIDATION_CHECK_DISABLE_QUERY_VALIDATION,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600264} ValidationCheckDisables;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600265
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600266
267// CHECK_DISABLED struct is a container for bools that can block validation checks from being performed.
268// These bools are all "false" by default meaning that all checks are enabled. Enum values can be specified
269// via the vk_layer_setting.txt config file or at CreateInstance time via the VK_EXT_validation_features extension
270// that can selectively disable checks.
271struct CHECK_DISABLED {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600272 bool command_buffer_state; // Skip command buffer state validation
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600273 bool object_in_use; // Skip all object in_use checking
274 bool idle_descriptor_set; // Skip check to verify that descriptor set is not in-use
275 bool push_constant_range; // Skip push constant range checks
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600276 bool query_validation; // Disable all core validation query-related checks
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600277 bool object_tracking; // Disable object lifetime validation
278 bool core_checks; // Disable core validation checks
279 bool thread_safety; // Disable thread safety validation
280 bool stateless_checks; // Disable stateless validation checks
281 bool handle_wrapping; // Disable unique handles/handle wrapping
282 bool shader_validation; // Skip validation for shaders
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700283
284 void SetAll(bool value) { std::fill(&command_buffer_state, &shader_validation + 1, value); }
285};
286
287struct CHECK_ENABLED {
288 bool gpu_validation;
289 bool gpu_validation_reserve_binding_slot;
290
291 void SetAll(bool value) { std::fill(&gpu_validation, &gpu_validation_reserve_binding_slot + 1, value); }
292};
293
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700294// Layer chassis validation object base class definition
295class ValidationObject {
296 public:
297 uint32_t api_version;
298 debug_report_data* report_data = nullptr;
299 std::vector<VkDebugReportCallbackEXT> logging_callback;
300 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
301
302 VkLayerInstanceDispatchTable instance_dispatch_table;
303 VkLayerDispatchTable device_dispatch_table;
304
305 InstanceExtensions instance_extensions;
306 DeviceExtensions device_extensions = {};
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700307 CHECK_DISABLED disabled = {};
308 CHECK_ENABLED enabled = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700309
310 VkInstance instance = VK_NULL_HANDLE;
311 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
312 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700313 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700314
315 std::vector<ValidationObject*> object_dispatch;
316 LayerObjectTypeId container_type;
317
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700318 std::string layer_name = "CHASSIS";
319
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700320 // Constructor
321 ValidationObject(){};
322 // Destructor
323 virtual ~ValidationObject() {};
324
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700325 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700326 virtual std::unique_lock<std::mutex> write_lock() {
327 return std::unique_lock<std::mutex>(validation_object_mutex);
328 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700329
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700330 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
331 for (auto validation_object : object_dispatch) {
332 if (validation_object->container_type == object_type) {
333 return validation_object;
334 }
335 }
336 return nullptr;
337 };
338
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700339 // Handle Wrapping Data
340 // Reverse map display handles
341 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
342 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700343 struct SubpassesUsageStates {
344 std::unordered_set<uint32_t> subpasses_using_color_attachment;
345 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
346 };
347 // Uses unwrapped handles
348 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
349 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
350 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
351 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700352 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
353 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700354
355
356 // Unwrap a handle. Must hold lock.
357 template <typename HandleType>
358 HandleType Unwrap(HandleType wrappedHandle) {
359 // TODO: don't use operator[] here.
360 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
361 }
362
363 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
364 template <typename HandleType>
365 HandleType WrapNew(HandleType newlyCreatedHandle) {
366 auto unique_id = global_unique_id++;
367 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
368 return (HandleType)unique_id;
369 }
370
371 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
372 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
373 auto unique_id = global_unique_id++;
374 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
375 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
376 return (VkDisplayKHR)unique_id;
377 }
378
379 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
380 // creating another. Must hold lock.
381 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
382 // See if this display is already known
383 auto it = map_data->display_id_reverse_mapping.find(handle);
384 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
385 // Unknown, so wrap
386 return WrapDisplay(handle, map_data);
387 }
388
389 // Pre/post hook point declarations
390"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600391
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700392 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600393// This file is ***GENERATED***. Do Not Edit.
394// See layer_chassis_generator.py for modifications.
395
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700396/* Copyright (c) 2015-2019 The Khronos Group Inc.
397 * Copyright (c) 2015-2019 Valve Corporation
398 * Copyright (c) 2015-2019 LunarG, Inc.
399 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600400 *
401 * Licensed under the Apache License, Version 2.0 (the "License");
402 * you may not use this file except in compliance with the License.
403 * You may obtain a copy of the License at
404 *
405 * http://www.apache.org/licenses/LICENSE-2.0
406 *
407 * Unless required by applicable law or agreed to in writing, software
408 * distributed under the License is distributed on an "AS IS" BASIS,
409 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
410 * See the License for the specific language governing permissions and
411 * limitations under the License.
412 *
413 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700414 */"""
415
416 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600417
418#include <string.h>
419#include <mutex>
420
421#define VALIDATION_ERROR_MAP_IMPL
422
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600423#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700424#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600425
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600426std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600427
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700428// Global unique object identifier. All increments must be guarded by a lock.
429uint64_t global_unique_id = 1;
430// Map uniqueID to actual object handle
431std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
432
433// TODO: This variable controls handle wrapping -- in the future it should be hooked
434// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
435#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
436bool wrap_handles = true;
437#else
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600438bool wrap_handles = false;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700439#endif
440
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600441// Set layer name -- Khronos layer name overrides any other defined names
Mark Lobodzinskiaa6fd7b2019-03-19 09:26:48 -0600442#if BUILD_KHRONOS_VALIDATION
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600443#define OBJECT_LAYER_NAME "VK_LAYER_KHRONOS_validation"
444#define OBJECT_LAYER_DESCRIPTION "khronos_validation"
445#elif BUILD_OBJECT_TRACKER
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700446#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600447#define OBJECT_LAYER_DESCRIPTION "lunarg_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700448#elif BUILD_THREAD_SAFETY
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700449#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600450#define OBJECT_LAYER_DESCRIPTION "google_thread_checker"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700451#elif BUILD_PARAMETER_VALIDATION
452#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600453#define OBJECT_LAYER_DESCRIPTION "lunarg_parameter_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700454#elif BUILD_CORE_VALIDATION
455#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600456#define OBJECT_LAYER_DESCRIPTION "lunarg_core_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700457#else
458#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600459#define OBJECT_LAYER_DESCRIPTION "lunarg_unique_objects"
460#endif
461
462// Include layer validation object definitions
463#if BUILD_OBJECT_TRACKER
464#include "object_lifetime_validation.h"
465#endif
466#if BUILD_THREAD_SAFETY
467#include "thread_safety.h"
468#endif
469#if BUILD_PARAMETER_VALIDATION
470#include "stateless_validation.h"
471#endif
472#if BUILD_CORE_VALIDATION
473#include "core_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700474#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600475
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600476namespace vulkan_layer_chassis {
477
478using std::unordered_map;
479
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600480static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700481 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600482};
483
John Zulauf358462e2019-04-10 11:10:32 -0600484static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION},
485 {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION}};
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600486
487extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
488
489
490// Manually written functions
491
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700492// Check enabled instance extensions against supported instance extension whitelist
493static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
494 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
495 // Check for recognized instance extensions
496 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
497 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
498 kVUIDUndefined,
499 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
500 "results and/or produce undefined behavior.",
501 pCreateInfo->ppEnabledExtensionNames[i]);
502 }
503 }
504}
505
506// Check enabled device extensions against supported device extension whitelist
507static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
508 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
509 // Check for recognized device extensions
510 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
511 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
512 kVUIDUndefined,
513 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
514 "results and/or produce undefined behavior.",
515 pCreateInfo->ppEnabledExtensionNames[i]);
516 }
517 }
518}
519
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600520
521// Process validation features, flags and settings specified through extensions, a layer settings file, or environment variables
522
523static const std::unordered_map<std::string, VkValidationFeatureDisableEXT> VkValFeatureDisableLookup = {
524 {"VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT", VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT},
525 {"VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT", VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT},
526 {"VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT", VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT},
527 {"VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT", VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT},
528 {"VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT", VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT},
529 {"VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT", VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT},
530 {"VK_VALIDATION_FEATURE_DISABLE_ALL_EXT", VK_VALIDATION_FEATURE_DISABLE_ALL_EXT},
531};
532
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600533static const std::unordered_map<std::string, VkValidationFeatureEnableEXT> VkValFeatureEnableLookup = {
534 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT},
535 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT},
536};
537
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600538static const std::unordered_map<std::string, ValidationCheckDisables> ValidationDisableLookup = {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600539 {"VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE", VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600540 {"VALIDATION_CHECK_DISABLE_OBJECT_IN_USE", VALIDATION_CHECK_DISABLE_OBJECT_IN_USE},
541 {"VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET", VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET},
542 {"VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE", VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE},
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600543 {"VALIDATION_CHECK_DISABLE_QUERY_VALIDATION", VALIDATION_CHECK_DISABLE_QUERY_VALIDATION},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600544};
545
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600546// Set the local disable flag for the appropriate VALIDATION_CHECK_DISABLE enum
547void SetValidationDisable(CHECK_DISABLED* disable_data, const ValidationCheckDisables disable_id) {
548 switch (disable_id) {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600549 case VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE:
550 disable_data->command_buffer_state = true;
551 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600552 case VALIDATION_CHECK_DISABLE_OBJECT_IN_USE:
553 disable_data->object_in_use = true;
554 break;
555 case VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET:
556 disable_data->idle_descriptor_set = true;
557 break;
558 case VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE:
559 disable_data->push_constant_range = true;
560 break;
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600561 case VALIDATION_CHECK_DISABLE_QUERY_VALIDATION:
562 disable_data->query_validation = true;
563 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600564 default:
565 assert(true);
566 }
567}
568
569// Set the local disable flag for a single VK_VALIDATION_FEATURE_DISABLE_* flag
570void SetValidationFeatureDisable(CHECK_DISABLED* disable_data, const VkValidationFeatureDisableEXT feature_disable) {
571 switch (feature_disable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700572 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600573 disable_data->shader_validation = true;
574 break;
575 case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
576 disable_data->thread_safety = true;
577 break;
578 case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
579 disable_data->stateless_checks = true;
580 break;
581 case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
582 disable_data->object_tracking = true;
583 break;
584 case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
585 disable_data->core_checks = true;
586 break;
587 case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
588 disable_data->handle_wrapping = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700589 break;
590 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
591 // Set all disabled flags to true
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600592 disable_data->SetAll(true);
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700593 break;
594 default:
595 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700596 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600597}
598
599// Set the local enable flag for a single VK_VALIDATION_FEATURE_ENABLE_* flag
600void SetValidationFeatureEnable(CHECK_ENABLED *enable_data, const VkValidationFeatureEnableEXT feature_enable) {
601 switch (feature_enable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700602 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600603 enable_data->gpu_validation = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700604 break;
605 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600606 enable_data->gpu_validation_reserve_binding_slot = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700607 break;
608 default:
609 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700610 }
611}
612
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600613// Set the local disable flag for settings specified through the VK_EXT_validation_flags extension
614void SetValidationFlags(CHECK_DISABLED* disables, const VkValidationFlagsEXT* val_flags_struct) {
615 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
616 switch (val_flags_struct->pDisabledValidationChecks[i]) {
617 case VK_VALIDATION_CHECK_SHADERS_EXT:
618 disables->shader_validation = true;
619 break;
620 case VK_VALIDATION_CHECK_ALL_EXT:
621 // Set all disabled flags to true
622 disables->SetAll(true);
623 break;
624 default:
625 break;
626 }
627 }
628}
629
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600630// Process Validation Features flags specified through the ValidationFeature extension
631void SetValidationFeatures(CHECK_DISABLED *disable_data, CHECK_ENABLED *enable_data,
632 const VkValidationFeaturesEXT *val_features_struct) {
633 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
634 SetValidationFeatureDisable(disable_data, val_features_struct->pDisabledValidationFeatures[i]);
635 }
636 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
637 SetValidationFeatureEnable(enable_data, val_features_struct->pEnabledValidationFeatures[i]);
638 }
639}
640
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600641// Given a string representation of a list of enable enum values, call the appropriate setter function
642void SetLocalEnableSetting(std::string list_of_enables, std::string delimiter, CHECK_ENABLED* enables) {
643 size_t pos = 0;
644 std::string token;
645 while (list_of_enables.length() != 0) {
646 pos = list_of_enables.find(delimiter);
647 if (pos != std::string::npos) {
648 token = list_of_enables.substr(0, pos);
649 } else {
650 pos = list_of_enables.length() - delimiter.length();
651 token = list_of_enables;
652 }
653 if (token.find("VK_VALIDATION_FEATURE_ENABLE_") != std::string::npos) {
654 auto result = VkValFeatureEnableLookup.find(token);
655 if (result != VkValFeatureEnableLookup.end()) {
656 SetValidationFeatureEnable(enables, result->second);
657 }
658 }
659 list_of_enables.erase(0, pos + delimiter.length());
660 }
661}
662
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600663// Given a string representation of a list of disable enum values, call the appropriate setter function
664void SetLocalDisableSetting(std::string list_of_disables, std::string delimiter, CHECK_DISABLED* disables) {
665 size_t pos = 0;
666 std::string token;
667 while (list_of_disables.length() != 0) {
668 pos = list_of_disables.find(delimiter);
669 if (pos != std::string::npos) {
670 token = list_of_disables.substr(0, pos);
671 } else {
672 pos = list_of_disables.length() - delimiter.length();
673 token = list_of_disables;
674 }
675 if (token.find("VK_VALIDATION_FEATURE_DISABLE_") != std::string::npos) {
676 auto result = VkValFeatureDisableLookup.find(token);
677 if (result != VkValFeatureDisableLookup.end()) {
678 SetValidationFeatureDisable(disables, result->second);
679 }
680 }
681 if (token.find("VALIDATION_CHECK_DISABLE_") != std::string::npos) {
682 auto result = ValidationDisableLookup.find(token);
683 if (result != ValidationDisableLookup.end()) {
684 SetValidationDisable(disables, result->second);
685 }
686 }
687 list_of_disables.erase(0, pos + delimiter.length());
688 }
689}
690
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600691// Process enables and disables set though the vk_layer_settings.txt config file or through an environment variable
692void ProcessConfigAndEnvSettings(const char* layer_description, CHECK_ENABLED* enables, CHECK_DISABLED* disables) {
693 std::string enable_key = layer_description;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600694 std::string disable_key = layer_description;
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600695 enable_key.append(".enables");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600696 disable_key.append(".disables");
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600697 std::string list_of_config_enables = getLayerOption(enable_key.c_str());
698 std::string list_of_env_enables = GetLayerEnvVar("VK_LAYER_ENABLES");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600699 std::string list_of_config_disables = getLayerOption(disable_key.c_str());
700 std::string list_of_env_disables = GetLayerEnvVar("VK_LAYER_DISABLES");
701#if defined(_WIN32)
702 std::string env_delimiter = ";";
703#else
704 std::string env_delimiter = ":";
705#endif
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600706 SetLocalEnableSetting(list_of_config_enables, ",", enables);
707 SetLocalEnableSetting(list_of_env_enables, env_delimiter, enables);
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600708 SetLocalDisableSetting(list_of_config_disables, ",", disables);
709 SetLocalDisableSetting(list_of_env_disables, env_delimiter, disables);
710}
711
712
713// Non-code-generated chassis API functions
714
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600715VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600716 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700717 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700718 return nullptr;
719 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600720 const auto &item = name_to_funcptr_map.find(funcName);
721 if (item != name_to_funcptr_map.end()) {
722 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
723 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600724 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600725 if (!table.GetDeviceProcAddr) return nullptr;
726 return table.GetDeviceProcAddr(device, funcName);
727}
728
729VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600730 const auto &item = name_to_funcptr_map.find(funcName);
731 if (item != name_to_funcptr_map.end()) {
732 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
733 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600734 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
735 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600736 if (!table.GetInstanceProcAddr) return nullptr;
737 return table.GetInstanceProcAddr(instance, funcName);
738}
739
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600740VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
741 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
742}
743
744VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
745 VkLayerProperties *pProperties) {
746 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
747}
748
749VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
750 VkExtensionProperties *pProperties) {
751 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
John Zulauf358462e2019-04-10 11:10:32 -0600752 return util_GetExtensionProperties(ARRAY_SIZE(instance_extensions), instance_extensions, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600753
754 return VK_ERROR_LAYER_NOT_PRESENT;
755}
756
757VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
758 uint32_t *pCount, VkExtensionProperties *pProperties) {
759 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600760 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600761 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
762 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600763}
764
765VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
766 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600767 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600768
769 assert(chain_info->u.pLayerInfo);
770 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
771 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
772 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
773 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700774 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
775 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
776
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600777 CHECK_ENABLED local_enables {};
778 CHECK_DISABLED local_disables {};
779 const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(pCreateInfo->pNext);
780 if (validation_features_ext) {
781 SetValidationFeatures(&local_disables, &local_enables, validation_features_ext);
782 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600783 const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
784 if (validation_flags_ext) {
785 SetValidationFlags(&local_disables, validation_flags_ext);
786 }
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600787 ProcessConfigAndEnvSettings(OBJECT_LAYER_DESCRIPTION, &local_enables, &local_disables);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600788
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600789 // Create temporary dispatch vector for pre-calls until instance is created
790 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600791 // Add VOs to dispatch vector. Order here will be the validation dispatch order!
792#if BUILD_THREAD_SAFETY
793 auto thread_checker = new ThreadSafety;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600794 if (!local_disables.thread_safety) {
795 local_object_dispatch.emplace_back(thread_checker);
796 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600797 thread_checker->container_type = LayerObjectTypeThreading;
798 thread_checker->api_version = api_version;
799#endif
800#if BUILD_PARAMETER_VALIDATION
801 auto parameter_validation = new StatelessValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600802 if (!local_disables.stateless_checks) {
803 local_object_dispatch.emplace_back(parameter_validation);
804 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600805 parameter_validation->container_type = LayerObjectTypeParameterValidation;
806 parameter_validation->api_version = api_version;
807#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700808#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600809 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600810 if (!local_disables.object_tracking) {
811 local_object_dispatch.emplace_back(object_tracker);
812 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600813 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700814 object_tracker->api_version = api_version;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600815#endif
816#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700817 auto core_checks = new CoreChecks;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600818 if (!local_disables.core_checks) {
819 local_object_dispatch.emplace_back(core_checks);
820 }
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700821 core_checks->container_type = LayerObjectTypeCoreValidation;
822 core_checks->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700823#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600824
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600825 // If handle wrapping is disabled via the ValidationFeatures extension, override build flag
826 if (local_disables.handle_wrapping) {
827 wrap_handles = false;
828 }
829
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600830 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600831 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600832 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
833 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600834 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600835 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
836 }
837
838 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600839 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600840
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600841 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600842
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600843 framework->object_dispatch = local_object_dispatch;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700844 framework->container_type = LayerObjectTypeInstance;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600845 framework->disabled = local_disables;
846 framework->enabled = local_enables;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600847
848 framework->instance = *pInstance;
849 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
850 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
851 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700852 framework->api_version = api_version;
853 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
854
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600855 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, OBJECT_LAYER_DESCRIPTION);
856
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700857#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700858 object_tracker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600859 object_tracker->instance_dispatch_table = framework->instance_dispatch_table;
860 object_tracker->enabled = framework->enabled;
861 object_tracker->disabled = framework->disabled;
862#endif
863#if BUILD_THREAD_SAFETY
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700864 thread_checker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600865 thread_checker->instance_dispatch_table = framework->instance_dispatch_table;
866 thread_checker->enabled = framework->enabled;
867 thread_checker->disabled = framework->disabled;
868#endif
869#if BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700870 parameter_validation->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600871 parameter_validation->instance_dispatch_table = framework->instance_dispatch_table;
872 parameter_validation->enabled = framework->enabled;
873 parameter_validation->disabled = framework->disabled;
874#endif
875#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700876 core_checks->report_data = framework->report_data;
877 core_checks->instance_dispatch_table = framework->instance_dispatch_table;
878 core_checks->instance = *pInstance;
879 core_checks->enabled = framework->enabled;
880 core_checks->disabled = framework->disabled;
881 core_checks->instance_state = core_checks;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700882#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600883
884 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700885 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600886 }
887
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700888 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
889
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600890 return result;
891}
892
893VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
894 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600895 auto layer_data = GetLayerDataPtr(key, layer_data_map);
896 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700897 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600898 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
899 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600900 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700901 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600902 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
903 }
904
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600905 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600906
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600907 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700908 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600909 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
910 }
911 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600912 while (layer_data->logging_messenger.size() > 0) {
913 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
914 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
915 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600916 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600917 while (layer_data->logging_callback.size() > 0) {
918 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
919 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
920 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600921 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600922
923 layer_debug_utils_destroy_instance(layer_data->report_data);
924
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700925 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
926 delete *item;
927 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600928 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600929}
930
931VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
932 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600933 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600934
935 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
936
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600937 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
938 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600939 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
940 if (fpCreateDevice == NULL) {
941 return VK_ERROR_INITIALIZATION_FAILED;
942 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600943 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
944
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700945 // Get physical device limits for device
946 VkPhysicalDeviceProperties device_properties = {};
947 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
948
949 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
950 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
951
952 DeviceExtensions device_extensions = {};
953 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
954 for (auto item : instance_interceptor->object_dispatch) {
955 item->device_extensions = device_extensions;
956 }
957
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700958 std::unique_ptr<safe_VkDeviceCreateInfo> modified_create_info(new safe_VkDeviceCreateInfo(pCreateInfo));
959
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700960 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600961 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700962 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700963 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700964 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600965 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600966 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700967 auto lock = intercept->write_lock();
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700968 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, modified_create_info);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600969 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600970
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700971 VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(modified_create_info.get()), pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600972 if (result != VK_SUCCESS) {
973 return result;
974 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600975
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600976 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700977 device_interceptor->container_type = LayerObjectTypeDevice;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700978
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700979 // Save local info in device object
980 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700981 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
982 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700983 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700984
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600985 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700986
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600987 device_interceptor->device = *pDevice;
988 device_interceptor->physical_device = gpu;
989 device_interceptor->instance = instance_interceptor->instance;
990 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600991
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600992 // Note that this defines the order in which the layer validation objects are called
993#if BUILD_THREAD_SAFETY
994 auto thread_safety = new ThreadSafety;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600995 thread_safety->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600996 if (!instance_interceptor->disabled.thread_safety) {
997 device_interceptor->object_dispatch.emplace_back(thread_safety);
998 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600999#endif
1000#if BUILD_PARAMETER_VALIDATION
1001 auto stateless_validation = new StatelessValidation;
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001002 stateless_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001003 if (!instance_interceptor->disabled.stateless_checks) {
1004 device_interceptor->object_dispatch.emplace_back(stateless_validation);
1005 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001006#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001007#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001008 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001009 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001010 if (!instance_interceptor->disabled.object_tracking) {
1011 device_interceptor->object_dispatch.emplace_back(object_tracker);
1012 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001013#endif
1014#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001015 auto core_checks = new CoreChecks;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001016 core_checks->container_type = LayerObjectTypeCoreValidation;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001017 core_checks->instance_state = reinterpret_cast<CoreChecks *>(
1018 core_checks->GetValidationObject(instance_interceptor->object_dispatch, LayerObjectTypeCoreValidation));
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001019 if (!instance_interceptor->disabled.core_checks) {
1020 device_interceptor->object_dispatch.emplace_back(core_checks);
1021 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001022#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001023
Mark Lobodzinski7314bf42019-03-28 08:54:53 -06001024 // Set per-intercept common data items
1025 for (auto dev_intercept : device_interceptor->object_dispatch) {
1026 dev_intercept->device = *pDevice;
1027 dev_intercept->physical_device = gpu;
1028 dev_intercept->instance = instance_interceptor->instance;
1029 dev_intercept->report_data = device_interceptor->report_data;
1030 dev_intercept->device_dispatch_table = device_interceptor->device_dispatch_table;
1031 dev_intercept->api_version = device_interceptor->api_version;
1032 dev_intercept->disabled = instance_interceptor->disabled;
1033 dev_intercept->enabled = instance_interceptor->enabled;
1034 dev_intercept->instance_dispatch_table = instance_interceptor->instance_dispatch_table;
1035 dev_intercept->instance_extensions = instance_interceptor->instance_extensions;
1036 dev_intercept->device_extensions = device_interceptor->device_extensions;
1037 }
1038
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001039 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001040 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001041 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001042 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001043
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001044 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
1045
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001046 return result;
1047}
1048
1049VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
1050 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001051 auto layer_data = GetLayerDataPtr(key, layer_data_map);
1052 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001053 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001054 intercept->PreCallValidateDestroyDevice(device, pAllocator);
1055 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001056 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001057 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001058 intercept->PreCallRecordDestroyDevice(device, pAllocator);
1059 }
1060 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001061
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001062 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001063
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001064 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001065 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001066 intercept->PostCallRecordDestroyDevice(device, pAllocator);
1067 }
1068
Mark Lobodzinskic5003372018-12-17 16:36:01 -07001069 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
1070 delete *item;
1071 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001072 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001073}
1074
1075
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001076// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001077
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001078VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
1079 VkDevice device,
1080 VkPipelineCache pipelineCache,
1081 uint32_t createInfoCount,
1082 const VkGraphicsPipelineCreateInfo* pCreateInfos,
1083 const VkAllocationCallbacks* pAllocator,
1084 VkPipeline* pPipelines) {
1085 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1086 bool skip = false;
1087
1088#ifdef BUILD_CORE_VALIDATION
1089 create_graphics_pipeline_api_state cgpl_state{};
1090#else
1091 struct create_graphics_pipeline_api_state {
1092 const VkGraphicsPipelineCreateInfo* pCreateInfos;
1093 } cgpl_state;
1094 cgpl_state.pCreateInfos = pCreateInfos;
1095#endif
1096
1097 for (auto intercept : layer_data->object_dispatch) {
1098 auto lock = intercept->write_lock();
1099 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1100 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1101 }
1102 for (auto intercept : layer_data->object_dispatch) {
1103 auto lock = intercept->write_lock();
1104 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1105 }
1106
Tony-LunarG152a88b2019-03-20 15:42:24 -06001107 VkResult result = DispatchCreateGraphicsPipelines(device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001108
1109 for (auto intercept : layer_data->object_dispatch) {
1110 auto lock = intercept->write_lock();
1111 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
1112 }
1113 return result;
1114}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001115
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001116// This API saves some core_validation pipeline state state on the stack for performance purposes
1117VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
1118 VkDevice device,
1119 VkPipelineCache pipelineCache,
1120 uint32_t createInfoCount,
1121 const VkComputePipelineCreateInfo* pCreateInfos,
1122 const VkAllocationCallbacks* pAllocator,
1123 VkPipeline* pPipelines) {
1124 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1125 bool skip = false;
1126
1127#ifndef BUILD_CORE_VALIDATION
1128 struct PIPELINE_STATE {};
1129#endif
1130
1131 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
1132
1133 for (auto intercept : layer_data->object_dispatch) {
1134 auto lock = intercept->write_lock();
1135 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
1136 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1137 }
1138 for (auto intercept : layer_data->object_dispatch) {
1139 auto lock = intercept->write_lock();
1140 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1141 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001142 VkResult result = DispatchCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001143 for (auto intercept : layer_data->object_dispatch) {
1144 auto lock = intercept->write_lock();
1145 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1146 }
1147 return result;
1148}
1149
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001150VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
1151 VkDevice device,
1152 VkPipelineCache pipelineCache,
1153 uint32_t createInfoCount,
1154 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
1155 const VkAllocationCallbacks* pAllocator,
1156 VkPipeline* pPipelines) {
1157 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1158 bool skip = false;
1159
1160#ifndef BUILD_CORE_VALIDATION
1161 struct PIPELINE_STATE {};
1162#endif
1163
1164 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
1165
1166 for (auto intercept : layer_data->object_dispatch) {
1167 auto lock = intercept->write_lock();
1168 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
1169 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1170 }
1171 for (auto intercept : layer_data->object_dispatch) {
1172 auto lock = intercept->write_lock();
1173 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1174 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001175 VkResult result = DispatchCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001176 for (auto intercept : layer_data->object_dispatch) {
1177 auto lock = intercept->write_lock();
1178 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1179 }
1180 return result;
1181}
1182
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001183// This API needs the ability to modify a down-chain parameter
1184VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
1185 VkDevice device,
1186 const VkPipelineLayoutCreateInfo* pCreateInfo,
1187 const VkAllocationCallbacks* pAllocator,
1188 VkPipelineLayout* pPipelineLayout) {
1189 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1190 bool skip = false;
1191
1192#ifndef BUILD_CORE_VALIDATION
1193 struct create_pipeline_layout_api_state {
1194 VkPipelineLayoutCreateInfo modified_create_info;
1195 };
1196#endif
1197 create_pipeline_layout_api_state cpl_state{};
1198 cpl_state.modified_create_info = *pCreateInfo;
1199
1200 for (auto intercept : layer_data->object_dispatch) {
1201 auto lock = intercept->write_lock();
1202 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1203 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1204 }
1205 for (auto intercept : layer_data->object_dispatch) {
1206 auto lock = intercept->write_lock();
1207 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1208 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001209 VkResult result = DispatchCreatePipelineLayout(device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001210 for (auto intercept : layer_data->object_dispatch) {
1211 auto lock = intercept->write_lock();
1212 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1213 }
1214 return result;
1215}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001216
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001217// This API needs some local stack data for performance reasons and also may modify a parameter
1218VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1219 VkDevice device,
1220 const VkShaderModuleCreateInfo* pCreateInfo,
1221 const VkAllocationCallbacks* pAllocator,
1222 VkShaderModule* pShaderModule) {
1223 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1224 bool skip = false;
1225
1226#ifndef BUILD_CORE_VALIDATION
1227 struct create_shader_module_api_state {
1228 VkShaderModuleCreateInfo instrumented_create_info;
1229 };
1230#endif
1231 create_shader_module_api_state csm_state{};
1232 csm_state.instrumented_create_info = *pCreateInfo;
1233
1234 for (auto intercept : layer_data->object_dispatch) {
1235 auto lock = intercept->write_lock();
1236 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1237 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1238 }
1239 for (auto intercept : layer_data->object_dispatch) {
1240 auto lock = intercept->write_lock();
1241 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1242 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001243 VkResult result = DispatchCreateShaderModule(device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001244 for (auto intercept : layer_data->object_dispatch) {
1245 auto lock = intercept->write_lock();
1246 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1247 }
1248 return result;
1249}
1250
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001251VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1252 VkDevice device,
1253 const VkDescriptorSetAllocateInfo* pAllocateInfo,
1254 VkDescriptorSet* pDescriptorSets) {
1255 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1256 bool skip = false;
1257
1258#ifdef BUILD_CORE_VALIDATION
1259 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1260#else
1261 struct ads_state {} ads_state;
1262#endif
1263
1264 for (auto intercept : layer_data->object_dispatch) {
1265 auto lock = intercept->write_lock();
1266 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1267 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1268 }
1269 for (auto intercept : layer_data->object_dispatch) {
1270 auto lock = intercept->write_lock();
1271 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1272 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001273 VkResult result = DispatchAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001274 for (auto intercept : layer_data->object_dispatch) {
1275 auto lock = intercept->write_lock();
1276 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1277 }
1278 return result;
1279}
1280
1281
1282
1283
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001284
1285// ValidationCache APIs do not dispatch
1286
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001287VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1288 VkDevice device,
1289 const VkValidationCacheCreateInfoEXT* pCreateInfo,
1290 const VkAllocationCallbacks* pAllocator,
1291 VkValidationCacheEXT* pValidationCache) {
1292 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1293 VkResult result = VK_SUCCESS;
1294
1295 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1296 if (validation_data) {
1297 auto lock = validation_data->write_lock();
1298 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1299 }
1300 return result;
1301}
1302
1303VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1304 VkDevice device,
1305 VkValidationCacheEXT validationCache,
1306 const VkAllocationCallbacks* pAllocator) {
1307 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1308
1309 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1310 if (validation_data) {
1311 auto lock = validation_data->write_lock();
1312 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1313 }
1314}
1315
1316VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1317 VkDevice device,
1318 VkValidationCacheEXT dstCache,
1319 uint32_t srcCacheCount,
1320 const VkValidationCacheEXT* pSrcCaches) {
1321 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1322 VkResult result = VK_SUCCESS;
1323
1324 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1325 if (validation_data) {
1326 auto lock = validation_data->write_lock();
1327 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1328 }
1329 return result;
1330}
1331
1332VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1333 VkDevice device,
1334 VkValidationCacheEXT validationCache,
1335 size_t* pDataSize,
1336 void* pData) {
1337 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1338 VkResult result = VK_SUCCESS;
1339
1340 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1341 if (validation_data) {
1342 auto lock = validation_data->write_lock();
1343 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1344 }
1345 return result;
1346
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001347}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001348
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001349 inline_custom_validation_class_definitions = """
1350 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1351 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1352 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1353 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001354
1355 // Allow additional parameter for CreateGraphicsPipelines
1356 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1357 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1358 };
1359 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1360 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1361 };
1362 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1363 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1364 };
1365
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001366 // Allow additional state parameter for CreateComputePipelines
1367 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1368 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1369 };
1370 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1371 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1372 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001373
1374 // Allow additional state parameter for CreateRayTracingPipelinesNV
1375 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1376 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1377 };
1378 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1379 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1380 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001381
1382 // Allow modification of a down-chain parameter for CreatePipelineLayout
1383 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1384 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1385 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001386
1387 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1388 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1389 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1390 };
1391 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1392 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1393 };
1394 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1395 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1396 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001397
1398 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1399 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1400 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1401 };
1402 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1403 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1404 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001405
1406 // Modify a parameter to CreateDevice
1407 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1408 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1409 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001410"""
1411
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001412 inline_custom_source_postamble = """
1413// loader-layer interface v0, just wrappers since there is only a layer
1414
1415VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1416 VkExtensionProperties *pProperties) {
1417 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1418}
1419
1420VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1421 VkLayerProperties *pProperties) {
1422 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1423}
1424
1425VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1426 VkLayerProperties *pProperties) {
1427 // the layer command handles VK_NULL_HANDLE just fine internally
1428 assert(physicalDevice == VK_NULL_HANDLE);
1429 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1430}
1431
1432VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1433 const char *pLayerName, uint32_t *pCount,
1434 VkExtensionProperties *pProperties) {
1435 // the layer command handles VK_NULL_HANDLE just fine internally
1436 assert(physicalDevice == VK_NULL_HANDLE);
1437 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1438}
1439
1440VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1441 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1442}
1443
1444VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1445 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1446}
1447
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001448VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1449 assert(pVersionStruct != NULL);
1450 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1451
1452 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1453 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1454 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1455 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
Mark Lobodzinski56e88122019-03-26 10:21:48 -06001456 pVersionStruct->pfnGetPhysicalDeviceProcAddr = nullptr;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001457 }
1458
1459 return VK_SUCCESS;
1460}"""
1461
1462
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001463 def __init__(self,
1464 errFile = sys.stderr,
1465 warnFile = sys.stderr,
1466 diagFile = sys.stdout):
1467 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1468 # Internal state - accumulators for different inner block text
1469 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1470 self.intercepts = []
1471 self.layer_factory = '' # String containing base layer factory class definition
1472
1473 # Check if the parameter passed in is a pointer to an array
1474 def paramIsArray(self, param):
1475 return param.attrib.get('len') is not None
1476
1477 # Check if the parameter passed in is a pointer
1478 def paramIsPointer(self, param):
1479 ispointer = False
1480 for elem in param:
1481 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
1482 ispointer = True
1483 return ispointer
1484
1485 # Check if an object is a non-dispatchable handle
1486 def isHandleTypeNonDispatchable(self, handletype):
1487 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1488 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1489 return True
1490 else:
1491 return False
1492
1493 # Check if an object is a dispatchable handle
1494 def isHandleTypeDispatchable(self, handletype):
1495 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1496 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
1497 return True
1498 else:
1499 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001500 #
1501 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001502 def beginFile(self, genOpts):
1503 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001504 # Output Copyright
1505 write(self.inline_copyright_message, file=self.outFile)
1506 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001507 self.header = False
1508 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1509 self.header = True
1510 write('#pragma once', file=self.outFile)
1511 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001512 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001513 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001514 else:
1515 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001516 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001517 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001518 #
1519 def endFile(self):
1520 # Finish C++ namespace and multiple inclusion protection
1521 self.newline()
1522 if not self.header:
1523 # Record intercepted procedures
1524 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
1525 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
1526 write('\n'.join(self.intercepts), file=self.outFile)
1527 write('};\n', file=self.outFile)
1528 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001529 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001530 if self.header:
1531 self.newline()
1532 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001533 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001534 self.layer_factory += '};\n\n'
1535 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001536 write(self.layer_factory, file=self.outFile)
1537 else:
1538 write(self.inline_custom_source_postamble, file=self.outFile)
1539 # Finish processing in superclass
1540 OutputGenerator.endFile(self)
1541
1542 def beginFeature(self, interface, emit):
1543 # Start processing in superclass
1544 OutputGenerator.beginFeature(self, interface, emit)
1545 # Get feature extra protect
1546 self.featureExtraProtect = GetFeatureProtect(interface)
1547 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1548 # feature. They're only printed in endFeature().
1549 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1550
1551 def endFeature(self):
1552 # Actually write the interface to the output file.
1553 if (self.emit):
1554 self.newline()
1555 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1556 # or move it below the 'for section...' loop.
1557 if (self.featureExtraProtect != None):
1558 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1559 for section in self.TYPE_SECTIONS:
1560 contents = self.sections[section]
1561 if contents:
1562 write('\n'.join(contents), file=self.outFile)
1563 self.newline()
1564 if (self.sections['command']):
1565 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1566 self.newline()
1567 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001568 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001569 # Finish processing in superclass
1570 OutputGenerator.endFeature(self)
1571 #
1572 # Append a definition to the specified section
1573 def appendSection(self, section, text):
1574 self.sections[section].append(text)
1575 #
1576 # Type generation
1577 def genType(self, typeinfo, name, alias):
1578 pass
1579 #
1580 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1581 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1582 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1583 # structs etc.)
1584 def genStruct(self, typeinfo, typeName):
1585 OutputGenerator.genStruct(self, typeinfo, typeName)
1586 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1587 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1588 for member in typeinfo.elem.findall('.//member'):
1589 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1590 body += ';\n'
1591 body += '} ' + typeName + ';\n'
1592 self.appendSection('struct', body)
1593 #
1594 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1595 def genGroup(self, groupinfo, groupName, alias):
1596 pass
1597 # Enumerant generation
1598 # <enum> tags may specify their values in several ways, but are usually just integers.
1599 def genEnum(self, enuminfo, name, alias):
1600 pass
1601 #
1602 # Customize Cdecl for layer factory base class
1603 def BaseClassCdecl(self, elem, name):
1604 raw = self.makeCDecls(elem)[1]
1605
1606 # Toss everything before the undecorated name
1607 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1608 prototype = prototype.replace(")", "", 1)
1609 prototype = prototype.replace(";", " {};")
1610
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001611 # Build up pre/post call virtual function declarations
1612 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1613 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1614 pre_call_record = 'virtual void PreCallRecord' + prototype
1615 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001616 resulttype = elem.find('proto/type')
1617 if resulttype.text == 'VkResult':
1618 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001619 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1620 #
1621 # Command generation
1622 def genCmd(self, cmdinfo, name, alias):
1623 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001624 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001625 ]
1626
1627 if name in ignore_functions:
1628 return
1629
1630 if self.header: # In the header declare all intercepts
1631 self.appendSection('command', '')
1632 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1633 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001634 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1635 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001636 if 'ValidationCache' not in name:
1637 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001638 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001639 self.layer_factory += '#endif\n'
1640 return
1641
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001642 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001643 if 'ValidationCache' not in name:
1644 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1645 else:
1646 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1647 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1648 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001649 return
1650 # Record that the function will be intercepted
1651 if (self.featureExtraProtect != None):
1652 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1653 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1654 if (self.featureExtraProtect != None):
1655 self.intercepts += [ '#endif' ]
1656 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1657 #
1658 decls = self.makeCDecls(cmdinfo.elem)
1659 self.appendSection('command', '')
1660 self.appendSection('command', '%s {' % decls[0][:-1])
1661 # Setup common to call wrappers. First parameter is always dispatchable
1662 dispatchable_type = cmdinfo.elem.find('param/type').text
1663 dispatchable_name = cmdinfo.elem.find('param/name').text
1664 # Default to device
1665 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001666 dispatch_table_name = 'VkLayerDispatchTable'
1667 # Set to instance as necessary
1668 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1669 device_or_instance = 'instance'
1670 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001671 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001672 api_function_name = cmdinfo.elem.attrib.get('name')
1673 params = cmdinfo.elem.findall('param/name')
1674 paramstext = ', '.join([str(param.text) for param in params])
Tony-LunarG152a88b2019-03-20 15:42:24 -06001675 API = api_function_name.replace('vk','Dispatch') + '('
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001676
1677 # Declare result variable, if any.
1678 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001679 'PFN_vkVoidFunction': 'return nullptr;',
1680 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001681 'VkDeviceAddress': 'return 0;',
1682 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1683 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001684 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001685 }
1686 resulttype = cmdinfo.elem.find('proto/type')
1687 assignresult = ''
1688 if (resulttype.text != 'void'):
1689 assignresult = resulttype.text + ' result = '
1690
1691 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001692 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001693
1694 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001695 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001696 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001697 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1698 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1699 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001700
1701 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001702 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001703 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001704 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001705 self.appendSection('command', ' }')
1706
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001707 # Insert pre-dispatch debug utils function call
1708 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001709 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001710
1711 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001712 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001713
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001714 # Insert post-dispatch debug utils function call
1715 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001716 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001717
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001718 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001719 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001720 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001721 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001722 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001723 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001724 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001725 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001726 # Return result variable, if any.
1727 if (resulttype.text != 'void'):
1728 self.appendSection('command', ' return result;')
1729 self.appendSection('command', '}')
1730 #
1731 # Override makeProtoName to drop the "vk" prefix
1732 def makeProtoName(self, name, tail):
1733 return self.genOpts.apientry + name[2:] + tail