blob: 690442a90580112451fd73032a22edc65213a93a [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
660 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600661 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700662 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700663 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700664 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600665 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600666 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700667 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600668 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
669 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600670
671 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600672 if (result != VK_SUCCESS) {
673 return result;
674 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600675
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600676 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700677
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700678 // Save local info in device object
679 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700680 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
681 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700682 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700683
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600684 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700685
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600686 device_interceptor->device = *pDevice;
687 device_interceptor->physical_device = gpu;
688 device_interceptor->instance = instance_interceptor->instance;
689 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600690
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700691#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600692 // Create child layer objects for this key and add to dispatch vector
693 auto object_tracker = new ObjectLifetimes;
694 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
695 object_tracker->container_type = LayerObjectTypeObjectTracker;
696 object_tracker->physical_device = gpu;
697 object_tracker->instance = instance_interceptor->instance;
698 object_tracker->report_data = device_interceptor->report_data;
699 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700700 object_tracker->api_version = device_interceptor->api_version;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600701 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700702#elif BUILD_THREAD_SAFETY
703 auto thread_safety = new ThreadSafety;
704 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
705 thread_safety->container_type = LayerObjectTypeThreading;
706 thread_safety->physical_device = gpu;
707 thread_safety->instance = instance_interceptor->instance;
708 thread_safety->report_data = device_interceptor->report_data;
709 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700710 thread_safety->api_version = device_interceptor->api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700711 device_interceptor->object_dispatch.emplace_back(thread_safety);
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700712#elif BUILD_PARAMETER_VALIDATION
713 auto stateless_validation = new StatelessValidation;
714 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
715 stateless_validation->container_type = LayerObjectTypeParameterValidation;
716 stateless_validation->physical_device = gpu;
717 stateless_validation->instance = instance_interceptor->instance;
718 stateless_validation->report_data = device_interceptor->report_data;
719 stateless_validation->device_dispatch_table = device_interceptor->device_dispatch_table;
720 stateless_validation->api_version = device_interceptor->api_version;
721 device_interceptor->object_dispatch.emplace_back(stateless_validation);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700722#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600723
724 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700725 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700726 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600727 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600728
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700729 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
730
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600731 return result;
732}
733
734VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
735 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600736 auto layer_data = GetLayerDataPtr(key, layer_data_map);
737 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700738 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600739 intercept->PreCallValidateDestroyDevice(device, pAllocator);
740 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600741 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700742 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600743 intercept->PreCallRecordDestroyDevice(device, pAllocator);
744 }
745 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600746
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600747 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600748
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600749 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700750 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600751 intercept->PostCallRecordDestroyDevice(device, pAllocator);
752 }
753
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700754 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
755 delete *item;
756 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600757 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700758}
759
760
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700761// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700762
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700763VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
764 VkDevice device,
765 VkPipelineCache pipelineCache,
766 uint32_t createInfoCount,
767 const VkGraphicsPipelineCreateInfo* pCreateInfos,
768 const VkAllocationCallbacks* pAllocator,
769 VkPipeline* pPipelines) {
770 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
771 bool skip = false;
772
773#ifdef BUILD_CORE_VALIDATION
774 create_graphics_pipeline_api_state cgpl_state{};
775#else
776 struct create_graphics_pipeline_api_state {
777 const VkGraphicsPipelineCreateInfo* pCreateInfos;
778 } cgpl_state;
779 cgpl_state.pCreateInfos = pCreateInfos;
780#endif
781
782 for (auto intercept : layer_data->object_dispatch) {
783 auto lock = intercept->write_lock();
784 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
785 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
786 }
787 for (auto intercept : layer_data->object_dispatch) {
788 auto lock = intercept->write_lock();
789 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
790 }
791
792 VkResult result = DispatchCreateGraphicsPipelines(layer_data, device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
793
794 for (auto intercept : layer_data->object_dispatch) {
795 auto lock = intercept->write_lock();
796 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
797 }
798 return result;
799}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700800
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700801// This API saves some core_validation pipeline state state on the stack for performance purposes
802VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
803 VkDevice device,
804 VkPipelineCache pipelineCache,
805 uint32_t createInfoCount,
806 const VkComputePipelineCreateInfo* pCreateInfos,
807 const VkAllocationCallbacks* pAllocator,
808 VkPipeline* pPipelines) {
809 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
810 bool skip = false;
811
812#ifndef BUILD_CORE_VALIDATION
813 struct PIPELINE_STATE {};
814#endif
815
816 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
817
818 for (auto intercept : layer_data->object_dispatch) {
819 auto lock = intercept->write_lock();
820 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
821 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
822 }
823 for (auto intercept : layer_data->object_dispatch) {
824 auto lock = intercept->write_lock();
825 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
826 }
827 VkResult result = DispatchCreateComputePipelines(layer_data, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
828 for (auto intercept : layer_data->object_dispatch) {
829 auto lock = intercept->write_lock();
830 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
831 }
832 return result;
833}
834
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700835VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
836 VkDevice device,
837 VkPipelineCache pipelineCache,
838 uint32_t createInfoCount,
839 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
840 const VkAllocationCallbacks* pAllocator,
841 VkPipeline* pPipelines) {
842 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
843 bool skip = false;
844
845#ifndef BUILD_CORE_VALIDATION
846 struct PIPELINE_STATE {};
847#endif
848
849 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
850
851 for (auto intercept : layer_data->object_dispatch) {
852 auto lock = intercept->write_lock();
853 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
854 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
855 }
856 for (auto intercept : layer_data->object_dispatch) {
857 auto lock = intercept->write_lock();
858 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
859 }
860 VkResult result = DispatchCreateRayTracingPipelinesNV(layer_data, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
861 for (auto intercept : layer_data->object_dispatch) {
862 auto lock = intercept->write_lock();
863 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
864 }
865 return result;
866}
867
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -0700868// This API needs the ability to modify a down-chain parameter
869VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
870 VkDevice device,
871 const VkPipelineLayoutCreateInfo* pCreateInfo,
872 const VkAllocationCallbacks* pAllocator,
873 VkPipelineLayout* pPipelineLayout) {
874 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
875 bool skip = false;
876
877#ifndef BUILD_CORE_VALIDATION
878 struct create_pipeline_layout_api_state {
879 VkPipelineLayoutCreateInfo modified_create_info;
880 };
881#endif
882 create_pipeline_layout_api_state cpl_state{};
883 cpl_state.modified_create_info = *pCreateInfo;
884
885 for (auto intercept : layer_data->object_dispatch) {
886 auto lock = intercept->write_lock();
887 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
888 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
889 }
890 for (auto intercept : layer_data->object_dispatch) {
891 auto lock = intercept->write_lock();
892 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
893 }
894 VkResult result = DispatchCreatePipelineLayout(layer_data, device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
895 for (auto intercept : layer_data->object_dispatch) {
896 auto lock = intercept->write_lock();
897 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
898 }
899 return result;
900}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700901
Mark Lobodzinski1db77e82019-03-01 10:02:54 -0700902// This API needs some local stack data for performance reasons and also may modify a parameter
903VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
904 VkDevice device,
905 const VkShaderModuleCreateInfo* pCreateInfo,
906 const VkAllocationCallbacks* pAllocator,
907 VkShaderModule* pShaderModule) {
908 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
909 bool skip = false;
910
911#ifndef BUILD_CORE_VALIDATION
912 struct create_shader_module_api_state {
913 VkShaderModuleCreateInfo instrumented_create_info;
914 };
915#endif
916 create_shader_module_api_state csm_state{};
917 csm_state.instrumented_create_info = *pCreateInfo;
918
919 for (auto intercept : layer_data->object_dispatch) {
920 auto lock = intercept->write_lock();
921 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
922 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
923 }
924 for (auto intercept : layer_data->object_dispatch) {
925 auto lock = intercept->write_lock();
926 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
927 }
928 VkResult result = DispatchCreateShaderModule(layer_data, device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
929 for (auto intercept : layer_data->object_dispatch) {
930 auto lock = intercept->write_lock();
931 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
932 }
933 return result;
934}
935
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -0700936VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
937 VkDevice device,
938 const VkDescriptorSetAllocateInfo* pAllocateInfo,
939 VkDescriptorSet* pDescriptorSets) {
940 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
941 bool skip = false;
942
943#ifdef BUILD_CORE_VALIDATION
944 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
945#else
946 struct ads_state {} ads_state;
947#endif
948
949 for (auto intercept : layer_data->object_dispatch) {
950 auto lock = intercept->write_lock();
951 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
952 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
953 }
954 for (auto intercept : layer_data->object_dispatch) {
955 auto lock = intercept->write_lock();
956 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
957 }
958 VkResult result = DispatchAllocateDescriptorSets(layer_data, device, pAllocateInfo, pDescriptorSets);
959 for (auto intercept : layer_data->object_dispatch) {
960 auto lock = intercept->write_lock();
961 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
962 }
963 return result;
964}
965
966
967
968
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700969
970// ValidationCache APIs do not dispatch
971
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700972VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
973 VkDevice device,
974 const VkValidationCacheCreateInfoEXT* pCreateInfo,
975 const VkAllocationCallbacks* pAllocator,
976 VkValidationCacheEXT* pValidationCache) {
977 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
978 VkResult result = VK_SUCCESS;
979
980 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
981 if (validation_data) {
982 auto lock = validation_data->write_lock();
983 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
984 }
985 return result;
986}
987
988VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
989 VkDevice device,
990 VkValidationCacheEXT validationCache,
991 const VkAllocationCallbacks* pAllocator) {
992 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
993
994 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
995 if (validation_data) {
996 auto lock = validation_data->write_lock();
997 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
998 }
999}
1000
1001VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1002 VkDevice device,
1003 VkValidationCacheEXT dstCache,
1004 uint32_t srcCacheCount,
1005 const VkValidationCacheEXT* pSrcCaches) {
1006 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1007 VkResult result = VK_SUCCESS;
1008
1009 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1010 if (validation_data) {
1011 auto lock = validation_data->write_lock();
1012 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1013 }
1014 return result;
1015}
1016
1017VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1018 VkDevice device,
1019 VkValidationCacheEXT validationCache,
1020 size_t* pDataSize,
1021 void* pData) {
1022 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1023 VkResult result = VK_SUCCESS;
1024
1025 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1026 if (validation_data) {
1027 auto lock = validation_data->write_lock();
1028 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1029 }
1030 return result;
1031
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001032}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001033
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001034 inline_custom_validation_class_definitions = """
1035 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1036 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1037 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1038 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001039
1040 // Allow additional parameter for CreateGraphicsPipelines
1041 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1042 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1043 };
1044 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1045 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1046 };
1047 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1048 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1049 };
1050
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001051 // Allow additional state parameter for CreateComputePipelines
1052 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1053 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1054 };
1055 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1056 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1057 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001058
1059 // Allow additional state parameter for CreateRayTracingPipelinesNV
1060 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1061 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1062 };
1063 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1064 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1065 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001066
1067 // Allow modification of a down-chain parameter for CreatePipelineLayout
1068 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1069 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1070 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001071
1072 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1073 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1074 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1075 };
1076 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1077 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1078 };
1079 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1080 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1081 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001082
1083 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1084 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1085 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1086 };
1087 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1088 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1089 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001090"""
1091
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001092 inline_custom_source_postamble = """
1093// loader-layer interface v0, just wrappers since there is only a layer
1094
1095VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1096 VkExtensionProperties *pProperties) {
1097 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1098}
1099
1100VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1101 VkLayerProperties *pProperties) {
1102 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1103}
1104
1105VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1106 VkLayerProperties *pProperties) {
1107 // the layer command handles VK_NULL_HANDLE just fine internally
1108 assert(physicalDevice == VK_NULL_HANDLE);
1109 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1110}
1111
1112VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1113 const char *pLayerName, uint32_t *pCount,
1114 VkExtensionProperties *pProperties) {
1115 // the layer command handles VK_NULL_HANDLE just fine internally
1116 assert(physicalDevice == VK_NULL_HANDLE);
1117 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1118}
1119
1120VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1121 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1122}
1123
1124VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1125 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1126}
1127
1128VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
1129 const char *funcName) {
1130 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
1131}
1132
1133VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1134 assert(pVersionStruct != NULL);
1135 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1136
1137 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1138 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1139 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1140 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
1141 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
1142 }
1143
1144 return VK_SUCCESS;
1145}"""
1146
1147
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001148 def __init__(self,
1149 errFile = sys.stderr,
1150 warnFile = sys.stderr,
1151 diagFile = sys.stdout):
1152 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1153 # Internal state - accumulators for different inner block text
1154 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1155 self.intercepts = []
1156 self.layer_factory = '' # String containing base layer factory class definition
1157
1158 # Check if the parameter passed in is a pointer to an array
1159 def paramIsArray(self, param):
1160 return param.attrib.get('len') is not None
1161
1162 # Check if the parameter passed in is a pointer
1163 def paramIsPointer(self, param):
1164 ispointer = False
1165 for elem in param:
1166 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
1167 ispointer = True
1168 return ispointer
1169
1170 # Check if an object is a non-dispatchable handle
1171 def isHandleTypeNonDispatchable(self, handletype):
1172 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1173 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1174 return True
1175 else:
1176 return False
1177
1178 # Check if an object is a dispatchable handle
1179 def isHandleTypeDispatchable(self, handletype):
1180 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1181 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
1182 return True
1183 else:
1184 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001185 #
1186 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001187 def beginFile(self, genOpts):
1188 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001189 # Output Copyright
1190 write(self.inline_copyright_message, file=self.outFile)
1191 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001192 self.header = False
1193 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1194 self.header = True
1195 write('#pragma once', file=self.outFile)
1196 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001197 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001198 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001199 else:
1200 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001201 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001202 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001203 #
1204 def endFile(self):
1205 # Finish C++ namespace and multiple inclusion protection
1206 self.newline()
1207 if not self.header:
1208 # Record intercepted procedures
1209 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
1210 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
1211 write('\n'.join(self.intercepts), file=self.outFile)
1212 write('};\n', file=self.outFile)
1213 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001214 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001215 if self.header:
1216 self.newline()
1217 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001218 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001219 self.layer_factory += '};\n\n'
1220 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001221 write(self.layer_factory, file=self.outFile)
1222 else:
1223 write(self.inline_custom_source_postamble, file=self.outFile)
1224 # Finish processing in superclass
1225 OutputGenerator.endFile(self)
1226
1227 def beginFeature(self, interface, emit):
1228 # Start processing in superclass
1229 OutputGenerator.beginFeature(self, interface, emit)
1230 # Get feature extra protect
1231 self.featureExtraProtect = GetFeatureProtect(interface)
1232 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1233 # feature. They're only printed in endFeature().
1234 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1235
1236 def endFeature(self):
1237 # Actually write the interface to the output file.
1238 if (self.emit):
1239 self.newline()
1240 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1241 # or move it below the 'for section...' loop.
1242 if (self.featureExtraProtect != None):
1243 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1244 for section in self.TYPE_SECTIONS:
1245 contents = self.sections[section]
1246 if contents:
1247 write('\n'.join(contents), file=self.outFile)
1248 self.newline()
1249 if (self.sections['command']):
1250 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1251 self.newline()
1252 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001253 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001254 # Finish processing in superclass
1255 OutputGenerator.endFeature(self)
1256 #
1257 # Append a definition to the specified section
1258 def appendSection(self, section, text):
1259 self.sections[section].append(text)
1260 #
1261 # Type generation
1262 def genType(self, typeinfo, name, alias):
1263 pass
1264 #
1265 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1266 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1267 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1268 # structs etc.)
1269 def genStruct(self, typeinfo, typeName):
1270 OutputGenerator.genStruct(self, typeinfo, typeName)
1271 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1272 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1273 for member in typeinfo.elem.findall('.//member'):
1274 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1275 body += ';\n'
1276 body += '} ' + typeName + ';\n'
1277 self.appendSection('struct', body)
1278 #
1279 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1280 def genGroup(self, groupinfo, groupName, alias):
1281 pass
1282 # Enumerant generation
1283 # <enum> tags may specify their values in several ways, but are usually just integers.
1284 def genEnum(self, enuminfo, name, alias):
1285 pass
1286 #
1287 # Customize Cdecl for layer factory base class
1288 def BaseClassCdecl(self, elem, name):
1289 raw = self.makeCDecls(elem)[1]
1290
1291 # Toss everything before the undecorated name
1292 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1293 prototype = prototype.replace(")", "", 1)
1294 prototype = prototype.replace(";", " {};")
1295
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001296 # Build up pre/post call virtual function declarations
1297 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1298 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1299 pre_call_record = 'virtual void PreCallRecord' + prototype
1300 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001301 resulttype = elem.find('proto/type')
1302 if resulttype.text == 'VkResult':
1303 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001304 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1305 #
1306 # Command generation
1307 def genCmd(self, cmdinfo, name, alias):
1308 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001309 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001310 ]
1311
1312 if name in ignore_functions:
1313 return
1314
1315 if self.header: # In the header declare all intercepts
1316 self.appendSection('command', '')
1317 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1318 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001319 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1320 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001321 if 'ValidationCache' not in name:
1322 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001323 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001324 self.layer_factory += '#endif\n'
1325 return
1326
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001327 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001328 if 'ValidationCache' not in name:
1329 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1330 else:
1331 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1332 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1333 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001334 return
1335 # Record that the function will be intercepted
1336 if (self.featureExtraProtect != None):
1337 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1338 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1339 if (self.featureExtraProtect != None):
1340 self.intercepts += [ '#endif' ]
1341 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1342 #
1343 decls = self.makeCDecls(cmdinfo.elem)
1344 self.appendSection('command', '')
1345 self.appendSection('command', '%s {' % decls[0][:-1])
1346 # Setup common to call wrappers. First parameter is always dispatchable
1347 dispatchable_type = cmdinfo.elem.find('param/type').text
1348 dispatchable_name = cmdinfo.elem.find('param/name').text
1349 # Default to device
1350 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001351 dispatch_table_name = 'VkLayerDispatchTable'
1352 # Set to instance as necessary
1353 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1354 device_or_instance = 'instance'
1355 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001356 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001357 api_function_name = cmdinfo.elem.attrib.get('name')
1358 params = cmdinfo.elem.findall('param/name')
1359 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001360 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001361
1362 # Declare result variable, if any.
1363 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001364 'PFN_vkVoidFunction': 'return nullptr;',
1365 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001366 'VkDeviceAddress': 'return 0;',
1367 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1368 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001369 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001370 }
1371 resulttype = cmdinfo.elem.find('proto/type')
1372 assignresult = ''
1373 if (resulttype.text != 'void'):
1374 assignresult = resulttype.text + ' result = '
1375
1376 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001377 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001378
1379 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001380 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001381 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001382 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1383 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1384 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001385
1386 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001387 self.appendSection('command', ' %s' % self.precallrecord_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', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001390 self.appendSection('command', ' }')
1391
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001392 # Insert pre-dispatch debug utils function call
1393 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001394 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001395
1396 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001397 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001398
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001399 # Insert post-dispatch debug utils function call
1400 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001401 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001402
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001403 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001404 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001405 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001406 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001407 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001408 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001409 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001410 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001411 # Return result variable, if any.
1412 if (resulttype.text != 'void'):
1413 self.appendSection('command', ' return result;')
1414 self.appendSection('command', '}')
1415 #
1416 # Override makeProtoName to drop the "vk" prefix
1417 def makeProtoName(self, name, tail):
1418 return self.genOpts.apientry + name[2:] + tail