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