blob: ca03d8242248fffa72b8702b563f3dedb50b4a71 [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07003# Copyright (c) 2015-2019 Valve Corporation
4# Copyright (c) 2015-2019 LunarG, Inc.
5# Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06006#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
20# Author: Mark Lobodzinski <mark@lunarg.com>
21#
22# This script generates the dispatch portion of a factory layer which intercepts
23# all Vulkan functions. The resultant factory layer allows rapid development of
24# layers and interceptors.
25
26import os,re,sys
27from generator import *
28from common_codegen import *
29
30# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31#
32# Adds options used by LayerFactoryOutputGenerator objects during factory
33# layer generation.
34#
35# Additional members
36# prefixText - list of strings to prefix generated header with
37# (usually a copyright statement + calling convention macros).
38# protectFile - True if multiple inclusion protection should be
39# generated (based on the filename) around the entire header.
40# protectFeature - True if #ifndef..#endif protection should be
41# generated around a feature interface in the header file.
42# genFuncPointers - True if function pointer typedefs should be
43# generated
44# protectProto - If conditional protection should be generated
45# around prototype declarations, set to either '#ifdef'
46# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47# to require opt-out (#ifndef protectProtoStr). Otherwise
48# set to None.
49# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50# declarations, if protectProto is set
51# apicall - string to use for the function declaration prefix,
52# such as APICALL on Windows.
53# apientry - string to use for the calling convention macro,
54# in typedefs, such as APIENTRY.
55# apientryp - string to use for the calling convention macro
56# in function pointer typedefs, such as APIENTRYP.
57# indentFuncProto - True if prototype declarations should put each
58# parameter on a separate line
59# indentFuncPointer - True if typedefed function pointers should put each
60# parameter on a separate line
61# alignFuncParam - if nonzero and parameters are being put on a
62# separate line, align parameter names at the specified column
63class LayerChassisGeneratorOptions(GeneratorOptions):
64 def __init__(self,
65 filename = None,
66 directory = '.',
67 apiname = None,
68 profile = None,
69 versions = '.*',
70 emitversions = '.*',
71 defaultExtensions = None,
72 addExtensions = None,
73 removeExtensions = None,
74 emitExtensions = None,
75 sortProcedure = regSortFeatures,
76 prefixText = "",
77 genFuncPointers = True,
78 protectFile = True,
79 protectFeature = True,
80 apicall = '',
81 apientry = '',
82 apientryp = '',
83 indentFuncProto = True,
84 indentFuncPointer = False,
85 alignFuncParam = 0,
86 helper_file_type = '',
87 expandEnumerants = True):
88 GeneratorOptions.__init__(self, filename, directory, apiname, profile,
89 versions, emitversions, defaultExtensions,
90 addExtensions, removeExtensions, emitExtensions, sortProcedure)
91 self.prefixText = prefixText
92 self.genFuncPointers = genFuncPointers
93 self.protectFile = protectFile
94 self.protectFeature = protectFeature
95 self.apicall = apicall
96 self.apientry = apientry
97 self.apientryp = apientryp
98 self.indentFuncProto = indentFuncProto
99 self.indentFuncPointer = indentFuncPointer
100 self.alignFuncParam = alignFuncParam
101
102# LayerChassisOutputGenerator - subclass of OutputGenerator.
103# Generates a LayerFactory layer that intercepts all API entrypoints
104# This is intended to be used as a starting point for creating custom layers
105#
106# ---- methods ----
107# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
108# OutputGenerator. Defines additional internal state.
109# ---- methods overriding base class ----
110# beginFile(genOpts)
111# endFile()
112# beginFeature(interface, emit)
113# endFeature()
114# genType(typeinfo,name)
115# genStruct(typeinfo,name)
116# genGroup(groupinfo,name)
117# genEnum(enuminfo, name)
118# genCmd(cmdinfo)
119class LayerChassisOutputGenerator(OutputGenerator):
120 """Generate specified API interfaces in a specific style, such as a C header"""
121 # This is an ordered list of sections in the header file.
122 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
123 'group', 'bitmask', 'funcpointer', 'struct']
124 ALL_SECTIONS = TYPE_SECTIONS + ['command']
125
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700126 manual_functions = [
127 # Include functions here to be interecpted w/ manually implemented function bodies
128 'vkGetDeviceProcAddr',
129 'vkGetInstanceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700130 'vkCreateDevice',
131 'vkDestroyDevice',
132 'vkCreateInstance',
133 'vkDestroyInstance',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700134 'vkEnumerateInstanceLayerProperties',
135 'vkEnumerateInstanceExtensionProperties',
136 'vkEnumerateDeviceLayerProperties',
137 'vkEnumerateDeviceExtensionProperties',
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700138 # Functions that are handled explicitly due to chassis architecture violations
139 'vkCreateGraphicsPipelines',
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700140 'vkCreateComputePipelines',
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700141 'vkCreateRayTracingPipelinesNV',
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -0700142 'vkCreatePipelineLayout',
Mark Lobodzinski1db77e82019-03-01 10:02:54 -0700143 'vkCreateShaderModule',
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -0700144 'vkAllocateDescriptorSets',
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700145 # ValidationCache functions do not get dispatched
146 'vkCreateValidationCacheEXT',
147 'vkDestroyValidationCacheEXT',
148 'vkMergeValidationCachesEXT',
149 'vkGetValidationCacheDataEXT',
Mark Lobodzinski56e88122019-03-26 10:21:48 -0600150 # We don't wanna hook this function
151 'vkGetPhysicalDeviceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700152 ]
153
154 alt_ret_codes = [
155 # Include functions here which must tolerate VK_INCOMPLETE as a return code
156 'vkEnumeratePhysicalDevices',
157 'vkEnumeratePhysicalDeviceGroupsKHR',
158 'vkGetValidationCacheDataEXT',
159 'vkGetPipelineCacheData',
160 'vkGetShaderInfoAMD',
161 'vkGetPhysicalDeviceDisplayPropertiesKHR',
162 'vkGetPhysicalDeviceDisplayProperties2KHR',
163 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
164 'vkGetDisplayPlaneSupportedDisplaysKHR',
165 'vkGetDisplayModePropertiesKHR',
166 'vkGetDisplayModeProperties2KHR',
167 'vkGetPhysicalDeviceSurfaceFormatsKHR',
168 'vkGetPhysicalDeviceSurfacePresentModesKHR',
169 'vkGetPhysicalDevicePresentRectanglesKHR',
170 'vkGetPastPresentationTimingGOOGLE',
171 'vkGetSwapchainImagesKHR',
172 'vkEnumerateInstanceLayerProperties',
173 'vkEnumerateDeviceLayerProperties',
174 'vkEnumerateInstanceExtensionProperties',
175 'vkEnumerateDeviceExtensionProperties',
176 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
177 ]
178
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700179 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700180 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
181 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700182 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
183 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
184 'vkCmdBeginDebugUtilsLabelEXT' : 'BeginCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
185 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
186 }
187
188 post_dispatch_debug_utils_functions = {
189 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
190 'vkCmdEndDebugUtilsLabelEXT' : 'EndCmdDebugUtilsLabel(layer_data->report_data, commandBuffer);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700191 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
192 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
193 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
194 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
195 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700196 }
197
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600198 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
199 precallrecord_loop = precallvalidate_loop
200 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600201
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700202 inline_custom_header_preamble = """
203#define NOMINMAX
204#include <mutex>
205#include <cinttypes>
206#include <stdio.h>
207#include <stdlib.h>
208#include <string.h>
209#include <unordered_map>
210#include <unordered_set>
211#include <algorithm>
212#include <memory>
213
214#include "vk_loader_platform.h"
215#include "vulkan/vulkan.h"
216#include "vk_layer_config.h"
217#include "vk_layer_data.h"
218#include "vk_layer_logging.h"
219#include "vk_object_types.h"
220#include "vulkan/vk_layer.h"
221#include "vk_enum_string_helper.h"
222#include "vk_layer_extension_utils.h"
223#include "vk_layer_utils.h"
224#include "vulkan/vk_layer.h"
225#include "vk_dispatch_table_helper.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700226#include "vk_extension_helper.h"
227#include "vk_safe_struct.h"
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700228#include "vk_typemap_helper.h"
229
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700230
231extern uint64_t global_unique_id;
232extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
233"""
234
235 inline_custom_header_class_definition = """
236
237// Layer object type identifiers
238enum LayerObjectTypeId {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700239 LayerObjectTypeInstance, // Container for an instance dispatch object
240 LayerObjectTypeDevice, // Container for a device dispatch object
241 LayerObjectTypeThreading, // Instance or device threading layer object
242 LayerObjectTypeParameterValidation, // Instance or device parameter validation layer object
243 LayerObjectTypeObjectTracker, // Instance or device object tracker layer object
244 LayerObjectTypeCoreValidation, // Instance or device core validation layer object
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700245};
246
247struct TEMPLATE_STATE {
248 VkDescriptorUpdateTemplateKHR desc_update_template;
249 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
250
251 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
252 : desc_update_template(update_template), create_info(*pCreateInfo) {}
253};
254
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700255class LAYER_PHYS_DEV_PROPERTIES {
256public:
257 VkPhysicalDeviceProperties properties;
258 std::vector<VkQueueFamilyProperties> queue_family_properties;
259};
260
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600261typedef enum ValidationCheckDisables {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600262 VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600263 VALIDATION_CHECK_DISABLE_OBJECT_IN_USE,
264 VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET,
265 VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600266} ValidationCheckDisables;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600267
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600268
269// CHECK_DISABLED struct is a container for bools that can block validation checks from being performed.
270// These bools are all "false" by default meaning that all checks are enabled. Enum values can be specified
271// via the vk_layer_setting.txt config file or at CreateInstance time via the VK_EXT_validation_features extension
272// that can selectively disable checks.
273struct CHECK_DISABLED {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600274 bool command_buffer_state; // Skip command buffer state validation
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600275 bool object_in_use; // Skip all object in_use checking
276 bool idle_descriptor_set; // Skip check to verify that descriptor set is not in-use
277 bool push_constant_range; // Skip push constant range checks
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600278 bool object_tracking; // Disable object lifetime validation
279 bool core_checks; // Disable core validation checks
280 bool thread_safety; // Disable thread safety validation
281 bool stateless_checks; // Disable stateless validation checks
282 bool handle_wrapping; // Disable unique handles/handle wrapping
283 bool shader_validation; // Skip validation for shaders
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700284
285 void SetAll(bool value) { std::fill(&command_buffer_state, &shader_validation + 1, value); }
286};
287
288struct CHECK_ENABLED {
289 bool gpu_validation;
290 bool gpu_validation_reserve_binding_slot;
291
292 void SetAll(bool value) { std::fill(&gpu_validation, &gpu_validation_reserve_binding_slot + 1, value); }
293};
294
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700295// Layer chassis validation object base class definition
296class ValidationObject {
297 public:
298 uint32_t api_version;
299 debug_report_data* report_data = nullptr;
300 std::vector<VkDebugReportCallbackEXT> logging_callback;
301 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
302
303 VkLayerInstanceDispatchTable instance_dispatch_table;
304 VkLayerDispatchTable device_dispatch_table;
305
306 InstanceExtensions instance_extensions;
307 DeviceExtensions device_extensions = {};
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700308 CHECK_DISABLED disabled = {};
309 CHECK_ENABLED enabled = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700310
311 VkInstance instance = VK_NULL_HANDLE;
312 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
313 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700314 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700315
316 std::vector<ValidationObject*> object_dispatch;
317 LayerObjectTypeId container_type;
318
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700319 std::string layer_name = "CHASSIS";
320
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700321 // Constructor
322 ValidationObject(){};
323 // Destructor
324 virtual ~ValidationObject() {};
325
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700326 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700327 virtual std::unique_lock<std::mutex> write_lock() {
328 return std::unique_lock<std::mutex>(validation_object_mutex);
329 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700330
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700331 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
332 for (auto validation_object : object_dispatch) {
333 if (validation_object->container_type == object_type) {
334 return validation_object;
335 }
336 }
337 return nullptr;
338 };
339
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700340 // Handle Wrapping Data
341 // Reverse map display handles
342 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
343 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700344 struct SubpassesUsageStates {
345 std::unordered_set<uint32_t> subpasses_using_color_attachment;
346 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
347 };
348 // Uses unwrapped handles
349 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
350 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
351 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
352 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700353 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
354 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700355
356
357 // Unwrap a handle. Must hold lock.
358 template <typename HandleType>
359 HandleType Unwrap(HandleType wrappedHandle) {
360 // TODO: don't use operator[] here.
361 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
362 }
363
364 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
365 template <typename HandleType>
366 HandleType WrapNew(HandleType newlyCreatedHandle) {
367 auto unique_id = global_unique_id++;
368 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
369 return (HandleType)unique_id;
370 }
371
372 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
373 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
374 auto unique_id = global_unique_id++;
375 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
376 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
377 return (VkDisplayKHR)unique_id;
378 }
379
380 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
381 // creating another. Must hold lock.
382 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
383 // See if this display is already known
384 auto it = map_data->display_id_reverse_mapping.find(handle);
385 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
386 // Unknown, so wrap
387 return WrapDisplay(handle, map_data);
388 }
389
390 // Pre/post hook point declarations
391"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600392
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700393 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600394// This file is ***GENERATED***. Do Not Edit.
395// See layer_chassis_generator.py for modifications.
396
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700397/* Copyright (c) 2015-2019 The Khronos Group Inc.
398 * Copyright (c) 2015-2019 Valve Corporation
399 * Copyright (c) 2015-2019 LunarG, Inc.
400 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600401 *
402 * Licensed under the Apache License, Version 2.0 (the "License");
403 * you may not use this file except in compliance with the License.
404 * You may obtain a copy of the License at
405 *
406 * http://www.apache.org/licenses/LICENSE-2.0
407 *
408 * Unless required by applicable law or agreed to in writing, software
409 * distributed under the License is distributed on an "AS IS" BASIS,
410 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
411 * See the License for the specific language governing permissions and
412 * limitations under the License.
413 *
414 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700415 */"""
416
417 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600418
419#include <string.h>
420#include <mutex>
421
422#define VALIDATION_ERROR_MAP_IMPL
423
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600424#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700425#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600426
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600427std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600428
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700429// Global unique object identifier. All increments must be guarded by a lock.
430uint64_t global_unique_id = 1;
431// Map uniqueID to actual object handle
432std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
433
434// TODO: This variable controls handle wrapping -- in the future it should be hooked
435// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
436#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
437bool wrap_handles = true;
438#else
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600439bool wrap_handles = false;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700440#endif
441
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600442// Set layer name -- Khronos layer name overrides any other defined names
Mark Lobodzinskiaa6fd7b2019-03-19 09:26:48 -0600443#if BUILD_KHRONOS_VALIDATION
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600444#define OBJECT_LAYER_NAME "VK_LAYER_KHRONOS_validation"
445#define OBJECT_LAYER_DESCRIPTION "khronos_validation"
446#elif BUILD_OBJECT_TRACKER
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700447#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600448#define OBJECT_LAYER_DESCRIPTION "lunarg_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700449#elif BUILD_THREAD_SAFETY
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700450#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600451#define OBJECT_LAYER_DESCRIPTION "google_thread_checker"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700452#elif BUILD_PARAMETER_VALIDATION
453#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600454#define OBJECT_LAYER_DESCRIPTION "lunarg_parameter_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700455#elif BUILD_CORE_VALIDATION
456#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600457#define OBJECT_LAYER_DESCRIPTION "lunarg_core_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700458#else
459#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600460#define OBJECT_LAYER_DESCRIPTION "lunarg_unique_objects"
461#endif
462
463// Include layer validation object definitions
464#if BUILD_OBJECT_TRACKER
465#include "object_lifetime_validation.h"
466#endif
467#if BUILD_THREAD_SAFETY
468#include "thread_safety.h"
469#endif
470#if BUILD_PARAMETER_VALIDATION
471#include "stateless_validation.h"
472#endif
473#if BUILD_CORE_VALIDATION
474#include "core_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700475#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600476
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600477namespace vulkan_layer_chassis {
478
479using std::unordered_map;
480
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600481static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700482 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600483};
484
485static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
486
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 Lobodzinski2af57ec2019-03-20 09:17:56 -0600543};
544
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600545// Set the local disable flag for the appropriate VALIDATION_CHECK_DISABLE enum
546void SetValidationDisable(CHECK_DISABLED* disable_data, const ValidationCheckDisables disable_id) {
547 switch (disable_id) {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600548 case VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE:
549 disable_data->command_buffer_state = true;
550 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600551 case VALIDATION_CHECK_DISABLE_OBJECT_IN_USE:
552 disable_data->object_in_use = true;
553 break;
554 case VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET:
555 disable_data->idle_descriptor_set = true;
556 break;
557 case VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE:
558 disable_data->push_constant_range = true;
559 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600560 default:
561 assert(true);
562 }
563}
564
565// Set the local disable flag for a single VK_VALIDATION_FEATURE_DISABLE_* flag
566void SetValidationFeatureDisable(CHECK_DISABLED* disable_data, const VkValidationFeatureDisableEXT feature_disable) {
567 switch (feature_disable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700568 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600569 disable_data->shader_validation = true;
570 break;
571 case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
572 disable_data->thread_safety = true;
573 break;
574 case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
575 disable_data->stateless_checks = true;
576 break;
577 case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
578 disable_data->object_tracking = true;
579 break;
580 case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
581 disable_data->core_checks = true;
582 break;
583 case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
584 disable_data->handle_wrapping = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700585 break;
586 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
587 // Set all disabled flags to true
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600588 disable_data->SetAll(true);
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700589 break;
590 default:
591 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700592 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600593}
594
595// Set the local enable flag for a single VK_VALIDATION_FEATURE_ENABLE_* flag
596void SetValidationFeatureEnable(CHECK_ENABLED *enable_data, const VkValidationFeatureEnableEXT feature_enable) {
597 switch (feature_enable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700598 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600599 enable_data->gpu_validation = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700600 break;
601 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600602 enable_data->gpu_validation_reserve_binding_slot = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700603 break;
604 default:
605 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700606 }
607}
608
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600609// Set the local disable flag for settings specified through the VK_EXT_validation_flags extension
610void SetValidationFlags(CHECK_DISABLED* disables, const VkValidationFlagsEXT* val_flags_struct) {
611 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
612 switch (val_flags_struct->pDisabledValidationChecks[i]) {
613 case VK_VALIDATION_CHECK_SHADERS_EXT:
614 disables->shader_validation = true;
615 break;
616 case VK_VALIDATION_CHECK_ALL_EXT:
617 // Set all disabled flags to true
618 disables->SetAll(true);
619 break;
620 default:
621 break;
622 }
623 }
624}
625
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600626// Process Validation Features flags specified through the ValidationFeature extension
627void SetValidationFeatures(CHECK_DISABLED *disable_data, CHECK_ENABLED *enable_data,
628 const VkValidationFeaturesEXT *val_features_struct) {
629 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
630 SetValidationFeatureDisable(disable_data, val_features_struct->pDisabledValidationFeatures[i]);
631 }
632 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
633 SetValidationFeatureEnable(enable_data, val_features_struct->pEnabledValidationFeatures[i]);
634 }
635}
636
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600637// Given a string representation of a list of enable enum values, call the appropriate setter function
638void SetLocalEnableSetting(std::string list_of_enables, std::string delimiter, CHECK_ENABLED* enables) {
639 size_t pos = 0;
640 std::string token;
641 while (list_of_enables.length() != 0) {
642 pos = list_of_enables.find(delimiter);
643 if (pos != std::string::npos) {
644 token = list_of_enables.substr(0, pos);
645 } else {
646 pos = list_of_enables.length() - delimiter.length();
647 token = list_of_enables;
648 }
649 if (token.find("VK_VALIDATION_FEATURE_ENABLE_") != std::string::npos) {
650 auto result = VkValFeatureEnableLookup.find(token);
651 if (result != VkValFeatureEnableLookup.end()) {
652 SetValidationFeatureEnable(enables, result->second);
653 }
654 }
655 list_of_enables.erase(0, pos + delimiter.length());
656 }
657}
658
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600659// Given a string representation of a list of disable enum values, call the appropriate setter function
660void SetLocalDisableSetting(std::string list_of_disables, std::string delimiter, CHECK_DISABLED* disables) {
661 size_t pos = 0;
662 std::string token;
663 while (list_of_disables.length() != 0) {
664 pos = list_of_disables.find(delimiter);
665 if (pos != std::string::npos) {
666 token = list_of_disables.substr(0, pos);
667 } else {
668 pos = list_of_disables.length() - delimiter.length();
669 token = list_of_disables;
670 }
671 if (token.find("VK_VALIDATION_FEATURE_DISABLE_") != std::string::npos) {
672 auto result = VkValFeatureDisableLookup.find(token);
673 if (result != VkValFeatureDisableLookup.end()) {
674 SetValidationFeatureDisable(disables, result->second);
675 }
676 }
677 if (token.find("VALIDATION_CHECK_DISABLE_") != std::string::npos) {
678 auto result = ValidationDisableLookup.find(token);
679 if (result != ValidationDisableLookup.end()) {
680 SetValidationDisable(disables, result->second);
681 }
682 }
683 list_of_disables.erase(0, pos + delimiter.length());
684 }
685}
686
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600687// Process enables and disables set though the vk_layer_settings.txt config file or through an environment variable
688void ProcessConfigAndEnvSettings(const char* layer_description, CHECK_ENABLED* enables, CHECK_DISABLED* disables) {
689 std::string enable_key = layer_description;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600690 std::string disable_key = layer_description;
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600691 enable_key.append(".enables");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600692 disable_key.append(".disables");
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600693 std::string list_of_config_enables = getLayerOption(enable_key.c_str());
694 std::string list_of_env_enables = GetLayerEnvVar("VK_LAYER_ENABLES");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600695 std::string list_of_config_disables = getLayerOption(disable_key.c_str());
696 std::string list_of_env_disables = GetLayerEnvVar("VK_LAYER_DISABLES");
697#if defined(_WIN32)
698 std::string env_delimiter = ";";
699#else
700 std::string env_delimiter = ":";
701#endif
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600702 SetLocalEnableSetting(list_of_config_enables, ",", enables);
703 SetLocalEnableSetting(list_of_env_enables, env_delimiter, enables);
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600704 SetLocalDisableSetting(list_of_config_disables, ",", disables);
705 SetLocalDisableSetting(list_of_env_disables, env_delimiter, disables);
706}
707
708
709// Non-code-generated chassis API functions
710
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600711VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600712 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700713 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700714 return nullptr;
715 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600716 const auto &item = name_to_funcptr_map.find(funcName);
717 if (item != name_to_funcptr_map.end()) {
718 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
719 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600720 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600721 if (!table.GetDeviceProcAddr) return nullptr;
722 return table.GetDeviceProcAddr(device, funcName);
723}
724
725VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600726 const auto &item = name_to_funcptr_map.find(funcName);
727 if (item != name_to_funcptr_map.end()) {
728 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
729 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600730 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
731 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600732 if (!table.GetInstanceProcAddr) return nullptr;
733 return table.GetInstanceProcAddr(instance, funcName);
734}
735
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600736VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
737 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
738}
739
740VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
741 VkLayerProperties *pProperties) {
742 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
743}
744
745VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
746 VkExtensionProperties *pProperties) {
747 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
748 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
749
750 return VK_ERROR_LAYER_NOT_PRESENT;
751}
752
753VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
754 uint32_t *pCount, VkExtensionProperties *pProperties) {
755 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600756 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600757 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
758 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600759}
760
761VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
762 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600763 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600764
765 assert(chain_info->u.pLayerInfo);
766 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
767 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
768 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
769 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700770 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
771 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
772
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600773 CHECK_ENABLED local_enables {};
774 CHECK_DISABLED local_disables {};
775 const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(pCreateInfo->pNext);
776 if (validation_features_ext) {
777 SetValidationFeatures(&local_disables, &local_enables, validation_features_ext);
778 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600779 const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
780 if (validation_flags_ext) {
781 SetValidationFlags(&local_disables, validation_flags_ext);
782 }
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600783 ProcessConfigAndEnvSettings(OBJECT_LAYER_DESCRIPTION, &local_enables, &local_disables);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600784
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600785 // Create temporary dispatch vector for pre-calls until instance is created
786 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600787 // Add VOs to dispatch vector. Order here will be the validation dispatch order!
788#if BUILD_THREAD_SAFETY
789 auto thread_checker = new ThreadSafety;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600790 if (!local_disables.thread_safety) {
791 local_object_dispatch.emplace_back(thread_checker);
792 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600793 thread_checker->container_type = LayerObjectTypeThreading;
794 thread_checker->api_version = api_version;
795#endif
796#if BUILD_PARAMETER_VALIDATION
797 auto parameter_validation = new StatelessValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600798 if (!local_disables.stateless_checks) {
799 local_object_dispatch.emplace_back(parameter_validation);
800 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600801 parameter_validation->container_type = LayerObjectTypeParameterValidation;
802 parameter_validation->api_version = api_version;
803#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700804#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600805 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600806 if (!local_disables.object_tracking) {
807 local_object_dispatch.emplace_back(object_tracker);
808 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600809 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700810 object_tracker->api_version = api_version;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600811#endif
812#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700813 auto core_checks = new CoreChecks;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600814 if (!local_disables.core_checks) {
815 local_object_dispatch.emplace_back(core_checks);
816 }
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700817 core_checks->container_type = LayerObjectTypeCoreValidation;
818 core_checks->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700819#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600820
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600821 // If handle wrapping is disabled via the ValidationFeatures extension, override build flag
822 if (local_disables.handle_wrapping) {
823 wrap_handles = false;
824 }
825
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600826 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600827 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600828 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
829 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600830 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600831 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
832 }
833
834 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600835 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600836
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600837 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600838
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600839 framework->object_dispatch = local_object_dispatch;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700840 framework->container_type = LayerObjectTypeInstance;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600841 framework->disabled = local_disables;
842 framework->enabled = local_enables;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600843
844 framework->instance = *pInstance;
845 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
846 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
847 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700848 framework->api_version = api_version;
849 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
850
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600851 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, OBJECT_LAYER_DESCRIPTION);
852
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700853#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700854 object_tracker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600855 object_tracker->instance_dispatch_table = framework->instance_dispatch_table;
856 object_tracker->enabled = framework->enabled;
857 object_tracker->disabled = framework->disabled;
858#endif
859#if BUILD_THREAD_SAFETY
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700860 thread_checker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600861 thread_checker->instance_dispatch_table = framework->instance_dispatch_table;
862 thread_checker->enabled = framework->enabled;
863 thread_checker->disabled = framework->disabled;
864#endif
865#if BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700866 parameter_validation->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600867 parameter_validation->instance_dispatch_table = framework->instance_dispatch_table;
868 parameter_validation->enabled = framework->enabled;
869 parameter_validation->disabled = framework->disabled;
870#endif
871#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700872 core_checks->report_data = framework->report_data;
873 core_checks->instance_dispatch_table = framework->instance_dispatch_table;
874 core_checks->instance = *pInstance;
875 core_checks->enabled = framework->enabled;
876 core_checks->disabled = framework->disabled;
877 core_checks->instance_state = core_checks;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700878#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600879
880 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700881 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600882 }
883
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700884 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
885
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600886 return result;
887}
888
889VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
890 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600891 auto layer_data = GetLayerDataPtr(key, layer_data_map);
892 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700893 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600894 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
895 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600896 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700897 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600898 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
899 }
900
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600901 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600902
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600903 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700904 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600905 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
906 }
907 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600908 while (layer_data->logging_messenger.size() > 0) {
909 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
910 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
911 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600912 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600913 while (layer_data->logging_callback.size() > 0) {
914 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
915 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
916 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600917 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600918
919 layer_debug_utils_destroy_instance(layer_data->report_data);
920
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700921 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
922 delete *item;
923 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600924 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600925}
926
927VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
928 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600929 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600930
931 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
932
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600933 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
934 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600935 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
936 if (fpCreateDevice == NULL) {
937 return VK_ERROR_INITIALIZATION_FAILED;
938 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600939 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
940
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700941 // Get physical device limits for device
942 VkPhysicalDeviceProperties device_properties = {};
943 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
944
945 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
946 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
947
948 DeviceExtensions device_extensions = {};
949 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
950 for (auto item : instance_interceptor->object_dispatch) {
951 item->device_extensions = device_extensions;
952 }
953
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700954 std::unique_ptr<safe_VkDeviceCreateInfo> modified_create_info(new safe_VkDeviceCreateInfo(pCreateInfo));
955
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700956 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600957 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700958 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700959 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700960 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600961 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600962 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700963 auto lock = intercept->write_lock();
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700964 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, modified_create_info);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600965 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600966
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700967 VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(modified_create_info.get()), pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600968 if (result != VK_SUCCESS) {
969 return result;
970 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600971
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600972 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700973 device_interceptor->container_type = LayerObjectTypeDevice;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700974
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700975 // Save local info in device object
976 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700977 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
978 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700979 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700980
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600981 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700982
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600983 device_interceptor->device = *pDevice;
984 device_interceptor->physical_device = gpu;
985 device_interceptor->instance = instance_interceptor->instance;
986 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600987
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600988 // Note that this defines the order in which the layer validation objects are called
989#if BUILD_THREAD_SAFETY
990 auto thread_safety = new ThreadSafety;
991 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
992 thread_safety->container_type = LayerObjectTypeThreading;
993 thread_safety->physical_device = gpu;
994 thread_safety->instance = instance_interceptor->instance;
995 thread_safety->report_data = device_interceptor->report_data;
996 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
997 thread_safety->api_version = device_interceptor->api_version;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600998 if (!instance_interceptor->disabled.thread_safety) {
999 device_interceptor->object_dispatch.emplace_back(thread_safety);
1000 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001001#endif
1002#if BUILD_PARAMETER_VALIDATION
1003 auto stateless_validation = new StatelessValidation;
1004 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
1005 stateless_validation->container_type = LayerObjectTypeParameterValidation;
1006 stateless_validation->physical_device = gpu;
1007 stateless_validation->instance = instance_interceptor->instance;
1008 stateless_validation->report_data = device_interceptor->report_data;
1009 stateless_validation->device_dispatch_table = device_interceptor->device_dispatch_table;
1010 stateless_validation->api_version = device_interceptor->api_version;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001011 if (!instance_interceptor->disabled.stateless_checks) {
1012 device_interceptor->object_dispatch.emplace_back(stateless_validation);
1013 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001014#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001015#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001016 // Create child layer objects for this key and add to dispatch vector
1017 auto object_tracker = new ObjectLifetimes;
1018 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
1019 object_tracker->container_type = LayerObjectTypeObjectTracker;
1020 object_tracker->physical_device = gpu;
1021 object_tracker->instance = instance_interceptor->instance;
1022 object_tracker->report_data = device_interceptor->report_data;
1023 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -07001024 object_tracker->api_version = device_interceptor->api_version;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001025 if (!instance_interceptor->disabled.object_tracking) {
1026 device_interceptor->object_dispatch.emplace_back(object_tracker);
1027 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001028#endif
1029#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001030 auto core_checks = new CoreChecks;
1031 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
1032 core_checks->container_type = LayerObjectTypeCoreValidation;
1033 core_checks->physical_device = gpu;
1034 core_checks->instance = instance_interceptor->instance;
1035 core_checks->report_data = device_interceptor->report_data;
1036 core_checks->device_dispatch_table = device_interceptor->device_dispatch_table;
1037 core_checks->instance_dispatch_table = instance_interceptor->instance_dispatch_table;
1038 core_checks->api_version = device_interceptor->api_version;
1039 core_checks->instance_extensions = instance_interceptor->instance_extensions;
1040 core_checks->device_extensions = device_interceptor->device_extensions;
1041 core_checks->instance_state = reinterpret_cast<CoreChecks *>(
1042 core_checks->GetValidationObject(instance_interceptor->object_dispatch, LayerObjectTypeCoreValidation));
1043 core_checks->device = *pDevice;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001044 if (!instance_interceptor->disabled.core_checks) {
1045 device_interceptor->object_dispatch.emplace_back(core_checks);
1046 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001047#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001048
1049 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001050 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001051 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001052 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001053
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001054 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
1055
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001056 return result;
1057}
1058
1059VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
1060 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001061 auto layer_data = GetLayerDataPtr(key, layer_data_map);
1062 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001063 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001064 intercept->PreCallValidateDestroyDevice(device, pAllocator);
1065 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001066 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001067 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001068 intercept->PreCallRecordDestroyDevice(device, pAllocator);
1069 }
1070 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001071
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001072 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001073
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001074 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001075 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001076 intercept->PostCallRecordDestroyDevice(device, pAllocator);
1077 }
1078
Mark Lobodzinskic5003372018-12-17 16:36:01 -07001079 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
1080 delete *item;
1081 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001082 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001083}
1084
1085
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001086// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001087
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001088VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
1089 VkDevice device,
1090 VkPipelineCache pipelineCache,
1091 uint32_t createInfoCount,
1092 const VkGraphicsPipelineCreateInfo* pCreateInfos,
1093 const VkAllocationCallbacks* pAllocator,
1094 VkPipeline* pPipelines) {
1095 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1096 bool skip = false;
1097
1098#ifdef BUILD_CORE_VALIDATION
1099 create_graphics_pipeline_api_state cgpl_state{};
1100#else
1101 struct create_graphics_pipeline_api_state {
1102 const VkGraphicsPipelineCreateInfo* pCreateInfos;
1103 } cgpl_state;
1104 cgpl_state.pCreateInfos = pCreateInfos;
1105#endif
1106
1107 for (auto intercept : layer_data->object_dispatch) {
1108 auto lock = intercept->write_lock();
1109 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1110 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1111 }
1112 for (auto intercept : layer_data->object_dispatch) {
1113 auto lock = intercept->write_lock();
1114 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1115 }
1116
Tony-LunarG152a88b2019-03-20 15:42:24 -06001117 VkResult result = DispatchCreateGraphicsPipelines(device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001118
1119 for (auto intercept : layer_data->object_dispatch) {
1120 auto lock = intercept->write_lock();
1121 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
1122 }
1123 return result;
1124}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001125
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001126// This API saves some core_validation pipeline state state on the stack for performance purposes
1127VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
1128 VkDevice device,
1129 VkPipelineCache pipelineCache,
1130 uint32_t createInfoCount,
1131 const VkComputePipelineCreateInfo* pCreateInfos,
1132 const VkAllocationCallbacks* pAllocator,
1133 VkPipeline* pPipelines) {
1134 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1135 bool skip = false;
1136
1137#ifndef BUILD_CORE_VALIDATION
1138 struct PIPELINE_STATE {};
1139#endif
1140
1141 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
1142
1143 for (auto intercept : layer_data->object_dispatch) {
1144 auto lock = intercept->write_lock();
1145 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
1146 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1147 }
1148 for (auto intercept : layer_data->object_dispatch) {
1149 auto lock = intercept->write_lock();
1150 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1151 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001152 VkResult result = DispatchCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001153 for (auto intercept : layer_data->object_dispatch) {
1154 auto lock = intercept->write_lock();
1155 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1156 }
1157 return result;
1158}
1159
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001160VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
1161 VkDevice device,
1162 VkPipelineCache pipelineCache,
1163 uint32_t createInfoCount,
1164 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
1165 const VkAllocationCallbacks* pAllocator,
1166 VkPipeline* pPipelines) {
1167 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1168 bool skip = false;
1169
1170#ifndef BUILD_CORE_VALIDATION
1171 struct PIPELINE_STATE {};
1172#endif
1173
1174 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
1175
1176 for (auto intercept : layer_data->object_dispatch) {
1177 auto lock = intercept->write_lock();
1178 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
1179 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1180 }
1181 for (auto intercept : layer_data->object_dispatch) {
1182 auto lock = intercept->write_lock();
1183 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1184 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001185 VkResult result = DispatchCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001186 for (auto intercept : layer_data->object_dispatch) {
1187 auto lock = intercept->write_lock();
1188 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1189 }
1190 return result;
1191}
1192
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001193// This API needs the ability to modify a down-chain parameter
1194VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
1195 VkDevice device,
1196 const VkPipelineLayoutCreateInfo* pCreateInfo,
1197 const VkAllocationCallbacks* pAllocator,
1198 VkPipelineLayout* pPipelineLayout) {
1199 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1200 bool skip = false;
1201
1202#ifndef BUILD_CORE_VALIDATION
1203 struct create_pipeline_layout_api_state {
1204 VkPipelineLayoutCreateInfo modified_create_info;
1205 };
1206#endif
1207 create_pipeline_layout_api_state cpl_state{};
1208 cpl_state.modified_create_info = *pCreateInfo;
1209
1210 for (auto intercept : layer_data->object_dispatch) {
1211 auto lock = intercept->write_lock();
1212 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1213 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1214 }
1215 for (auto intercept : layer_data->object_dispatch) {
1216 auto lock = intercept->write_lock();
1217 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1218 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001219 VkResult result = DispatchCreatePipelineLayout(device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001220 for (auto intercept : layer_data->object_dispatch) {
1221 auto lock = intercept->write_lock();
1222 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1223 }
1224 return result;
1225}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001226
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001227// This API needs some local stack data for performance reasons and also may modify a parameter
1228VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1229 VkDevice device,
1230 const VkShaderModuleCreateInfo* pCreateInfo,
1231 const VkAllocationCallbacks* pAllocator,
1232 VkShaderModule* pShaderModule) {
1233 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1234 bool skip = false;
1235
1236#ifndef BUILD_CORE_VALIDATION
1237 struct create_shader_module_api_state {
1238 VkShaderModuleCreateInfo instrumented_create_info;
1239 };
1240#endif
1241 create_shader_module_api_state csm_state{};
1242 csm_state.instrumented_create_info = *pCreateInfo;
1243
1244 for (auto intercept : layer_data->object_dispatch) {
1245 auto lock = intercept->write_lock();
1246 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1247 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1248 }
1249 for (auto intercept : layer_data->object_dispatch) {
1250 auto lock = intercept->write_lock();
1251 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1252 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001253 VkResult result = DispatchCreateShaderModule(device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001254 for (auto intercept : layer_data->object_dispatch) {
1255 auto lock = intercept->write_lock();
1256 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1257 }
1258 return result;
1259}
1260
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001261VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1262 VkDevice device,
1263 const VkDescriptorSetAllocateInfo* pAllocateInfo,
1264 VkDescriptorSet* pDescriptorSets) {
1265 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1266 bool skip = false;
1267
1268#ifdef BUILD_CORE_VALIDATION
1269 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1270#else
1271 struct ads_state {} ads_state;
1272#endif
1273
1274 for (auto intercept : layer_data->object_dispatch) {
1275 auto lock = intercept->write_lock();
1276 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1277 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1278 }
1279 for (auto intercept : layer_data->object_dispatch) {
1280 auto lock = intercept->write_lock();
1281 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1282 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001283 VkResult result = DispatchAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001284 for (auto intercept : layer_data->object_dispatch) {
1285 auto lock = intercept->write_lock();
1286 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1287 }
1288 return result;
1289}
1290
1291
1292
1293
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001294
1295// ValidationCache APIs do not dispatch
1296
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001297VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1298 VkDevice device,
1299 const VkValidationCacheCreateInfoEXT* pCreateInfo,
1300 const VkAllocationCallbacks* pAllocator,
1301 VkValidationCacheEXT* pValidationCache) {
1302 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1303 VkResult result = VK_SUCCESS;
1304
1305 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1306 if (validation_data) {
1307 auto lock = validation_data->write_lock();
1308 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1309 }
1310 return result;
1311}
1312
1313VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1314 VkDevice device,
1315 VkValidationCacheEXT validationCache,
1316 const VkAllocationCallbacks* pAllocator) {
1317 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1318
1319 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1320 if (validation_data) {
1321 auto lock = validation_data->write_lock();
1322 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1323 }
1324}
1325
1326VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1327 VkDevice device,
1328 VkValidationCacheEXT dstCache,
1329 uint32_t srcCacheCount,
1330 const VkValidationCacheEXT* pSrcCaches) {
1331 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1332 VkResult result = VK_SUCCESS;
1333
1334 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1335 if (validation_data) {
1336 auto lock = validation_data->write_lock();
1337 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1338 }
1339 return result;
1340}
1341
1342VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1343 VkDevice device,
1344 VkValidationCacheEXT validationCache,
1345 size_t* pDataSize,
1346 void* pData) {
1347 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1348 VkResult result = VK_SUCCESS;
1349
1350 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1351 if (validation_data) {
1352 auto lock = validation_data->write_lock();
1353 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1354 }
1355 return result;
1356
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001357}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001358
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001359 inline_custom_validation_class_definitions = """
1360 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1361 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1362 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1363 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001364
1365 // Allow additional parameter for CreateGraphicsPipelines
1366 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1367 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1368 };
1369 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1370 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1371 };
1372 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1373 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1374 };
1375
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001376 // Allow additional state parameter for CreateComputePipelines
1377 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1378 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1379 };
1380 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1381 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1382 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001383
1384 // Allow additional state parameter for CreateRayTracingPipelinesNV
1385 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1386 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1387 };
1388 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1389 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1390 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001391
1392 // Allow modification of a down-chain parameter for CreatePipelineLayout
1393 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1394 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1395 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001396
1397 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1398 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1399 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1400 };
1401 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1402 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1403 };
1404 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1405 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1406 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001407
1408 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1409 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1410 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1411 };
1412 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1413 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1414 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001415
1416 // Modify a parameter to CreateDevice
1417 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1418 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1419 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001420"""
1421
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001422 inline_custom_source_postamble = """
1423// loader-layer interface v0, just wrappers since there is only a layer
1424
1425VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1426 VkExtensionProperties *pProperties) {
1427 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1428}
1429
1430VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1431 VkLayerProperties *pProperties) {
1432 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1433}
1434
1435VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1436 VkLayerProperties *pProperties) {
1437 // the layer command handles VK_NULL_HANDLE just fine internally
1438 assert(physicalDevice == VK_NULL_HANDLE);
1439 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1440}
1441
1442VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1443 const char *pLayerName, uint32_t *pCount,
1444 VkExtensionProperties *pProperties) {
1445 // the layer command handles VK_NULL_HANDLE just fine internally
1446 assert(physicalDevice == VK_NULL_HANDLE);
1447 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1448}
1449
1450VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1451 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1452}
1453
1454VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1455 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1456}
1457
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001458VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1459 assert(pVersionStruct != NULL);
1460 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1461
1462 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1463 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1464 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1465 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
Mark Lobodzinski56e88122019-03-26 10:21:48 -06001466 pVersionStruct->pfnGetPhysicalDeviceProcAddr = nullptr;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001467 }
1468
1469 return VK_SUCCESS;
1470}"""
1471
1472
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001473 def __init__(self,
1474 errFile = sys.stderr,
1475 warnFile = sys.stderr,
1476 diagFile = sys.stdout):
1477 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1478 # Internal state - accumulators for different inner block text
1479 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1480 self.intercepts = []
1481 self.layer_factory = '' # String containing base layer factory class definition
1482
1483 # Check if the parameter passed in is a pointer to an array
1484 def paramIsArray(self, param):
1485 return param.attrib.get('len') is not None
1486
1487 # Check if the parameter passed in is a pointer
1488 def paramIsPointer(self, param):
1489 ispointer = False
1490 for elem in param:
1491 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
1492 ispointer = True
1493 return ispointer
1494
1495 # Check if an object is a non-dispatchable handle
1496 def isHandleTypeNonDispatchable(self, handletype):
1497 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1498 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1499 return True
1500 else:
1501 return False
1502
1503 # Check if an object is a dispatchable handle
1504 def isHandleTypeDispatchable(self, handletype):
1505 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1506 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
1507 return True
1508 else:
1509 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001510 #
1511 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001512 def beginFile(self, genOpts):
1513 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001514 # Output Copyright
1515 write(self.inline_copyright_message, file=self.outFile)
1516 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001517 self.header = False
1518 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1519 self.header = True
1520 write('#pragma once', file=self.outFile)
1521 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001522 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001523 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001524 else:
1525 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001526 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001527 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001528 #
1529 def endFile(self):
1530 # Finish C++ namespace and multiple inclusion protection
1531 self.newline()
1532 if not self.header:
1533 # Record intercepted procedures
1534 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
1535 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
1536 write('\n'.join(self.intercepts), file=self.outFile)
1537 write('};\n', file=self.outFile)
1538 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001539 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001540 if self.header:
1541 self.newline()
1542 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001543 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001544 self.layer_factory += '};\n\n'
1545 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001546 write(self.layer_factory, file=self.outFile)
1547 else:
1548 write(self.inline_custom_source_postamble, file=self.outFile)
1549 # Finish processing in superclass
1550 OutputGenerator.endFile(self)
1551
1552 def beginFeature(self, interface, emit):
1553 # Start processing in superclass
1554 OutputGenerator.beginFeature(self, interface, emit)
1555 # Get feature extra protect
1556 self.featureExtraProtect = GetFeatureProtect(interface)
1557 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1558 # feature. They're only printed in endFeature().
1559 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1560
1561 def endFeature(self):
1562 # Actually write the interface to the output file.
1563 if (self.emit):
1564 self.newline()
1565 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1566 # or move it below the 'for section...' loop.
1567 if (self.featureExtraProtect != None):
1568 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1569 for section in self.TYPE_SECTIONS:
1570 contents = self.sections[section]
1571 if contents:
1572 write('\n'.join(contents), file=self.outFile)
1573 self.newline()
1574 if (self.sections['command']):
1575 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1576 self.newline()
1577 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001578 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001579 # Finish processing in superclass
1580 OutputGenerator.endFeature(self)
1581 #
1582 # Append a definition to the specified section
1583 def appendSection(self, section, text):
1584 self.sections[section].append(text)
1585 #
1586 # Type generation
1587 def genType(self, typeinfo, name, alias):
1588 pass
1589 #
1590 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1591 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1592 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1593 # structs etc.)
1594 def genStruct(self, typeinfo, typeName):
1595 OutputGenerator.genStruct(self, typeinfo, typeName)
1596 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1597 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1598 for member in typeinfo.elem.findall('.//member'):
1599 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1600 body += ';\n'
1601 body += '} ' + typeName + ';\n'
1602 self.appendSection('struct', body)
1603 #
1604 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1605 def genGroup(self, groupinfo, groupName, alias):
1606 pass
1607 # Enumerant generation
1608 # <enum> tags may specify their values in several ways, but are usually just integers.
1609 def genEnum(self, enuminfo, name, alias):
1610 pass
1611 #
1612 # Customize Cdecl for layer factory base class
1613 def BaseClassCdecl(self, elem, name):
1614 raw = self.makeCDecls(elem)[1]
1615
1616 # Toss everything before the undecorated name
1617 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1618 prototype = prototype.replace(")", "", 1)
1619 prototype = prototype.replace(";", " {};")
1620
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001621 # Build up pre/post call virtual function declarations
1622 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1623 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1624 pre_call_record = 'virtual void PreCallRecord' + prototype
1625 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001626 resulttype = elem.find('proto/type')
1627 if resulttype.text == 'VkResult':
1628 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001629 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1630 #
1631 # Command generation
1632 def genCmd(self, cmdinfo, name, alias):
1633 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001634 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001635 ]
1636
1637 if name in ignore_functions:
1638 return
1639
1640 if self.header: # In the header declare all intercepts
1641 self.appendSection('command', '')
1642 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1643 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001644 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1645 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001646 if 'ValidationCache' not in name:
1647 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001648 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001649 self.layer_factory += '#endif\n'
1650 return
1651
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001652 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001653 if 'ValidationCache' not in name:
1654 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1655 else:
1656 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1657 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1658 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001659 return
1660 # Record that the function will be intercepted
1661 if (self.featureExtraProtect != None):
1662 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1663 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1664 if (self.featureExtraProtect != None):
1665 self.intercepts += [ '#endif' ]
1666 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1667 #
1668 decls = self.makeCDecls(cmdinfo.elem)
1669 self.appendSection('command', '')
1670 self.appendSection('command', '%s {' % decls[0][:-1])
1671 # Setup common to call wrappers. First parameter is always dispatchable
1672 dispatchable_type = cmdinfo.elem.find('param/type').text
1673 dispatchable_name = cmdinfo.elem.find('param/name').text
1674 # Default to device
1675 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001676 dispatch_table_name = 'VkLayerDispatchTable'
1677 # Set to instance as necessary
1678 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1679 device_or_instance = 'instance'
1680 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001681 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001682 api_function_name = cmdinfo.elem.attrib.get('name')
1683 params = cmdinfo.elem.findall('param/name')
1684 paramstext = ', '.join([str(param.text) for param in params])
Tony-LunarG152a88b2019-03-20 15:42:24 -06001685 API = api_function_name.replace('vk','Dispatch') + '('
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001686
1687 # Declare result variable, if any.
1688 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001689 'PFN_vkVoidFunction': 'return nullptr;',
1690 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001691 'VkDeviceAddress': 'return 0;',
1692 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1693 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001694 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001695 }
1696 resulttype = cmdinfo.elem.find('proto/type')
1697 assignresult = ''
1698 if (resulttype.text != 'void'):
1699 assignresult = resulttype.text + ' result = '
1700
1701 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001702 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001703
1704 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001705 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001706 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001707 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1708 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1709 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001710
1711 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001712 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001713 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001714 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001715 self.appendSection('command', ' }')
1716
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001717 # Insert pre-dispatch debug utils function call
1718 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001719 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001720
1721 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001722 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001723
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001724 # Insert post-dispatch debug utils function call
1725 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001726 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001727
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001728 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001729 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001730 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001731 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001732 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001733 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001734 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001735 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001736 # Return result variable, if any.
1737 if (resulttype.text != 'void'):
1738 self.appendSection('command', ' return result;')
1739 self.appendSection('command', '}')
1740 #
1741 # Override makeProtoName to drop the "vk" prefix
1742 def makeProtoName(self, name, tail):
1743 return self.genOpts.apientry + name[2:] + tail