blob: 05fa0c3ad51bb38d23741bf86f69cc44241f5eb2 [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 Lobodzinskic37c82a2019-02-28 13:13:02 -0700141 # ValidationCache functions do not get dispatched
142 'vkCreateValidationCacheEXT',
143 'vkDestroyValidationCacheEXT',
144 'vkMergeValidationCachesEXT',
145 'vkGetValidationCacheDataEXT',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700146 ]
147
148 alt_ret_codes = [
149 # Include functions here which must tolerate VK_INCOMPLETE as a return code
150 'vkEnumeratePhysicalDevices',
151 'vkEnumeratePhysicalDeviceGroupsKHR',
152 'vkGetValidationCacheDataEXT',
153 'vkGetPipelineCacheData',
154 'vkGetShaderInfoAMD',
155 'vkGetPhysicalDeviceDisplayPropertiesKHR',
156 'vkGetPhysicalDeviceDisplayProperties2KHR',
157 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
158 'vkGetDisplayPlaneSupportedDisplaysKHR',
159 'vkGetDisplayModePropertiesKHR',
160 'vkGetDisplayModeProperties2KHR',
161 'vkGetPhysicalDeviceSurfaceFormatsKHR',
162 'vkGetPhysicalDeviceSurfacePresentModesKHR',
163 'vkGetPhysicalDevicePresentRectanglesKHR',
164 'vkGetPastPresentationTimingGOOGLE',
165 'vkGetSwapchainImagesKHR',
166 'vkEnumerateInstanceLayerProperties',
167 'vkEnumerateDeviceLayerProperties',
168 'vkEnumerateInstanceExtensionProperties',
169 'vkEnumerateDeviceExtensionProperties',
170 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
171 ]
172
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700173 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700174 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
175 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700176 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
177 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
178 'vkCmdBeginDebugUtilsLabelEXT' : 'BeginCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
179 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
180 }
181
182 post_dispatch_debug_utils_functions = {
183 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
184 'vkCmdEndDebugUtilsLabelEXT' : 'EndCmdDebugUtilsLabel(layer_data->report_data, commandBuffer);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700185 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
186 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
187 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
188 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
189 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700190 }
191
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600192 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
193 precallrecord_loop = precallvalidate_loop
194 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600195
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700196 inline_custom_header_preamble = """
197#define NOMINMAX
198#include <mutex>
199#include <cinttypes>
200#include <stdio.h>
201#include <stdlib.h>
202#include <string.h>
203#include <unordered_map>
204#include <unordered_set>
205#include <algorithm>
206#include <memory>
207
208#include "vk_loader_platform.h"
209#include "vulkan/vulkan.h"
210#include "vk_layer_config.h"
211#include "vk_layer_data.h"
212#include "vk_layer_logging.h"
213#include "vk_object_types.h"
214#include "vulkan/vk_layer.h"
215#include "vk_enum_string_helper.h"
216#include "vk_layer_extension_utils.h"
217#include "vk_layer_utils.h"
218#include "vulkan/vk_layer.h"
219#include "vk_dispatch_table_helper.h"
220#include "vk_validation_error_messages.h"
221#include "vk_extension_helper.h"
222#include "vk_safe_struct.h"
223
224extern uint64_t global_unique_id;
225extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
226"""
227
228 inline_custom_header_class_definition = """
229
230// Layer object type identifiers
231enum LayerObjectTypeId {
232 LayerObjectTypeThreading,
233 LayerObjectTypeParameterValidation,
234 LayerObjectTypeObjectTracker,
235 LayerObjectTypeCoreValidation,
236};
237
238struct TEMPLATE_STATE {
239 VkDescriptorUpdateTemplateKHR desc_update_template;
240 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
241
242 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
243 : desc_update_template(update_template), create_info(*pCreateInfo) {}
244};
245
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700246class LAYER_PHYS_DEV_PROPERTIES {
247public:
248 VkPhysicalDeviceProperties properties;
249 std::vector<VkQueueFamilyProperties> queue_family_properties;
250};
251
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700252// Layer chassis validation object base class definition
253class ValidationObject {
254 public:
255 uint32_t api_version;
256 debug_report_data* report_data = nullptr;
257 std::vector<VkDebugReportCallbackEXT> logging_callback;
258 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
259
260 VkLayerInstanceDispatchTable instance_dispatch_table;
261 VkLayerDispatchTable device_dispatch_table;
262
263 InstanceExtensions instance_extensions;
264 DeviceExtensions device_extensions = {};
265
266 VkInstance instance = VK_NULL_HANDLE;
267 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
268 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700269 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700270
271 std::vector<ValidationObject*> object_dispatch;
272 LayerObjectTypeId container_type;
273
274 // Constructor
275 ValidationObject(){};
276 // Destructor
277 virtual ~ValidationObject() {};
278
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700279 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700280 virtual std::unique_lock<std::mutex> write_lock() {
281 return std::unique_lock<std::mutex>(validation_object_mutex);
282 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700283
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700284 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
285 for (auto validation_object : object_dispatch) {
286 if (validation_object->container_type == object_type) {
287 return validation_object;
288 }
289 }
290 return nullptr;
291 };
292
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700293 std::string layer_name = "CHASSIS";
294
295 // Handle Wrapping Data
296 // Reverse map display handles
297 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
298 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700299 struct SubpassesUsageStates {
300 std::unordered_set<uint32_t> subpasses_using_color_attachment;
301 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
302 };
303 // Uses unwrapped handles
304 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
305 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
306 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
307 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700308 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
309 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700310
311
312 // Unwrap a handle. Must hold lock.
313 template <typename HandleType>
314 HandleType Unwrap(HandleType wrappedHandle) {
315 // TODO: don't use operator[] here.
316 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
317 }
318
319 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
320 template <typename HandleType>
321 HandleType WrapNew(HandleType newlyCreatedHandle) {
322 auto unique_id = global_unique_id++;
323 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
324 return (HandleType)unique_id;
325 }
326
327 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
328 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
329 auto unique_id = global_unique_id++;
330 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
331 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
332 return (VkDisplayKHR)unique_id;
333 }
334
335 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
336 // creating another. Must hold lock.
337 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
338 // See if this display is already known
339 auto it = map_data->display_id_reverse_mapping.find(handle);
340 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
341 // Unknown, so wrap
342 return WrapDisplay(handle, map_data);
343 }
344
345 // Pre/post hook point declarations
346"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600347
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700348 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600349// This file is ***GENERATED***. Do Not Edit.
350// See layer_chassis_generator.py for modifications.
351
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700352/* Copyright (c) 2015-2019 The Khronos Group Inc.
353 * Copyright (c) 2015-2019 Valve Corporation
354 * Copyright (c) 2015-2019 LunarG, Inc.
355 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600356 *
357 * Licensed under the Apache License, Version 2.0 (the "License");
358 * you may not use this file except in compliance with the License.
359 * You may obtain a copy of the License at
360 *
361 * http://www.apache.org/licenses/LICENSE-2.0
362 *
363 * Unless required by applicable law or agreed to in writing, software
364 * distributed under the License is distributed on an "AS IS" BASIS,
365 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
366 * See the License for the specific language governing permissions and
367 * limitations under the License.
368 *
369 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700370 */"""
371
372 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600373
374#include <string.h>
375#include <mutex>
376
377#define VALIDATION_ERROR_MAP_IMPL
378
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600379#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700380#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600381
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600382std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600383
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700384// Global unique object identifier. All increments must be guarded by a lock.
385uint64_t global_unique_id = 1;
386// Map uniqueID to actual object handle
387std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
388
389// TODO: This variable controls handle wrapping -- in the future it should be hooked
390// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
391#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
392bool wrap_handles = true;
393#else
394const bool wrap_handles = false;
395#endif
396
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600397// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700398#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600399#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700400#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700401#elif BUILD_THREAD_SAFETY
Mark Lobodzinski706e52b2018-12-11 13:21:52 -0700402#include "thread_safety.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700403#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
404#elif BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700405#include "stateless_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700406#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
407#elif BUILD_CORE_VALIDATION
408#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
409#else
410#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
411#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600412
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600413namespace vulkan_layer_chassis {
414
415using std::unordered_map;
416
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600417static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700418 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600419};
420
421static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
422
423extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
424
425
426// Manually written functions
427
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700428// Check enabled instance extensions against supported instance extension whitelist
429static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
430 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
431 // Check for recognized instance extensions
432 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
433 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
434 kVUIDUndefined,
435 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
436 "results and/or produce undefined behavior.",
437 pCreateInfo->ppEnabledExtensionNames[i]);
438 }
439 }
440}
441
442// Check enabled device extensions against supported device extension whitelist
443static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
444 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
445 // Check for recognized device extensions
446 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
447 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
448 kVUIDUndefined,
449 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
450 "results and/or produce undefined behavior.",
451 pCreateInfo->ppEnabledExtensionNames[i]);
452 }
453 }
454}
455
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600456VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600457 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700458 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700459 return nullptr;
460 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600461 const auto &item = name_to_funcptr_map.find(funcName);
462 if (item != name_to_funcptr_map.end()) {
463 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
464 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600465 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600466 if (!table.GetDeviceProcAddr) return nullptr;
467 return table.GetDeviceProcAddr(device, funcName);
468}
469
470VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600471 const auto &item = name_to_funcptr_map.find(funcName);
472 if (item != name_to_funcptr_map.end()) {
473 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
474 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600475 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
476 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600477 if (!table.GetInstanceProcAddr) return nullptr;
478 return table.GetInstanceProcAddr(instance, funcName);
479}
480
481VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600482 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
483 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600484 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
485 return table.GetPhysicalDeviceProcAddr(instance, funcName);
486}
487
488VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
489 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
490}
491
492VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
493 VkLayerProperties *pProperties) {
494 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
495}
496
497VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
498 VkExtensionProperties *pProperties) {
499 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
500 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
501
502 return VK_ERROR_LAYER_NOT_PRESENT;
503}
504
505VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
506 uint32_t *pCount, VkExtensionProperties *pProperties) {
507 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600508 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600509 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
510 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600511}
512
513VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
514 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600515 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600516
517 assert(chain_info->u.pLayerInfo);
518 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
519 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
520 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
521 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700522 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
523 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
524
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600525
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600526 // Create temporary dispatch vector for pre-calls until instance is created
527 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700528#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600529 auto object_tracker = new ObjectLifetimes;
530 local_object_dispatch.emplace_back(object_tracker);
531 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700532 object_tracker->api_version = api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700533#elif BUILD_THREAD_SAFETY
534 auto thread_checker = new ThreadSafety;
535 local_object_dispatch.emplace_back(thread_checker);
536 thread_checker->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700537 thread_checker->api_version = api_version;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700538#elif BUILD_PARAMETER_VALIDATION
539 auto parameter_validation = new StatelessValidation;
540 local_object_dispatch.emplace_back(parameter_validation);
541 parameter_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700542 parameter_validation->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700543#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600544
545
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600546 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600547 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600548 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
549 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600550 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600551 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
552 }
553
554 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600555 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600556
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600557 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600558
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600559 framework->object_dispatch = local_object_dispatch;
560
561 framework->instance = *pInstance;
562 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
563 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
564 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700565 framework->api_version = api_version;
566 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
567
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700568#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600569 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700570 object_tracker->report_data = framework->report_data;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700571#elif BUILD_THREAD_SAFETY
572 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "google_thread_checker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700573 thread_checker->report_data = framework->report_data;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700574#elif BUILD_PARAMETER_VALIDATION
575 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_parameter_validation");
576 parameter_validation->report_data = framework->report_data;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700577#else
578 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
579#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600580
581 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700582 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600583 }
584
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700585 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
586
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600587 return result;
588}
589
590VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
591 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600592 auto layer_data = GetLayerDataPtr(key, layer_data_map);
593 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700594 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600595 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
596 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600597 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700598 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600599 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
600 }
601
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600602 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600603
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600604 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700605 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600606 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
607 }
608 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600609 while (layer_data->logging_messenger.size() > 0) {
610 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
611 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
612 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600613 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600614 while (layer_data->logging_callback.size() > 0) {
615 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
616 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
617 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600618 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600619
620 layer_debug_utils_destroy_instance(layer_data->report_data);
621
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700622 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
623 delete *item;
624 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600625 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600626}
627
628VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
629 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600630 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600631
632 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
633
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600634 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
635 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600636 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
637 if (fpCreateDevice == NULL) {
638 return VK_ERROR_INITIALIZATION_FAILED;
639 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600640 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
641
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700642 // Get physical device limits for device
643 VkPhysicalDeviceProperties device_properties = {};
644 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
645
646 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
647 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
648
649 DeviceExtensions device_extensions = {};
650 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
651 for (auto item : instance_interceptor->object_dispatch) {
652 item->device_extensions = device_extensions;
653 }
654
655 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600656 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700657 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700658 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700659 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600660 }
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 Lobodzinski9b6522d2018-09-26 11:07:45 -0600663 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
664 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600665
666 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600667 if (result != VK_SUCCESS) {
668 return result;
669 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600670
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600671 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700672
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700673 // Save local info in device object
674 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700675 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
676 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700677 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700678
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600679 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700680
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600681 device_interceptor->device = *pDevice;
682 device_interceptor->physical_device = gpu;
683 device_interceptor->instance = instance_interceptor->instance;
684 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600685
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700686#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600687 // Create child layer objects for this key and add to dispatch vector
688 auto object_tracker = new ObjectLifetimes;
689 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
690 object_tracker->container_type = LayerObjectTypeObjectTracker;
691 object_tracker->physical_device = gpu;
692 object_tracker->instance = instance_interceptor->instance;
693 object_tracker->report_data = device_interceptor->report_data;
694 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700695 object_tracker->api_version = device_interceptor->api_version;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600696 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700697#elif BUILD_THREAD_SAFETY
698 auto thread_safety = new ThreadSafety;
699 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
700 thread_safety->container_type = LayerObjectTypeThreading;
701 thread_safety->physical_device = gpu;
702 thread_safety->instance = instance_interceptor->instance;
703 thread_safety->report_data = device_interceptor->report_data;
704 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700705 thread_safety->api_version = device_interceptor->api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700706 device_interceptor->object_dispatch.emplace_back(thread_safety);
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700707#elif BUILD_PARAMETER_VALIDATION
708 auto stateless_validation = new StatelessValidation;
709 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
710 stateless_validation->container_type = LayerObjectTypeParameterValidation;
711 stateless_validation->physical_device = gpu;
712 stateless_validation->instance = instance_interceptor->instance;
713 stateless_validation->report_data = device_interceptor->report_data;
714 stateless_validation->device_dispatch_table = device_interceptor->device_dispatch_table;
715 stateless_validation->api_version = device_interceptor->api_version;
716 device_interceptor->object_dispatch.emplace_back(stateless_validation);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700717#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600718
719 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700720 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700721 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600722 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600723
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700724 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
725
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600726 return result;
727}
728
729VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
730 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600731 auto layer_data = GetLayerDataPtr(key, layer_data_map);
732 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700733 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600734 intercept->PreCallValidateDestroyDevice(device, pAllocator);
735 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600736 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700737 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600738 intercept->PreCallRecordDestroyDevice(device, pAllocator);
739 }
740 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600741
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600742 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600743
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600744 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700745 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600746 intercept->PostCallRecordDestroyDevice(device, pAllocator);
747 }
748
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700749 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
750 delete *item;
751 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600752 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700753}
754
755
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700756// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700757
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700758VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
759 VkDevice device,
760 VkPipelineCache pipelineCache,
761 uint32_t createInfoCount,
762 const VkGraphicsPipelineCreateInfo* pCreateInfos,
763 const VkAllocationCallbacks* pAllocator,
764 VkPipeline* pPipelines) {
765 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
766 bool skip = false;
767
768#ifdef BUILD_CORE_VALIDATION
769 create_graphics_pipeline_api_state cgpl_state{};
770#else
771 struct create_graphics_pipeline_api_state {
772 const VkGraphicsPipelineCreateInfo* pCreateInfos;
773 } cgpl_state;
774 cgpl_state.pCreateInfos = pCreateInfos;
775#endif
776
777 for (auto intercept : layer_data->object_dispatch) {
778 auto lock = intercept->write_lock();
779 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
780 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
781 }
782 for (auto intercept : layer_data->object_dispatch) {
783 auto lock = intercept->write_lock();
784 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
785 }
786
787 VkResult result = DispatchCreateGraphicsPipelines(layer_data, device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
788
789 for (auto intercept : layer_data->object_dispatch) {
790 auto lock = intercept->write_lock();
791 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
792 }
793 return result;
794}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700795
796VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
797 VkDevice device,
798 const VkValidationCacheCreateInfoEXT* pCreateInfo,
799 const VkAllocationCallbacks* pAllocator,
800 VkValidationCacheEXT* pValidationCache) {
801 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
802 VkResult result = VK_SUCCESS;
803
804 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
805 if (validation_data) {
806 auto lock = validation_data->write_lock();
807 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
808 }
809 return result;
810}
811
812VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
813 VkDevice device,
814 VkValidationCacheEXT validationCache,
815 const VkAllocationCallbacks* pAllocator) {
816 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
817
818 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
819 if (validation_data) {
820 auto lock = validation_data->write_lock();
821 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
822 }
823}
824
825VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
826 VkDevice device,
827 VkValidationCacheEXT dstCache,
828 uint32_t srcCacheCount,
829 const VkValidationCacheEXT* pSrcCaches) {
830 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
831 VkResult result = VK_SUCCESS;
832
833 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
834 if (validation_data) {
835 auto lock = validation_data->write_lock();
836 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
837 }
838 return result;
839}
840
841VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
842 VkDevice device,
843 VkValidationCacheEXT validationCache,
844 size_t* pDataSize,
845 void* pData) {
846 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
847 VkResult result = VK_SUCCESS;
848
849 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
850 if (validation_data) {
851 auto lock = validation_data->write_lock();
852 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
853 }
854 return result;
855
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700856}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600857
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700858 inline_custom_validation_class_definitions = """
859 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
860 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
861 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
862 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700863
864 // Allow additional parameter for CreateGraphicsPipelines
865 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
866 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
867 };
868 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
869 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
870 };
871 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
872 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
873 };
874
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700875"""
876
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600877 inline_custom_source_postamble = """
878// loader-layer interface v0, just wrappers since there is only a layer
879
880VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
881 VkExtensionProperties *pProperties) {
882 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
883}
884
885VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
886 VkLayerProperties *pProperties) {
887 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
888}
889
890VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
891 VkLayerProperties *pProperties) {
892 // the layer command handles VK_NULL_HANDLE just fine internally
893 assert(physicalDevice == VK_NULL_HANDLE);
894 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
895}
896
897VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
898 const char *pLayerName, uint32_t *pCount,
899 VkExtensionProperties *pProperties) {
900 // the layer command handles VK_NULL_HANDLE just fine internally
901 assert(physicalDevice == VK_NULL_HANDLE);
902 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
903}
904
905VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
906 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
907}
908
909VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
910 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
911}
912
913VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
914 const char *funcName) {
915 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
916}
917
918VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
919 assert(pVersionStruct != NULL);
920 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
921
922 // Fill in the function pointers if our version is at least capable of having the structure contain them.
923 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
924 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
925 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
926 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
927 }
928
929 return VK_SUCCESS;
930}"""
931
932
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600933 def __init__(self,
934 errFile = sys.stderr,
935 warnFile = sys.stderr,
936 diagFile = sys.stdout):
937 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
938 # Internal state - accumulators for different inner block text
939 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
940 self.intercepts = []
941 self.layer_factory = '' # String containing base layer factory class definition
942
943 # Check if the parameter passed in is a pointer to an array
944 def paramIsArray(self, param):
945 return param.attrib.get('len') is not None
946
947 # Check if the parameter passed in is a pointer
948 def paramIsPointer(self, param):
949 ispointer = False
950 for elem in param:
951 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
952 ispointer = True
953 return ispointer
954
955 # Check if an object is a non-dispatchable handle
956 def isHandleTypeNonDispatchable(self, handletype):
957 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
958 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
959 return True
960 else:
961 return False
962
963 # Check if an object is a dispatchable handle
964 def isHandleTypeDispatchable(self, handletype):
965 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
966 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
967 return True
968 else:
969 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700970 #
971 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600972 def beginFile(self, genOpts):
973 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700974 # Output Copyright
975 write(self.inline_copyright_message, file=self.outFile)
976 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600977 self.header = False
978 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
979 self.header = True
980 write('#pragma once', file=self.outFile)
981 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600982 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700983 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600984 else:
985 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700986 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700987 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600988 #
989 def endFile(self):
990 # Finish C++ namespace and multiple inclusion protection
991 self.newline()
992 if not self.header:
993 # Record intercepted procedures
994 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
995 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
996 write('\n'.join(self.intercepts), file=self.outFile)
997 write('};\n', file=self.outFile)
998 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600999 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001000 if self.header:
1001 self.newline()
1002 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001003 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001004 self.layer_factory += '};\n\n'
1005 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001006 write(self.layer_factory, file=self.outFile)
1007 else:
1008 write(self.inline_custom_source_postamble, file=self.outFile)
1009 # Finish processing in superclass
1010 OutputGenerator.endFile(self)
1011
1012 def beginFeature(self, interface, emit):
1013 # Start processing in superclass
1014 OutputGenerator.beginFeature(self, interface, emit)
1015 # Get feature extra protect
1016 self.featureExtraProtect = GetFeatureProtect(interface)
1017 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1018 # feature. They're only printed in endFeature().
1019 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1020
1021 def endFeature(self):
1022 # Actually write the interface to the output file.
1023 if (self.emit):
1024 self.newline()
1025 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1026 # or move it below the 'for section...' loop.
1027 if (self.featureExtraProtect != None):
1028 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1029 for section in self.TYPE_SECTIONS:
1030 contents = self.sections[section]
1031 if contents:
1032 write('\n'.join(contents), file=self.outFile)
1033 self.newline()
1034 if (self.sections['command']):
1035 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1036 self.newline()
1037 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001038 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001039 # Finish processing in superclass
1040 OutputGenerator.endFeature(self)
1041 #
1042 # Append a definition to the specified section
1043 def appendSection(self, section, text):
1044 self.sections[section].append(text)
1045 #
1046 # Type generation
1047 def genType(self, typeinfo, name, alias):
1048 pass
1049 #
1050 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1051 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1052 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1053 # structs etc.)
1054 def genStruct(self, typeinfo, typeName):
1055 OutputGenerator.genStruct(self, typeinfo, typeName)
1056 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1057 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1058 for member in typeinfo.elem.findall('.//member'):
1059 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1060 body += ';\n'
1061 body += '} ' + typeName + ';\n'
1062 self.appendSection('struct', body)
1063 #
1064 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1065 def genGroup(self, groupinfo, groupName, alias):
1066 pass
1067 # Enumerant generation
1068 # <enum> tags may specify their values in several ways, but are usually just integers.
1069 def genEnum(self, enuminfo, name, alias):
1070 pass
1071 #
1072 # Customize Cdecl for layer factory base class
1073 def BaseClassCdecl(self, elem, name):
1074 raw = self.makeCDecls(elem)[1]
1075
1076 # Toss everything before the undecorated name
1077 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1078 prototype = prototype.replace(")", "", 1)
1079 prototype = prototype.replace(";", " {};")
1080
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001081 # Build up pre/post call virtual function declarations
1082 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1083 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1084 pre_call_record = 'virtual void PreCallRecord' + prototype
1085 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001086 resulttype = elem.find('proto/type')
1087 if resulttype.text == 'VkResult':
1088 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001089 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1090 #
1091 # Command generation
1092 def genCmd(self, cmdinfo, name, alias):
1093 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001094 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001095 ]
1096
1097 if name in ignore_functions:
1098 return
1099
1100 if self.header: # In the header declare all intercepts
1101 self.appendSection('command', '')
1102 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1103 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001104 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1105 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001106 if 'ValidationCache' not in name:
1107 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001108 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001109 self.layer_factory += '#endif\n'
1110 return
1111
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001112 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001113 if 'ValidationCache' not in name:
1114 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1115 else:
1116 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1117 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1118 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001119 return
1120 # Record that the function will be intercepted
1121 if (self.featureExtraProtect != None):
1122 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1123 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1124 if (self.featureExtraProtect != None):
1125 self.intercepts += [ '#endif' ]
1126 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1127 #
1128 decls = self.makeCDecls(cmdinfo.elem)
1129 self.appendSection('command', '')
1130 self.appendSection('command', '%s {' % decls[0][:-1])
1131 # Setup common to call wrappers. First parameter is always dispatchable
1132 dispatchable_type = cmdinfo.elem.find('param/type').text
1133 dispatchable_name = cmdinfo.elem.find('param/name').text
1134 # Default to device
1135 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001136 dispatch_table_name = 'VkLayerDispatchTable'
1137 # Set to instance as necessary
1138 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1139 device_or_instance = 'instance'
1140 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001141 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001142 api_function_name = cmdinfo.elem.attrib.get('name')
1143 params = cmdinfo.elem.findall('param/name')
1144 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001145 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001146
1147 # Declare result variable, if any.
1148 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001149 'PFN_vkVoidFunction': 'return nullptr;',
1150 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001151 'VkDeviceAddress': 'return 0;',
1152 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1153 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001154 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001155 }
1156 resulttype = cmdinfo.elem.find('proto/type')
1157 assignresult = ''
1158 if (resulttype.text != 'void'):
1159 assignresult = resulttype.text + ' result = '
1160
1161 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001162 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001163
1164 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001165 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001166 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001167 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1168 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1169 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001170
1171 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001172 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001173 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001174 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001175 self.appendSection('command', ' }')
1176
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001177 # Insert pre-dispatch debug utils function call
1178 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001179 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001180
1181 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001182 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001183
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001184 # Insert post-dispatch debug utils function call
1185 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001186 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001187
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001188 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001189 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001190 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001191 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001192 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001193 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001194 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001195 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001196 # Return result variable, if any.
1197 if (resulttype.text != 'void'):
1198 self.appendSection('command', ' return result;')
1199 self.appendSection('command', '}')
1200 #
1201 # Override makeProtoName to drop the "vk" prefix
1202 def makeProtoName(self, name, tail):
1203 return self.genOpts.apientry + name[2:] + tail