blob: 3ed0952963786bbd9660a47ff1aa9dd54ce5d449 [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 Lobodzinskic37c82a2019-02-28 13:13:02 -0700144 # ValidationCache functions do not get dispatched
145 'vkCreateValidationCacheEXT',
146 'vkDestroyValidationCacheEXT',
147 'vkMergeValidationCachesEXT',
148 'vkGetValidationCacheDataEXT',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700149 ]
150
151 alt_ret_codes = [
152 # Include functions here which must tolerate VK_INCOMPLETE as a return code
153 'vkEnumeratePhysicalDevices',
154 'vkEnumeratePhysicalDeviceGroupsKHR',
155 'vkGetValidationCacheDataEXT',
156 'vkGetPipelineCacheData',
157 'vkGetShaderInfoAMD',
158 'vkGetPhysicalDeviceDisplayPropertiesKHR',
159 'vkGetPhysicalDeviceDisplayProperties2KHR',
160 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
161 'vkGetDisplayPlaneSupportedDisplaysKHR',
162 'vkGetDisplayModePropertiesKHR',
163 'vkGetDisplayModeProperties2KHR',
164 'vkGetPhysicalDeviceSurfaceFormatsKHR',
165 'vkGetPhysicalDeviceSurfacePresentModesKHR',
166 'vkGetPhysicalDevicePresentRectanglesKHR',
167 'vkGetPastPresentationTimingGOOGLE',
168 'vkGetSwapchainImagesKHR',
169 'vkEnumerateInstanceLayerProperties',
170 'vkEnumerateDeviceLayerProperties',
171 'vkEnumerateInstanceExtensionProperties',
172 'vkEnumerateDeviceExtensionProperties',
173 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
174 ]
175
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700176 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700177 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
178 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700179 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
180 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
181 'vkCmdBeginDebugUtilsLabelEXT' : 'BeginCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
182 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
183 }
184
185 post_dispatch_debug_utils_functions = {
186 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
187 'vkCmdEndDebugUtilsLabelEXT' : 'EndCmdDebugUtilsLabel(layer_data->report_data, commandBuffer);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700188 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
189 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
190 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
191 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
192 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700193 }
194
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600195 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
196 precallrecord_loop = precallvalidate_loop
197 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600198
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700199 inline_custom_header_preamble = """
200#define NOMINMAX
201#include <mutex>
202#include <cinttypes>
203#include <stdio.h>
204#include <stdlib.h>
205#include <string.h>
206#include <unordered_map>
207#include <unordered_set>
208#include <algorithm>
209#include <memory>
210
211#include "vk_loader_platform.h"
212#include "vulkan/vulkan.h"
213#include "vk_layer_config.h"
214#include "vk_layer_data.h"
215#include "vk_layer_logging.h"
216#include "vk_object_types.h"
217#include "vulkan/vk_layer.h"
218#include "vk_enum_string_helper.h"
219#include "vk_layer_extension_utils.h"
220#include "vk_layer_utils.h"
221#include "vulkan/vk_layer.h"
222#include "vk_dispatch_table_helper.h"
223#include "vk_validation_error_messages.h"
224#include "vk_extension_helper.h"
225#include "vk_safe_struct.h"
226
227extern uint64_t global_unique_id;
228extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
229"""
230
231 inline_custom_header_class_definition = """
232
233// Layer object type identifiers
234enum LayerObjectTypeId {
235 LayerObjectTypeThreading,
236 LayerObjectTypeParameterValidation,
237 LayerObjectTypeObjectTracker,
238 LayerObjectTypeCoreValidation,
239};
240
241struct TEMPLATE_STATE {
242 VkDescriptorUpdateTemplateKHR desc_update_template;
243 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
244
245 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
246 : desc_update_template(update_template), create_info(*pCreateInfo) {}
247};
248
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700249class LAYER_PHYS_DEV_PROPERTIES {
250public:
251 VkPhysicalDeviceProperties properties;
252 std::vector<VkQueueFamilyProperties> queue_family_properties;
253};
254
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700255// Layer chassis validation object base class definition
256class ValidationObject {
257 public:
258 uint32_t api_version;
259 debug_report_data* report_data = nullptr;
260 std::vector<VkDebugReportCallbackEXT> logging_callback;
261 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
262
263 VkLayerInstanceDispatchTable instance_dispatch_table;
264 VkLayerDispatchTable device_dispatch_table;
265
266 InstanceExtensions instance_extensions;
267 DeviceExtensions device_extensions = {};
268
269 VkInstance instance = VK_NULL_HANDLE;
270 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
271 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700272 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700273
274 std::vector<ValidationObject*> object_dispatch;
275 LayerObjectTypeId container_type;
276
277 // Constructor
278 ValidationObject(){};
279 // Destructor
280 virtual ~ValidationObject() {};
281
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700282 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700283 virtual std::unique_lock<std::mutex> write_lock() {
284 return std::unique_lock<std::mutex>(validation_object_mutex);
285 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700286
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700287 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
288 for (auto validation_object : object_dispatch) {
289 if (validation_object->container_type == object_type) {
290 return validation_object;
291 }
292 }
293 return nullptr;
294 };
295
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700296 std::string layer_name = "CHASSIS";
297
298 // Handle Wrapping Data
299 // Reverse map display handles
300 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
301 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700302 struct SubpassesUsageStates {
303 std::unordered_set<uint32_t> subpasses_using_color_attachment;
304 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
305 };
306 // Uses unwrapped handles
307 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
308 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
309 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
310 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700311 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
312 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700313
314
315 // Unwrap a handle. Must hold lock.
316 template <typename HandleType>
317 HandleType Unwrap(HandleType wrappedHandle) {
318 // TODO: don't use operator[] here.
319 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
320 }
321
322 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
323 template <typename HandleType>
324 HandleType WrapNew(HandleType newlyCreatedHandle) {
325 auto unique_id = global_unique_id++;
326 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
327 return (HandleType)unique_id;
328 }
329
330 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
331 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
332 auto unique_id = global_unique_id++;
333 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
334 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
335 return (VkDisplayKHR)unique_id;
336 }
337
338 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
339 // creating another. Must hold lock.
340 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
341 // See if this display is already known
342 auto it = map_data->display_id_reverse_mapping.find(handle);
343 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
344 // Unknown, so wrap
345 return WrapDisplay(handle, map_data);
346 }
347
348 // Pre/post hook point declarations
349"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600350
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700351 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600352// This file is ***GENERATED***. Do Not Edit.
353// See layer_chassis_generator.py for modifications.
354
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700355/* Copyright (c) 2015-2019 The Khronos Group Inc.
356 * Copyright (c) 2015-2019 Valve Corporation
357 * Copyright (c) 2015-2019 LunarG, Inc.
358 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600359 *
360 * Licensed under the Apache License, Version 2.0 (the "License");
361 * you may not use this file except in compliance with the License.
362 * You may obtain a copy of the License at
363 *
364 * http://www.apache.org/licenses/LICENSE-2.0
365 *
366 * Unless required by applicable law or agreed to in writing, software
367 * distributed under the License is distributed on an "AS IS" BASIS,
368 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
369 * See the License for the specific language governing permissions and
370 * limitations under the License.
371 *
372 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700373 */"""
374
375 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600376
377#include <string.h>
378#include <mutex>
379
380#define VALIDATION_ERROR_MAP_IMPL
381
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600382#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700383#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600384
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600385std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600386
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700387// Global unique object identifier. All increments must be guarded by a lock.
388uint64_t global_unique_id = 1;
389// Map uniqueID to actual object handle
390std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
391
392// TODO: This variable controls handle wrapping -- in the future it should be hooked
393// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
394#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
395bool wrap_handles = true;
396#else
397const bool wrap_handles = false;
398#endif
399
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600400// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700401#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600402#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700403#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700404#elif BUILD_THREAD_SAFETY
Mark Lobodzinski706e52b2018-12-11 13:21:52 -0700405#include "thread_safety.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700406#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
407#elif BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700408#include "stateless_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700409#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
410#elif BUILD_CORE_VALIDATION
411#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
412#else
413#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
414#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600415
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600416namespace vulkan_layer_chassis {
417
418using std::unordered_map;
419
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600420static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700421 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600422};
423
424static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
425
426extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
427
428
429// Manually written functions
430
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700431// Check enabled instance extensions against supported instance extension whitelist
432static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
433 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
434 // Check for recognized instance extensions
435 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
436 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
437 kVUIDUndefined,
438 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
439 "results and/or produce undefined behavior.",
440 pCreateInfo->ppEnabledExtensionNames[i]);
441 }
442 }
443}
444
445// Check enabled device extensions against supported device extension whitelist
446static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
447 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
448 // Check for recognized device extensions
449 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
450 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
451 kVUIDUndefined,
452 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
453 "results and/or produce undefined behavior.",
454 pCreateInfo->ppEnabledExtensionNames[i]);
455 }
456 }
457}
458
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600459VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600460 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700461 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700462 return nullptr;
463 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600464 const auto &item = name_to_funcptr_map.find(funcName);
465 if (item != name_to_funcptr_map.end()) {
466 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
467 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600468 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600469 if (!table.GetDeviceProcAddr) return nullptr;
470 return table.GetDeviceProcAddr(device, funcName);
471}
472
473VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600474 const auto &item = name_to_funcptr_map.find(funcName);
475 if (item != name_to_funcptr_map.end()) {
476 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
477 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600478 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
479 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600480 if (!table.GetInstanceProcAddr) return nullptr;
481 return table.GetInstanceProcAddr(instance, funcName);
482}
483
484VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600485 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
486 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600487 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
488 return table.GetPhysicalDeviceProcAddr(instance, funcName);
489}
490
491VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
492 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
493}
494
495VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
496 VkLayerProperties *pProperties) {
497 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
498}
499
500VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
501 VkExtensionProperties *pProperties) {
502 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
503 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
504
505 return VK_ERROR_LAYER_NOT_PRESENT;
506}
507
508VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
509 uint32_t *pCount, VkExtensionProperties *pProperties) {
510 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600511 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600512 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
513 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600514}
515
516VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
517 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600518 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600519
520 assert(chain_info->u.pLayerInfo);
521 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
522 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
523 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
524 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700525 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
526 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
527
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600528
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600529 // Create temporary dispatch vector for pre-calls until instance is created
530 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700531#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600532 auto object_tracker = new ObjectLifetimes;
533 local_object_dispatch.emplace_back(object_tracker);
534 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700535 object_tracker->api_version = api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700536#elif BUILD_THREAD_SAFETY
537 auto thread_checker = new ThreadSafety;
538 local_object_dispatch.emplace_back(thread_checker);
539 thread_checker->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700540 thread_checker->api_version = api_version;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700541#elif BUILD_PARAMETER_VALIDATION
542 auto parameter_validation = new StatelessValidation;
543 local_object_dispatch.emplace_back(parameter_validation);
544 parameter_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700545 parameter_validation->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700546#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600547
548
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600549 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600550 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600551 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
552 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600553 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600554 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
555 }
556
557 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600558 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600559
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600560 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600561
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600562 framework->object_dispatch = local_object_dispatch;
563
564 framework->instance = *pInstance;
565 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
566 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
567 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700568 framework->api_version = api_version;
569 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
570
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700571#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600572 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700573 object_tracker->report_data = framework->report_data;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700574#elif BUILD_THREAD_SAFETY
575 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "google_thread_checker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700576 thread_checker->report_data = framework->report_data;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700577#elif BUILD_PARAMETER_VALIDATION
578 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_parameter_validation");
579 parameter_validation->report_data = framework->report_data;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700580#else
581 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
582#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600583
584 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700585 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600586 }
587
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700588 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
589
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600590 return result;
591}
592
593VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
594 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600595 auto layer_data = GetLayerDataPtr(key, layer_data_map);
596 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700597 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600598 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
599 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600600 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700601 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600602 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
603 }
604
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600605 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600606
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600607 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700608 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600609 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
610 }
611 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600612 while (layer_data->logging_messenger.size() > 0) {
613 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
614 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
615 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600616 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600617 while (layer_data->logging_callback.size() > 0) {
618 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
619 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
620 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600621 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600622
623 layer_debug_utils_destroy_instance(layer_data->report_data);
624
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700625 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
626 delete *item;
627 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600628 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600629}
630
631VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
632 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600633 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600634
635 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
636
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600637 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
638 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600639 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
640 if (fpCreateDevice == NULL) {
641 return VK_ERROR_INITIALIZATION_FAILED;
642 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600643 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
644
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700645 // Get physical device limits for device
646 VkPhysicalDeviceProperties device_properties = {};
647 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
648
649 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
650 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
651
652 DeviceExtensions device_extensions = {};
653 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
654 for (auto item : instance_interceptor->object_dispatch) {
655 item->device_extensions = device_extensions;
656 }
657
658 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600659 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700660 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700661 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700662 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600663 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600664 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700665 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600666 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
667 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600668
669 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600670 if (result != VK_SUCCESS) {
671 return result;
672 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600673
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600674 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700675
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700676 // Save local info in device object
677 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700678 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
679 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700680 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700681
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600682 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700683
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600684 device_interceptor->device = *pDevice;
685 device_interceptor->physical_device = gpu;
686 device_interceptor->instance = instance_interceptor->instance;
687 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600688
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700689#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600690 // Create child layer objects for this key and add to dispatch vector
691 auto object_tracker = new ObjectLifetimes;
692 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
693 object_tracker->container_type = LayerObjectTypeObjectTracker;
694 object_tracker->physical_device = gpu;
695 object_tracker->instance = instance_interceptor->instance;
696 object_tracker->report_data = device_interceptor->report_data;
697 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700698 object_tracker->api_version = device_interceptor->api_version;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600699 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700700#elif BUILD_THREAD_SAFETY
701 auto thread_safety = new ThreadSafety;
702 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
703 thread_safety->container_type = LayerObjectTypeThreading;
704 thread_safety->physical_device = gpu;
705 thread_safety->instance = instance_interceptor->instance;
706 thread_safety->report_data = device_interceptor->report_data;
707 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700708 thread_safety->api_version = device_interceptor->api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700709 device_interceptor->object_dispatch.emplace_back(thread_safety);
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700710#elif BUILD_PARAMETER_VALIDATION
711 auto stateless_validation = new StatelessValidation;
712 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
713 stateless_validation->container_type = LayerObjectTypeParameterValidation;
714 stateless_validation->physical_device = gpu;
715 stateless_validation->instance = instance_interceptor->instance;
716 stateless_validation->report_data = device_interceptor->report_data;
717 stateless_validation->device_dispatch_table = device_interceptor->device_dispatch_table;
718 stateless_validation->api_version = device_interceptor->api_version;
719 device_interceptor->object_dispatch.emplace_back(stateless_validation);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700720#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600721
722 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700723 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700724 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600725 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600726
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700727 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
728
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600729 return result;
730}
731
732VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
733 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600734 auto layer_data = GetLayerDataPtr(key, layer_data_map);
735 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700736 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600737 intercept->PreCallValidateDestroyDevice(device, pAllocator);
738 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600739 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700740 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600741 intercept->PreCallRecordDestroyDevice(device, pAllocator);
742 }
743 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600744
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600745 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600746
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600747 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700748 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600749 intercept->PostCallRecordDestroyDevice(device, pAllocator);
750 }
751
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700752 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
753 delete *item;
754 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600755 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700756}
757
758
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700759// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700760
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700761VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
762 VkDevice device,
763 VkPipelineCache pipelineCache,
764 uint32_t createInfoCount,
765 const VkGraphicsPipelineCreateInfo* pCreateInfos,
766 const VkAllocationCallbacks* pAllocator,
767 VkPipeline* pPipelines) {
768 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
769 bool skip = false;
770
771#ifdef BUILD_CORE_VALIDATION
772 create_graphics_pipeline_api_state cgpl_state{};
773#else
774 struct create_graphics_pipeline_api_state {
775 const VkGraphicsPipelineCreateInfo* pCreateInfos;
776 } cgpl_state;
777 cgpl_state.pCreateInfos = pCreateInfos;
778#endif
779
780 for (auto intercept : layer_data->object_dispatch) {
781 auto lock = intercept->write_lock();
782 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
783 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
784 }
785 for (auto intercept : layer_data->object_dispatch) {
786 auto lock = intercept->write_lock();
787 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
788 }
789
790 VkResult result = DispatchCreateGraphicsPipelines(layer_data, device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
791
792 for (auto intercept : layer_data->object_dispatch) {
793 auto lock = intercept->write_lock();
794 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
795 }
796 return result;
797}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700798
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700799// This API saves some core_validation pipeline state state on the stack for performance purposes
800VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
801 VkDevice device,
802 VkPipelineCache pipelineCache,
803 uint32_t createInfoCount,
804 const VkComputePipelineCreateInfo* pCreateInfos,
805 const VkAllocationCallbacks* pAllocator,
806 VkPipeline* pPipelines) {
807 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
808 bool skip = false;
809
810#ifndef BUILD_CORE_VALIDATION
811 struct PIPELINE_STATE {};
812#endif
813
814 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
815
816 for (auto intercept : layer_data->object_dispatch) {
817 auto lock = intercept->write_lock();
818 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
819 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
820 }
821 for (auto intercept : layer_data->object_dispatch) {
822 auto lock = intercept->write_lock();
823 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
824 }
825 VkResult result = DispatchCreateComputePipelines(layer_data, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
826 for (auto intercept : layer_data->object_dispatch) {
827 auto lock = intercept->write_lock();
828 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
829 }
830 return result;
831}
832
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700833VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
834 VkDevice device,
835 VkPipelineCache pipelineCache,
836 uint32_t createInfoCount,
837 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
838 const VkAllocationCallbacks* pAllocator,
839 VkPipeline* pPipelines) {
840 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
841 bool skip = false;
842
843#ifndef BUILD_CORE_VALIDATION
844 struct PIPELINE_STATE {};
845#endif
846
847 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
848
849 for (auto intercept : layer_data->object_dispatch) {
850 auto lock = intercept->write_lock();
851 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
852 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
853 }
854 for (auto intercept : layer_data->object_dispatch) {
855 auto lock = intercept->write_lock();
856 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
857 }
858 VkResult result = DispatchCreateRayTracingPipelinesNV(layer_data, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
859 for (auto intercept : layer_data->object_dispatch) {
860 auto lock = intercept->write_lock();
861 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
862 }
863 return result;
864}
865
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -0700866// This API needs the ability to modify a down-chain parameter
867VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
868 VkDevice device,
869 const VkPipelineLayoutCreateInfo* pCreateInfo,
870 const VkAllocationCallbacks* pAllocator,
871 VkPipelineLayout* pPipelineLayout) {
872 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
873 bool skip = false;
874
875#ifndef BUILD_CORE_VALIDATION
876 struct create_pipeline_layout_api_state {
877 VkPipelineLayoutCreateInfo modified_create_info;
878 };
879#endif
880 create_pipeline_layout_api_state cpl_state{};
881 cpl_state.modified_create_info = *pCreateInfo;
882
883 for (auto intercept : layer_data->object_dispatch) {
884 auto lock = intercept->write_lock();
885 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
886 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
887 }
888 for (auto intercept : layer_data->object_dispatch) {
889 auto lock = intercept->write_lock();
890 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
891 }
892 VkResult result = DispatchCreatePipelineLayout(layer_data, device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
893 for (auto intercept : layer_data->object_dispatch) {
894 auto lock = intercept->write_lock();
895 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
896 }
897 return result;
898}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700899
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700900
901// ValidationCache APIs do not dispatch
902
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700903VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
904 VkDevice device,
905 const VkValidationCacheCreateInfoEXT* pCreateInfo,
906 const VkAllocationCallbacks* pAllocator,
907 VkValidationCacheEXT* pValidationCache) {
908 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
909 VkResult result = VK_SUCCESS;
910
911 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
912 if (validation_data) {
913 auto lock = validation_data->write_lock();
914 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
915 }
916 return result;
917}
918
919VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
920 VkDevice device,
921 VkValidationCacheEXT validationCache,
922 const VkAllocationCallbacks* pAllocator) {
923 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
924
925 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
926 if (validation_data) {
927 auto lock = validation_data->write_lock();
928 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
929 }
930}
931
932VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
933 VkDevice device,
934 VkValidationCacheEXT dstCache,
935 uint32_t srcCacheCount,
936 const VkValidationCacheEXT* pSrcCaches) {
937 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
938 VkResult result = VK_SUCCESS;
939
940 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
941 if (validation_data) {
942 auto lock = validation_data->write_lock();
943 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
944 }
945 return result;
946}
947
948VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
949 VkDevice device,
950 VkValidationCacheEXT validationCache,
951 size_t* pDataSize,
952 void* pData) {
953 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
954 VkResult result = VK_SUCCESS;
955
956 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
957 if (validation_data) {
958 auto lock = validation_data->write_lock();
959 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
960 }
961 return result;
962
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700963}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600964
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700965 inline_custom_validation_class_definitions = """
966 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
967 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
968 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
969 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700970
971 // Allow additional parameter for CreateGraphicsPipelines
972 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
973 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
974 };
975 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
976 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
977 };
978 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
979 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
980 };
981
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700982 // Allow additional state parameter for CreateComputePipelines
983 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
984 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
985 };
986 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
987 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
988 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700989
990 // Allow additional state parameter for CreateRayTracingPipelinesNV
991 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
992 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
993 };
994 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
995 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
996 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -0700997
998 // Allow modification of a down-chain parameter for CreatePipelineLayout
999 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1000 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1001 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001002"""
1003
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001004 inline_custom_source_postamble = """
1005// loader-layer interface v0, just wrappers since there is only a layer
1006
1007VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1008 VkExtensionProperties *pProperties) {
1009 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1010}
1011
1012VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1013 VkLayerProperties *pProperties) {
1014 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1015}
1016
1017VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1018 VkLayerProperties *pProperties) {
1019 // the layer command handles VK_NULL_HANDLE just fine internally
1020 assert(physicalDevice == VK_NULL_HANDLE);
1021 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1022}
1023
1024VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1025 const char *pLayerName, uint32_t *pCount,
1026 VkExtensionProperties *pProperties) {
1027 // the layer command handles VK_NULL_HANDLE just fine internally
1028 assert(physicalDevice == VK_NULL_HANDLE);
1029 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1030}
1031
1032VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1033 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1034}
1035
1036VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1037 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1038}
1039
1040VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
1041 const char *funcName) {
1042 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
1043}
1044
1045VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1046 assert(pVersionStruct != NULL);
1047 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1048
1049 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1050 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1051 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1052 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
1053 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
1054 }
1055
1056 return VK_SUCCESS;
1057}"""
1058
1059
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001060 def __init__(self,
1061 errFile = sys.stderr,
1062 warnFile = sys.stderr,
1063 diagFile = sys.stdout):
1064 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1065 # Internal state - accumulators for different inner block text
1066 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1067 self.intercepts = []
1068 self.layer_factory = '' # String containing base layer factory class definition
1069
1070 # Check if the parameter passed in is a pointer to an array
1071 def paramIsArray(self, param):
1072 return param.attrib.get('len') is not None
1073
1074 # Check if the parameter passed in is a pointer
1075 def paramIsPointer(self, param):
1076 ispointer = False
1077 for elem in param:
1078 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
1079 ispointer = True
1080 return ispointer
1081
1082 # Check if an object is a non-dispatchable handle
1083 def isHandleTypeNonDispatchable(self, handletype):
1084 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1085 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1086 return True
1087 else:
1088 return False
1089
1090 # Check if an object is a dispatchable handle
1091 def isHandleTypeDispatchable(self, handletype):
1092 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1093 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
1094 return True
1095 else:
1096 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001097 #
1098 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001099 def beginFile(self, genOpts):
1100 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001101 # Output Copyright
1102 write(self.inline_copyright_message, file=self.outFile)
1103 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001104 self.header = False
1105 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1106 self.header = True
1107 write('#pragma once', file=self.outFile)
1108 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001109 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001110 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001111 else:
1112 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001113 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001114 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001115 #
1116 def endFile(self):
1117 # Finish C++ namespace and multiple inclusion protection
1118 self.newline()
1119 if not self.header:
1120 # Record intercepted procedures
1121 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
1122 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
1123 write('\n'.join(self.intercepts), file=self.outFile)
1124 write('};\n', file=self.outFile)
1125 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001126 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001127 if self.header:
1128 self.newline()
1129 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001130 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001131 self.layer_factory += '};\n\n'
1132 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001133 write(self.layer_factory, file=self.outFile)
1134 else:
1135 write(self.inline_custom_source_postamble, file=self.outFile)
1136 # Finish processing in superclass
1137 OutputGenerator.endFile(self)
1138
1139 def beginFeature(self, interface, emit):
1140 # Start processing in superclass
1141 OutputGenerator.beginFeature(self, interface, emit)
1142 # Get feature extra protect
1143 self.featureExtraProtect = GetFeatureProtect(interface)
1144 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1145 # feature. They're only printed in endFeature().
1146 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1147
1148 def endFeature(self):
1149 # Actually write the interface to the output file.
1150 if (self.emit):
1151 self.newline()
1152 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1153 # or move it below the 'for section...' loop.
1154 if (self.featureExtraProtect != None):
1155 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1156 for section in self.TYPE_SECTIONS:
1157 contents = self.sections[section]
1158 if contents:
1159 write('\n'.join(contents), file=self.outFile)
1160 self.newline()
1161 if (self.sections['command']):
1162 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1163 self.newline()
1164 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001165 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001166 # Finish processing in superclass
1167 OutputGenerator.endFeature(self)
1168 #
1169 # Append a definition to the specified section
1170 def appendSection(self, section, text):
1171 self.sections[section].append(text)
1172 #
1173 # Type generation
1174 def genType(self, typeinfo, name, alias):
1175 pass
1176 #
1177 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1178 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1179 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1180 # structs etc.)
1181 def genStruct(self, typeinfo, typeName):
1182 OutputGenerator.genStruct(self, typeinfo, typeName)
1183 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1184 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1185 for member in typeinfo.elem.findall('.//member'):
1186 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1187 body += ';\n'
1188 body += '} ' + typeName + ';\n'
1189 self.appendSection('struct', body)
1190 #
1191 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1192 def genGroup(self, groupinfo, groupName, alias):
1193 pass
1194 # Enumerant generation
1195 # <enum> tags may specify their values in several ways, but are usually just integers.
1196 def genEnum(self, enuminfo, name, alias):
1197 pass
1198 #
1199 # Customize Cdecl for layer factory base class
1200 def BaseClassCdecl(self, elem, name):
1201 raw = self.makeCDecls(elem)[1]
1202
1203 # Toss everything before the undecorated name
1204 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1205 prototype = prototype.replace(")", "", 1)
1206 prototype = prototype.replace(";", " {};")
1207
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001208 # Build up pre/post call virtual function declarations
1209 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1210 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1211 pre_call_record = 'virtual void PreCallRecord' + prototype
1212 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001213 resulttype = elem.find('proto/type')
1214 if resulttype.text == 'VkResult':
1215 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001216 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1217 #
1218 # Command generation
1219 def genCmd(self, cmdinfo, name, alias):
1220 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001221 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001222 ]
1223
1224 if name in ignore_functions:
1225 return
1226
1227 if self.header: # In the header declare all intercepts
1228 self.appendSection('command', '')
1229 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1230 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001231 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1232 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001233 if 'ValidationCache' not in name:
1234 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001235 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001236 self.layer_factory += '#endif\n'
1237 return
1238
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001239 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001240 if 'ValidationCache' not in name:
1241 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1242 else:
1243 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1244 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1245 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001246 return
1247 # Record that the function will be intercepted
1248 if (self.featureExtraProtect != None):
1249 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1250 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1251 if (self.featureExtraProtect != None):
1252 self.intercepts += [ '#endif' ]
1253 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1254 #
1255 decls = self.makeCDecls(cmdinfo.elem)
1256 self.appendSection('command', '')
1257 self.appendSection('command', '%s {' % decls[0][:-1])
1258 # Setup common to call wrappers. First parameter is always dispatchable
1259 dispatchable_type = cmdinfo.elem.find('param/type').text
1260 dispatchable_name = cmdinfo.elem.find('param/name').text
1261 # Default to device
1262 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001263 dispatch_table_name = 'VkLayerDispatchTable'
1264 # Set to instance as necessary
1265 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1266 device_or_instance = 'instance'
1267 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001268 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001269 api_function_name = cmdinfo.elem.attrib.get('name')
1270 params = cmdinfo.elem.findall('param/name')
1271 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001272 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001273
1274 # Declare result variable, if any.
1275 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001276 'PFN_vkVoidFunction': 'return nullptr;',
1277 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001278 'VkDeviceAddress': 'return 0;',
1279 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1280 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001281 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001282 }
1283 resulttype = cmdinfo.elem.find('proto/type')
1284 assignresult = ''
1285 if (resulttype.text != 'void'):
1286 assignresult = resulttype.text + ' result = '
1287
1288 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001289 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001290
1291 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001292 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001293 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001294 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1295 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1296 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001297
1298 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001299 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001300 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001301 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001302 self.appendSection('command', ' }')
1303
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001304 # Insert pre-dispatch debug utils function call
1305 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001306 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001307
1308 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001309 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001310
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001311 # Insert post-dispatch debug utils function call
1312 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001313 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001314
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001315 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001316 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001317 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001318 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001319 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001320 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001321 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001322 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001323 # Return result variable, if any.
1324 if (resulttype.text != 'void'):
1325 self.appendSection('command', ' return result;')
1326 self.appendSection('command', '}')
1327 #
1328 # Override makeProtoName to drop the "vk" prefix
1329 def makeProtoName(self, name, tail):
1330 return self.genOpts.apientry + name[2:] + tail