blob: a7f33188e83f7daa0f7de77283dabd28071a16a2 [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',
130 'vkGetPhysicalDeviceProcAddr',
131 'vkCreateDevice',
132 'vkDestroyDevice',
133 'vkCreateInstance',
134 'vkDestroyInstance',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700135 'vkEnumerateInstanceLayerProperties',
136 'vkEnumerateInstanceExtensionProperties',
137 'vkEnumerateDeviceLayerProperties',
138 'vkEnumerateDeviceExtensionProperties',
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700139 # Functions that are handled explicitly due to chassis architecture violations
140 'vkCreateGraphicsPipelines',
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700141 'vkCreateComputePipelines',
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700142 'vkCreateRayTracingPipelinesNV',
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -0700143 'vkCreatePipelineLayout',
Mark Lobodzinski1db77e82019-03-01 10:02:54 -0700144 'vkCreateShaderModule',
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -0700145 'vkAllocateDescriptorSets',
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700146 # ValidationCache functions do not get dispatched
147 'vkCreateValidationCacheEXT',
148 'vkDestroyValidationCacheEXT',
149 'vkMergeValidationCachesEXT',
150 'vkGetValidationCacheDataEXT',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700151 ]
152
153 alt_ret_codes = [
154 # Include functions here which must tolerate VK_INCOMPLETE as a return code
155 'vkEnumeratePhysicalDevices',
156 'vkEnumeratePhysicalDeviceGroupsKHR',
157 'vkGetValidationCacheDataEXT',
158 'vkGetPipelineCacheData',
159 'vkGetShaderInfoAMD',
160 'vkGetPhysicalDeviceDisplayPropertiesKHR',
161 'vkGetPhysicalDeviceDisplayProperties2KHR',
162 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
163 'vkGetDisplayPlaneSupportedDisplaysKHR',
164 'vkGetDisplayModePropertiesKHR',
165 'vkGetDisplayModeProperties2KHR',
166 'vkGetPhysicalDeviceSurfaceFormatsKHR',
167 'vkGetPhysicalDeviceSurfacePresentModesKHR',
168 'vkGetPhysicalDevicePresentRectanglesKHR',
169 'vkGetPastPresentationTimingGOOGLE',
170 'vkGetSwapchainImagesKHR',
171 'vkEnumerateInstanceLayerProperties',
172 'vkEnumerateDeviceLayerProperties',
173 'vkEnumerateInstanceExtensionProperties',
174 'vkEnumerateDeviceExtensionProperties',
175 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
176 ]
177
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700178 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700179 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
180 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700181 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
182 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
183 'vkCmdBeginDebugUtilsLabelEXT' : 'BeginCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
184 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
185 }
186
187 post_dispatch_debug_utils_functions = {
188 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
189 'vkCmdEndDebugUtilsLabelEXT' : 'EndCmdDebugUtilsLabel(layer_data->report_data, commandBuffer);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700190 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
191 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
192 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
193 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
194 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700195 }
196
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600197 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
198 precallrecord_loop = precallvalidate_loop
199 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600200
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700201 inline_custom_header_preamble = """
202#define NOMINMAX
203#include <mutex>
204#include <cinttypes>
205#include <stdio.h>
206#include <stdlib.h>
207#include <string.h>
208#include <unordered_map>
209#include <unordered_set>
210#include <algorithm>
211#include <memory>
212
213#include "vk_loader_platform.h"
214#include "vulkan/vulkan.h"
215#include "vk_layer_config.h"
216#include "vk_layer_data.h"
217#include "vk_layer_logging.h"
218#include "vk_object_types.h"
219#include "vulkan/vk_layer.h"
220#include "vk_enum_string_helper.h"
221#include "vk_layer_extension_utils.h"
222#include "vk_layer_utils.h"
223#include "vulkan/vk_layer.h"
224#include "vk_dispatch_table_helper.h"
225#include "vk_validation_error_messages.h"
226#include "vk_extension_helper.h"
227#include "vk_safe_struct.h"
228
229extern uint64_t global_unique_id;
230extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
231"""
232
233 inline_custom_header_class_definition = """
234
235// Layer object type identifiers
236enum LayerObjectTypeId {
237 LayerObjectTypeThreading,
238 LayerObjectTypeParameterValidation,
239 LayerObjectTypeObjectTracker,
240 LayerObjectTypeCoreValidation,
241};
242
243struct TEMPLATE_STATE {
244 VkDescriptorUpdateTemplateKHR desc_update_template;
245 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
246
247 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
248 : desc_update_template(update_template), create_info(*pCreateInfo) {}
249};
250
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700251class LAYER_PHYS_DEV_PROPERTIES {
252public:
253 VkPhysicalDeviceProperties properties;
254 std::vector<VkQueueFamilyProperties> queue_family_properties;
255};
256
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700257// Layer chassis validation object base class definition
258class ValidationObject {
259 public:
260 uint32_t api_version;
261 debug_report_data* report_data = nullptr;
262 std::vector<VkDebugReportCallbackEXT> logging_callback;
263 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
264
265 VkLayerInstanceDispatchTable instance_dispatch_table;
266 VkLayerDispatchTable device_dispatch_table;
267
268 InstanceExtensions instance_extensions;
269 DeviceExtensions device_extensions = {};
270
271 VkInstance instance = VK_NULL_HANDLE;
272 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
273 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700274 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700275
276 std::vector<ValidationObject*> object_dispatch;
277 LayerObjectTypeId container_type;
278
279 // Constructor
280 ValidationObject(){};
281 // Destructor
282 virtual ~ValidationObject() {};
283
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700284 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700285 virtual std::unique_lock<std::mutex> write_lock() {
286 return std::unique_lock<std::mutex>(validation_object_mutex);
287 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700288
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700289 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
290 for (auto validation_object : object_dispatch) {
291 if (validation_object->container_type == object_type) {
292 return validation_object;
293 }
294 }
295 return nullptr;
296 };
297
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700298 std::string layer_name = "CHASSIS";
299
300 // Handle Wrapping Data
301 // Reverse map display handles
302 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
303 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700304 struct SubpassesUsageStates {
305 std::unordered_set<uint32_t> subpasses_using_color_attachment;
306 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
307 };
308 // Uses unwrapped handles
309 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
310 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
311 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
312 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700313 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
314 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700315
316
317 // Unwrap a handle. Must hold lock.
318 template <typename HandleType>
319 HandleType Unwrap(HandleType wrappedHandle) {
320 // TODO: don't use operator[] here.
321 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
322 }
323
324 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
325 template <typename HandleType>
326 HandleType WrapNew(HandleType newlyCreatedHandle) {
327 auto unique_id = global_unique_id++;
328 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
329 return (HandleType)unique_id;
330 }
331
332 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
333 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
334 auto unique_id = global_unique_id++;
335 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
336 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
337 return (VkDisplayKHR)unique_id;
338 }
339
340 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
341 // creating another. Must hold lock.
342 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
343 // See if this display is already known
344 auto it = map_data->display_id_reverse_mapping.find(handle);
345 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
346 // Unknown, so wrap
347 return WrapDisplay(handle, map_data);
348 }
349
350 // Pre/post hook point declarations
351"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600352
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700353 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600354// This file is ***GENERATED***. Do Not Edit.
355// See layer_chassis_generator.py for modifications.
356
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700357/* Copyright (c) 2015-2019 The Khronos Group Inc.
358 * Copyright (c) 2015-2019 Valve Corporation
359 * Copyright (c) 2015-2019 LunarG, Inc.
360 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600361 *
362 * Licensed under the Apache License, Version 2.0 (the "License");
363 * you may not use this file except in compliance with the License.
364 * You may obtain a copy of the License at
365 *
366 * http://www.apache.org/licenses/LICENSE-2.0
367 *
368 * Unless required by applicable law or agreed to in writing, software
369 * distributed under the License is distributed on an "AS IS" BASIS,
370 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
371 * See the License for the specific language governing permissions and
372 * limitations under the License.
373 *
374 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700375 */"""
376
377 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600378
379#include <string.h>
380#include <mutex>
381
382#define VALIDATION_ERROR_MAP_IMPL
383
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600384#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700385#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600386
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600387std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600388
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700389// Global unique object identifier. All increments must be guarded by a lock.
390uint64_t global_unique_id = 1;
391// Map uniqueID to actual object handle
392std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
393
394// TODO: This variable controls handle wrapping -- in the future it should be hooked
395// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
396#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
397bool wrap_handles = true;
398#else
399const bool wrap_handles = false;
400#endif
401
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600402// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700403#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600404#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700405#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700406#elif BUILD_THREAD_SAFETY
Mark Lobodzinski706e52b2018-12-11 13:21:52 -0700407#include "thread_safety.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700408#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
409#elif BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700410#include "stateless_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700411#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
412#elif BUILD_CORE_VALIDATION
413#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
414#else
415#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
416#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600417
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600418namespace vulkan_layer_chassis {
419
420using std::unordered_map;
421
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600422static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700423 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600424};
425
426static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
427
428extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
429
430
431// Manually written functions
432
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700433// Check enabled instance extensions against supported instance extension whitelist
434static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
435 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
436 // Check for recognized instance extensions
437 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
438 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
439 kVUIDUndefined,
440 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
441 "results and/or produce undefined behavior.",
442 pCreateInfo->ppEnabledExtensionNames[i]);
443 }
444 }
445}
446
447// Check enabled device extensions against supported device extension whitelist
448static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
449 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
450 // Check for recognized device extensions
451 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
452 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
453 kVUIDUndefined,
454 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
455 "results and/or produce undefined behavior.",
456 pCreateInfo->ppEnabledExtensionNames[i]);
457 }
458 }
459}
460
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600461VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600462 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700463 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700464 return nullptr;
465 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600466 const auto &item = name_to_funcptr_map.find(funcName);
467 if (item != name_to_funcptr_map.end()) {
468 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
469 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600470 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600471 if (!table.GetDeviceProcAddr) return nullptr;
472 return table.GetDeviceProcAddr(device, funcName);
473}
474
475VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600476 const auto &item = name_to_funcptr_map.find(funcName);
477 if (item != name_to_funcptr_map.end()) {
478 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
479 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600480 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
481 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600482 if (!table.GetInstanceProcAddr) return nullptr;
483 return table.GetInstanceProcAddr(instance, funcName);
484}
485
486VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600487 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
488 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600489 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
490 return table.GetPhysicalDeviceProcAddr(instance, funcName);
491}
492
493VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
494 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
495}
496
497VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
498 VkLayerProperties *pProperties) {
499 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
500}
501
502VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
503 VkExtensionProperties *pProperties) {
504 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
505 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
506
507 return VK_ERROR_LAYER_NOT_PRESENT;
508}
509
510VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
511 uint32_t *pCount, VkExtensionProperties *pProperties) {
512 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600513 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600514 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
515 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600516}
517
518VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
519 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600520 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600521
522 assert(chain_info->u.pLayerInfo);
523 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
524 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
525 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
526 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700527 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
528 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
529
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600530
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600531 // Create temporary dispatch vector for pre-calls until instance is created
532 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700533#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600534 auto object_tracker = new ObjectLifetimes;
535 local_object_dispatch.emplace_back(object_tracker);
536 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700537 object_tracker->api_version = api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700538#elif BUILD_THREAD_SAFETY
539 auto thread_checker = new ThreadSafety;
540 local_object_dispatch.emplace_back(thread_checker);
541 thread_checker->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700542 thread_checker->api_version = api_version;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700543#elif BUILD_PARAMETER_VALIDATION
544 auto parameter_validation = new StatelessValidation;
545 local_object_dispatch.emplace_back(parameter_validation);
546 parameter_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700547 parameter_validation->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700548#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600549
550
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600551 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600552 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600553 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
554 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600555 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600556 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
557 }
558
559 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600560 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600561
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600562 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600563
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600564 framework->object_dispatch = local_object_dispatch;
565
566 framework->instance = *pInstance;
567 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
568 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
569 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700570 framework->api_version = api_version;
571 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
572
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700573#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600574 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700575 object_tracker->report_data = framework->report_data;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700576#elif BUILD_THREAD_SAFETY
577 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "google_thread_checker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700578 thread_checker->report_data = framework->report_data;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700579#elif BUILD_PARAMETER_VALIDATION
580 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_parameter_validation");
581 parameter_validation->report_data = framework->report_data;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700582#else
583 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
584#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600585
586 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700587 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600588 }
589
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700590 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
591
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600592 return result;
593}
594
595VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
596 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600597 auto layer_data = GetLayerDataPtr(key, layer_data_map);
598 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700599 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600600 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
601 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600602 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700603 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600604 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
605 }
606
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600607 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600608
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600609 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700610 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600611 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
612 }
613 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600614 while (layer_data->logging_messenger.size() > 0) {
615 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
616 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
617 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600618 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600619 while (layer_data->logging_callback.size() > 0) {
620 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
621 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
622 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600623 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600624
625 layer_debug_utils_destroy_instance(layer_data->report_data);
626
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700627 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
628 delete *item;
629 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600630 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600631}
632
633VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
634 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600635 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600636
637 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
638
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600639 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
640 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600641 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
642 if (fpCreateDevice == NULL) {
643 return VK_ERROR_INITIALIZATION_FAILED;
644 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600645 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
646
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700647 // Get physical device limits for device
648 VkPhysicalDeviceProperties device_properties = {};
649 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
650
651 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
652 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
653
654 DeviceExtensions device_extensions = {};
655 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
656 for (auto item : instance_interceptor->object_dispatch) {
657 item->device_extensions = device_extensions;
658 }
659
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700660 std::unique_ptr<safe_VkDeviceCreateInfo> modified_create_info(new safe_VkDeviceCreateInfo(pCreateInfo));
661
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700662 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600663 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700664 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700665 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700666 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600667 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600668 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700669 auto lock = intercept->write_lock();
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700670 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, modified_create_info);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600671 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600672
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700673 VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(modified_create_info.get()), pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600674 if (result != VK_SUCCESS) {
675 return result;
676 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600677
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600678 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700679
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700680 // Save local info in device object
681 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700682 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
683 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700684 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700685
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600686 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700687
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600688 device_interceptor->device = *pDevice;
689 device_interceptor->physical_device = gpu;
690 device_interceptor->instance = instance_interceptor->instance;
691 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600692
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700693#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600694 // Create child layer objects for this key and add to dispatch vector
695 auto object_tracker = new ObjectLifetimes;
696 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
697 object_tracker->container_type = LayerObjectTypeObjectTracker;
698 object_tracker->physical_device = gpu;
699 object_tracker->instance = instance_interceptor->instance;
700 object_tracker->report_data = device_interceptor->report_data;
701 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700702 object_tracker->api_version = device_interceptor->api_version;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600703 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700704#elif BUILD_THREAD_SAFETY
705 auto thread_safety = new ThreadSafety;
706 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
707 thread_safety->container_type = LayerObjectTypeThreading;
708 thread_safety->physical_device = gpu;
709 thread_safety->instance = instance_interceptor->instance;
710 thread_safety->report_data = device_interceptor->report_data;
711 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700712 thread_safety->api_version = device_interceptor->api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700713 device_interceptor->object_dispatch.emplace_back(thread_safety);
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700714#elif BUILD_PARAMETER_VALIDATION
715 auto stateless_validation = new StatelessValidation;
716 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
717 stateless_validation->container_type = LayerObjectTypeParameterValidation;
718 stateless_validation->physical_device = gpu;
719 stateless_validation->instance = instance_interceptor->instance;
720 stateless_validation->report_data = device_interceptor->report_data;
721 stateless_validation->device_dispatch_table = device_interceptor->device_dispatch_table;
722 stateless_validation->api_version = device_interceptor->api_version;
723 device_interceptor->object_dispatch.emplace_back(stateless_validation);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700724#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600725
726 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700727 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700728 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600729 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600730
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700731 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
732
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600733 return result;
734}
735
736VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
737 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600738 auto layer_data = GetLayerDataPtr(key, layer_data_map);
739 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700740 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600741 intercept->PreCallValidateDestroyDevice(device, pAllocator);
742 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600743 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700744 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600745 intercept->PreCallRecordDestroyDevice(device, pAllocator);
746 }
747 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600748
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600749 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600750
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600751 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700752 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600753 intercept->PostCallRecordDestroyDevice(device, pAllocator);
754 }
755
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700756 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
757 delete *item;
758 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600759 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700760}
761
762
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700763// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700764
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700765VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
766 VkDevice device,
767 VkPipelineCache pipelineCache,
768 uint32_t createInfoCount,
769 const VkGraphicsPipelineCreateInfo* pCreateInfos,
770 const VkAllocationCallbacks* pAllocator,
771 VkPipeline* pPipelines) {
772 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
773 bool skip = false;
774
775#ifdef BUILD_CORE_VALIDATION
776 create_graphics_pipeline_api_state cgpl_state{};
777#else
778 struct create_graphics_pipeline_api_state {
779 const VkGraphicsPipelineCreateInfo* pCreateInfos;
780 } cgpl_state;
781 cgpl_state.pCreateInfos = pCreateInfos;
782#endif
783
784 for (auto intercept : layer_data->object_dispatch) {
785 auto lock = intercept->write_lock();
786 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
787 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
788 }
789 for (auto intercept : layer_data->object_dispatch) {
790 auto lock = intercept->write_lock();
791 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
792 }
793
794 VkResult result = DispatchCreateGraphicsPipelines(layer_data, device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
795
796 for (auto intercept : layer_data->object_dispatch) {
797 auto lock = intercept->write_lock();
798 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
799 }
800 return result;
801}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700802
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700803// This API saves some core_validation pipeline state state on the stack for performance purposes
804VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
805 VkDevice device,
806 VkPipelineCache pipelineCache,
807 uint32_t createInfoCount,
808 const VkComputePipelineCreateInfo* pCreateInfos,
809 const VkAllocationCallbacks* pAllocator,
810 VkPipeline* pPipelines) {
811 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
812 bool skip = false;
813
814#ifndef BUILD_CORE_VALIDATION
815 struct PIPELINE_STATE {};
816#endif
817
818 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
819
820 for (auto intercept : layer_data->object_dispatch) {
821 auto lock = intercept->write_lock();
822 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
823 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
824 }
825 for (auto intercept : layer_data->object_dispatch) {
826 auto lock = intercept->write_lock();
827 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
828 }
829 VkResult result = DispatchCreateComputePipelines(layer_data, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
830 for (auto intercept : layer_data->object_dispatch) {
831 auto lock = intercept->write_lock();
832 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
833 }
834 return result;
835}
836
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700837VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
838 VkDevice device,
839 VkPipelineCache pipelineCache,
840 uint32_t createInfoCount,
841 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
842 const VkAllocationCallbacks* pAllocator,
843 VkPipeline* pPipelines) {
844 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
845 bool skip = false;
846
847#ifndef BUILD_CORE_VALIDATION
848 struct PIPELINE_STATE {};
849#endif
850
851 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
852
853 for (auto intercept : layer_data->object_dispatch) {
854 auto lock = intercept->write_lock();
855 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
856 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
857 }
858 for (auto intercept : layer_data->object_dispatch) {
859 auto lock = intercept->write_lock();
860 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
861 }
862 VkResult result = DispatchCreateRayTracingPipelinesNV(layer_data, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
863 for (auto intercept : layer_data->object_dispatch) {
864 auto lock = intercept->write_lock();
865 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
866 }
867 return result;
868}
869
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -0700870// This API needs the ability to modify a down-chain parameter
871VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
872 VkDevice device,
873 const VkPipelineLayoutCreateInfo* pCreateInfo,
874 const VkAllocationCallbacks* pAllocator,
875 VkPipelineLayout* pPipelineLayout) {
876 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
877 bool skip = false;
878
879#ifndef BUILD_CORE_VALIDATION
880 struct create_pipeline_layout_api_state {
881 VkPipelineLayoutCreateInfo modified_create_info;
882 };
883#endif
884 create_pipeline_layout_api_state cpl_state{};
885 cpl_state.modified_create_info = *pCreateInfo;
886
887 for (auto intercept : layer_data->object_dispatch) {
888 auto lock = intercept->write_lock();
889 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
890 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
891 }
892 for (auto intercept : layer_data->object_dispatch) {
893 auto lock = intercept->write_lock();
894 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
895 }
896 VkResult result = DispatchCreatePipelineLayout(layer_data, device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
897 for (auto intercept : layer_data->object_dispatch) {
898 auto lock = intercept->write_lock();
899 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
900 }
901 return result;
902}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700903
Mark Lobodzinski1db77e82019-03-01 10:02:54 -0700904// This API needs some local stack data for performance reasons and also may modify a parameter
905VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
906 VkDevice device,
907 const VkShaderModuleCreateInfo* pCreateInfo,
908 const VkAllocationCallbacks* pAllocator,
909 VkShaderModule* pShaderModule) {
910 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
911 bool skip = false;
912
913#ifndef BUILD_CORE_VALIDATION
914 struct create_shader_module_api_state {
915 VkShaderModuleCreateInfo instrumented_create_info;
916 };
917#endif
918 create_shader_module_api_state csm_state{};
919 csm_state.instrumented_create_info = *pCreateInfo;
920
921 for (auto intercept : layer_data->object_dispatch) {
922 auto lock = intercept->write_lock();
923 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
924 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
925 }
926 for (auto intercept : layer_data->object_dispatch) {
927 auto lock = intercept->write_lock();
928 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
929 }
930 VkResult result = DispatchCreateShaderModule(layer_data, device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
931 for (auto intercept : layer_data->object_dispatch) {
932 auto lock = intercept->write_lock();
933 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
934 }
935 return result;
936}
937
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -0700938VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
939 VkDevice device,
940 const VkDescriptorSetAllocateInfo* pAllocateInfo,
941 VkDescriptorSet* pDescriptorSets) {
942 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
943 bool skip = false;
944
945#ifdef BUILD_CORE_VALIDATION
946 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
947#else
948 struct ads_state {} ads_state;
949#endif
950
951 for (auto intercept : layer_data->object_dispatch) {
952 auto lock = intercept->write_lock();
953 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
954 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
955 }
956 for (auto intercept : layer_data->object_dispatch) {
957 auto lock = intercept->write_lock();
958 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
959 }
960 VkResult result = DispatchAllocateDescriptorSets(layer_data, device, pAllocateInfo, pDescriptorSets);
961 for (auto intercept : layer_data->object_dispatch) {
962 auto lock = intercept->write_lock();
963 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
964 }
965 return result;
966}
967
968
969
970
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700971
972// ValidationCache APIs do not dispatch
973
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700974VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
975 VkDevice device,
976 const VkValidationCacheCreateInfoEXT* pCreateInfo,
977 const VkAllocationCallbacks* pAllocator,
978 VkValidationCacheEXT* pValidationCache) {
979 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
980 VkResult result = VK_SUCCESS;
981
982 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
983 if (validation_data) {
984 auto lock = validation_data->write_lock();
985 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
986 }
987 return result;
988}
989
990VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
991 VkDevice device,
992 VkValidationCacheEXT validationCache,
993 const VkAllocationCallbacks* pAllocator) {
994 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
995
996 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
997 if (validation_data) {
998 auto lock = validation_data->write_lock();
999 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1000 }
1001}
1002
1003VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1004 VkDevice device,
1005 VkValidationCacheEXT dstCache,
1006 uint32_t srcCacheCount,
1007 const VkValidationCacheEXT* pSrcCaches) {
1008 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1009 VkResult result = VK_SUCCESS;
1010
1011 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1012 if (validation_data) {
1013 auto lock = validation_data->write_lock();
1014 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1015 }
1016 return result;
1017}
1018
1019VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1020 VkDevice device,
1021 VkValidationCacheEXT validationCache,
1022 size_t* pDataSize,
1023 void* pData) {
1024 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1025 VkResult result = VK_SUCCESS;
1026
1027 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1028 if (validation_data) {
1029 auto lock = validation_data->write_lock();
1030 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1031 }
1032 return result;
1033
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001034}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001035
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001036 inline_custom_validation_class_definitions = """
1037 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1038 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1039 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1040 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001041
1042 // Allow additional parameter for CreateGraphicsPipelines
1043 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1044 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1045 };
1046 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1047 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1048 };
1049 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1050 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1051 };
1052
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001053 // Allow additional state parameter for CreateComputePipelines
1054 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1055 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1056 };
1057 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1058 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1059 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001060
1061 // Allow additional state parameter for CreateRayTracingPipelinesNV
1062 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1063 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1064 };
1065 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1066 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1067 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001068
1069 // Allow modification of a down-chain parameter for CreatePipelineLayout
1070 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1071 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1072 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001073
1074 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1075 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1076 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1077 };
1078 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1079 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1080 };
1081 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1082 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1083 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001084
1085 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1086 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1087 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1088 };
1089 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1090 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1091 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001092
1093 // Modify a parameter to CreateDevice
1094 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1095 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1096 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001097"""
1098
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001099 inline_custom_source_postamble = """
1100// loader-layer interface v0, just wrappers since there is only a layer
1101
1102VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1103 VkExtensionProperties *pProperties) {
1104 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1105}
1106
1107VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1108 VkLayerProperties *pProperties) {
1109 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1110}
1111
1112VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1113 VkLayerProperties *pProperties) {
1114 // the layer command handles VK_NULL_HANDLE just fine internally
1115 assert(physicalDevice == VK_NULL_HANDLE);
1116 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1117}
1118
1119VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1120 const char *pLayerName, uint32_t *pCount,
1121 VkExtensionProperties *pProperties) {
1122 // the layer command handles VK_NULL_HANDLE just fine internally
1123 assert(physicalDevice == VK_NULL_HANDLE);
1124 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1125}
1126
1127VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1128 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1129}
1130
1131VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1132 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1133}
1134
1135VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
1136 const char *funcName) {
1137 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
1138}
1139
1140VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1141 assert(pVersionStruct != NULL);
1142 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1143
1144 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1145 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1146 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1147 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
1148 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
1149 }
1150
1151 return VK_SUCCESS;
1152}"""
1153
1154
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001155 def __init__(self,
1156 errFile = sys.stderr,
1157 warnFile = sys.stderr,
1158 diagFile = sys.stdout):
1159 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1160 # Internal state - accumulators for different inner block text
1161 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1162 self.intercepts = []
1163 self.layer_factory = '' # String containing base layer factory class definition
1164
1165 # Check if the parameter passed in is a pointer to an array
1166 def paramIsArray(self, param):
1167 return param.attrib.get('len') is not None
1168
1169 # Check if the parameter passed in is a pointer
1170 def paramIsPointer(self, param):
1171 ispointer = False
1172 for elem in param:
1173 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
1174 ispointer = True
1175 return ispointer
1176
1177 # Check if an object is a non-dispatchable handle
1178 def isHandleTypeNonDispatchable(self, handletype):
1179 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1180 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1181 return True
1182 else:
1183 return False
1184
1185 # Check if an object is a dispatchable handle
1186 def isHandleTypeDispatchable(self, handletype):
1187 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1188 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
1189 return True
1190 else:
1191 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001192 #
1193 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001194 def beginFile(self, genOpts):
1195 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001196 # Output Copyright
1197 write(self.inline_copyright_message, file=self.outFile)
1198 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001199 self.header = False
1200 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1201 self.header = True
1202 write('#pragma once', file=self.outFile)
1203 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001204 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001205 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001206 else:
1207 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001208 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001209 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001210 #
1211 def endFile(self):
1212 # Finish C++ namespace and multiple inclusion protection
1213 self.newline()
1214 if not self.header:
1215 # Record intercepted procedures
1216 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
1217 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
1218 write('\n'.join(self.intercepts), file=self.outFile)
1219 write('};\n', file=self.outFile)
1220 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001221 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001222 if self.header:
1223 self.newline()
1224 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001225 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001226 self.layer_factory += '};\n\n'
1227 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001228 write(self.layer_factory, file=self.outFile)
1229 else:
1230 write(self.inline_custom_source_postamble, file=self.outFile)
1231 # Finish processing in superclass
1232 OutputGenerator.endFile(self)
1233
1234 def beginFeature(self, interface, emit):
1235 # Start processing in superclass
1236 OutputGenerator.beginFeature(self, interface, emit)
1237 # Get feature extra protect
1238 self.featureExtraProtect = GetFeatureProtect(interface)
1239 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1240 # feature. They're only printed in endFeature().
1241 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1242
1243 def endFeature(self):
1244 # Actually write the interface to the output file.
1245 if (self.emit):
1246 self.newline()
1247 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1248 # or move it below the 'for section...' loop.
1249 if (self.featureExtraProtect != None):
1250 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1251 for section in self.TYPE_SECTIONS:
1252 contents = self.sections[section]
1253 if contents:
1254 write('\n'.join(contents), file=self.outFile)
1255 self.newline()
1256 if (self.sections['command']):
1257 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1258 self.newline()
1259 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001260 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001261 # Finish processing in superclass
1262 OutputGenerator.endFeature(self)
1263 #
1264 # Append a definition to the specified section
1265 def appendSection(self, section, text):
1266 self.sections[section].append(text)
1267 #
1268 # Type generation
1269 def genType(self, typeinfo, name, alias):
1270 pass
1271 #
1272 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1273 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1274 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1275 # structs etc.)
1276 def genStruct(self, typeinfo, typeName):
1277 OutputGenerator.genStruct(self, typeinfo, typeName)
1278 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1279 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1280 for member in typeinfo.elem.findall('.//member'):
1281 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1282 body += ';\n'
1283 body += '} ' + typeName + ';\n'
1284 self.appendSection('struct', body)
1285 #
1286 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1287 def genGroup(self, groupinfo, groupName, alias):
1288 pass
1289 # Enumerant generation
1290 # <enum> tags may specify their values in several ways, but are usually just integers.
1291 def genEnum(self, enuminfo, name, alias):
1292 pass
1293 #
1294 # Customize Cdecl for layer factory base class
1295 def BaseClassCdecl(self, elem, name):
1296 raw = self.makeCDecls(elem)[1]
1297
1298 # Toss everything before the undecorated name
1299 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1300 prototype = prototype.replace(")", "", 1)
1301 prototype = prototype.replace(";", " {};")
1302
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001303 # Build up pre/post call virtual function declarations
1304 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1305 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1306 pre_call_record = 'virtual void PreCallRecord' + prototype
1307 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001308 resulttype = elem.find('proto/type')
1309 if resulttype.text == 'VkResult':
1310 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001311 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1312 #
1313 # Command generation
1314 def genCmd(self, cmdinfo, name, alias):
1315 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001316 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001317 ]
1318
1319 if name in ignore_functions:
1320 return
1321
1322 if self.header: # In the header declare all intercepts
1323 self.appendSection('command', '')
1324 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1325 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001326 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1327 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001328 if 'ValidationCache' not in name:
1329 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001330 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001331 self.layer_factory += '#endif\n'
1332 return
1333
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001334 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001335 if 'ValidationCache' not in name:
1336 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1337 else:
1338 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1339 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1340 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001341 return
1342 # Record that the function will be intercepted
1343 if (self.featureExtraProtect != None):
1344 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1345 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1346 if (self.featureExtraProtect != None):
1347 self.intercepts += [ '#endif' ]
1348 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1349 #
1350 decls = self.makeCDecls(cmdinfo.elem)
1351 self.appendSection('command', '')
1352 self.appendSection('command', '%s {' % decls[0][:-1])
1353 # Setup common to call wrappers. First parameter is always dispatchable
1354 dispatchable_type = cmdinfo.elem.find('param/type').text
1355 dispatchable_name = cmdinfo.elem.find('param/name').text
1356 # Default to device
1357 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001358 dispatch_table_name = 'VkLayerDispatchTable'
1359 # Set to instance as necessary
1360 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1361 device_or_instance = 'instance'
1362 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001363 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001364 api_function_name = cmdinfo.elem.attrib.get('name')
1365 params = cmdinfo.elem.findall('param/name')
1366 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001367 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001368
1369 # Declare result variable, if any.
1370 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001371 'PFN_vkVoidFunction': 'return nullptr;',
1372 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001373 'VkDeviceAddress': 'return 0;',
1374 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1375 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001376 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001377 }
1378 resulttype = cmdinfo.elem.find('proto/type')
1379 assignresult = ''
1380 if (resulttype.text != 'void'):
1381 assignresult = resulttype.text + ' result = '
1382
1383 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001384 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001385
1386 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001387 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001388 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001389 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1390 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1391 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001392
1393 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001394 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001395 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001396 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001397 self.appendSection('command', ' }')
1398
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001399 # Insert pre-dispatch debug utils function call
1400 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001401 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001402
1403 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001404 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001405
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001406 # Insert post-dispatch debug utils function call
1407 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001408 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001409
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001410 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001411 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001412 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001413 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001414 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001415 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001416 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001417 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001418 # Return result variable, if any.
1419 if (resulttype.text != 'void'):
1420 self.appendSection('command', ' return result;')
1421 self.appendSection('command', '}')
1422 #
1423 # Override makeProtoName to drop the "vk" prefix
1424 def makeProtoName(self, name, tail):
1425 return self.genOpts.apientry + name[2:] + tail