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