blob: a630d2992f2ce2f4db3116f030c763385fe21ecc [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 Lobodzinskic37c82a2019-02-28 13:13:02 -0700142 # ValidationCache functions do not get dispatched
143 'vkCreateValidationCacheEXT',
144 'vkDestroyValidationCacheEXT',
145 'vkMergeValidationCachesEXT',
146 'vkGetValidationCacheDataEXT',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700147 ]
148
149 alt_ret_codes = [
150 # Include functions here which must tolerate VK_INCOMPLETE as a return code
151 'vkEnumeratePhysicalDevices',
152 'vkEnumeratePhysicalDeviceGroupsKHR',
153 'vkGetValidationCacheDataEXT',
154 'vkGetPipelineCacheData',
155 'vkGetShaderInfoAMD',
156 'vkGetPhysicalDeviceDisplayPropertiesKHR',
157 'vkGetPhysicalDeviceDisplayProperties2KHR',
158 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
159 'vkGetDisplayPlaneSupportedDisplaysKHR',
160 'vkGetDisplayModePropertiesKHR',
161 'vkGetDisplayModeProperties2KHR',
162 'vkGetPhysicalDeviceSurfaceFormatsKHR',
163 'vkGetPhysicalDeviceSurfacePresentModesKHR',
164 'vkGetPhysicalDevicePresentRectanglesKHR',
165 'vkGetPastPresentationTimingGOOGLE',
166 'vkGetSwapchainImagesKHR',
167 'vkEnumerateInstanceLayerProperties',
168 'vkEnumerateDeviceLayerProperties',
169 'vkEnumerateInstanceExtensionProperties',
170 'vkEnumerateDeviceExtensionProperties',
171 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
172 ]
173
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700174 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700175 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
176 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700177 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
178 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
179 'vkCmdBeginDebugUtilsLabelEXT' : 'BeginCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
180 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
181 }
182
183 post_dispatch_debug_utils_functions = {
184 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
185 'vkCmdEndDebugUtilsLabelEXT' : 'EndCmdDebugUtilsLabel(layer_data->report_data, commandBuffer);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700186 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
187 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
188 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
189 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
190 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700191 }
192
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600193 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
194 precallrecord_loop = precallvalidate_loop
195 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600196
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700197 inline_custom_header_preamble = """
198#define NOMINMAX
199#include <mutex>
200#include <cinttypes>
201#include <stdio.h>
202#include <stdlib.h>
203#include <string.h>
204#include <unordered_map>
205#include <unordered_set>
206#include <algorithm>
207#include <memory>
208
209#include "vk_loader_platform.h"
210#include "vulkan/vulkan.h"
211#include "vk_layer_config.h"
212#include "vk_layer_data.h"
213#include "vk_layer_logging.h"
214#include "vk_object_types.h"
215#include "vulkan/vk_layer.h"
216#include "vk_enum_string_helper.h"
217#include "vk_layer_extension_utils.h"
218#include "vk_layer_utils.h"
219#include "vulkan/vk_layer.h"
220#include "vk_dispatch_table_helper.h"
221#include "vk_validation_error_messages.h"
222#include "vk_extension_helper.h"
223#include "vk_safe_struct.h"
224
225extern uint64_t global_unique_id;
226extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
227"""
228
229 inline_custom_header_class_definition = """
230
231// Layer object type identifiers
232enum LayerObjectTypeId {
233 LayerObjectTypeThreading,
234 LayerObjectTypeParameterValidation,
235 LayerObjectTypeObjectTracker,
236 LayerObjectTypeCoreValidation,
237};
238
239struct TEMPLATE_STATE {
240 VkDescriptorUpdateTemplateKHR desc_update_template;
241 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
242
243 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
244 : desc_update_template(update_template), create_info(*pCreateInfo) {}
245};
246
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700247class LAYER_PHYS_DEV_PROPERTIES {
248public:
249 VkPhysicalDeviceProperties properties;
250 std::vector<VkQueueFamilyProperties> queue_family_properties;
251};
252
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700253// Layer chassis validation object base class definition
254class ValidationObject {
255 public:
256 uint32_t api_version;
257 debug_report_data* report_data = nullptr;
258 std::vector<VkDebugReportCallbackEXT> logging_callback;
259 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
260
261 VkLayerInstanceDispatchTable instance_dispatch_table;
262 VkLayerDispatchTable device_dispatch_table;
263
264 InstanceExtensions instance_extensions;
265 DeviceExtensions device_extensions = {};
266
267 VkInstance instance = VK_NULL_HANDLE;
268 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
269 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700270 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700271
272 std::vector<ValidationObject*> object_dispatch;
273 LayerObjectTypeId container_type;
274
275 // Constructor
276 ValidationObject(){};
277 // Destructor
278 virtual ~ValidationObject() {};
279
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700280 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700281 virtual std::unique_lock<std::mutex> write_lock() {
282 return std::unique_lock<std::mutex>(validation_object_mutex);
283 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700284
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700285 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
286 for (auto validation_object : object_dispatch) {
287 if (validation_object->container_type == object_type) {
288 return validation_object;
289 }
290 }
291 return nullptr;
292 };
293
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700294 std::string layer_name = "CHASSIS";
295
296 // Handle Wrapping Data
297 // Reverse map display handles
298 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
299 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700300 struct SubpassesUsageStates {
301 std::unordered_set<uint32_t> subpasses_using_color_attachment;
302 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
303 };
304 // Uses unwrapped handles
305 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
306 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
307 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
308 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700309 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
310 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700311
312
313 // Unwrap a handle. Must hold lock.
314 template <typename HandleType>
315 HandleType Unwrap(HandleType wrappedHandle) {
316 // TODO: don't use operator[] here.
317 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
318 }
319
320 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
321 template <typename HandleType>
322 HandleType WrapNew(HandleType newlyCreatedHandle) {
323 auto unique_id = global_unique_id++;
324 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
325 return (HandleType)unique_id;
326 }
327
328 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
329 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
330 auto unique_id = global_unique_id++;
331 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
332 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
333 return (VkDisplayKHR)unique_id;
334 }
335
336 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
337 // creating another. Must hold lock.
338 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
339 // See if this display is already known
340 auto it = map_data->display_id_reverse_mapping.find(handle);
341 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
342 // Unknown, so wrap
343 return WrapDisplay(handle, map_data);
344 }
345
346 // Pre/post hook point declarations
347"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600348
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700349 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600350// This file is ***GENERATED***. Do Not Edit.
351// See layer_chassis_generator.py for modifications.
352
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700353/* Copyright (c) 2015-2019 The Khronos Group Inc.
354 * Copyright (c) 2015-2019 Valve Corporation
355 * Copyright (c) 2015-2019 LunarG, Inc.
356 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600357 *
358 * Licensed under the Apache License, Version 2.0 (the "License");
359 * you may not use this file except in compliance with the License.
360 * You may obtain a copy of the License at
361 *
362 * http://www.apache.org/licenses/LICENSE-2.0
363 *
364 * Unless required by applicable law or agreed to in writing, software
365 * distributed under the License is distributed on an "AS IS" BASIS,
366 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
367 * See the License for the specific language governing permissions and
368 * limitations under the License.
369 *
370 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700371 */"""
372
373 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600374
375#include <string.h>
376#include <mutex>
377
378#define VALIDATION_ERROR_MAP_IMPL
379
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600380#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700381#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600382
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600383std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600384
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700385// Global unique object identifier. All increments must be guarded by a lock.
386uint64_t global_unique_id = 1;
387// Map uniqueID to actual object handle
388std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
389
390// TODO: This variable controls handle wrapping -- in the future it should be hooked
391// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
392#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
393bool wrap_handles = true;
394#else
395const bool wrap_handles = false;
396#endif
397
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600398// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700399#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600400#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700401#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700402#elif BUILD_THREAD_SAFETY
Mark Lobodzinski706e52b2018-12-11 13:21:52 -0700403#include "thread_safety.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700404#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
405#elif BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700406#include "stateless_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700407#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
408#elif BUILD_CORE_VALIDATION
409#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
410#else
411#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
412#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600413
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600414namespace vulkan_layer_chassis {
415
416using std::unordered_map;
417
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600418static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700419 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600420};
421
422static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
423
424extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
425
426
427// Manually written functions
428
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700429// Check enabled instance extensions against supported instance extension whitelist
430static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
431 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
432 // Check for recognized instance extensions
433 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
434 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
435 kVUIDUndefined,
436 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
437 "results and/or produce undefined behavior.",
438 pCreateInfo->ppEnabledExtensionNames[i]);
439 }
440 }
441}
442
443// Check enabled device extensions against supported device extension whitelist
444static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
445 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
446 // Check for recognized device extensions
447 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
448 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
449 kVUIDUndefined,
450 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
451 "results and/or produce undefined behavior.",
452 pCreateInfo->ppEnabledExtensionNames[i]);
453 }
454 }
455}
456
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600457VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600458 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700459 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700460 return nullptr;
461 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600462 const auto &item = name_to_funcptr_map.find(funcName);
463 if (item != name_to_funcptr_map.end()) {
464 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
465 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600466 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600467 if (!table.GetDeviceProcAddr) return nullptr;
468 return table.GetDeviceProcAddr(device, funcName);
469}
470
471VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600472 const auto &item = name_to_funcptr_map.find(funcName);
473 if (item != name_to_funcptr_map.end()) {
474 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
475 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600476 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
477 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600478 if (!table.GetInstanceProcAddr) return nullptr;
479 return table.GetInstanceProcAddr(instance, funcName);
480}
481
482VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600483 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
484 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600485 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
486 return table.GetPhysicalDeviceProcAddr(instance, funcName);
487}
488
489VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
490 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
491}
492
493VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
494 VkLayerProperties *pProperties) {
495 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
496}
497
498VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
499 VkExtensionProperties *pProperties) {
500 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
501 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
502
503 return VK_ERROR_LAYER_NOT_PRESENT;
504}
505
506VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
507 uint32_t *pCount, VkExtensionProperties *pProperties) {
508 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600509 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600510 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
511 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600512}
513
514VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
515 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600516 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600517
518 assert(chain_info->u.pLayerInfo);
519 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
520 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
521 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
522 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700523 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
524 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
525
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600526
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600527 // Create temporary dispatch vector for pre-calls until instance is created
528 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700529#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600530 auto object_tracker = new ObjectLifetimes;
531 local_object_dispatch.emplace_back(object_tracker);
532 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700533 object_tracker->api_version = api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700534#elif BUILD_THREAD_SAFETY
535 auto thread_checker = new ThreadSafety;
536 local_object_dispatch.emplace_back(thread_checker);
537 thread_checker->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700538 thread_checker->api_version = api_version;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700539#elif BUILD_PARAMETER_VALIDATION
540 auto parameter_validation = new StatelessValidation;
541 local_object_dispatch.emplace_back(parameter_validation);
542 parameter_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700543 parameter_validation->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700544#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600545
546
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600547 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600548 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600549 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
550 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600551 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600552 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
553 }
554
555 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600556 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600557
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600558 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600559
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600560 framework->object_dispatch = local_object_dispatch;
561
562 framework->instance = *pInstance;
563 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
564 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
565 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700566 framework->api_version = api_version;
567 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
568
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700569#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600570 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700571 object_tracker->report_data = framework->report_data;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700572#elif BUILD_THREAD_SAFETY
573 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "google_thread_checker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700574 thread_checker->report_data = framework->report_data;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700575#elif BUILD_PARAMETER_VALIDATION
576 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_parameter_validation");
577 parameter_validation->report_data = framework->report_data;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700578#else
579 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
580#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600581
582 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700583 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600584 }
585
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700586 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
587
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600588 return result;
589}
590
591VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
592 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600593 auto layer_data = GetLayerDataPtr(key, layer_data_map);
594 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700595 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600596 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
597 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600598 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700599 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600600 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
601 }
602
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600603 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600604
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600605 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700606 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600607 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
608 }
609 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600610 while (layer_data->logging_messenger.size() > 0) {
611 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
612 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
613 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600614 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600615 while (layer_data->logging_callback.size() > 0) {
616 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
617 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
618 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600619 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600620
621 layer_debug_utils_destroy_instance(layer_data->report_data);
622
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700623 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
624 delete *item;
625 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600626 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600627}
628
629VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
630 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600631 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600632
633 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
634
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600635 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
636 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600637 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
638 if (fpCreateDevice == NULL) {
639 return VK_ERROR_INITIALIZATION_FAILED;
640 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600641 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
642
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700643 // Get physical device limits for device
644 VkPhysicalDeviceProperties device_properties = {};
645 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
646
647 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
648 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
649
650 DeviceExtensions device_extensions = {};
651 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
652 for (auto item : instance_interceptor->object_dispatch) {
653 item->device_extensions = device_extensions;
654 }
655
656 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600657 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700658 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700659 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700660 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600661 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600662 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700663 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600664 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
665 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600666
667 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600668 if (result != VK_SUCCESS) {
669 return result;
670 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600671
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600672 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700673
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700674 // Save local info in device object
675 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700676 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
677 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700678 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700679
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600680 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700681
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600682 device_interceptor->device = *pDevice;
683 device_interceptor->physical_device = gpu;
684 device_interceptor->instance = instance_interceptor->instance;
685 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600686
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700687#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600688 // Create child layer objects for this key and add to dispatch vector
689 auto object_tracker = new ObjectLifetimes;
690 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
691 object_tracker->container_type = LayerObjectTypeObjectTracker;
692 object_tracker->physical_device = gpu;
693 object_tracker->instance = instance_interceptor->instance;
694 object_tracker->report_data = device_interceptor->report_data;
695 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700696 object_tracker->api_version = device_interceptor->api_version;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600697 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700698#elif BUILD_THREAD_SAFETY
699 auto thread_safety = new ThreadSafety;
700 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
701 thread_safety->container_type = LayerObjectTypeThreading;
702 thread_safety->physical_device = gpu;
703 thread_safety->instance = instance_interceptor->instance;
704 thread_safety->report_data = device_interceptor->report_data;
705 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700706 thread_safety->api_version = device_interceptor->api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700707 device_interceptor->object_dispatch.emplace_back(thread_safety);
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700708#elif BUILD_PARAMETER_VALIDATION
709 auto stateless_validation = new StatelessValidation;
710 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
711 stateless_validation->container_type = LayerObjectTypeParameterValidation;
712 stateless_validation->physical_device = gpu;
713 stateless_validation->instance = instance_interceptor->instance;
714 stateless_validation->report_data = device_interceptor->report_data;
715 stateless_validation->device_dispatch_table = device_interceptor->device_dispatch_table;
716 stateless_validation->api_version = device_interceptor->api_version;
717 device_interceptor->object_dispatch.emplace_back(stateless_validation);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700718#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600719
720 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700721 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700722 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600723 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600724
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700725 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
726
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600727 return result;
728}
729
730VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
731 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600732 auto layer_data = GetLayerDataPtr(key, layer_data_map);
733 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700734 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600735 intercept->PreCallValidateDestroyDevice(device, pAllocator);
736 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600737 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700738 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600739 intercept->PreCallRecordDestroyDevice(device, pAllocator);
740 }
741 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600742
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600743 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600744
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600745 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700746 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600747 intercept->PostCallRecordDestroyDevice(device, pAllocator);
748 }
749
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700750 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
751 delete *item;
752 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600753 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700754}
755
756
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700757// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700758
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700759VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
760 VkDevice device,
761 VkPipelineCache pipelineCache,
762 uint32_t createInfoCount,
763 const VkGraphicsPipelineCreateInfo* pCreateInfos,
764 const VkAllocationCallbacks* pAllocator,
765 VkPipeline* pPipelines) {
766 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
767 bool skip = false;
768
769#ifdef BUILD_CORE_VALIDATION
770 create_graphics_pipeline_api_state cgpl_state{};
771#else
772 struct create_graphics_pipeline_api_state {
773 const VkGraphicsPipelineCreateInfo* pCreateInfos;
774 } cgpl_state;
775 cgpl_state.pCreateInfos = pCreateInfos;
776#endif
777
778 for (auto intercept : layer_data->object_dispatch) {
779 auto lock = intercept->write_lock();
780 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
781 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
782 }
783 for (auto intercept : layer_data->object_dispatch) {
784 auto lock = intercept->write_lock();
785 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
786 }
787
788 VkResult result = DispatchCreateGraphicsPipelines(layer_data, device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
789
790 for (auto intercept : layer_data->object_dispatch) {
791 auto lock = intercept->write_lock();
792 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
793 }
794 return result;
795}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700796
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700797// This API saves some core_validation pipeline state state on the stack for performance purposes
798VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
799 VkDevice device,
800 VkPipelineCache pipelineCache,
801 uint32_t createInfoCount,
802 const VkComputePipelineCreateInfo* pCreateInfos,
803 const VkAllocationCallbacks* pAllocator,
804 VkPipeline* pPipelines) {
805 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
806 bool skip = false;
807
808#ifndef BUILD_CORE_VALIDATION
809 struct PIPELINE_STATE {};
810#endif
811
812 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
813
814 for (auto intercept : layer_data->object_dispatch) {
815 auto lock = intercept->write_lock();
816 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
817 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
818 }
819 for (auto intercept : layer_data->object_dispatch) {
820 auto lock = intercept->write_lock();
821 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
822 }
823 VkResult result = DispatchCreateComputePipelines(layer_data, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
824 for (auto intercept : layer_data->object_dispatch) {
825 auto lock = intercept->write_lock();
826 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
827 }
828 return result;
829}
830
831
832// ValidationCache APIs do not dispatch
833
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700834VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
835 VkDevice device,
836 const VkValidationCacheCreateInfoEXT* pCreateInfo,
837 const VkAllocationCallbacks* pAllocator,
838 VkValidationCacheEXT* pValidationCache) {
839 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
840 VkResult result = VK_SUCCESS;
841
842 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
843 if (validation_data) {
844 auto lock = validation_data->write_lock();
845 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
846 }
847 return result;
848}
849
850VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
851 VkDevice device,
852 VkValidationCacheEXT validationCache,
853 const VkAllocationCallbacks* pAllocator) {
854 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
855
856 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
857 if (validation_data) {
858 auto lock = validation_data->write_lock();
859 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
860 }
861}
862
863VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
864 VkDevice device,
865 VkValidationCacheEXT dstCache,
866 uint32_t srcCacheCount,
867 const VkValidationCacheEXT* pSrcCaches) {
868 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
869 VkResult result = VK_SUCCESS;
870
871 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
872 if (validation_data) {
873 auto lock = validation_data->write_lock();
874 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
875 }
876 return result;
877}
878
879VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
880 VkDevice device,
881 VkValidationCacheEXT validationCache,
882 size_t* pDataSize,
883 void* pData) {
884 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
885 VkResult result = VK_SUCCESS;
886
887 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
888 if (validation_data) {
889 auto lock = validation_data->write_lock();
890 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
891 }
892 return result;
893
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700894}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600895
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700896 inline_custom_validation_class_definitions = """
897 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
898 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
899 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
900 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700901
902 // Allow additional parameter for CreateGraphicsPipelines
903 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
904 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
905 };
906 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
907 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
908 };
909 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
910 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
911 };
912
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700913 // Allow additional state parameter for CreateComputePipelines
914 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
915 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
916 };
917 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
918 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
919 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700920"""
921
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600922 inline_custom_source_postamble = """
923// loader-layer interface v0, just wrappers since there is only a layer
924
925VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
926 VkExtensionProperties *pProperties) {
927 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
928}
929
930VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
931 VkLayerProperties *pProperties) {
932 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
933}
934
935VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
936 VkLayerProperties *pProperties) {
937 // the layer command handles VK_NULL_HANDLE just fine internally
938 assert(physicalDevice == VK_NULL_HANDLE);
939 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
940}
941
942VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
943 const char *pLayerName, uint32_t *pCount,
944 VkExtensionProperties *pProperties) {
945 // the layer command handles VK_NULL_HANDLE just fine internally
946 assert(physicalDevice == VK_NULL_HANDLE);
947 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
948}
949
950VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
951 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
952}
953
954VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
955 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
956}
957
958VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
959 const char *funcName) {
960 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
961}
962
963VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
964 assert(pVersionStruct != NULL);
965 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
966
967 // Fill in the function pointers if our version is at least capable of having the structure contain them.
968 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
969 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
970 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
971 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
972 }
973
974 return VK_SUCCESS;
975}"""
976
977
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600978 def __init__(self,
979 errFile = sys.stderr,
980 warnFile = sys.stderr,
981 diagFile = sys.stdout):
982 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
983 # Internal state - accumulators for different inner block text
984 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
985 self.intercepts = []
986 self.layer_factory = '' # String containing base layer factory class definition
987
988 # Check if the parameter passed in is a pointer to an array
989 def paramIsArray(self, param):
990 return param.attrib.get('len') is not None
991
992 # Check if the parameter passed in is a pointer
993 def paramIsPointer(self, param):
994 ispointer = False
995 for elem in param:
996 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
997 ispointer = True
998 return ispointer
999
1000 # Check if an object is a non-dispatchable handle
1001 def isHandleTypeNonDispatchable(self, handletype):
1002 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1003 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1004 return True
1005 else:
1006 return False
1007
1008 # Check if an object is a dispatchable handle
1009 def isHandleTypeDispatchable(self, handletype):
1010 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1011 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
1012 return True
1013 else:
1014 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001015 #
1016 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001017 def beginFile(self, genOpts):
1018 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001019 # Output Copyright
1020 write(self.inline_copyright_message, file=self.outFile)
1021 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001022 self.header = False
1023 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1024 self.header = True
1025 write('#pragma once', file=self.outFile)
1026 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001027 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001028 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001029 else:
1030 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001031 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001032 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001033 #
1034 def endFile(self):
1035 # Finish C++ namespace and multiple inclusion protection
1036 self.newline()
1037 if not self.header:
1038 # Record intercepted procedures
1039 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
1040 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
1041 write('\n'.join(self.intercepts), file=self.outFile)
1042 write('};\n', file=self.outFile)
1043 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001044 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001045 if self.header:
1046 self.newline()
1047 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001048 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001049 self.layer_factory += '};\n\n'
1050 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001051 write(self.layer_factory, file=self.outFile)
1052 else:
1053 write(self.inline_custom_source_postamble, file=self.outFile)
1054 # Finish processing in superclass
1055 OutputGenerator.endFile(self)
1056
1057 def beginFeature(self, interface, emit):
1058 # Start processing in superclass
1059 OutputGenerator.beginFeature(self, interface, emit)
1060 # Get feature extra protect
1061 self.featureExtraProtect = GetFeatureProtect(interface)
1062 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1063 # feature. They're only printed in endFeature().
1064 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1065
1066 def endFeature(self):
1067 # Actually write the interface to the output file.
1068 if (self.emit):
1069 self.newline()
1070 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1071 # or move it below the 'for section...' loop.
1072 if (self.featureExtraProtect != None):
1073 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1074 for section in self.TYPE_SECTIONS:
1075 contents = self.sections[section]
1076 if contents:
1077 write('\n'.join(contents), file=self.outFile)
1078 self.newline()
1079 if (self.sections['command']):
1080 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1081 self.newline()
1082 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001083 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001084 # Finish processing in superclass
1085 OutputGenerator.endFeature(self)
1086 #
1087 # Append a definition to the specified section
1088 def appendSection(self, section, text):
1089 self.sections[section].append(text)
1090 #
1091 # Type generation
1092 def genType(self, typeinfo, name, alias):
1093 pass
1094 #
1095 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1096 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1097 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1098 # structs etc.)
1099 def genStruct(self, typeinfo, typeName):
1100 OutputGenerator.genStruct(self, typeinfo, typeName)
1101 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1102 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1103 for member in typeinfo.elem.findall('.//member'):
1104 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1105 body += ';\n'
1106 body += '} ' + typeName + ';\n'
1107 self.appendSection('struct', body)
1108 #
1109 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1110 def genGroup(self, groupinfo, groupName, alias):
1111 pass
1112 # Enumerant generation
1113 # <enum> tags may specify their values in several ways, but are usually just integers.
1114 def genEnum(self, enuminfo, name, alias):
1115 pass
1116 #
1117 # Customize Cdecl for layer factory base class
1118 def BaseClassCdecl(self, elem, name):
1119 raw = self.makeCDecls(elem)[1]
1120
1121 # Toss everything before the undecorated name
1122 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1123 prototype = prototype.replace(")", "", 1)
1124 prototype = prototype.replace(";", " {};")
1125
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001126 # Build up pre/post call virtual function declarations
1127 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1128 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1129 pre_call_record = 'virtual void PreCallRecord' + prototype
1130 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001131 resulttype = elem.find('proto/type')
1132 if resulttype.text == 'VkResult':
1133 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001134 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1135 #
1136 # Command generation
1137 def genCmd(self, cmdinfo, name, alias):
1138 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001139 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001140 ]
1141
1142 if name in ignore_functions:
1143 return
1144
1145 if self.header: # In the header declare all intercepts
1146 self.appendSection('command', '')
1147 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1148 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001149 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1150 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001151 if 'ValidationCache' not in name:
1152 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001153 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001154 self.layer_factory += '#endif\n'
1155 return
1156
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001157 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001158 if 'ValidationCache' not in name:
1159 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1160 else:
1161 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1162 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1163 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001164 return
1165 # Record that the function will be intercepted
1166 if (self.featureExtraProtect != None):
1167 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1168 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1169 if (self.featureExtraProtect != None):
1170 self.intercepts += [ '#endif' ]
1171 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1172 #
1173 decls = self.makeCDecls(cmdinfo.elem)
1174 self.appendSection('command', '')
1175 self.appendSection('command', '%s {' % decls[0][:-1])
1176 # Setup common to call wrappers. First parameter is always dispatchable
1177 dispatchable_type = cmdinfo.elem.find('param/type').text
1178 dispatchable_name = cmdinfo.elem.find('param/name').text
1179 # Default to device
1180 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001181 dispatch_table_name = 'VkLayerDispatchTable'
1182 # Set to instance as necessary
1183 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1184 device_or_instance = 'instance'
1185 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001186 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001187 api_function_name = cmdinfo.elem.attrib.get('name')
1188 params = cmdinfo.elem.findall('param/name')
1189 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001190 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001191
1192 # Declare result variable, if any.
1193 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001194 'PFN_vkVoidFunction': 'return nullptr;',
1195 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001196 'VkDeviceAddress': 'return 0;',
1197 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1198 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001199 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001200 }
1201 resulttype = cmdinfo.elem.find('proto/type')
1202 assignresult = ''
1203 if (resulttype.text != 'void'):
1204 assignresult = resulttype.text + ' result = '
1205
1206 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001207 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001208
1209 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001210 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001211 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001212 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1213 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1214 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001215
1216 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001217 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001218 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001219 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001220 self.appendSection('command', ' }')
1221
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001222 # Insert pre-dispatch debug utils function call
1223 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001224 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001225
1226 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001227 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001228
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001229 # Insert post-dispatch debug utils function call
1230 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001231 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001232
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001233 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001234 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001235 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001236 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001237 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001238 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001239 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001240 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001241 # Return result variable, if any.
1242 if (resulttype.text != 'void'):
1243 self.appendSection('command', ' return result;')
1244 self.appendSection('command', '}')
1245 #
1246 # Override makeProtoName to drop the "vk" prefix
1247 def makeProtoName(self, name, tail):
1248 return self.genOpts.apientry + name[2:] + tail