blob: babceb63808c8ee63d0235d1617b99eb61889462 [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;
Mark Lobodzinskidd28ee22019-06-04 14:20:56 -0600342 // Wrapping Descriptor Template Update structures requires access to the template createinfo structs
343 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_createinfo_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700344 struct SubpassesUsageStates {
345 std::unordered_set<uint32_t> subpasses_using_color_attachment;
346 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
347 };
348 // Uses unwrapped handles
349 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
350 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
351 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
352 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700353 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
354 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700355
356
357 // Unwrap a handle. Must hold lock.
358 template <typename HandleType>
359 HandleType Unwrap(HandleType wrappedHandle) {
360 // TODO: don't use operator[] here.
361 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
362 }
363
364 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
365 template <typename HandleType>
366 HandleType WrapNew(HandleType newlyCreatedHandle) {
367 auto unique_id = global_unique_id++;
368 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
369 return (HandleType)unique_id;
370 }
371
372 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
373 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
374 auto unique_id = global_unique_id++;
375 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
376 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
377 return (VkDisplayKHR)unique_id;
378 }
379
380 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
381 // creating another. Must hold lock.
382 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
383 // See if this display is already known
384 auto it = map_data->display_id_reverse_mapping.find(handle);
385 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
386 // Unknown, so wrap
387 return WrapDisplay(handle, map_data);
388 }
389
390 // Pre/post hook point declarations
391"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600392
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700393 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600394// This file is ***GENERATED***. Do Not Edit.
395// See layer_chassis_generator.py for modifications.
396
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700397/* Copyright (c) 2015-2019 The Khronos Group Inc.
398 * Copyright (c) 2015-2019 Valve Corporation
399 * Copyright (c) 2015-2019 LunarG, Inc.
400 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600401 *
402 * Licensed under the Apache License, Version 2.0 (the "License");
403 * you may not use this file except in compliance with the License.
404 * You may obtain a copy of the License at
405 *
406 * http://www.apache.org/licenses/LICENSE-2.0
407 *
408 * Unless required by applicable law or agreed to in writing, software
409 * distributed under the License is distributed on an "AS IS" BASIS,
410 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
411 * See the License for the specific language governing permissions and
412 * limitations under the License.
413 *
414 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700415 */"""
416
417 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600418
419#include <string.h>
420#include <mutex>
421
422#define VALIDATION_ERROR_MAP_IMPL
423
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600424#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700425#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600426
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600427std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600428
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700429// Global unique object identifier. All increments must be guarded by a lock.
430uint64_t global_unique_id = 1;
431// Map uniqueID to actual object handle
432std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
433
434// TODO: This variable controls handle wrapping -- in the future it should be hooked
435// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
436#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
437bool wrap_handles = true;
438#else
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600439bool wrap_handles = false;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700440#endif
441
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600442// Set layer name -- Khronos layer name overrides any other defined names
Mark Lobodzinskiaa6fd7b2019-03-19 09:26:48 -0600443#if BUILD_KHRONOS_VALIDATION
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600444#define OBJECT_LAYER_NAME "VK_LAYER_KHRONOS_validation"
445#define OBJECT_LAYER_DESCRIPTION "khronos_validation"
446#elif BUILD_OBJECT_TRACKER
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700447#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600448#define OBJECT_LAYER_DESCRIPTION "lunarg_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700449#elif BUILD_THREAD_SAFETY
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700450#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600451#define OBJECT_LAYER_DESCRIPTION "google_thread_checker"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700452#elif BUILD_PARAMETER_VALIDATION
453#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600454#define OBJECT_LAYER_DESCRIPTION "lunarg_parameter_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700455#elif BUILD_CORE_VALIDATION
456#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600457#define OBJECT_LAYER_DESCRIPTION "lunarg_core_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700458#else
459#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600460#define OBJECT_LAYER_DESCRIPTION "lunarg_unique_objects"
461#endif
462
463// Include layer validation object definitions
464#if BUILD_OBJECT_TRACKER
465#include "object_lifetime_validation.h"
466#endif
467#if BUILD_THREAD_SAFETY
468#include "thread_safety.h"
469#endif
470#if BUILD_PARAMETER_VALIDATION
471#include "stateless_validation.h"
472#endif
473#if BUILD_CORE_VALIDATION
474#include "core_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700475#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600476
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600477namespace vulkan_layer_chassis {
478
479using std::unordered_map;
480
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600481static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700482 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600483};
484
John Zulauf358462e2019-04-10 11:10:32 -0600485static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION},
486 {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION}};
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600487
488extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
489
490
491// Manually written functions
492
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700493// Check enabled instance extensions against supported instance extension whitelist
494static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
495 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
496 // Check for recognized instance extensions
497 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
498 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
499 kVUIDUndefined,
500 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
501 "results and/or produce undefined behavior.",
502 pCreateInfo->ppEnabledExtensionNames[i]);
503 }
504 }
505}
506
507// Check enabled device extensions against supported device extension whitelist
508static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
509 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
510 // Check for recognized device extensions
511 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
512 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
513 kVUIDUndefined,
514 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
515 "results and/or produce undefined behavior.",
516 pCreateInfo->ppEnabledExtensionNames[i]);
517 }
518 }
519}
520
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600521
522// Process validation features, flags and settings specified through extensions, a layer settings file, or environment variables
523
524static const std::unordered_map<std::string, VkValidationFeatureDisableEXT> VkValFeatureDisableLookup = {
525 {"VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT", VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT},
526 {"VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT", VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT},
527 {"VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT", VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT},
528 {"VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT", VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT},
529 {"VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT", VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT},
530 {"VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT", VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT},
531 {"VK_VALIDATION_FEATURE_DISABLE_ALL_EXT", VK_VALIDATION_FEATURE_DISABLE_ALL_EXT},
532};
533
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600534static const std::unordered_map<std::string, VkValidationFeatureEnableEXT> VkValFeatureEnableLookup = {
535 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT},
536 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT},
537};
538
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600539static const std::unordered_map<std::string, ValidationCheckDisables> ValidationDisableLookup = {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600540 {"VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE", VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600541 {"VALIDATION_CHECK_DISABLE_OBJECT_IN_USE", VALIDATION_CHECK_DISABLE_OBJECT_IN_USE},
542 {"VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET", VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET},
543 {"VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE", VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE},
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600544 {"VALIDATION_CHECK_DISABLE_QUERY_VALIDATION", VALIDATION_CHECK_DISABLE_QUERY_VALIDATION},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600545};
546
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600547// Set the local disable flag for the appropriate VALIDATION_CHECK_DISABLE enum
548void SetValidationDisable(CHECK_DISABLED* disable_data, const ValidationCheckDisables disable_id) {
549 switch (disable_id) {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600550 case VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE:
551 disable_data->command_buffer_state = true;
552 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600553 case VALIDATION_CHECK_DISABLE_OBJECT_IN_USE:
554 disable_data->object_in_use = true;
555 break;
556 case VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET:
557 disable_data->idle_descriptor_set = true;
558 break;
559 case VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE:
560 disable_data->push_constant_range = true;
561 break;
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600562 case VALIDATION_CHECK_DISABLE_QUERY_VALIDATION:
563 disable_data->query_validation = true;
564 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600565 default:
566 assert(true);
567 }
568}
569
570// Set the local disable flag for a single VK_VALIDATION_FEATURE_DISABLE_* flag
571void SetValidationFeatureDisable(CHECK_DISABLED* disable_data, const VkValidationFeatureDisableEXT feature_disable) {
572 switch (feature_disable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700573 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600574 disable_data->shader_validation = true;
575 break;
576 case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
577 disable_data->thread_safety = true;
578 break;
579 case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
580 disable_data->stateless_checks = true;
581 break;
582 case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
583 disable_data->object_tracking = true;
584 break;
585 case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
586 disable_data->core_checks = true;
587 break;
588 case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
589 disable_data->handle_wrapping = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700590 break;
591 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
592 // Set all disabled flags to true
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600593 disable_data->SetAll(true);
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700594 break;
595 default:
596 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700597 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600598}
599
600// Set the local enable flag for a single VK_VALIDATION_FEATURE_ENABLE_* flag
601void SetValidationFeatureEnable(CHECK_ENABLED *enable_data, const VkValidationFeatureEnableEXT feature_enable) {
602 switch (feature_enable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700603 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600604 enable_data->gpu_validation = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700605 break;
606 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600607 enable_data->gpu_validation_reserve_binding_slot = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700608 break;
609 default:
610 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700611 }
612}
613
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600614// Set the local disable flag for settings specified through the VK_EXT_validation_flags extension
615void SetValidationFlags(CHECK_DISABLED* disables, const VkValidationFlagsEXT* val_flags_struct) {
616 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
617 switch (val_flags_struct->pDisabledValidationChecks[i]) {
618 case VK_VALIDATION_CHECK_SHADERS_EXT:
619 disables->shader_validation = true;
620 break;
621 case VK_VALIDATION_CHECK_ALL_EXT:
622 // Set all disabled flags to true
623 disables->SetAll(true);
624 break;
625 default:
626 break;
627 }
628 }
629}
630
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600631// Process Validation Features flags specified through the ValidationFeature extension
632void SetValidationFeatures(CHECK_DISABLED *disable_data, CHECK_ENABLED *enable_data,
633 const VkValidationFeaturesEXT *val_features_struct) {
634 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
635 SetValidationFeatureDisable(disable_data, val_features_struct->pDisabledValidationFeatures[i]);
636 }
637 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
638 SetValidationFeatureEnable(enable_data, val_features_struct->pEnabledValidationFeatures[i]);
639 }
640}
641
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600642// Given a string representation of a list of enable enum values, call the appropriate setter function
643void SetLocalEnableSetting(std::string list_of_enables, std::string delimiter, CHECK_ENABLED* enables) {
644 size_t pos = 0;
645 std::string token;
646 while (list_of_enables.length() != 0) {
647 pos = list_of_enables.find(delimiter);
648 if (pos != std::string::npos) {
649 token = list_of_enables.substr(0, pos);
650 } else {
651 pos = list_of_enables.length() - delimiter.length();
652 token = list_of_enables;
653 }
654 if (token.find("VK_VALIDATION_FEATURE_ENABLE_") != std::string::npos) {
655 auto result = VkValFeatureEnableLookup.find(token);
656 if (result != VkValFeatureEnableLookup.end()) {
657 SetValidationFeatureEnable(enables, result->second);
658 }
659 }
660 list_of_enables.erase(0, pos + delimiter.length());
661 }
662}
663
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600664// Given a string representation of a list of disable enum values, call the appropriate setter function
665void SetLocalDisableSetting(std::string list_of_disables, std::string delimiter, CHECK_DISABLED* disables) {
666 size_t pos = 0;
667 std::string token;
668 while (list_of_disables.length() != 0) {
669 pos = list_of_disables.find(delimiter);
670 if (pos != std::string::npos) {
671 token = list_of_disables.substr(0, pos);
672 } else {
673 pos = list_of_disables.length() - delimiter.length();
674 token = list_of_disables;
675 }
676 if (token.find("VK_VALIDATION_FEATURE_DISABLE_") != std::string::npos) {
677 auto result = VkValFeatureDisableLookup.find(token);
678 if (result != VkValFeatureDisableLookup.end()) {
679 SetValidationFeatureDisable(disables, result->second);
680 }
681 }
682 if (token.find("VALIDATION_CHECK_DISABLE_") != std::string::npos) {
683 auto result = ValidationDisableLookup.find(token);
684 if (result != ValidationDisableLookup.end()) {
685 SetValidationDisable(disables, result->second);
686 }
687 }
688 list_of_disables.erase(0, pos + delimiter.length());
689 }
690}
691
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600692// Process enables and disables set though the vk_layer_settings.txt config file or through an environment variable
693void ProcessConfigAndEnvSettings(const char* layer_description, CHECK_ENABLED* enables, CHECK_DISABLED* disables) {
694 std::string enable_key = layer_description;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600695 std::string disable_key = layer_description;
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600696 enable_key.append(".enables");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600697 disable_key.append(".disables");
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600698 std::string list_of_config_enables = getLayerOption(enable_key.c_str());
699 std::string list_of_env_enables = GetLayerEnvVar("VK_LAYER_ENABLES");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600700 std::string list_of_config_disables = getLayerOption(disable_key.c_str());
701 std::string list_of_env_disables = GetLayerEnvVar("VK_LAYER_DISABLES");
702#if defined(_WIN32)
703 std::string env_delimiter = ";";
704#else
705 std::string env_delimiter = ":";
706#endif
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600707 SetLocalEnableSetting(list_of_config_enables, ",", enables);
708 SetLocalEnableSetting(list_of_env_enables, env_delimiter, enables);
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600709 SetLocalDisableSetting(list_of_config_disables, ",", disables);
710 SetLocalDisableSetting(list_of_env_disables, env_delimiter, disables);
711}
712
713
714// Non-code-generated chassis API functions
715
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600716VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600717 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700718 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700719 return nullptr;
720 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600721 const auto &item = name_to_funcptr_map.find(funcName);
722 if (item != name_to_funcptr_map.end()) {
723 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
724 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600725 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600726 if (!table.GetDeviceProcAddr) return nullptr;
727 return table.GetDeviceProcAddr(device, funcName);
728}
729
730VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600731 const auto &item = name_to_funcptr_map.find(funcName);
732 if (item != name_to_funcptr_map.end()) {
733 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
734 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600735 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
736 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600737 if (!table.GetInstanceProcAddr) return nullptr;
738 return table.GetInstanceProcAddr(instance, funcName);
739}
740
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600741VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
742 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
743}
744
745VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
746 VkLayerProperties *pProperties) {
747 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
748}
749
750VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
751 VkExtensionProperties *pProperties) {
752 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
John Zulauf358462e2019-04-10 11:10:32 -0600753 return util_GetExtensionProperties(ARRAY_SIZE(instance_extensions), instance_extensions, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600754
755 return VK_ERROR_LAYER_NOT_PRESENT;
756}
757
758VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
759 uint32_t *pCount, VkExtensionProperties *pProperties) {
760 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600761 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600762 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
Lenny Komow7b567f72019-06-10 16:49:43 -0600763 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600764}
765
766VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
767 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600768 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600769
770 assert(chain_info->u.pLayerInfo);
771 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
772 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
773 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
774 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700775 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
776 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
777
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600778 CHECK_ENABLED local_enables {};
779 CHECK_DISABLED local_disables {};
780 const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(pCreateInfo->pNext);
781 if (validation_features_ext) {
782 SetValidationFeatures(&local_disables, &local_enables, validation_features_ext);
783 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600784 const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
785 if (validation_flags_ext) {
786 SetValidationFlags(&local_disables, validation_flags_ext);
787 }
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600788 ProcessConfigAndEnvSettings(OBJECT_LAYER_DESCRIPTION, &local_enables, &local_disables);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600789
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600790 // Create temporary dispatch vector for pre-calls until instance is created
791 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600792 // Add VOs to dispatch vector. Order here will be the validation dispatch order!
793#if BUILD_THREAD_SAFETY
794 auto thread_checker = new ThreadSafety;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600795 if (!local_disables.thread_safety) {
796 local_object_dispatch.emplace_back(thread_checker);
797 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600798 thread_checker->container_type = LayerObjectTypeThreading;
799 thread_checker->api_version = api_version;
800#endif
801#if BUILD_PARAMETER_VALIDATION
802 auto parameter_validation = new StatelessValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600803 if (!local_disables.stateless_checks) {
804 local_object_dispatch.emplace_back(parameter_validation);
805 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600806 parameter_validation->container_type = LayerObjectTypeParameterValidation;
807 parameter_validation->api_version = api_version;
808#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700809#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600810 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600811 if (!local_disables.object_tracking) {
812 local_object_dispatch.emplace_back(object_tracker);
813 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600814 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700815 object_tracker->api_version = api_version;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600816#endif
817#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700818 auto core_checks = new CoreChecks;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600819 if (!local_disables.core_checks) {
820 local_object_dispatch.emplace_back(core_checks);
821 }
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700822 core_checks->container_type = LayerObjectTypeCoreValidation;
823 core_checks->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700824#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600825
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600826 // If handle wrapping is disabled via the ValidationFeatures extension, override build flag
827 if (local_disables.handle_wrapping) {
828 wrap_handles = false;
829 }
830
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600831 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600832 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600833 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
834 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600835 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600836 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
837 }
838
839 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600840 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600841
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600842 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600843
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600844 framework->object_dispatch = local_object_dispatch;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700845 framework->container_type = LayerObjectTypeInstance;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600846 framework->disabled = local_disables;
847 framework->enabled = local_enables;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600848
849 framework->instance = *pInstance;
850 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
851 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
852 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700853 framework->api_version = api_version;
854 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
855
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600856 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, OBJECT_LAYER_DESCRIPTION);
857
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700858#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700859 object_tracker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600860 object_tracker->instance_dispatch_table = framework->instance_dispatch_table;
861 object_tracker->enabled = framework->enabled;
862 object_tracker->disabled = framework->disabled;
863#endif
864#if BUILD_THREAD_SAFETY
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700865 thread_checker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600866 thread_checker->instance_dispatch_table = framework->instance_dispatch_table;
867 thread_checker->enabled = framework->enabled;
868 thread_checker->disabled = framework->disabled;
869#endif
870#if BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700871 parameter_validation->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600872 parameter_validation->instance_dispatch_table = framework->instance_dispatch_table;
873 parameter_validation->enabled = framework->enabled;
874 parameter_validation->disabled = framework->disabled;
875#endif
876#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700877 core_checks->report_data = framework->report_data;
878 core_checks->instance_dispatch_table = framework->instance_dispatch_table;
879 core_checks->instance = *pInstance;
880 core_checks->enabled = framework->enabled;
881 core_checks->disabled = framework->disabled;
882 core_checks->instance_state = core_checks;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700883#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600884
885 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700886 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600887 }
888
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700889 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
890
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600891 return result;
892}
893
894VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
895 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600896 auto layer_data = GetLayerDataPtr(key, layer_data_map);
897 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700898 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600899 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
900 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600901 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700902 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600903 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
904 }
905
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600906 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600907
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600908 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700909 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600910 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
911 }
912 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600913 while (layer_data->logging_messenger.size() > 0) {
914 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
915 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
916 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600917 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600918 while (layer_data->logging_callback.size() > 0) {
919 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
920 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
921 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600922 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600923
924 layer_debug_utils_destroy_instance(layer_data->report_data);
925
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700926 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
927 delete *item;
928 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600929 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600930}
931
932VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
933 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600934 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600935
936 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
937
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600938 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
939 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600940 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
941 if (fpCreateDevice == NULL) {
942 return VK_ERROR_INITIALIZATION_FAILED;
943 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600944 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
945
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700946 // Get physical device limits for device
947 VkPhysicalDeviceProperties device_properties = {};
948 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
949
950 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
951 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
952
953 DeviceExtensions device_extensions = {};
954 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
955 for (auto item : instance_interceptor->object_dispatch) {
956 item->device_extensions = device_extensions;
957 }
958
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700959 std::unique_ptr<safe_VkDeviceCreateInfo> modified_create_info(new safe_VkDeviceCreateInfo(pCreateInfo));
960
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700961 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600962 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700963 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700964 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700965 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600966 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600967 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700968 auto lock = intercept->write_lock();
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700969 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, modified_create_info);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600970 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600971
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700972 VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(modified_create_info.get()), pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600973 if (result != VK_SUCCESS) {
974 return result;
975 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600976
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600977 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700978 device_interceptor->container_type = LayerObjectTypeDevice;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700979
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700980 // Save local info in device object
981 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700982 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
983 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700984 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700985
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600986 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700987
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600988 device_interceptor->device = *pDevice;
989 device_interceptor->physical_device = gpu;
990 device_interceptor->instance = instance_interceptor->instance;
991 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600992
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600993 // Note that this defines the order in which the layer validation objects are called
994#if BUILD_THREAD_SAFETY
995 auto thread_safety = new ThreadSafety;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600996 thread_safety->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600997 if (!instance_interceptor->disabled.thread_safety) {
998 device_interceptor->object_dispatch.emplace_back(thread_safety);
999 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001000#endif
1001#if BUILD_PARAMETER_VALIDATION
1002 auto stateless_validation = new StatelessValidation;
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001003 stateless_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001004 if (!instance_interceptor->disabled.stateless_checks) {
1005 device_interceptor->object_dispatch.emplace_back(stateless_validation);
1006 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001007#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001008#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001009 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001010 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001011 if (!instance_interceptor->disabled.object_tracking) {
1012 device_interceptor->object_dispatch.emplace_back(object_tracker);
1013 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001014#endif
1015#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001016 auto core_checks = new CoreChecks;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001017 core_checks->container_type = LayerObjectTypeCoreValidation;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001018 core_checks->instance_state = reinterpret_cast<CoreChecks *>(
1019 core_checks->GetValidationObject(instance_interceptor->object_dispatch, LayerObjectTypeCoreValidation));
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001020 if (!instance_interceptor->disabled.core_checks) {
1021 device_interceptor->object_dispatch.emplace_back(core_checks);
1022 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001023#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001024
Mark Lobodzinski7314bf42019-03-28 08:54:53 -06001025 // Set per-intercept common data items
1026 for (auto dev_intercept : device_interceptor->object_dispatch) {
1027 dev_intercept->device = *pDevice;
1028 dev_intercept->physical_device = gpu;
1029 dev_intercept->instance = instance_interceptor->instance;
1030 dev_intercept->report_data = device_interceptor->report_data;
1031 dev_intercept->device_dispatch_table = device_interceptor->device_dispatch_table;
1032 dev_intercept->api_version = device_interceptor->api_version;
1033 dev_intercept->disabled = instance_interceptor->disabled;
1034 dev_intercept->enabled = instance_interceptor->enabled;
1035 dev_intercept->instance_dispatch_table = instance_interceptor->instance_dispatch_table;
1036 dev_intercept->instance_extensions = instance_interceptor->instance_extensions;
1037 dev_intercept->device_extensions = device_interceptor->device_extensions;
1038 }
1039
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001040 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001041 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001042 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001043 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001044
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001045 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
1046
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001047 return result;
1048}
1049
1050VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
1051 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001052 auto layer_data = GetLayerDataPtr(key, layer_data_map);
1053 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001054 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001055 intercept->PreCallValidateDestroyDevice(device, pAllocator);
1056 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001057 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001058 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001059 intercept->PreCallRecordDestroyDevice(device, pAllocator);
1060 }
1061 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001062
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001063 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001064
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001065 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001066 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001067 intercept->PostCallRecordDestroyDevice(device, pAllocator);
1068 }
1069
Mark Lobodzinskic5003372018-12-17 16:36:01 -07001070 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
1071 delete *item;
1072 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001073 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001074}
1075
1076
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001077// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001078
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001079VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
1080 VkDevice device,
1081 VkPipelineCache pipelineCache,
1082 uint32_t createInfoCount,
1083 const VkGraphicsPipelineCreateInfo* pCreateInfos,
1084 const VkAllocationCallbacks* pAllocator,
1085 VkPipeline* pPipelines) {
1086 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1087 bool skip = false;
1088
1089#ifdef BUILD_CORE_VALIDATION
1090 create_graphics_pipeline_api_state cgpl_state{};
1091#else
1092 struct create_graphics_pipeline_api_state {
1093 const VkGraphicsPipelineCreateInfo* pCreateInfos;
1094 } cgpl_state;
1095 cgpl_state.pCreateInfos = pCreateInfos;
1096#endif
1097
1098 for (auto intercept : layer_data->object_dispatch) {
1099 auto lock = intercept->write_lock();
1100 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1101 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1102 }
1103 for (auto intercept : layer_data->object_dispatch) {
1104 auto lock = intercept->write_lock();
1105 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1106 }
1107
Tony-LunarG152a88b2019-03-20 15:42:24 -06001108 VkResult result = DispatchCreateGraphicsPipelines(device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001109
1110 for (auto intercept : layer_data->object_dispatch) {
1111 auto lock = intercept->write_lock();
1112 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
1113 }
1114 return result;
1115}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001116
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001117// This API saves some core_validation pipeline state state on the stack for performance purposes
1118VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
1119 VkDevice device,
1120 VkPipelineCache pipelineCache,
1121 uint32_t createInfoCount,
1122 const VkComputePipelineCreateInfo* pCreateInfos,
1123 const VkAllocationCallbacks* pAllocator,
1124 VkPipeline* pPipelines) {
1125 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1126 bool skip = false;
1127
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001128#ifdef BUILD_CORE_VALIDATION
1129 create_compute_pipeline_api_state ccpl_state{};
1130#else
1131 struct create_compute_pipeline_api_state {
1132 const VkComputePipelineCreateInfo* pCreateInfos;
1133 } ccpl_state;
1134 ccpl_state.pCreateInfos = pCreateInfos;
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001135#endif
1136
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001137 for (auto intercept : layer_data->object_dispatch) {
1138 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001139 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001140 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1141 }
1142 for (auto intercept : layer_data->object_dispatch) {
1143 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001144 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001145 }
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001146 VkResult result = DispatchCreateComputePipelines(device, pipelineCache, createInfoCount, ccpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001147 for (auto intercept : layer_data->object_dispatch) {
1148 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001149 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001150 }
1151 return result;
1152}
1153
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001154VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
1155 VkDevice device,
1156 VkPipelineCache pipelineCache,
1157 uint32_t createInfoCount,
1158 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
1159 const VkAllocationCallbacks* pAllocator,
1160 VkPipeline* pPipelines) {
1161 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1162 bool skip = false;
1163
1164#ifndef BUILD_CORE_VALIDATION
1165 struct PIPELINE_STATE {};
1166#endif
1167
1168 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
1169
1170 for (auto intercept : layer_data->object_dispatch) {
1171 auto lock = intercept->write_lock();
1172 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
1173 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1174 }
1175 for (auto intercept : layer_data->object_dispatch) {
1176 auto lock = intercept->write_lock();
1177 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1178 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001179 VkResult result = DispatchCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001180 for (auto intercept : layer_data->object_dispatch) {
1181 auto lock = intercept->write_lock();
1182 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1183 }
1184 return result;
1185}
1186
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001187// This API needs the ability to modify a down-chain parameter
1188VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
1189 VkDevice device,
1190 const VkPipelineLayoutCreateInfo* pCreateInfo,
1191 const VkAllocationCallbacks* pAllocator,
1192 VkPipelineLayout* pPipelineLayout) {
1193 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1194 bool skip = false;
1195
1196#ifndef BUILD_CORE_VALIDATION
1197 struct create_pipeline_layout_api_state {
1198 VkPipelineLayoutCreateInfo modified_create_info;
1199 };
1200#endif
1201 create_pipeline_layout_api_state cpl_state{};
1202 cpl_state.modified_create_info = *pCreateInfo;
1203
1204 for (auto intercept : layer_data->object_dispatch) {
1205 auto lock = intercept->write_lock();
1206 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1207 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1208 }
1209 for (auto intercept : layer_data->object_dispatch) {
1210 auto lock = intercept->write_lock();
1211 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1212 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001213 VkResult result = DispatchCreatePipelineLayout(device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001214 for (auto intercept : layer_data->object_dispatch) {
1215 auto lock = intercept->write_lock();
1216 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1217 }
1218 return result;
1219}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001220
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001221// This API needs some local stack data for performance reasons and also may modify a parameter
1222VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1223 VkDevice device,
1224 const VkShaderModuleCreateInfo* pCreateInfo,
1225 const VkAllocationCallbacks* pAllocator,
1226 VkShaderModule* pShaderModule) {
1227 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1228 bool skip = false;
1229
1230#ifndef BUILD_CORE_VALIDATION
1231 struct create_shader_module_api_state {
1232 VkShaderModuleCreateInfo instrumented_create_info;
1233 };
1234#endif
1235 create_shader_module_api_state csm_state{};
1236 csm_state.instrumented_create_info = *pCreateInfo;
1237
1238 for (auto intercept : layer_data->object_dispatch) {
1239 auto lock = intercept->write_lock();
1240 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1241 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1242 }
1243 for (auto intercept : layer_data->object_dispatch) {
1244 auto lock = intercept->write_lock();
1245 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1246 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001247 VkResult result = DispatchCreateShaderModule(device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001248 for (auto intercept : layer_data->object_dispatch) {
1249 auto lock = intercept->write_lock();
1250 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1251 }
1252 return result;
1253}
1254
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001255VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1256 VkDevice device,
1257 const VkDescriptorSetAllocateInfo* pAllocateInfo,
1258 VkDescriptorSet* pDescriptorSets) {
1259 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1260 bool skip = false;
1261
1262#ifdef BUILD_CORE_VALIDATION
1263 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1264#else
1265 struct ads_state {} ads_state;
1266#endif
1267
1268 for (auto intercept : layer_data->object_dispatch) {
1269 auto lock = intercept->write_lock();
1270 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1271 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1272 }
1273 for (auto intercept : layer_data->object_dispatch) {
1274 auto lock = intercept->write_lock();
1275 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1276 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001277 VkResult result = DispatchAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001278 for (auto intercept : layer_data->object_dispatch) {
1279 auto lock = intercept->write_lock();
1280 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1281 }
1282 return result;
1283}
1284
1285
1286
1287
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001288
1289// ValidationCache APIs do not dispatch
1290
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001291VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1292 VkDevice device,
1293 const VkValidationCacheCreateInfoEXT* pCreateInfo,
1294 const VkAllocationCallbacks* pAllocator,
1295 VkValidationCacheEXT* pValidationCache) {
1296 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1297 VkResult result = VK_SUCCESS;
1298
1299 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1300 if (validation_data) {
1301 auto lock = validation_data->write_lock();
1302 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1303 }
1304 return result;
1305}
1306
1307VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1308 VkDevice device,
1309 VkValidationCacheEXT validationCache,
1310 const VkAllocationCallbacks* pAllocator) {
1311 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1312
1313 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1314 if (validation_data) {
1315 auto lock = validation_data->write_lock();
1316 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1317 }
1318}
1319
1320VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1321 VkDevice device,
1322 VkValidationCacheEXT dstCache,
1323 uint32_t srcCacheCount,
1324 const VkValidationCacheEXT* pSrcCaches) {
1325 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1326 VkResult result = VK_SUCCESS;
1327
1328 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1329 if (validation_data) {
1330 auto lock = validation_data->write_lock();
1331 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1332 }
1333 return result;
1334}
1335
1336VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1337 VkDevice device,
1338 VkValidationCacheEXT validationCache,
1339 size_t* pDataSize,
1340 void* pData) {
1341 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1342 VkResult result = VK_SUCCESS;
1343
1344 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1345 if (validation_data) {
1346 auto lock = validation_data->write_lock();
1347 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1348 }
1349 return result;
1350
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001351}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001352
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001353 inline_custom_validation_class_definitions = """
1354 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1355 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1356 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1357 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001358
1359 // Allow additional parameter for CreateGraphicsPipelines
1360 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1361 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1362 };
1363 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1364 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1365 };
1366 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1367 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1368 };
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001369 virtual void PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* ccpl_state) {
1370 PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1371 };
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001372 // Allow additional state parameter for CreateComputePipelines
1373 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1374 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1375 };
1376 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1377 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1378 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001379
1380 // Allow additional state parameter for CreateRayTracingPipelinesNV
1381 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1382 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1383 };
1384 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1385 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1386 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001387
1388 // Allow modification of a down-chain parameter for CreatePipelineLayout
1389 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1390 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1391 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001392
1393 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1394 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1395 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1396 };
1397 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1398 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1399 };
1400 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1401 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1402 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001403
1404 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1405 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1406 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1407 };
1408 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1409 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1410 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001411
1412 // Modify a parameter to CreateDevice
1413 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1414 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1415 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001416"""
1417
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001418 inline_custom_source_postamble = """
1419// loader-layer interface v0, just wrappers since there is only a layer
1420
1421VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1422 VkExtensionProperties *pProperties) {
1423 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1424}
1425
1426VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1427 VkLayerProperties *pProperties) {
1428 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1429}
1430
1431VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1432 VkLayerProperties *pProperties) {
1433 // the layer command handles VK_NULL_HANDLE just fine internally
1434 assert(physicalDevice == VK_NULL_HANDLE);
1435 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1436}
1437
1438VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1439 const char *pLayerName, uint32_t *pCount,
1440 VkExtensionProperties *pProperties) {
1441 // the layer command handles VK_NULL_HANDLE just fine internally
1442 assert(physicalDevice == VK_NULL_HANDLE);
1443 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1444}
1445
1446VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1447 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1448}
1449
1450VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1451 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1452}
1453
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001454VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1455 assert(pVersionStruct != NULL);
1456 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1457
1458 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1459 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1460 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1461 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
Mark Lobodzinski56e88122019-03-26 10:21:48 -06001462 pVersionStruct->pfnGetPhysicalDeviceProcAddr = nullptr;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001463 }
1464
1465 return VK_SUCCESS;
1466}"""
1467
1468
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001469 def __init__(self,
1470 errFile = sys.stderr,
1471 warnFile = sys.stderr,
1472 diagFile = sys.stdout):
1473 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1474 # Internal state - accumulators for different inner block text
1475 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1476 self.intercepts = []
1477 self.layer_factory = '' # String containing base layer factory class definition
1478
1479 # Check if the parameter passed in is a pointer to an array
1480 def paramIsArray(self, param):
1481 return param.attrib.get('len') is not None
1482
1483 # Check if the parameter passed in is a pointer
1484 def paramIsPointer(self, param):
1485 ispointer = False
1486 for elem in param:
Raul Tambre7b300182019-05-04 11:25:14 +03001487 if elem.tag == 'type' and elem.tail is not None and '*' in elem.tail:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001488 ispointer = True
1489 return ispointer
1490
1491 # Check if an object is a non-dispatchable handle
1492 def isHandleTypeNonDispatchable(self, handletype):
1493 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1494 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1495 return True
1496 else:
1497 return False
1498
1499 # Check if an object is a dispatchable handle
1500 def isHandleTypeDispatchable(self, handletype):
1501 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1502 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
1503 return True
1504 else:
1505 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001506 #
1507 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001508 def beginFile(self, genOpts):
1509 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001510 # Output Copyright
1511 write(self.inline_copyright_message, file=self.outFile)
1512 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001513 self.header = False
1514 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1515 self.header = True
1516 write('#pragma once', file=self.outFile)
1517 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001518 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001519 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001520 else:
1521 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001522 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001523 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001524 #
1525 def endFile(self):
1526 # Finish C++ namespace and multiple inclusion protection
1527 self.newline()
1528 if not self.header:
1529 # Record intercepted procedures
1530 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
1531 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
1532 write('\n'.join(self.intercepts), file=self.outFile)
1533 write('};\n', file=self.outFile)
1534 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001535 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001536 if self.header:
1537 self.newline()
1538 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001539 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001540 self.layer_factory += '};\n\n'
1541 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001542 write(self.layer_factory, file=self.outFile)
1543 else:
1544 write(self.inline_custom_source_postamble, file=self.outFile)
1545 # Finish processing in superclass
1546 OutputGenerator.endFile(self)
1547
1548 def beginFeature(self, interface, emit):
1549 # Start processing in superclass
1550 OutputGenerator.beginFeature(self, interface, emit)
1551 # Get feature extra protect
1552 self.featureExtraProtect = GetFeatureProtect(interface)
1553 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1554 # feature. They're only printed in endFeature().
1555 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1556
1557 def endFeature(self):
1558 # Actually write the interface to the output file.
1559 if (self.emit):
1560 self.newline()
1561 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1562 # or move it below the 'for section...' loop.
1563 if (self.featureExtraProtect != None):
1564 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1565 for section in self.TYPE_SECTIONS:
1566 contents = self.sections[section]
1567 if contents:
1568 write('\n'.join(contents), file=self.outFile)
1569 self.newline()
1570 if (self.sections['command']):
1571 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1572 self.newline()
1573 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001574 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001575 # Finish processing in superclass
1576 OutputGenerator.endFeature(self)
1577 #
1578 # Append a definition to the specified section
1579 def appendSection(self, section, text):
1580 self.sections[section].append(text)
1581 #
1582 # Type generation
1583 def genType(self, typeinfo, name, alias):
1584 pass
1585 #
1586 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1587 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1588 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1589 # structs etc.)
1590 def genStruct(self, typeinfo, typeName):
1591 OutputGenerator.genStruct(self, typeinfo, typeName)
1592 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1593 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1594 for member in typeinfo.elem.findall('.//member'):
1595 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1596 body += ';\n'
1597 body += '} ' + typeName + ';\n'
1598 self.appendSection('struct', body)
1599 #
1600 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1601 def genGroup(self, groupinfo, groupName, alias):
1602 pass
1603 # Enumerant generation
1604 # <enum> tags may specify their values in several ways, but are usually just integers.
1605 def genEnum(self, enuminfo, name, alias):
1606 pass
1607 #
1608 # Customize Cdecl for layer factory base class
1609 def BaseClassCdecl(self, elem, name):
1610 raw = self.makeCDecls(elem)[1]
1611
1612 # Toss everything before the undecorated name
1613 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1614 prototype = prototype.replace(")", "", 1)
1615 prototype = prototype.replace(";", " {};")
1616
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001617 # Build up pre/post call virtual function declarations
1618 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1619 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1620 pre_call_record = 'virtual void PreCallRecord' + prototype
1621 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001622 resulttype = elem.find('proto/type')
1623 if resulttype.text == 'VkResult':
1624 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001625 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1626 #
1627 # Command generation
1628 def genCmd(self, cmdinfo, name, alias):
1629 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001630 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001631 ]
1632
1633 if name in ignore_functions:
1634 return
1635
1636 if self.header: # In the header declare all intercepts
1637 self.appendSection('command', '')
1638 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1639 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001640 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1641 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001642 if 'ValidationCache' not in name:
1643 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001644 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001645 self.layer_factory += '#endif\n'
1646 return
1647
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001648 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001649 if 'ValidationCache' not in name:
1650 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1651 else:
1652 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1653 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1654 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001655 return
1656 # Record that the function will be intercepted
1657 if (self.featureExtraProtect != None):
1658 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1659 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1660 if (self.featureExtraProtect != None):
1661 self.intercepts += [ '#endif' ]
1662 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1663 #
1664 decls = self.makeCDecls(cmdinfo.elem)
1665 self.appendSection('command', '')
1666 self.appendSection('command', '%s {' % decls[0][:-1])
1667 # Setup common to call wrappers. First parameter is always dispatchable
1668 dispatchable_type = cmdinfo.elem.find('param/type').text
1669 dispatchable_name = cmdinfo.elem.find('param/name').text
1670 # Default to device
1671 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001672 dispatch_table_name = 'VkLayerDispatchTable'
1673 # Set to instance as necessary
1674 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1675 device_or_instance = 'instance'
1676 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001677 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001678 api_function_name = cmdinfo.elem.attrib.get('name')
1679 params = cmdinfo.elem.findall('param/name')
1680 paramstext = ', '.join([str(param.text) for param in params])
Tony-LunarG152a88b2019-03-20 15:42:24 -06001681 API = api_function_name.replace('vk','Dispatch') + '('
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001682
1683 # Declare result variable, if any.
1684 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001685 'PFN_vkVoidFunction': 'return nullptr;',
1686 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001687 'VkDeviceAddress': 'return 0;',
1688 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1689 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001690 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001691 }
1692 resulttype = cmdinfo.elem.find('proto/type')
1693 assignresult = ''
1694 if (resulttype.text != 'void'):
1695 assignresult = resulttype.text + ' result = '
1696
1697 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001698 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001699
1700 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001701 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001702 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001703 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1704 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1705 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001706
1707 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001708 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001709 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001710 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001711 self.appendSection('command', ' }')
1712
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001713 # Insert pre-dispatch debug utils function call
1714 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001715 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001716
1717 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001718 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001719
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001720 # Insert post-dispatch debug utils function call
1721 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001722 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001723
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001724 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001725 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001726 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001727 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001728 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001729 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001730 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001731 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001732 # Return result variable, if any.
1733 if (resulttype.text != 'void'):
1734 self.appendSection('command', ' return result;')
1735 self.appendSection('command', '}')
1736 #
1737 # Override makeProtoName to drop the "vk" prefix
1738 def makeProtoName(self, name, tail):
1739 return self.genOpts.apientry + name[2:] + tail