blob: 7104667a69df13e2af224c0917ab236bb006c697 [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07003# Copyright (c) 2015-2019 Valve Corporation
4# Copyright (c) 2015-2019 LunarG, Inc.
5# Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06006#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
20# Author: Mark Lobodzinski <mark@lunarg.com>
21#
22# This script generates the dispatch portion of a factory layer which intercepts
23# all Vulkan functions. The resultant factory layer allows rapid development of
24# layers and interceptors.
25
26import os,re,sys
27from generator import *
28from common_codegen import *
29
30# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31#
32# Adds options used by LayerFactoryOutputGenerator objects during factory
33# layer generation.
34#
35# Additional members
36# prefixText - list of strings to prefix generated header with
37# (usually a copyright statement + calling convention macros).
38# protectFile - True if multiple inclusion protection should be
39# generated (based on the filename) around the entire header.
40# protectFeature - True if #ifndef..#endif protection should be
41# generated around a feature interface in the header file.
42# genFuncPointers - True if function pointer typedefs should be
43# generated
44# protectProto - If conditional protection should be generated
45# around prototype declarations, set to either '#ifdef'
46# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47# to require opt-out (#ifndef protectProtoStr). Otherwise
48# set to None.
49# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50# declarations, if protectProto is set
51# apicall - string to use for the function declaration prefix,
52# such as APICALL on Windows.
53# apientry - string to use for the calling convention macro,
54# in typedefs, such as APIENTRY.
55# apientryp - string to use for the calling convention macro
56# in function pointer typedefs, such as APIENTRYP.
57# indentFuncProto - True if prototype declarations should put each
58# parameter on a separate line
59# indentFuncPointer - True if typedefed function pointers should put each
60# parameter on a separate line
61# alignFuncParam - if nonzero and parameters are being put on a
62# separate line, align parameter names at the specified column
63class LayerChassisGeneratorOptions(GeneratorOptions):
64 def __init__(self,
65 filename = None,
66 directory = '.',
67 apiname = None,
68 profile = None,
69 versions = '.*',
70 emitversions = '.*',
71 defaultExtensions = None,
72 addExtensions = None,
73 removeExtensions = None,
74 emitExtensions = None,
75 sortProcedure = regSortFeatures,
76 prefixText = "",
77 genFuncPointers = True,
78 protectFile = True,
79 protectFeature = True,
80 apicall = '',
81 apientry = '',
82 apientryp = '',
83 indentFuncProto = True,
84 indentFuncPointer = False,
85 alignFuncParam = 0,
86 helper_file_type = '',
87 expandEnumerants = True):
88 GeneratorOptions.__init__(self, filename, directory, apiname, profile,
89 versions, emitversions, defaultExtensions,
90 addExtensions, removeExtensions, emitExtensions, sortProcedure)
91 self.prefixText = prefixText
92 self.genFuncPointers = genFuncPointers
93 self.protectFile = protectFile
94 self.protectFeature = protectFeature
95 self.apicall = apicall
96 self.apientry = apientry
97 self.apientryp = apientryp
98 self.indentFuncProto = indentFuncProto
99 self.indentFuncPointer = indentFuncPointer
100 self.alignFuncParam = alignFuncParam
101
102# LayerChassisOutputGenerator - subclass of OutputGenerator.
103# Generates a LayerFactory layer that intercepts all API entrypoints
104# This is intended to be used as a starting point for creating custom layers
105#
106# ---- methods ----
107# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
108# OutputGenerator. Defines additional internal state.
109# ---- methods overriding base class ----
110# beginFile(genOpts)
111# endFile()
112# beginFeature(interface, emit)
113# endFeature()
114# genType(typeinfo,name)
115# genStruct(typeinfo,name)
116# genGroup(groupinfo,name)
117# genEnum(enuminfo, name)
118# genCmd(cmdinfo)
119class LayerChassisOutputGenerator(OutputGenerator):
120 """Generate specified API interfaces in a specific style, such as a C header"""
121 # This is an ordered list of sections in the header file.
122 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
123 'group', 'bitmask', 'funcpointer', 'struct']
124 ALL_SECTIONS = TYPE_SECTIONS + ['command']
125
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700126 manual_functions = [
127 # Include functions here to be interecpted w/ manually implemented function bodies
128 'vkGetDeviceProcAddr',
129 'vkGetInstanceProcAddr',
130 'vkGetPhysicalDeviceProcAddr',
131 'vkCreateDevice',
132 'vkDestroyDevice',
133 'vkCreateInstance',
134 'vkDestroyInstance',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700135 'vkEnumerateInstanceLayerProperties',
136 'vkEnumerateInstanceExtensionProperties',
137 'vkEnumerateDeviceLayerProperties',
138 'vkEnumerateDeviceExtensionProperties',
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700139 # Functions that are handled explicitly due to chassis architecture violations
140 'vkCreateGraphicsPipelines',
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700141 'vkCreateComputePipelines',
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700142 'vkCreateRayTracingPipelinesNV',
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700143 # ValidationCache functions do not get dispatched
144 'vkCreateValidationCacheEXT',
145 'vkDestroyValidationCacheEXT',
146 'vkMergeValidationCachesEXT',
147 'vkGetValidationCacheDataEXT',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700148 ]
149
150 alt_ret_codes = [
151 # Include functions here which must tolerate VK_INCOMPLETE as a return code
152 'vkEnumeratePhysicalDevices',
153 'vkEnumeratePhysicalDeviceGroupsKHR',
154 'vkGetValidationCacheDataEXT',
155 'vkGetPipelineCacheData',
156 'vkGetShaderInfoAMD',
157 'vkGetPhysicalDeviceDisplayPropertiesKHR',
158 'vkGetPhysicalDeviceDisplayProperties2KHR',
159 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
160 'vkGetDisplayPlaneSupportedDisplaysKHR',
161 'vkGetDisplayModePropertiesKHR',
162 'vkGetDisplayModeProperties2KHR',
163 'vkGetPhysicalDeviceSurfaceFormatsKHR',
164 'vkGetPhysicalDeviceSurfacePresentModesKHR',
165 'vkGetPhysicalDevicePresentRectanglesKHR',
166 'vkGetPastPresentationTimingGOOGLE',
167 'vkGetSwapchainImagesKHR',
168 'vkEnumerateInstanceLayerProperties',
169 'vkEnumerateDeviceLayerProperties',
170 'vkEnumerateInstanceExtensionProperties',
171 'vkEnumerateDeviceExtensionProperties',
172 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
173 ]
174
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700175 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700176 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
177 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700178 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
179 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
180 'vkCmdBeginDebugUtilsLabelEXT' : 'BeginCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
181 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
182 }
183
184 post_dispatch_debug_utils_functions = {
185 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
186 'vkCmdEndDebugUtilsLabelEXT' : 'EndCmdDebugUtilsLabel(layer_data->report_data, commandBuffer);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700187 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
188 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
189 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
190 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
191 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700192 }
193
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600194 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
195 precallrecord_loop = precallvalidate_loop
196 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600197
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700198 inline_custom_header_preamble = """
199#define NOMINMAX
200#include <mutex>
201#include <cinttypes>
202#include <stdio.h>
203#include <stdlib.h>
204#include <string.h>
205#include <unordered_map>
206#include <unordered_set>
207#include <algorithm>
208#include <memory>
209
210#include "vk_loader_platform.h"
211#include "vulkan/vulkan.h"
212#include "vk_layer_config.h"
213#include "vk_layer_data.h"
214#include "vk_layer_logging.h"
215#include "vk_object_types.h"
216#include "vulkan/vk_layer.h"
217#include "vk_enum_string_helper.h"
218#include "vk_layer_extension_utils.h"
219#include "vk_layer_utils.h"
220#include "vulkan/vk_layer.h"
221#include "vk_dispatch_table_helper.h"
222#include "vk_validation_error_messages.h"
223#include "vk_extension_helper.h"
224#include "vk_safe_struct.h"
225
226extern uint64_t global_unique_id;
227extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
228"""
229
230 inline_custom_header_class_definition = """
231
232// Layer object type identifiers
233enum LayerObjectTypeId {
234 LayerObjectTypeThreading,
235 LayerObjectTypeParameterValidation,
236 LayerObjectTypeObjectTracker,
237 LayerObjectTypeCoreValidation,
238};
239
240struct TEMPLATE_STATE {
241 VkDescriptorUpdateTemplateKHR desc_update_template;
242 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
243
244 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
245 : desc_update_template(update_template), create_info(*pCreateInfo) {}
246};
247
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700248class LAYER_PHYS_DEV_PROPERTIES {
249public:
250 VkPhysicalDeviceProperties properties;
251 std::vector<VkQueueFamilyProperties> queue_family_properties;
252};
253
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700254// Layer chassis validation object base class definition
255class ValidationObject {
256 public:
257 uint32_t api_version;
258 debug_report_data* report_data = nullptr;
259 std::vector<VkDebugReportCallbackEXT> logging_callback;
260 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
261
262 VkLayerInstanceDispatchTable instance_dispatch_table;
263 VkLayerDispatchTable device_dispatch_table;
264
265 InstanceExtensions instance_extensions;
266 DeviceExtensions device_extensions = {};
267
268 VkInstance instance = VK_NULL_HANDLE;
269 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
270 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700271 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700272
273 std::vector<ValidationObject*> object_dispatch;
274 LayerObjectTypeId container_type;
275
276 // Constructor
277 ValidationObject(){};
278 // Destructor
279 virtual ~ValidationObject() {};
280
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700281 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700282 virtual std::unique_lock<std::mutex> write_lock() {
283 return std::unique_lock<std::mutex>(validation_object_mutex);
284 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700285
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700286 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
287 for (auto validation_object : object_dispatch) {
288 if (validation_object->container_type == object_type) {
289 return validation_object;
290 }
291 }
292 return nullptr;
293 };
294
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700295 std::string layer_name = "CHASSIS";
296
297 // Handle Wrapping Data
298 // Reverse map display handles
299 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
300 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700301 struct SubpassesUsageStates {
302 std::unordered_set<uint32_t> subpasses_using_color_attachment;
303 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
304 };
305 // Uses unwrapped handles
306 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
307 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
308 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
309 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700310 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
311 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700312
313
314 // Unwrap a handle. Must hold lock.
315 template <typename HandleType>
316 HandleType Unwrap(HandleType wrappedHandle) {
317 // TODO: don't use operator[] here.
318 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
319 }
320
321 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
322 template <typename HandleType>
323 HandleType WrapNew(HandleType newlyCreatedHandle) {
324 auto unique_id = global_unique_id++;
325 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
326 return (HandleType)unique_id;
327 }
328
329 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
330 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
331 auto unique_id = global_unique_id++;
332 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
333 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
334 return (VkDisplayKHR)unique_id;
335 }
336
337 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
338 // creating another. Must hold lock.
339 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
340 // See if this display is already known
341 auto it = map_data->display_id_reverse_mapping.find(handle);
342 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
343 // Unknown, so wrap
344 return WrapDisplay(handle, map_data);
345 }
346
347 // Pre/post hook point declarations
348"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600349
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700350 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600351// This file is ***GENERATED***. Do Not Edit.
352// See layer_chassis_generator.py for modifications.
353
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700354/* Copyright (c) 2015-2019 The Khronos Group Inc.
355 * Copyright (c) 2015-2019 Valve Corporation
356 * Copyright (c) 2015-2019 LunarG, Inc.
357 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600358 *
359 * Licensed under the Apache License, Version 2.0 (the "License");
360 * you may not use this file except in compliance with the License.
361 * You may obtain a copy of the License at
362 *
363 * http://www.apache.org/licenses/LICENSE-2.0
364 *
365 * Unless required by applicable law or agreed to in writing, software
366 * distributed under the License is distributed on an "AS IS" BASIS,
367 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
368 * See the License for the specific language governing permissions and
369 * limitations under the License.
370 *
371 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700372 */"""
373
374 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600375
376#include <string.h>
377#include <mutex>
378
379#define VALIDATION_ERROR_MAP_IMPL
380
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600381#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700382#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600383
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600384std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600385
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700386// Global unique object identifier. All increments must be guarded by a lock.
387uint64_t global_unique_id = 1;
388// Map uniqueID to actual object handle
389std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
390
391// TODO: This variable controls handle wrapping -- in the future it should be hooked
392// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
393#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
394bool wrap_handles = true;
395#else
396const bool wrap_handles = false;
397#endif
398
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600399// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700400#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600401#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700402#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700403#elif BUILD_THREAD_SAFETY
Mark Lobodzinski706e52b2018-12-11 13:21:52 -0700404#include "thread_safety.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700405#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
406#elif BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700407#include "stateless_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700408#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
409#elif BUILD_CORE_VALIDATION
410#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
411#else
412#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
413#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600414
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600415namespace vulkan_layer_chassis {
416
417using std::unordered_map;
418
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600419static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700420 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600421};
422
423static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
424
425extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
426
427
428// Manually written functions
429
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700430// Check enabled instance extensions against supported instance extension whitelist
431static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
432 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
433 // Check for recognized instance extensions
434 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
435 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
436 kVUIDUndefined,
437 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
438 "results and/or produce undefined behavior.",
439 pCreateInfo->ppEnabledExtensionNames[i]);
440 }
441 }
442}
443
444// Check enabled device extensions against supported device extension whitelist
445static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
446 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
447 // Check for recognized device extensions
448 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
449 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
450 kVUIDUndefined,
451 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
452 "results and/or produce undefined behavior.",
453 pCreateInfo->ppEnabledExtensionNames[i]);
454 }
455 }
456}
457
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600458VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600459 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700460 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700461 return nullptr;
462 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600463 const auto &item = name_to_funcptr_map.find(funcName);
464 if (item != name_to_funcptr_map.end()) {
465 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
466 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600467 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600468 if (!table.GetDeviceProcAddr) return nullptr;
469 return table.GetDeviceProcAddr(device, funcName);
470}
471
472VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600473 const auto &item = name_to_funcptr_map.find(funcName);
474 if (item != name_to_funcptr_map.end()) {
475 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
476 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600477 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
478 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600479 if (!table.GetInstanceProcAddr) return nullptr;
480 return table.GetInstanceProcAddr(instance, funcName);
481}
482
483VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600484 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
485 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600486 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
487 return table.GetPhysicalDeviceProcAddr(instance, funcName);
488}
489
490VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
491 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
492}
493
494VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
495 VkLayerProperties *pProperties) {
496 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
497}
498
499VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
500 VkExtensionProperties *pProperties) {
501 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
502 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
503
504 return VK_ERROR_LAYER_NOT_PRESENT;
505}
506
507VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
508 uint32_t *pCount, VkExtensionProperties *pProperties) {
509 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600510 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600511 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
512 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600513}
514
515VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
516 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600517 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600518
519 assert(chain_info->u.pLayerInfo);
520 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
521 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
522 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
523 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700524 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
525 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
526
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600527
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600528 // Create temporary dispatch vector for pre-calls until instance is created
529 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700530#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600531 auto object_tracker = new ObjectLifetimes;
532 local_object_dispatch.emplace_back(object_tracker);
533 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700534 object_tracker->api_version = api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700535#elif BUILD_THREAD_SAFETY
536 auto thread_checker = new ThreadSafety;
537 local_object_dispatch.emplace_back(thread_checker);
538 thread_checker->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700539 thread_checker->api_version = api_version;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700540#elif BUILD_PARAMETER_VALIDATION
541 auto parameter_validation = new StatelessValidation;
542 local_object_dispatch.emplace_back(parameter_validation);
543 parameter_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700544 parameter_validation->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700545#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600546
547
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600548 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600549 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600550 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
551 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600552 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600553 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
554 }
555
556 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600557 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600558
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600559 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600560
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600561 framework->object_dispatch = local_object_dispatch;
562
563 framework->instance = *pInstance;
564 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
565 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
566 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700567 framework->api_version = api_version;
568 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
569
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700570#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600571 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700572 object_tracker->report_data = framework->report_data;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700573#elif BUILD_THREAD_SAFETY
574 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "google_thread_checker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700575 thread_checker->report_data = framework->report_data;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700576#elif BUILD_PARAMETER_VALIDATION
577 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_parameter_validation");
578 parameter_validation->report_data = framework->report_data;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700579#else
580 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
581#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600582
583 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700584 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600585 }
586
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700587 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
588
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600589 return result;
590}
591
592VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
593 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600594 auto layer_data = GetLayerDataPtr(key, layer_data_map);
595 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700596 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600597 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
598 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600599 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700600 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600601 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
602 }
603
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600604 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600605
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600606 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700607 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600608 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
609 }
610 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600611 while (layer_data->logging_messenger.size() > 0) {
612 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
613 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
614 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600615 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600616 while (layer_data->logging_callback.size() > 0) {
617 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
618 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
619 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600620 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600621
622 layer_debug_utils_destroy_instance(layer_data->report_data);
623
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700624 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
625 delete *item;
626 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600627 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600628}
629
630VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
631 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600632 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600633
634 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
635
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600636 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
637 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600638 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
639 if (fpCreateDevice == NULL) {
640 return VK_ERROR_INITIALIZATION_FAILED;
641 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600642 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
643
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700644 // Get physical device limits for device
645 VkPhysicalDeviceProperties device_properties = {};
646 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
647
648 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
649 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
650
651 DeviceExtensions device_extensions = {};
652 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
653 for (auto item : instance_interceptor->object_dispatch) {
654 item->device_extensions = device_extensions;
655 }
656
657 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600658 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700659 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700660 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700661 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600662 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600663 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700664 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600665 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
666 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600667
668 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600669 if (result != VK_SUCCESS) {
670 return result;
671 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600672
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600673 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700674
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700675 // Save local info in device object
676 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700677 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
678 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700679 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700680
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600681 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700682
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600683 device_interceptor->device = *pDevice;
684 device_interceptor->physical_device = gpu;
685 device_interceptor->instance = instance_interceptor->instance;
686 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600687
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700688#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600689 // Create child layer objects for this key and add to dispatch vector
690 auto object_tracker = new ObjectLifetimes;
691 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
692 object_tracker->container_type = LayerObjectTypeObjectTracker;
693 object_tracker->physical_device = gpu;
694 object_tracker->instance = instance_interceptor->instance;
695 object_tracker->report_data = device_interceptor->report_data;
696 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700697 object_tracker->api_version = device_interceptor->api_version;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600698 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700699#elif BUILD_THREAD_SAFETY
700 auto thread_safety = new ThreadSafety;
701 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
702 thread_safety->container_type = LayerObjectTypeThreading;
703 thread_safety->physical_device = gpu;
704 thread_safety->instance = instance_interceptor->instance;
705 thread_safety->report_data = device_interceptor->report_data;
706 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700707 thread_safety->api_version = device_interceptor->api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700708 device_interceptor->object_dispatch.emplace_back(thread_safety);
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700709#elif BUILD_PARAMETER_VALIDATION
710 auto stateless_validation = new StatelessValidation;
711 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
712 stateless_validation->container_type = LayerObjectTypeParameterValidation;
713 stateless_validation->physical_device = gpu;
714 stateless_validation->instance = instance_interceptor->instance;
715 stateless_validation->report_data = device_interceptor->report_data;
716 stateless_validation->device_dispatch_table = device_interceptor->device_dispatch_table;
717 stateless_validation->api_version = device_interceptor->api_version;
718 device_interceptor->object_dispatch.emplace_back(stateless_validation);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700719#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600720
721 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700722 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700723 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600724 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600725
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700726 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
727
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600728 return result;
729}
730
731VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
732 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600733 auto layer_data = GetLayerDataPtr(key, layer_data_map);
734 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700735 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600736 intercept->PreCallValidateDestroyDevice(device, pAllocator);
737 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600738 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700739 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600740 intercept->PreCallRecordDestroyDevice(device, pAllocator);
741 }
742 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600743
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600744 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600745
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600746 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700747 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600748 intercept->PostCallRecordDestroyDevice(device, pAllocator);
749 }
750
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700751 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
752 delete *item;
753 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600754 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700755}
756
757
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700758// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700759
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700760VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
761 VkDevice device,
762 VkPipelineCache pipelineCache,
763 uint32_t createInfoCount,
764 const VkGraphicsPipelineCreateInfo* pCreateInfos,
765 const VkAllocationCallbacks* pAllocator,
766 VkPipeline* pPipelines) {
767 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
768 bool skip = false;
769
770#ifdef BUILD_CORE_VALIDATION
771 create_graphics_pipeline_api_state cgpl_state{};
772#else
773 struct create_graphics_pipeline_api_state {
774 const VkGraphicsPipelineCreateInfo* pCreateInfos;
775 } cgpl_state;
776 cgpl_state.pCreateInfos = pCreateInfos;
777#endif
778
779 for (auto intercept : layer_data->object_dispatch) {
780 auto lock = intercept->write_lock();
781 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
782 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
783 }
784 for (auto intercept : layer_data->object_dispatch) {
785 auto lock = intercept->write_lock();
786 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
787 }
788
789 VkResult result = DispatchCreateGraphicsPipelines(layer_data, device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
790
791 for (auto intercept : layer_data->object_dispatch) {
792 auto lock = intercept->write_lock();
793 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
794 }
795 return result;
796}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700797
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700798// This API saves some core_validation pipeline state state on the stack for performance purposes
799VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
800 VkDevice device,
801 VkPipelineCache pipelineCache,
802 uint32_t createInfoCount,
803 const VkComputePipelineCreateInfo* pCreateInfos,
804 const VkAllocationCallbacks* pAllocator,
805 VkPipeline* pPipelines) {
806 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
807 bool skip = false;
808
809#ifndef BUILD_CORE_VALIDATION
810 struct PIPELINE_STATE {};
811#endif
812
813 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
814
815 for (auto intercept : layer_data->object_dispatch) {
816 auto lock = intercept->write_lock();
817 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
818 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
819 }
820 for (auto intercept : layer_data->object_dispatch) {
821 auto lock = intercept->write_lock();
822 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
823 }
824 VkResult result = DispatchCreateComputePipelines(layer_data, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
825 for (auto intercept : layer_data->object_dispatch) {
826 auto lock = intercept->write_lock();
827 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
828 }
829 return result;
830}
831
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700832VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
833 VkDevice device,
834 VkPipelineCache pipelineCache,
835 uint32_t createInfoCount,
836 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
837 const VkAllocationCallbacks* pAllocator,
838 VkPipeline* pPipelines) {
839 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
840 bool skip = false;
841
842#ifndef BUILD_CORE_VALIDATION
843 struct PIPELINE_STATE {};
844#endif
845
846 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
847
848 for (auto intercept : layer_data->object_dispatch) {
849 auto lock = intercept->write_lock();
850 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
851 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
852 }
853 for (auto intercept : layer_data->object_dispatch) {
854 auto lock = intercept->write_lock();
855 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
856 }
857 VkResult result = DispatchCreateRayTracingPipelinesNV(layer_data, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
858 for (auto intercept : layer_data->object_dispatch) {
859 auto lock = intercept->write_lock();
860 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
861 }
862 return result;
863}
864
865
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700866
867// ValidationCache APIs do not dispatch
868
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700869VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
870 VkDevice device,
871 const VkValidationCacheCreateInfoEXT* pCreateInfo,
872 const VkAllocationCallbacks* pAllocator,
873 VkValidationCacheEXT* pValidationCache) {
874 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
875 VkResult result = VK_SUCCESS;
876
877 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
878 if (validation_data) {
879 auto lock = validation_data->write_lock();
880 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
881 }
882 return result;
883}
884
885VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
886 VkDevice device,
887 VkValidationCacheEXT validationCache,
888 const VkAllocationCallbacks* pAllocator) {
889 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
890
891 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
892 if (validation_data) {
893 auto lock = validation_data->write_lock();
894 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
895 }
896}
897
898VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
899 VkDevice device,
900 VkValidationCacheEXT dstCache,
901 uint32_t srcCacheCount,
902 const VkValidationCacheEXT* pSrcCaches) {
903 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
904 VkResult result = VK_SUCCESS;
905
906 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
907 if (validation_data) {
908 auto lock = validation_data->write_lock();
909 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
910 }
911 return result;
912}
913
914VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
915 VkDevice device,
916 VkValidationCacheEXT validationCache,
917 size_t* pDataSize,
918 void* pData) {
919 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
920 VkResult result = VK_SUCCESS;
921
922 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
923 if (validation_data) {
924 auto lock = validation_data->write_lock();
925 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
926 }
927 return result;
928
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700929}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600930
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700931 inline_custom_validation_class_definitions = """
932 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
933 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
934 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
935 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700936
937 // Allow additional parameter for CreateGraphicsPipelines
938 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
939 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
940 };
941 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
942 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
943 };
944 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
945 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
946 };
947
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700948 // Allow additional state parameter for CreateComputePipelines
949 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
950 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
951 };
952 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
953 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
954 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700955
956 // Allow additional state parameter for CreateRayTracingPipelinesNV
957 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
958 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
959 };
960 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
961 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
962 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700963"""
964
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600965 inline_custom_source_postamble = """
966// loader-layer interface v0, just wrappers since there is only a layer
967
968VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
969 VkExtensionProperties *pProperties) {
970 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
971}
972
973VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
974 VkLayerProperties *pProperties) {
975 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
976}
977
978VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
979 VkLayerProperties *pProperties) {
980 // the layer command handles VK_NULL_HANDLE just fine internally
981 assert(physicalDevice == VK_NULL_HANDLE);
982 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
983}
984
985VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
986 const char *pLayerName, uint32_t *pCount,
987 VkExtensionProperties *pProperties) {
988 // the layer command handles VK_NULL_HANDLE just fine internally
989 assert(physicalDevice == VK_NULL_HANDLE);
990 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
991}
992
993VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
994 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
995}
996
997VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
998 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
999}
1000
1001VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
1002 const char *funcName) {
1003 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
1004}
1005
1006VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1007 assert(pVersionStruct != NULL);
1008 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1009
1010 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1011 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1012 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1013 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
1014 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
1015 }
1016
1017 return VK_SUCCESS;
1018}"""
1019
1020
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001021 def __init__(self,
1022 errFile = sys.stderr,
1023 warnFile = sys.stderr,
1024 diagFile = sys.stdout):
1025 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1026 # Internal state - accumulators for different inner block text
1027 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1028 self.intercepts = []
1029 self.layer_factory = '' # String containing base layer factory class definition
1030
1031 # Check if the parameter passed in is a pointer to an array
1032 def paramIsArray(self, param):
1033 return param.attrib.get('len') is not None
1034
1035 # Check if the parameter passed in is a pointer
1036 def paramIsPointer(self, param):
1037 ispointer = False
1038 for elem in param:
1039 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
1040 ispointer = True
1041 return ispointer
1042
1043 # Check if an object is a non-dispatchable handle
1044 def isHandleTypeNonDispatchable(self, handletype):
1045 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1046 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1047 return True
1048 else:
1049 return False
1050
1051 # Check if an object is a dispatchable handle
1052 def isHandleTypeDispatchable(self, handletype):
1053 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1054 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
1055 return True
1056 else:
1057 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001058 #
1059 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001060 def beginFile(self, genOpts):
1061 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001062 # Output Copyright
1063 write(self.inline_copyright_message, file=self.outFile)
1064 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001065 self.header = False
1066 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1067 self.header = True
1068 write('#pragma once', file=self.outFile)
1069 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001070 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001071 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001072 else:
1073 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001074 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001075 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001076 #
1077 def endFile(self):
1078 # Finish C++ namespace and multiple inclusion protection
1079 self.newline()
1080 if not self.header:
1081 # Record intercepted procedures
1082 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
1083 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
1084 write('\n'.join(self.intercepts), file=self.outFile)
1085 write('};\n', file=self.outFile)
1086 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001087 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001088 if self.header:
1089 self.newline()
1090 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001091 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001092 self.layer_factory += '};\n\n'
1093 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001094 write(self.layer_factory, file=self.outFile)
1095 else:
1096 write(self.inline_custom_source_postamble, file=self.outFile)
1097 # Finish processing in superclass
1098 OutputGenerator.endFile(self)
1099
1100 def beginFeature(self, interface, emit):
1101 # Start processing in superclass
1102 OutputGenerator.beginFeature(self, interface, emit)
1103 # Get feature extra protect
1104 self.featureExtraProtect = GetFeatureProtect(interface)
1105 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1106 # feature. They're only printed in endFeature().
1107 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1108
1109 def endFeature(self):
1110 # Actually write the interface to the output file.
1111 if (self.emit):
1112 self.newline()
1113 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1114 # or move it below the 'for section...' loop.
1115 if (self.featureExtraProtect != None):
1116 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1117 for section in self.TYPE_SECTIONS:
1118 contents = self.sections[section]
1119 if contents:
1120 write('\n'.join(contents), file=self.outFile)
1121 self.newline()
1122 if (self.sections['command']):
1123 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1124 self.newline()
1125 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001126 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001127 # Finish processing in superclass
1128 OutputGenerator.endFeature(self)
1129 #
1130 # Append a definition to the specified section
1131 def appendSection(self, section, text):
1132 self.sections[section].append(text)
1133 #
1134 # Type generation
1135 def genType(self, typeinfo, name, alias):
1136 pass
1137 #
1138 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1139 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1140 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1141 # structs etc.)
1142 def genStruct(self, typeinfo, typeName):
1143 OutputGenerator.genStruct(self, typeinfo, typeName)
1144 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1145 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1146 for member in typeinfo.elem.findall('.//member'):
1147 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1148 body += ';\n'
1149 body += '} ' + typeName + ';\n'
1150 self.appendSection('struct', body)
1151 #
1152 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1153 def genGroup(self, groupinfo, groupName, alias):
1154 pass
1155 # Enumerant generation
1156 # <enum> tags may specify their values in several ways, but are usually just integers.
1157 def genEnum(self, enuminfo, name, alias):
1158 pass
1159 #
1160 # Customize Cdecl for layer factory base class
1161 def BaseClassCdecl(self, elem, name):
1162 raw = self.makeCDecls(elem)[1]
1163
1164 # Toss everything before the undecorated name
1165 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1166 prototype = prototype.replace(")", "", 1)
1167 prototype = prototype.replace(";", " {};")
1168
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001169 # Build up pre/post call virtual function declarations
1170 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1171 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1172 pre_call_record = 'virtual void PreCallRecord' + prototype
1173 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001174 resulttype = elem.find('proto/type')
1175 if resulttype.text == 'VkResult':
1176 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001177 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1178 #
1179 # Command generation
1180 def genCmd(self, cmdinfo, name, alias):
1181 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001182 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001183 ]
1184
1185 if name in ignore_functions:
1186 return
1187
1188 if self.header: # In the header declare all intercepts
1189 self.appendSection('command', '')
1190 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1191 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001192 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1193 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001194 if 'ValidationCache' not in name:
1195 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001196 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001197 self.layer_factory += '#endif\n'
1198 return
1199
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001200 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001201 if 'ValidationCache' not in name:
1202 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1203 else:
1204 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1205 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1206 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001207 return
1208 # Record that the function will be intercepted
1209 if (self.featureExtraProtect != None):
1210 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1211 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1212 if (self.featureExtraProtect != None):
1213 self.intercepts += [ '#endif' ]
1214 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1215 #
1216 decls = self.makeCDecls(cmdinfo.elem)
1217 self.appendSection('command', '')
1218 self.appendSection('command', '%s {' % decls[0][:-1])
1219 # Setup common to call wrappers. First parameter is always dispatchable
1220 dispatchable_type = cmdinfo.elem.find('param/type').text
1221 dispatchable_name = cmdinfo.elem.find('param/name').text
1222 # Default to device
1223 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001224 dispatch_table_name = 'VkLayerDispatchTable'
1225 # Set to instance as necessary
1226 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1227 device_or_instance = 'instance'
1228 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001229 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001230 api_function_name = cmdinfo.elem.attrib.get('name')
1231 params = cmdinfo.elem.findall('param/name')
1232 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001233 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001234
1235 # Declare result variable, if any.
1236 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001237 'PFN_vkVoidFunction': 'return nullptr;',
1238 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001239 'VkDeviceAddress': 'return 0;',
1240 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1241 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001242 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001243 }
1244 resulttype = cmdinfo.elem.find('proto/type')
1245 assignresult = ''
1246 if (resulttype.text != 'void'):
1247 assignresult = resulttype.text + ' result = '
1248
1249 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001250 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001251
1252 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001253 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001254 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001255 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1256 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1257 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001258
1259 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001260 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001261 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001262 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001263 self.appendSection('command', ' }')
1264
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001265 # Insert pre-dispatch debug utils function call
1266 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001267 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001268
1269 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001270 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001271
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001272 # Insert post-dispatch debug utils function call
1273 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001274 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001275
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001276 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001277 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001278 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001279 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001280 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001281 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001282 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001283 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001284 # Return result variable, if any.
1285 if (resulttype.text != 'void'):
1286 self.appendSection('command', ' return result;')
1287 self.appendSection('command', '}')
1288 #
1289 # Override makeProtoName to drop the "vk" prefix
1290 def makeProtoName(self, name, tail):
1291 return self.genOpts.apientry + name[2:] + tail