blob: cae2a58e999bba7fbf410aac1b7f1870f32241f8 [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07003# Copyright (c) 2015-2019 Valve Corporation
4# Copyright (c) 2015-2019 LunarG, Inc.
5# Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06006#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
20# Author: Mark Lobodzinski <mark@lunarg.com>
21#
22# This script generates the dispatch portion of a factory layer which intercepts
23# all Vulkan functions. The resultant factory layer allows rapid development of
24# layers and interceptors.
25
26import os,re,sys
27from generator import *
28from common_codegen import *
29
30# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31#
32# Adds options used by LayerFactoryOutputGenerator objects during factory
33# layer generation.
34#
35# Additional members
36# prefixText - list of strings to prefix generated header with
37# (usually a copyright statement + calling convention macros).
38# protectFile - True if multiple inclusion protection should be
39# generated (based on the filename) around the entire header.
40# protectFeature - True if #ifndef..#endif protection should be
41# generated around a feature interface in the header file.
42# genFuncPointers - True if function pointer typedefs should be
43# generated
44# protectProto - If conditional protection should be generated
45# around prototype declarations, set to either '#ifdef'
46# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47# to require opt-out (#ifndef protectProtoStr). Otherwise
48# set to None.
49# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50# declarations, if protectProto is set
51# apicall - string to use for the function declaration prefix,
52# such as APICALL on Windows.
53# apientry - string to use for the calling convention macro,
54# in typedefs, such as APIENTRY.
55# apientryp - string to use for the calling convention macro
56# in function pointer typedefs, such as APIENTRYP.
57# indentFuncProto - True if prototype declarations should put each
58# parameter on a separate line
59# indentFuncPointer - True if typedefed function pointers should put each
60# parameter on a separate line
61# alignFuncParam - if nonzero and parameters are being put on a
62# separate line, align parameter names at the specified column
63class LayerChassisGeneratorOptions(GeneratorOptions):
64 def __init__(self,
65 filename = None,
66 directory = '.',
67 apiname = None,
68 profile = None,
69 versions = '.*',
70 emitversions = '.*',
71 defaultExtensions = None,
72 addExtensions = None,
73 removeExtensions = None,
74 emitExtensions = None,
75 sortProcedure = regSortFeatures,
76 prefixText = "",
77 genFuncPointers = True,
78 protectFile = True,
79 protectFeature = True,
80 apicall = '',
81 apientry = '',
82 apientryp = '',
83 indentFuncProto = True,
84 indentFuncPointer = False,
85 alignFuncParam = 0,
86 helper_file_type = '',
87 expandEnumerants = True):
88 GeneratorOptions.__init__(self, filename, directory, apiname, profile,
89 versions, emitversions, defaultExtensions,
90 addExtensions, removeExtensions, emitExtensions, sortProcedure)
91 self.prefixText = prefixText
92 self.genFuncPointers = genFuncPointers
93 self.protectFile = protectFile
94 self.protectFeature = protectFeature
95 self.apicall = apicall
96 self.apientry = apientry
97 self.apientryp = apientryp
98 self.indentFuncProto = indentFuncProto
99 self.indentFuncPointer = indentFuncPointer
100 self.alignFuncParam = alignFuncParam
101
102# LayerChassisOutputGenerator - subclass of OutputGenerator.
103# Generates a LayerFactory layer that intercepts all API entrypoints
104# This is intended to be used as a starting point for creating custom layers
105#
106# ---- methods ----
107# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
108# OutputGenerator. Defines additional internal state.
109# ---- methods overriding base class ----
110# beginFile(genOpts)
111# endFile()
112# beginFeature(interface, emit)
113# endFeature()
114# genType(typeinfo,name)
115# genStruct(typeinfo,name)
116# genGroup(groupinfo,name)
117# genEnum(enuminfo, name)
118# genCmd(cmdinfo)
119class LayerChassisOutputGenerator(OutputGenerator):
120 """Generate specified API interfaces in a specific style, such as a C header"""
121 # This is an ordered list of sections in the header file.
122 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
123 'group', 'bitmask', 'funcpointer', 'struct']
124 ALL_SECTIONS = TYPE_SECTIONS + ['command']
125
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700126 manual_functions = [
127 # Include functions here to be interecpted w/ manually implemented function bodies
128 'vkGetDeviceProcAddr',
129 'vkGetInstanceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700130 'vkCreateDevice',
131 'vkDestroyDevice',
132 'vkCreateInstance',
133 'vkDestroyInstance',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700134 'vkEnumerateInstanceLayerProperties',
135 'vkEnumerateInstanceExtensionProperties',
136 'vkEnumerateDeviceLayerProperties',
137 'vkEnumerateDeviceExtensionProperties',
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700138 # Functions that are handled explicitly due to chassis architecture violations
139 'vkCreateGraphicsPipelines',
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700140 'vkCreateComputePipelines',
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700141 'vkCreateRayTracingPipelinesNV',
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -0700142 'vkCreatePipelineLayout',
Mark Lobodzinski1db77e82019-03-01 10:02:54 -0700143 'vkCreateShaderModule',
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -0700144 'vkAllocateDescriptorSets',
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700145 # ValidationCache functions do not get dispatched
146 'vkCreateValidationCacheEXT',
147 'vkDestroyValidationCacheEXT',
148 'vkMergeValidationCachesEXT',
149 'vkGetValidationCacheDataEXT',
Mark Lobodzinski56e88122019-03-26 10:21:48 -0600150 # We don't wanna hook this function
151 'vkGetPhysicalDeviceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700152 ]
153
154 alt_ret_codes = [
155 # Include functions here which must tolerate VK_INCOMPLETE as a return code
156 'vkEnumeratePhysicalDevices',
157 'vkEnumeratePhysicalDeviceGroupsKHR',
158 'vkGetValidationCacheDataEXT',
159 'vkGetPipelineCacheData',
160 'vkGetShaderInfoAMD',
161 'vkGetPhysicalDeviceDisplayPropertiesKHR',
162 'vkGetPhysicalDeviceDisplayProperties2KHR',
163 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
164 'vkGetDisplayPlaneSupportedDisplaysKHR',
165 'vkGetDisplayModePropertiesKHR',
166 'vkGetDisplayModeProperties2KHR',
167 'vkGetPhysicalDeviceSurfaceFormatsKHR',
168 'vkGetPhysicalDeviceSurfacePresentModesKHR',
169 'vkGetPhysicalDevicePresentRectanglesKHR',
170 'vkGetPastPresentationTimingGOOGLE',
171 'vkGetSwapchainImagesKHR',
172 'vkEnumerateInstanceLayerProperties',
173 'vkEnumerateDeviceLayerProperties',
174 'vkEnumerateInstanceExtensionProperties',
175 'vkEnumerateDeviceExtensionProperties',
176 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
177 ]
178
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700179 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700180 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
181 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700182 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
183 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
184 'vkCmdBeginDebugUtilsLabelEXT' : 'BeginCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
185 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
186 }
187
188 post_dispatch_debug_utils_functions = {
189 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
190 'vkCmdEndDebugUtilsLabelEXT' : 'EndCmdDebugUtilsLabel(layer_data->report_data, commandBuffer);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700191 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
192 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
193 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
194 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
195 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700196 }
197
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600198 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
199 precallrecord_loop = precallvalidate_loop
200 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600201
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700202 inline_custom_header_preamble = """
203#define NOMINMAX
204#include <mutex>
205#include <cinttypes>
206#include <stdio.h>
207#include <stdlib.h>
208#include <string.h>
209#include <unordered_map>
210#include <unordered_set>
211#include <algorithm>
212#include <memory>
213
214#include "vk_loader_platform.h"
215#include "vulkan/vulkan.h"
216#include "vk_layer_config.h"
217#include "vk_layer_data.h"
218#include "vk_layer_logging.h"
219#include "vk_object_types.h"
220#include "vulkan/vk_layer.h"
221#include "vk_enum_string_helper.h"
222#include "vk_layer_extension_utils.h"
223#include "vk_layer_utils.h"
224#include "vulkan/vk_layer.h"
225#include "vk_dispatch_table_helper.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700226#include "vk_extension_helper.h"
227#include "vk_safe_struct.h"
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700228#include "vk_typemap_helper.h"
229
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700230
231extern uint64_t global_unique_id;
232extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
233"""
234
235 inline_custom_header_class_definition = """
236
237// Layer object type identifiers
238enum LayerObjectTypeId {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700239 LayerObjectTypeInstance, // Container for an instance dispatch object
240 LayerObjectTypeDevice, // Container for a device dispatch object
241 LayerObjectTypeThreading, // Instance or device threading layer object
242 LayerObjectTypeParameterValidation, // Instance or device parameter validation layer object
243 LayerObjectTypeObjectTracker, // Instance or device object tracker layer object
244 LayerObjectTypeCoreValidation, // Instance or device core validation layer object
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700245};
246
247struct TEMPLATE_STATE {
248 VkDescriptorUpdateTemplateKHR desc_update_template;
249 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
250
251 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
252 : desc_update_template(update_template), create_info(*pCreateInfo) {}
253};
254
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700255class LAYER_PHYS_DEV_PROPERTIES {
256public:
257 VkPhysicalDeviceProperties properties;
258 std::vector<VkQueueFamilyProperties> queue_family_properties;
259};
260
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600261typedef enum ValidationCheckDisables {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600262 VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600263 VALIDATION_CHECK_DISABLE_OBJECT_IN_USE,
264 VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET,
265 VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE,
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600266 VALIDATION_CHECK_DISABLE_QUERY_VALIDATION,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600267} ValidationCheckDisables;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600268
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600269
270// CHECK_DISABLED struct is a container for bools that can block validation checks from being performed.
271// These bools are all "false" by default meaning that all checks are enabled. Enum values can be specified
272// via the vk_layer_setting.txt config file or at CreateInstance time via the VK_EXT_validation_features extension
273// that can selectively disable checks.
274struct CHECK_DISABLED {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600275 bool command_buffer_state; // Skip command buffer state validation
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600276 bool object_in_use; // Skip all object in_use checking
277 bool idle_descriptor_set; // Skip check to verify that descriptor set is not in-use
278 bool push_constant_range; // Skip push constant range checks
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600279 bool query_validation; // Disable all core validation query-related checks
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600280 bool object_tracking; // Disable object lifetime validation
281 bool core_checks; // Disable core validation checks
282 bool thread_safety; // Disable thread safety validation
283 bool stateless_checks; // Disable stateless validation checks
284 bool handle_wrapping; // Disable unique handles/handle wrapping
285 bool shader_validation; // Skip validation for shaders
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700286
287 void SetAll(bool value) { std::fill(&command_buffer_state, &shader_validation + 1, value); }
288};
289
290struct CHECK_ENABLED {
291 bool gpu_validation;
292 bool gpu_validation_reserve_binding_slot;
293
294 void SetAll(bool value) { std::fill(&gpu_validation, &gpu_validation_reserve_binding_slot + 1, value); }
295};
296
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700297// Layer chassis validation object base class definition
298class ValidationObject {
299 public:
300 uint32_t api_version;
301 debug_report_data* report_data = nullptr;
302 std::vector<VkDebugReportCallbackEXT> logging_callback;
303 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
304
305 VkLayerInstanceDispatchTable instance_dispatch_table;
306 VkLayerDispatchTable device_dispatch_table;
307
308 InstanceExtensions instance_extensions;
309 DeviceExtensions device_extensions = {};
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700310 CHECK_DISABLED disabled = {};
311 CHECK_ENABLED enabled = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700312
313 VkInstance instance = VK_NULL_HANDLE;
314 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
315 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700316 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700317
318 std::vector<ValidationObject*> object_dispatch;
319 LayerObjectTypeId container_type;
320
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700321 std::string layer_name = "CHASSIS";
322
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700323 // Constructor
324 ValidationObject(){};
325 // Destructor
326 virtual ~ValidationObject() {};
327
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700328 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700329 virtual std::unique_lock<std::mutex> write_lock() {
330 return std::unique_lock<std::mutex>(validation_object_mutex);
331 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700332
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700333 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
334 for (auto validation_object : object_dispatch) {
335 if (validation_object->container_type == object_type) {
336 return validation_object;
337 }
338 }
339 return nullptr;
340 };
341
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700342 // Handle Wrapping Data
343 // Reverse map display handles
344 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
345 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700346 struct SubpassesUsageStates {
347 std::unordered_set<uint32_t> subpasses_using_color_attachment;
348 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
349 };
350 // Uses unwrapped handles
351 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
352 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
353 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
354 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700355 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
356 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700357
358
359 // Unwrap a handle. Must hold lock.
360 template <typename HandleType>
361 HandleType Unwrap(HandleType wrappedHandle) {
362 // TODO: don't use operator[] here.
363 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
364 }
365
366 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
367 template <typename HandleType>
368 HandleType WrapNew(HandleType newlyCreatedHandle) {
369 auto unique_id = global_unique_id++;
370 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
371 return (HandleType)unique_id;
372 }
373
374 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
375 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
376 auto unique_id = global_unique_id++;
377 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
378 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
379 return (VkDisplayKHR)unique_id;
380 }
381
382 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
383 // creating another. Must hold lock.
384 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
385 // See if this display is already known
386 auto it = map_data->display_id_reverse_mapping.find(handle);
387 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
388 // Unknown, so wrap
389 return WrapDisplay(handle, map_data);
390 }
391
392 // Pre/post hook point declarations
393"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600394
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700395 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600396// This file is ***GENERATED***. Do Not Edit.
397// See layer_chassis_generator.py for modifications.
398
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700399/* Copyright (c) 2015-2019 The Khronos Group Inc.
400 * Copyright (c) 2015-2019 Valve Corporation
401 * Copyright (c) 2015-2019 LunarG, Inc.
402 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600403 *
404 * Licensed under the Apache License, Version 2.0 (the "License");
405 * you may not use this file except in compliance with the License.
406 * You may obtain a copy of the License at
407 *
408 * http://www.apache.org/licenses/LICENSE-2.0
409 *
410 * Unless required by applicable law or agreed to in writing, software
411 * distributed under the License is distributed on an "AS IS" BASIS,
412 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
413 * See the License for the specific language governing permissions and
414 * limitations under the License.
415 *
416 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700417 */"""
418
419 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600420
421#include <string.h>
422#include <mutex>
423
424#define VALIDATION_ERROR_MAP_IMPL
425
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600426#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700427#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600428
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600429std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600430
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700431// Global unique object identifier. All increments must be guarded by a lock.
432uint64_t global_unique_id = 1;
433// Map uniqueID to actual object handle
434std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
435
436// TODO: This variable controls handle wrapping -- in the future it should be hooked
437// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
438#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
439bool wrap_handles = true;
440#else
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600441bool wrap_handles = false;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700442#endif
443
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600444// Set layer name -- Khronos layer name overrides any other defined names
Mark Lobodzinskiaa6fd7b2019-03-19 09:26:48 -0600445#if BUILD_KHRONOS_VALIDATION
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600446#define OBJECT_LAYER_NAME "VK_LAYER_KHRONOS_validation"
447#define OBJECT_LAYER_DESCRIPTION "khronos_validation"
448#elif BUILD_OBJECT_TRACKER
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700449#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600450#define OBJECT_LAYER_DESCRIPTION "lunarg_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700451#elif BUILD_THREAD_SAFETY
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700452#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600453#define OBJECT_LAYER_DESCRIPTION "google_thread_checker"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700454#elif BUILD_PARAMETER_VALIDATION
455#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600456#define OBJECT_LAYER_DESCRIPTION "lunarg_parameter_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700457#elif BUILD_CORE_VALIDATION
458#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600459#define OBJECT_LAYER_DESCRIPTION "lunarg_core_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700460#else
461#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600462#define OBJECT_LAYER_DESCRIPTION "lunarg_unique_objects"
463#endif
464
465// Include layer validation object definitions
466#if BUILD_OBJECT_TRACKER
467#include "object_lifetime_validation.h"
468#endif
469#if BUILD_THREAD_SAFETY
470#include "thread_safety.h"
471#endif
472#if BUILD_PARAMETER_VALIDATION
473#include "stateless_validation.h"
474#endif
475#if BUILD_CORE_VALIDATION
476#include "core_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700477#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600478
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600479namespace vulkan_layer_chassis {
480
481using std::unordered_map;
482
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600483static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700484 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600485};
486
487static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
488
489extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
490
491
492// Manually written functions
493
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700494// Check enabled instance extensions against supported instance extension whitelist
495static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
496 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
497 // Check for recognized instance extensions
498 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
499 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
500 kVUIDUndefined,
501 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
502 "results and/or produce undefined behavior.",
503 pCreateInfo->ppEnabledExtensionNames[i]);
504 }
505 }
506}
507
508// Check enabled device extensions against supported device extension whitelist
509static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
510 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
511 // Check for recognized device extensions
512 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
513 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
514 kVUIDUndefined,
515 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
516 "results and/or produce undefined behavior.",
517 pCreateInfo->ppEnabledExtensionNames[i]);
518 }
519 }
520}
521
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600522
523// Process validation features, flags and settings specified through extensions, a layer settings file, or environment variables
524
525static const std::unordered_map<std::string, VkValidationFeatureDisableEXT> VkValFeatureDisableLookup = {
526 {"VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT", VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT},
527 {"VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT", VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT},
528 {"VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT", VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT},
529 {"VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT", VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT},
530 {"VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT", VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT},
531 {"VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT", VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT},
532 {"VK_VALIDATION_FEATURE_DISABLE_ALL_EXT", VK_VALIDATION_FEATURE_DISABLE_ALL_EXT},
533};
534
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600535static const std::unordered_map<std::string, VkValidationFeatureEnableEXT> VkValFeatureEnableLookup = {
536 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT},
537 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT},
538};
539
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600540static const std::unordered_map<std::string, ValidationCheckDisables> ValidationDisableLookup = {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600541 {"VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE", VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600542 {"VALIDATION_CHECK_DISABLE_OBJECT_IN_USE", VALIDATION_CHECK_DISABLE_OBJECT_IN_USE},
543 {"VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET", VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET},
544 {"VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE", VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE},
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600545 {"VALIDATION_CHECK_DISABLE_QUERY_VALIDATION", VALIDATION_CHECK_DISABLE_QUERY_VALIDATION},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600546};
547
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600548// Set the local disable flag for the appropriate VALIDATION_CHECK_DISABLE enum
549void SetValidationDisable(CHECK_DISABLED* disable_data, const ValidationCheckDisables disable_id) {
550 switch (disable_id) {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600551 case VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE:
552 disable_data->command_buffer_state = true;
553 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600554 case VALIDATION_CHECK_DISABLE_OBJECT_IN_USE:
555 disable_data->object_in_use = true;
556 break;
557 case VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET:
558 disable_data->idle_descriptor_set = true;
559 break;
560 case VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE:
561 disable_data->push_constant_range = true;
562 break;
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600563 case VALIDATION_CHECK_DISABLE_QUERY_VALIDATION:
564 disable_data->query_validation = true;
565 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600566 default:
567 assert(true);
568 }
569}
570
571// Set the local disable flag for a single VK_VALIDATION_FEATURE_DISABLE_* flag
572void SetValidationFeatureDisable(CHECK_DISABLED* disable_data, const VkValidationFeatureDisableEXT feature_disable) {
573 switch (feature_disable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700574 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600575 disable_data->shader_validation = true;
576 break;
577 case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
578 disable_data->thread_safety = true;
579 break;
580 case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
581 disable_data->stateless_checks = true;
582 break;
583 case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
584 disable_data->object_tracking = true;
585 break;
586 case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
587 disable_data->core_checks = true;
588 break;
589 case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
590 disable_data->handle_wrapping = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700591 break;
592 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
593 // Set all disabled flags to true
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600594 disable_data->SetAll(true);
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700595 break;
596 default:
597 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700598 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600599}
600
601// Set the local enable flag for a single VK_VALIDATION_FEATURE_ENABLE_* flag
602void SetValidationFeatureEnable(CHECK_ENABLED *enable_data, const VkValidationFeatureEnableEXT feature_enable) {
603 switch (feature_enable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700604 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600605 enable_data->gpu_validation = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700606 break;
607 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600608 enable_data->gpu_validation_reserve_binding_slot = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700609 break;
610 default:
611 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700612 }
613}
614
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600615// Set the local disable flag for settings specified through the VK_EXT_validation_flags extension
616void SetValidationFlags(CHECK_DISABLED* disables, const VkValidationFlagsEXT* val_flags_struct) {
617 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
618 switch (val_flags_struct->pDisabledValidationChecks[i]) {
619 case VK_VALIDATION_CHECK_SHADERS_EXT:
620 disables->shader_validation = true;
621 break;
622 case VK_VALIDATION_CHECK_ALL_EXT:
623 // Set all disabled flags to true
624 disables->SetAll(true);
625 break;
626 default:
627 break;
628 }
629 }
630}
631
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600632// Process Validation Features flags specified through the ValidationFeature extension
633void SetValidationFeatures(CHECK_DISABLED *disable_data, CHECK_ENABLED *enable_data,
634 const VkValidationFeaturesEXT *val_features_struct) {
635 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
636 SetValidationFeatureDisable(disable_data, val_features_struct->pDisabledValidationFeatures[i]);
637 }
638 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
639 SetValidationFeatureEnable(enable_data, val_features_struct->pEnabledValidationFeatures[i]);
640 }
641}
642
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600643// Given a string representation of a list of enable enum values, call the appropriate setter function
644void SetLocalEnableSetting(std::string list_of_enables, std::string delimiter, CHECK_ENABLED* enables) {
645 size_t pos = 0;
646 std::string token;
647 while (list_of_enables.length() != 0) {
648 pos = list_of_enables.find(delimiter);
649 if (pos != std::string::npos) {
650 token = list_of_enables.substr(0, pos);
651 } else {
652 pos = list_of_enables.length() - delimiter.length();
653 token = list_of_enables;
654 }
655 if (token.find("VK_VALIDATION_FEATURE_ENABLE_") != std::string::npos) {
656 auto result = VkValFeatureEnableLookup.find(token);
657 if (result != VkValFeatureEnableLookup.end()) {
658 SetValidationFeatureEnable(enables, result->second);
659 }
660 }
661 list_of_enables.erase(0, pos + delimiter.length());
662 }
663}
664
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600665// Given a string representation of a list of disable enum values, call the appropriate setter function
666void SetLocalDisableSetting(std::string list_of_disables, std::string delimiter, CHECK_DISABLED* disables) {
667 size_t pos = 0;
668 std::string token;
669 while (list_of_disables.length() != 0) {
670 pos = list_of_disables.find(delimiter);
671 if (pos != std::string::npos) {
672 token = list_of_disables.substr(0, pos);
673 } else {
674 pos = list_of_disables.length() - delimiter.length();
675 token = list_of_disables;
676 }
677 if (token.find("VK_VALIDATION_FEATURE_DISABLE_") != std::string::npos) {
678 auto result = VkValFeatureDisableLookup.find(token);
679 if (result != VkValFeatureDisableLookup.end()) {
680 SetValidationFeatureDisable(disables, result->second);
681 }
682 }
683 if (token.find("VALIDATION_CHECK_DISABLE_") != std::string::npos) {
684 auto result = ValidationDisableLookup.find(token);
685 if (result != ValidationDisableLookup.end()) {
686 SetValidationDisable(disables, result->second);
687 }
688 }
689 list_of_disables.erase(0, pos + delimiter.length());
690 }
691}
692
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600693// Process enables and disables set though the vk_layer_settings.txt config file or through an environment variable
694void ProcessConfigAndEnvSettings(const char* layer_description, CHECK_ENABLED* enables, CHECK_DISABLED* disables) {
695 std::string enable_key = layer_description;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600696 std::string disable_key = layer_description;
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600697 enable_key.append(".enables");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600698 disable_key.append(".disables");
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600699 std::string list_of_config_enables = getLayerOption(enable_key.c_str());
700 std::string list_of_env_enables = GetLayerEnvVar("VK_LAYER_ENABLES");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600701 std::string list_of_config_disables = getLayerOption(disable_key.c_str());
702 std::string list_of_env_disables = GetLayerEnvVar("VK_LAYER_DISABLES");
703#if defined(_WIN32)
704 std::string env_delimiter = ";";
705#else
706 std::string env_delimiter = ":";
707#endif
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600708 SetLocalEnableSetting(list_of_config_enables, ",", enables);
709 SetLocalEnableSetting(list_of_env_enables, env_delimiter, enables);
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600710 SetLocalDisableSetting(list_of_config_disables, ",", disables);
711 SetLocalDisableSetting(list_of_env_disables, env_delimiter, disables);
712}
713
714
715// Non-code-generated chassis API functions
716
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600717VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600718 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700719 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700720 return nullptr;
721 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600722 const auto &item = name_to_funcptr_map.find(funcName);
723 if (item != name_to_funcptr_map.end()) {
724 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
725 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600726 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600727 if (!table.GetDeviceProcAddr) return nullptr;
728 return table.GetDeviceProcAddr(device, funcName);
729}
730
731VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600732 const auto &item = name_to_funcptr_map.find(funcName);
733 if (item != name_to_funcptr_map.end()) {
734 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
735 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600736 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
737 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600738 if (!table.GetInstanceProcAddr) return nullptr;
739 return table.GetInstanceProcAddr(instance, funcName);
740}
741
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600742VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
743 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
744}
745
746VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
747 VkLayerProperties *pProperties) {
748 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
749}
750
751VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
752 VkExtensionProperties *pProperties) {
753 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
754 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
755
756 return VK_ERROR_LAYER_NOT_PRESENT;
757}
758
759VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
760 uint32_t *pCount, VkExtensionProperties *pProperties) {
761 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600762 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600763 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
764 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600765}
766
767VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
768 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600769 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600770
771 assert(chain_info->u.pLayerInfo);
772 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
773 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
774 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
775 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700776 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
777 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
778
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600779 CHECK_ENABLED local_enables {};
780 CHECK_DISABLED local_disables {};
781 const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(pCreateInfo->pNext);
782 if (validation_features_ext) {
783 SetValidationFeatures(&local_disables, &local_enables, validation_features_ext);
784 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600785 const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
786 if (validation_flags_ext) {
787 SetValidationFlags(&local_disables, validation_flags_ext);
788 }
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600789 ProcessConfigAndEnvSettings(OBJECT_LAYER_DESCRIPTION, &local_enables, &local_disables);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600790
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600791 // Create temporary dispatch vector for pre-calls until instance is created
792 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600793 // Add VOs to dispatch vector. Order here will be the validation dispatch order!
794#if BUILD_THREAD_SAFETY
795 auto thread_checker = new ThreadSafety;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600796 if (!local_disables.thread_safety) {
797 local_object_dispatch.emplace_back(thread_checker);
798 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600799 thread_checker->container_type = LayerObjectTypeThreading;
800 thread_checker->api_version = api_version;
801#endif
802#if BUILD_PARAMETER_VALIDATION
803 auto parameter_validation = new StatelessValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600804 if (!local_disables.stateless_checks) {
805 local_object_dispatch.emplace_back(parameter_validation);
806 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600807 parameter_validation->container_type = LayerObjectTypeParameterValidation;
808 parameter_validation->api_version = api_version;
809#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700810#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600811 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600812 if (!local_disables.object_tracking) {
813 local_object_dispatch.emplace_back(object_tracker);
814 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600815 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700816 object_tracker->api_version = api_version;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600817#endif
818#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700819 auto core_checks = new CoreChecks;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600820 if (!local_disables.core_checks) {
821 local_object_dispatch.emplace_back(core_checks);
822 }
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700823 core_checks->container_type = LayerObjectTypeCoreValidation;
824 core_checks->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700825#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600826
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600827 // If handle wrapping is disabled via the ValidationFeatures extension, override build flag
828 if (local_disables.handle_wrapping) {
829 wrap_handles = false;
830 }
831
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600832 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600833 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600834 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
835 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600836 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600837 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
838 }
839
840 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600841 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600842
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600843 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600844
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600845 framework->object_dispatch = local_object_dispatch;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700846 framework->container_type = LayerObjectTypeInstance;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600847 framework->disabled = local_disables;
848 framework->enabled = local_enables;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600849
850 framework->instance = *pInstance;
851 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
852 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
853 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700854 framework->api_version = api_version;
855 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
856
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600857 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, OBJECT_LAYER_DESCRIPTION);
858
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700859#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700860 object_tracker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600861 object_tracker->instance_dispatch_table = framework->instance_dispatch_table;
862 object_tracker->enabled = framework->enabled;
863 object_tracker->disabled = framework->disabled;
864#endif
865#if BUILD_THREAD_SAFETY
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700866 thread_checker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600867 thread_checker->instance_dispatch_table = framework->instance_dispatch_table;
868 thread_checker->enabled = framework->enabled;
869 thread_checker->disabled = framework->disabled;
870#endif
871#if BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700872 parameter_validation->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600873 parameter_validation->instance_dispatch_table = framework->instance_dispatch_table;
874 parameter_validation->enabled = framework->enabled;
875 parameter_validation->disabled = framework->disabled;
876#endif
877#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700878 core_checks->report_data = framework->report_data;
879 core_checks->instance_dispatch_table = framework->instance_dispatch_table;
880 core_checks->instance = *pInstance;
881 core_checks->enabled = framework->enabled;
882 core_checks->disabled = framework->disabled;
883 core_checks->instance_state = core_checks;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700884#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600885
886 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700887 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600888 }
889
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700890 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
891
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600892 return result;
893}
894
895VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
896 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600897 auto layer_data = GetLayerDataPtr(key, layer_data_map);
898 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700899 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600900 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
901 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600902 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700903 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600904 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
905 }
906
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600907 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600908
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600909 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700910 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600911 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
912 }
913 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600914 while (layer_data->logging_messenger.size() > 0) {
915 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
916 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
917 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600918 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600919 while (layer_data->logging_callback.size() > 0) {
920 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
921 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
922 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600923 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600924
925 layer_debug_utils_destroy_instance(layer_data->report_data);
926
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700927 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
928 delete *item;
929 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600930 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600931}
932
933VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
934 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600935 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600936
937 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
938
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600939 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
940 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600941 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
942 if (fpCreateDevice == NULL) {
943 return VK_ERROR_INITIALIZATION_FAILED;
944 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600945 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
946
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700947 // Get physical device limits for device
948 VkPhysicalDeviceProperties device_properties = {};
949 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
950
951 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
952 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
953
954 DeviceExtensions device_extensions = {};
955 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
956 for (auto item : instance_interceptor->object_dispatch) {
957 item->device_extensions = device_extensions;
958 }
959
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700960 std::unique_ptr<safe_VkDeviceCreateInfo> modified_create_info(new safe_VkDeviceCreateInfo(pCreateInfo));
961
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700962 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600963 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700964 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700965 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700966 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600967 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600968 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700969 auto lock = intercept->write_lock();
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700970 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, modified_create_info);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600971 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600972
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700973 VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(modified_create_info.get()), pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600974 if (result != VK_SUCCESS) {
975 return result;
976 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600977
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600978 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700979 device_interceptor->container_type = LayerObjectTypeDevice;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700980
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700981 // Save local info in device object
982 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700983 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
984 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700985 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700986
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600987 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700988
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600989 device_interceptor->device = *pDevice;
990 device_interceptor->physical_device = gpu;
991 device_interceptor->instance = instance_interceptor->instance;
992 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600993
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600994 // Note that this defines the order in which the layer validation objects are called
995#if BUILD_THREAD_SAFETY
996 auto thread_safety = new ThreadSafety;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600997 thread_safety->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600998 if (!instance_interceptor->disabled.thread_safety) {
999 device_interceptor->object_dispatch.emplace_back(thread_safety);
1000 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001001#endif
1002#if BUILD_PARAMETER_VALIDATION
1003 auto stateless_validation = new StatelessValidation;
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001004 stateless_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001005 if (!instance_interceptor->disabled.stateless_checks) {
1006 device_interceptor->object_dispatch.emplace_back(stateless_validation);
1007 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001008#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001009#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001010 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001011 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001012 if (!instance_interceptor->disabled.object_tracking) {
1013 device_interceptor->object_dispatch.emplace_back(object_tracker);
1014 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001015#endif
1016#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001017 auto core_checks = new CoreChecks;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001018 core_checks->container_type = LayerObjectTypeCoreValidation;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001019 core_checks->instance_state = reinterpret_cast<CoreChecks *>(
1020 core_checks->GetValidationObject(instance_interceptor->object_dispatch, LayerObjectTypeCoreValidation));
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001021 if (!instance_interceptor->disabled.core_checks) {
1022 device_interceptor->object_dispatch.emplace_back(core_checks);
1023 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001024#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001025
Mark Lobodzinski7314bf42019-03-28 08:54:53 -06001026 // Set per-intercept common data items
1027 for (auto dev_intercept : device_interceptor->object_dispatch) {
1028 dev_intercept->device = *pDevice;
1029 dev_intercept->physical_device = gpu;
1030 dev_intercept->instance = instance_interceptor->instance;
1031 dev_intercept->report_data = device_interceptor->report_data;
1032 dev_intercept->device_dispatch_table = device_interceptor->device_dispatch_table;
1033 dev_intercept->api_version = device_interceptor->api_version;
1034 dev_intercept->disabled = instance_interceptor->disabled;
1035 dev_intercept->enabled = instance_interceptor->enabled;
1036 dev_intercept->instance_dispatch_table = instance_interceptor->instance_dispatch_table;
1037 dev_intercept->instance_extensions = instance_interceptor->instance_extensions;
1038 dev_intercept->device_extensions = device_interceptor->device_extensions;
1039 }
1040
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001041 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001042 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001043 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001044 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001045
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001046 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
1047
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001048 return result;
1049}
1050
1051VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
1052 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001053 auto layer_data = GetLayerDataPtr(key, layer_data_map);
1054 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001055 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001056 intercept->PreCallValidateDestroyDevice(device, pAllocator);
1057 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001058 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001059 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001060 intercept->PreCallRecordDestroyDevice(device, pAllocator);
1061 }
1062 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001063
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001064 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001065
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001066 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001067 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001068 intercept->PostCallRecordDestroyDevice(device, pAllocator);
1069 }
1070
Mark Lobodzinskic5003372018-12-17 16:36:01 -07001071 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
1072 delete *item;
1073 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001074 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001075}
1076
1077
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001078// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001079
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001080VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
1081 VkDevice device,
1082 VkPipelineCache pipelineCache,
1083 uint32_t createInfoCount,
1084 const VkGraphicsPipelineCreateInfo* pCreateInfos,
1085 const VkAllocationCallbacks* pAllocator,
1086 VkPipeline* pPipelines) {
1087 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1088 bool skip = false;
1089
1090#ifdef BUILD_CORE_VALIDATION
1091 create_graphics_pipeline_api_state cgpl_state{};
1092#else
1093 struct create_graphics_pipeline_api_state {
1094 const VkGraphicsPipelineCreateInfo* pCreateInfos;
1095 } cgpl_state;
1096 cgpl_state.pCreateInfos = pCreateInfos;
1097#endif
1098
1099 for (auto intercept : layer_data->object_dispatch) {
1100 auto lock = intercept->write_lock();
1101 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1102 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1103 }
1104 for (auto intercept : layer_data->object_dispatch) {
1105 auto lock = intercept->write_lock();
1106 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1107 }
1108
Tony-LunarG152a88b2019-03-20 15:42:24 -06001109 VkResult result = DispatchCreateGraphicsPipelines(device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001110
1111 for (auto intercept : layer_data->object_dispatch) {
1112 auto lock = intercept->write_lock();
1113 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
1114 }
1115 return result;
1116}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001117
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001118// This API saves some core_validation pipeline state state on the stack for performance purposes
1119VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
1120 VkDevice device,
1121 VkPipelineCache pipelineCache,
1122 uint32_t createInfoCount,
1123 const VkComputePipelineCreateInfo* pCreateInfos,
1124 const VkAllocationCallbacks* pAllocator,
1125 VkPipeline* pPipelines) {
1126 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1127 bool skip = false;
1128
1129#ifndef BUILD_CORE_VALIDATION
1130 struct PIPELINE_STATE {};
1131#endif
1132
1133 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
1134
1135 for (auto intercept : layer_data->object_dispatch) {
1136 auto lock = intercept->write_lock();
1137 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
1138 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1139 }
1140 for (auto intercept : layer_data->object_dispatch) {
1141 auto lock = intercept->write_lock();
1142 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1143 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001144 VkResult result = DispatchCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001145 for (auto intercept : layer_data->object_dispatch) {
1146 auto lock = intercept->write_lock();
1147 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1148 }
1149 return result;
1150}
1151
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001152VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
1153 VkDevice device,
1154 VkPipelineCache pipelineCache,
1155 uint32_t createInfoCount,
1156 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
1157 const VkAllocationCallbacks* pAllocator,
1158 VkPipeline* pPipelines) {
1159 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1160 bool skip = false;
1161
1162#ifndef BUILD_CORE_VALIDATION
1163 struct PIPELINE_STATE {};
1164#endif
1165
1166 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
1167
1168 for (auto intercept : layer_data->object_dispatch) {
1169 auto lock = intercept->write_lock();
1170 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
1171 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1172 }
1173 for (auto intercept : layer_data->object_dispatch) {
1174 auto lock = intercept->write_lock();
1175 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1176 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001177 VkResult result = DispatchCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001178 for (auto intercept : layer_data->object_dispatch) {
1179 auto lock = intercept->write_lock();
1180 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1181 }
1182 return result;
1183}
1184
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001185// This API needs the ability to modify a down-chain parameter
1186VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
1187 VkDevice device,
1188 const VkPipelineLayoutCreateInfo* pCreateInfo,
1189 const VkAllocationCallbacks* pAllocator,
1190 VkPipelineLayout* pPipelineLayout) {
1191 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1192 bool skip = false;
1193
1194#ifndef BUILD_CORE_VALIDATION
1195 struct create_pipeline_layout_api_state {
1196 VkPipelineLayoutCreateInfo modified_create_info;
1197 };
1198#endif
1199 create_pipeline_layout_api_state cpl_state{};
1200 cpl_state.modified_create_info = *pCreateInfo;
1201
1202 for (auto intercept : layer_data->object_dispatch) {
1203 auto lock = intercept->write_lock();
1204 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1205 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1206 }
1207 for (auto intercept : layer_data->object_dispatch) {
1208 auto lock = intercept->write_lock();
1209 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1210 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001211 VkResult result = DispatchCreatePipelineLayout(device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001212 for (auto intercept : layer_data->object_dispatch) {
1213 auto lock = intercept->write_lock();
1214 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1215 }
1216 return result;
1217}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001218
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001219// This API needs some local stack data for performance reasons and also may modify a parameter
1220VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1221 VkDevice device,
1222 const VkShaderModuleCreateInfo* pCreateInfo,
1223 const VkAllocationCallbacks* pAllocator,
1224 VkShaderModule* pShaderModule) {
1225 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1226 bool skip = false;
1227
1228#ifndef BUILD_CORE_VALIDATION
1229 struct create_shader_module_api_state {
1230 VkShaderModuleCreateInfo instrumented_create_info;
1231 };
1232#endif
1233 create_shader_module_api_state csm_state{};
1234 csm_state.instrumented_create_info = *pCreateInfo;
1235
1236 for (auto intercept : layer_data->object_dispatch) {
1237 auto lock = intercept->write_lock();
1238 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1239 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1240 }
1241 for (auto intercept : layer_data->object_dispatch) {
1242 auto lock = intercept->write_lock();
1243 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1244 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001245 VkResult result = DispatchCreateShaderModule(device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001246 for (auto intercept : layer_data->object_dispatch) {
1247 auto lock = intercept->write_lock();
1248 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1249 }
1250 return result;
1251}
1252
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001253VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1254 VkDevice device,
1255 const VkDescriptorSetAllocateInfo* pAllocateInfo,
1256 VkDescriptorSet* pDescriptorSets) {
1257 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1258 bool skip = false;
1259
1260#ifdef BUILD_CORE_VALIDATION
1261 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1262#else
1263 struct ads_state {} ads_state;
1264#endif
1265
1266 for (auto intercept : layer_data->object_dispatch) {
1267 auto lock = intercept->write_lock();
1268 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1269 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1270 }
1271 for (auto intercept : layer_data->object_dispatch) {
1272 auto lock = intercept->write_lock();
1273 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1274 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001275 VkResult result = DispatchAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001276 for (auto intercept : layer_data->object_dispatch) {
1277 auto lock = intercept->write_lock();
1278 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1279 }
1280 return result;
1281}
1282
1283
1284
1285
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001286
1287// ValidationCache APIs do not dispatch
1288
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001289VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1290 VkDevice device,
1291 const VkValidationCacheCreateInfoEXT* pCreateInfo,
1292 const VkAllocationCallbacks* pAllocator,
1293 VkValidationCacheEXT* pValidationCache) {
1294 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1295 VkResult result = VK_SUCCESS;
1296
1297 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1298 if (validation_data) {
1299 auto lock = validation_data->write_lock();
1300 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1301 }
1302 return result;
1303}
1304
1305VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1306 VkDevice device,
1307 VkValidationCacheEXT validationCache,
1308 const VkAllocationCallbacks* pAllocator) {
1309 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1310
1311 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1312 if (validation_data) {
1313 auto lock = validation_data->write_lock();
1314 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1315 }
1316}
1317
1318VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1319 VkDevice device,
1320 VkValidationCacheEXT dstCache,
1321 uint32_t srcCacheCount,
1322 const VkValidationCacheEXT* pSrcCaches) {
1323 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1324 VkResult result = VK_SUCCESS;
1325
1326 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1327 if (validation_data) {
1328 auto lock = validation_data->write_lock();
1329 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1330 }
1331 return result;
1332}
1333
1334VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1335 VkDevice device,
1336 VkValidationCacheEXT validationCache,
1337 size_t* pDataSize,
1338 void* pData) {
1339 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1340 VkResult result = VK_SUCCESS;
1341
1342 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1343 if (validation_data) {
1344 auto lock = validation_data->write_lock();
1345 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1346 }
1347 return result;
1348
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001349}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001350
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001351 inline_custom_validation_class_definitions = """
1352 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1353 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1354 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1355 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001356
1357 // Allow additional parameter for CreateGraphicsPipelines
1358 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1359 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1360 };
1361 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1362 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1363 };
1364 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1365 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1366 };
1367
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001368 // Allow additional state parameter for CreateComputePipelines
1369 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1370 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1371 };
1372 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1373 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1374 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001375
1376 // Allow additional state parameter for CreateRayTracingPipelinesNV
1377 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1378 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1379 };
1380 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1381 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1382 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001383
1384 // Allow modification of a down-chain parameter for CreatePipelineLayout
1385 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1386 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1387 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001388
1389 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1390 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1391 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1392 };
1393 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1394 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1395 };
1396 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1397 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1398 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001399
1400 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1401 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1402 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1403 };
1404 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1405 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1406 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001407
1408 // Modify a parameter to CreateDevice
1409 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1410 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1411 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001412"""
1413
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001414 inline_custom_source_postamble = """
1415// loader-layer interface v0, just wrappers since there is only a layer
1416
1417VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1418 VkExtensionProperties *pProperties) {
1419 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1420}
1421
1422VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1423 VkLayerProperties *pProperties) {
1424 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1425}
1426
1427VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1428 VkLayerProperties *pProperties) {
1429 // the layer command handles VK_NULL_HANDLE just fine internally
1430 assert(physicalDevice == VK_NULL_HANDLE);
1431 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1432}
1433
1434VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1435 const char *pLayerName, uint32_t *pCount,
1436 VkExtensionProperties *pProperties) {
1437 // the layer command handles VK_NULL_HANDLE just fine internally
1438 assert(physicalDevice == VK_NULL_HANDLE);
1439 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1440}
1441
1442VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1443 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1444}
1445
1446VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1447 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1448}
1449
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001450VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1451 assert(pVersionStruct != NULL);
1452 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1453
1454 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1455 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1456 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1457 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
Mark Lobodzinski56e88122019-03-26 10:21:48 -06001458 pVersionStruct->pfnGetPhysicalDeviceProcAddr = nullptr;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001459 }
1460
1461 return VK_SUCCESS;
1462}"""
1463
1464
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001465 def __init__(self,
1466 errFile = sys.stderr,
1467 warnFile = sys.stderr,
1468 diagFile = sys.stdout):
1469 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1470 # Internal state - accumulators for different inner block text
1471 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1472 self.intercepts = []
1473 self.layer_factory = '' # String containing base layer factory class definition
1474
1475 # Check if the parameter passed in is a pointer to an array
1476 def paramIsArray(self, param):
1477 return param.attrib.get('len') is not None
1478
1479 # Check if the parameter passed in is a pointer
1480 def paramIsPointer(self, param):
1481 ispointer = False
1482 for elem in param:
1483 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
1484 ispointer = True
1485 return ispointer
1486
1487 # Check if an object is a non-dispatchable handle
1488 def isHandleTypeNonDispatchable(self, handletype):
1489 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1490 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1491 return True
1492 else:
1493 return False
1494
1495 # Check if an object is a dispatchable handle
1496 def isHandleTypeDispatchable(self, handletype):
1497 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1498 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
1499 return True
1500 else:
1501 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001502 #
1503 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001504 def beginFile(self, genOpts):
1505 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001506 # Output Copyright
1507 write(self.inline_copyright_message, file=self.outFile)
1508 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001509 self.header = False
1510 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1511 self.header = True
1512 write('#pragma once', file=self.outFile)
1513 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001514 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001515 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001516 else:
1517 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001518 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001519 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001520 #
1521 def endFile(self):
1522 # Finish C++ namespace and multiple inclusion protection
1523 self.newline()
1524 if not self.header:
1525 # Record intercepted procedures
1526 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
1527 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
1528 write('\n'.join(self.intercepts), file=self.outFile)
1529 write('};\n', file=self.outFile)
1530 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001531 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001532 if self.header:
1533 self.newline()
1534 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001535 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001536 self.layer_factory += '};\n\n'
1537 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001538 write(self.layer_factory, file=self.outFile)
1539 else:
1540 write(self.inline_custom_source_postamble, file=self.outFile)
1541 # Finish processing in superclass
1542 OutputGenerator.endFile(self)
1543
1544 def beginFeature(self, interface, emit):
1545 # Start processing in superclass
1546 OutputGenerator.beginFeature(self, interface, emit)
1547 # Get feature extra protect
1548 self.featureExtraProtect = GetFeatureProtect(interface)
1549 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1550 # feature. They're only printed in endFeature().
1551 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1552
1553 def endFeature(self):
1554 # Actually write the interface to the output file.
1555 if (self.emit):
1556 self.newline()
1557 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1558 # or move it below the 'for section...' loop.
1559 if (self.featureExtraProtect != None):
1560 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1561 for section in self.TYPE_SECTIONS:
1562 contents = self.sections[section]
1563 if contents:
1564 write('\n'.join(contents), file=self.outFile)
1565 self.newline()
1566 if (self.sections['command']):
1567 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1568 self.newline()
1569 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001570 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001571 # Finish processing in superclass
1572 OutputGenerator.endFeature(self)
1573 #
1574 # Append a definition to the specified section
1575 def appendSection(self, section, text):
1576 self.sections[section].append(text)
1577 #
1578 # Type generation
1579 def genType(self, typeinfo, name, alias):
1580 pass
1581 #
1582 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1583 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1584 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1585 # structs etc.)
1586 def genStruct(self, typeinfo, typeName):
1587 OutputGenerator.genStruct(self, typeinfo, typeName)
1588 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1589 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1590 for member in typeinfo.elem.findall('.//member'):
1591 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1592 body += ';\n'
1593 body += '} ' + typeName + ';\n'
1594 self.appendSection('struct', body)
1595 #
1596 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1597 def genGroup(self, groupinfo, groupName, alias):
1598 pass
1599 # Enumerant generation
1600 # <enum> tags may specify their values in several ways, but are usually just integers.
1601 def genEnum(self, enuminfo, name, alias):
1602 pass
1603 #
1604 # Customize Cdecl for layer factory base class
1605 def BaseClassCdecl(self, elem, name):
1606 raw = self.makeCDecls(elem)[1]
1607
1608 # Toss everything before the undecorated name
1609 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1610 prototype = prototype.replace(")", "", 1)
1611 prototype = prototype.replace(";", " {};")
1612
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001613 # Build up pre/post call virtual function declarations
1614 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1615 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1616 pre_call_record = 'virtual void PreCallRecord' + prototype
1617 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001618 resulttype = elem.find('proto/type')
1619 if resulttype.text == 'VkResult':
1620 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001621 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1622 #
1623 # Command generation
1624 def genCmd(self, cmdinfo, name, alias):
1625 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001626 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001627 ]
1628
1629 if name in ignore_functions:
1630 return
1631
1632 if self.header: # In the header declare all intercepts
1633 self.appendSection('command', '')
1634 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1635 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001636 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1637 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001638 if 'ValidationCache' not in name:
1639 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001640 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001641 self.layer_factory += '#endif\n'
1642 return
1643
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001644 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001645 if 'ValidationCache' not in name:
1646 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1647 else:
1648 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1649 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1650 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001651 return
1652 # Record that the function will be intercepted
1653 if (self.featureExtraProtect != None):
1654 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1655 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1656 if (self.featureExtraProtect != None):
1657 self.intercepts += [ '#endif' ]
1658 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1659 #
1660 decls = self.makeCDecls(cmdinfo.elem)
1661 self.appendSection('command', '')
1662 self.appendSection('command', '%s {' % decls[0][:-1])
1663 # Setup common to call wrappers. First parameter is always dispatchable
1664 dispatchable_type = cmdinfo.elem.find('param/type').text
1665 dispatchable_name = cmdinfo.elem.find('param/name').text
1666 # Default to device
1667 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001668 dispatch_table_name = 'VkLayerDispatchTable'
1669 # Set to instance as necessary
1670 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1671 device_or_instance = 'instance'
1672 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001673 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001674 api_function_name = cmdinfo.elem.attrib.get('name')
1675 params = cmdinfo.elem.findall('param/name')
1676 paramstext = ', '.join([str(param.text) for param in params])
Tony-LunarG152a88b2019-03-20 15:42:24 -06001677 API = api_function_name.replace('vk','Dispatch') + '('
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001678
1679 # Declare result variable, if any.
1680 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001681 'PFN_vkVoidFunction': 'return nullptr;',
1682 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001683 'VkDeviceAddress': 'return 0;',
1684 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1685 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001686 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001687 }
1688 resulttype = cmdinfo.elem.find('proto/type')
1689 assignresult = ''
1690 if (resulttype.text != 'void'):
1691 assignresult = resulttype.text + ' result = '
1692
1693 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001694 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001695
1696 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001697 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001698 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001699 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1700 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1701 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001702
1703 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001704 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001705 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001706 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001707 self.appendSection('command', ' }')
1708
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001709 # Insert pre-dispatch debug utils function call
1710 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001711 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001712
1713 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001714 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001715
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001716 # Insert post-dispatch debug utils function call
1717 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001718 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001719
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001720 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001721 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001722 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001723 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001724 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001725 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001726 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001727 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001728 # Return result variable, if any.
1729 if (resulttype.text != 'void'):
1730 self.appendSection('command', ' return result;')
1731 self.appendSection('command', '}')
1732 #
1733 # Override makeProtoName to drop the "vk" prefix
1734 def makeProtoName(self, name, tail):
1735 return self.genOpts.apientry + name[2:] + tail