blob: 5b3233bdd21a7de7b1947dd914e225c9bf92450d [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
3# Copyright (c) 2015-2016 Valve Corporation
4# Copyright (c) 2015-2016 LunarG, Inc.
5# Copyright (c) 2015-2016 Google Inc.
6#
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',
135 'vkCreateDebugReportCallbackEXT',
136 'vkDestroyDebugReportCallbackEXT',
137 'vkEnumerateInstanceLayerProperties',
138 'vkEnumerateInstanceExtensionProperties',
139 'vkEnumerateDeviceLayerProperties',
140 'vkEnumerateDeviceExtensionProperties',
141 ]
142
143 alt_ret_codes = [
144 # Include functions here which must tolerate VK_INCOMPLETE as a return code
145 'vkEnumeratePhysicalDevices',
146 'vkEnumeratePhysicalDeviceGroupsKHR',
147 'vkGetValidationCacheDataEXT',
148 'vkGetPipelineCacheData',
149 'vkGetShaderInfoAMD',
150 'vkGetPhysicalDeviceDisplayPropertiesKHR',
151 'vkGetPhysicalDeviceDisplayProperties2KHR',
152 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
153 'vkGetDisplayPlaneSupportedDisplaysKHR',
154 'vkGetDisplayModePropertiesKHR',
155 'vkGetDisplayModeProperties2KHR',
156 'vkGetPhysicalDeviceSurfaceFormatsKHR',
157 'vkGetPhysicalDeviceSurfacePresentModesKHR',
158 'vkGetPhysicalDevicePresentRectanglesKHR',
159 'vkGetPastPresentationTimingGOOGLE',
160 'vkGetSwapchainImagesKHR',
161 'vkEnumerateInstanceLayerProperties',
162 'vkEnumerateDeviceLayerProperties',
163 'vkEnumerateInstanceExtensionProperties',
164 'vkEnumerateDeviceExtensionProperties',
165 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
166 ]
167
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600168 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
169 precallrecord_loop = precallvalidate_loop
170 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600171
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700172 inline_custom_header_preamble = """
173#define NOMINMAX
174#include <mutex>
175#include <cinttypes>
176#include <stdio.h>
177#include <stdlib.h>
178#include <string.h>
179#include <unordered_map>
180#include <unordered_set>
181#include <algorithm>
182#include <memory>
183
184#include "vk_loader_platform.h"
185#include "vulkan/vulkan.h"
186#include "vk_layer_config.h"
187#include "vk_layer_data.h"
188#include "vk_layer_logging.h"
189#include "vk_object_types.h"
190#include "vulkan/vk_layer.h"
191#include "vk_enum_string_helper.h"
192#include "vk_layer_extension_utils.h"
193#include "vk_layer_utils.h"
194#include "vulkan/vk_layer.h"
195#include "vk_dispatch_table_helper.h"
196#include "vk_validation_error_messages.h"
197#include "vk_extension_helper.h"
198#include "vk_safe_struct.h"
199
200extern uint64_t global_unique_id;
201extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
202"""
203
204 inline_custom_header_class_definition = """
205
206// Layer object type identifiers
207enum LayerObjectTypeId {
208 LayerObjectTypeThreading,
209 LayerObjectTypeParameterValidation,
210 LayerObjectTypeObjectTracker,
211 LayerObjectTypeCoreValidation,
212};
213
214struct TEMPLATE_STATE {
215 VkDescriptorUpdateTemplateKHR desc_update_template;
216 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
217
218 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
219 : desc_update_template(update_template), create_info(*pCreateInfo) {}
220};
221
222// Layer chassis validation object base class definition
223class ValidationObject {
224 public:
225 uint32_t api_version;
226 debug_report_data* report_data = nullptr;
227 std::vector<VkDebugReportCallbackEXT> logging_callback;
228 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
229
230 VkLayerInstanceDispatchTable instance_dispatch_table;
231 VkLayerDispatchTable device_dispatch_table;
232
233 InstanceExtensions instance_extensions;
234 DeviceExtensions device_extensions = {};
235
236 VkInstance instance = VK_NULL_HANDLE;
237 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
238 VkDevice device = VK_NULL_HANDLE;
239
240 std::vector<ValidationObject*> object_dispatch;
241 LayerObjectTypeId container_type;
242
243 // Constructor
244 ValidationObject(){};
245 // Destructor
246 virtual ~ValidationObject() {};
247
248 std::mutex layer_mutex;
249
250 std::string layer_name = "CHASSIS";
251
252 // Handle Wrapping Data
253 // Reverse map display handles
254 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
255 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
256 std::unordered_set<std::string> device_extension_set;
257 struct SubpassesUsageStates {
258 std::unordered_set<uint32_t> subpasses_using_color_attachment;
259 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
260 };
261 // Uses unwrapped handles
262 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
263 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
264 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
265 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700266 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
267 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700268
269
270 // Unwrap a handle. Must hold lock.
271 template <typename HandleType>
272 HandleType Unwrap(HandleType wrappedHandle) {
273 // TODO: don't use operator[] here.
274 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
275 }
276
277 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
278 template <typename HandleType>
279 HandleType WrapNew(HandleType newlyCreatedHandle) {
280 auto unique_id = global_unique_id++;
281 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
282 return (HandleType)unique_id;
283 }
284
285 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
286 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
287 auto unique_id = global_unique_id++;
288 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
289 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
290 return (VkDisplayKHR)unique_id;
291 }
292
293 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
294 // creating another. Must hold lock.
295 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
296 // See if this display is already known
297 auto it = map_data->display_id_reverse_mapping.find(handle);
298 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
299 // Unknown, so wrap
300 return WrapDisplay(handle, map_data);
301 }
302
303 // Pre/post hook point declarations
304"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600305
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700306 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600307// This file is ***GENERATED***. Do Not Edit.
308// See layer_chassis_generator.py for modifications.
309
310/* Copyright (c) 2015-2018 The Khronos Group Inc.
311 * Copyright (c) 2015-2018 Valve Corporation
312 * Copyright (c) 2015-2018 LunarG, Inc.
313 * Copyright (c) 2015-2018 Google Inc.
314 *
315 * Licensed under the Apache License, Version 2.0 (the "License");
316 * you may not use this file except in compliance with the License.
317 * You may obtain a copy of the License at
318 *
319 * http://www.apache.org/licenses/LICENSE-2.0
320 *
321 * Unless required by applicable law or agreed to in writing, software
322 * distributed under the License is distributed on an "AS IS" BASIS,
323 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
324 * See the License for the specific language governing permissions and
325 * limitations under the License.
326 *
327 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700328 */"""
329
330 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600331
332#include <string.h>
333#include <mutex>
334
335#define VALIDATION_ERROR_MAP_IMPL
336
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600337#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700338#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600339
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600340std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600341
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700342// Global unique object identifier. All increments must be guarded by a lock.
343uint64_t global_unique_id = 1;
344// Map uniqueID to actual object handle
345std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
346
347// TODO: This variable controls handle wrapping -- in the future it should be hooked
348// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
349#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
350bool wrap_handles = true;
351#else
352const bool wrap_handles = false;
353#endif
354
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600355// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700356#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600357#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700358#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
359#elif BUILD_THREAD_CHECKER
360#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
361#elif BUILD_PARAMETER_VALIDATION
362#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
363#elif BUILD_CORE_VALIDATION
364#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
365#else
366#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
367#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600368
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600369namespace vulkan_layer_chassis {
370
371using std::unordered_map;
372
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600373static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700374 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600375};
376
377static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
378
379extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
380
381
382// Manually written functions
383
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700384// Check enabled instance extensions against supported instance extension whitelist
385static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
386 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
387 // Check for recognized instance extensions
388 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
389 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
390 kVUIDUndefined,
391 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
392 "results and/or produce undefined behavior.",
393 pCreateInfo->ppEnabledExtensionNames[i]);
394 }
395 }
396}
397
398// Check enabled device extensions against supported device extension whitelist
399static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
400 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
401 // Check for recognized device extensions
402 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
403 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
404 kVUIDUndefined,
405 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
406 "results and/or produce undefined behavior.",
407 pCreateInfo->ppEnabledExtensionNames[i]);
408 }
409 }
410}
411
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600412VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600413 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600414 const auto &item = name_to_funcptr_map.find(funcName);
415 if (item != name_to_funcptr_map.end()) {
416 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
417 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600418 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600419 if (!table.GetDeviceProcAddr) return nullptr;
420 return table.GetDeviceProcAddr(device, funcName);
421}
422
423VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600424 const auto &item = name_to_funcptr_map.find(funcName);
425 if (item != name_to_funcptr_map.end()) {
426 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
427 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600428 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
429 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600430 if (!table.GetInstanceProcAddr) return nullptr;
431 return table.GetInstanceProcAddr(instance, funcName);
432}
433
434VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600435 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
436 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600437 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
438 return table.GetPhysicalDeviceProcAddr(instance, funcName);
439}
440
441VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
442 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
443}
444
445VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
446 VkLayerProperties *pProperties) {
447 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
448}
449
450VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
451 VkExtensionProperties *pProperties) {
452 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
453 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
454
455 return VK_ERROR_LAYER_NOT_PRESENT;
456}
457
458VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
459 uint32_t *pCount, VkExtensionProperties *pProperties) {
460 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600461 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600462 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
463 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600464}
465
466VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
467 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600468 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600469
470 assert(chain_info->u.pLayerInfo);
471 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
472 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
473 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
474 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
475
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600476 // Create temporary dispatch vector for pre-calls until instance is created
477 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700478#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600479 auto object_tracker = new ObjectLifetimes;
480 local_object_dispatch.emplace_back(object_tracker);
481 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700482#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600483
484
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600485 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600486 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600487 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
488 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600489 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600490 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
491 }
492
493 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600494 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600495
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600496 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600497
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600498 framework->object_dispatch = local_object_dispatch;
499
500 framework->instance = *pInstance;
501 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
502 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
503 pCreateInfo->ppEnabledExtensionNames);
504 framework->api_version = framework->instance_extensions.InitFromInstanceCreateInfo(
505 (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0), pCreateInfo);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700506#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600507 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700508#else
509 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
510#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600511
512 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600513 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
514 }
515
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700516 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
517
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600518 return result;
519}
520
521VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
522 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600523 auto layer_data = GetLayerDataPtr(key, layer_data_map);
524 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700525 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600526 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
527 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600528 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700529 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600530 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
531 }
532
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600533 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600534
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600535 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700536 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600537 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
538 }
539 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600540 while (layer_data->logging_messenger.size() > 0) {
541 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
542 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
543 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600544 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600545 while (layer_data->logging_callback.size() > 0) {
546 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
547 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
548 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600549 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600550
551 layer_debug_utils_destroy_instance(layer_data->report_data);
552
553 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600554}
555
556VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
557 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600558 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600559
560 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
561
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600562 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
563 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600564 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
565 if (fpCreateDevice == NULL) {
566 return VK_ERROR_INITIALIZATION_FAILED;
567 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600568 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
569
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600570 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700571 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600572 intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
573 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600574 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700575 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600576 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
577 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600578
579 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600580 if (result != VK_SUCCESS) {
581 return result;
582 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600583
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600584 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
585 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
586 device_interceptor->device = *pDevice;
587 device_interceptor->physical_device = gpu;
588 device_interceptor->instance = instance_interceptor->instance;
589 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
590 device_interceptor->api_version = instance_interceptor->api_version;
591
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700592#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600593 // Create child layer objects for this key and add to dispatch vector
594 auto object_tracker = new ObjectLifetimes;
595 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
596 object_tracker->container_type = LayerObjectTypeObjectTracker;
597 object_tracker->physical_device = gpu;
598 object_tracker->instance = instance_interceptor->instance;
599 object_tracker->report_data = device_interceptor->report_data;
600 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
601 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700602#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600603
604 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700605 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600606 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
607 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600608
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700609 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
610
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600611 return result;
612}
613
614VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
615 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600616 auto layer_data = GetLayerDataPtr(key, layer_data_map);
617 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700618 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600619 intercept->PreCallValidateDestroyDevice(device, pAllocator);
620 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600621 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700622 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600623 intercept->PreCallRecordDestroyDevice(device, pAllocator);
624 }
625 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600626
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600627 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600628
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600629 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700630 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600631 intercept->PostCallRecordDestroyDevice(device, pAllocator);
632 }
633
634 FreeLayerDataPtr(key, layer_data_map);
635}
636
637VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
638 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
639 const VkAllocationCallbacks *pAllocator,
640 VkDebugReportCallbackEXT *pCallback) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600641 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
642 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700643 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600644 intercept->PreCallValidateCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
645 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600646 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700647 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600648 intercept->PreCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
649 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700650 VkResult result = DispatchCreateDebugReportCallbackEXT(layer_data, instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600651 result = layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);
652 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700653 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600654 intercept->PostCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
655 }
656 return result;
657}
658
659VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
660 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600661 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
662 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700663 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600664 intercept->PreCallValidateDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
665 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600666 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700667 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600668 intercept->PreCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
669 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700670 DispatchDestroyDebugReportCallbackEXT(layer_data, instance, callback, pAllocator);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600671 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
672 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700673 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600674 intercept->PostCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
675 }
676}
677"""
678
679 inline_custom_source_postamble = """
680// loader-layer interface v0, just wrappers since there is only a layer
681
682VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
683 VkExtensionProperties *pProperties) {
684 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
685}
686
687VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
688 VkLayerProperties *pProperties) {
689 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
690}
691
692VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
693 VkLayerProperties *pProperties) {
694 // the layer command handles VK_NULL_HANDLE just fine internally
695 assert(physicalDevice == VK_NULL_HANDLE);
696 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
697}
698
699VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
700 const char *pLayerName, uint32_t *pCount,
701 VkExtensionProperties *pProperties) {
702 // the layer command handles VK_NULL_HANDLE just fine internally
703 assert(physicalDevice == VK_NULL_HANDLE);
704 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
705}
706
707VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
708 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
709}
710
711VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
712 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
713}
714
715VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
716 const char *funcName) {
717 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
718}
719
720VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
721 assert(pVersionStruct != NULL);
722 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
723
724 // Fill in the function pointers if our version is at least capable of having the structure contain them.
725 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
726 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
727 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
728 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
729 }
730
731 return VK_SUCCESS;
732}"""
733
734
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600735 def __init__(self,
736 errFile = sys.stderr,
737 warnFile = sys.stderr,
738 diagFile = sys.stdout):
739 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
740 # Internal state - accumulators for different inner block text
741 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
742 self.intercepts = []
743 self.layer_factory = '' # String containing base layer factory class definition
744
745 # Check if the parameter passed in is a pointer to an array
746 def paramIsArray(self, param):
747 return param.attrib.get('len') is not None
748
749 # Check if the parameter passed in is a pointer
750 def paramIsPointer(self, param):
751 ispointer = False
752 for elem in param:
753 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
754 ispointer = True
755 return ispointer
756
757 # Check if an object is a non-dispatchable handle
758 def isHandleTypeNonDispatchable(self, handletype):
759 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
760 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
761 return True
762 else:
763 return False
764
765 # Check if an object is a dispatchable handle
766 def isHandleTypeDispatchable(self, handletype):
767 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
768 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
769 return True
770 else:
771 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700772 #
773 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600774 def beginFile(self, genOpts):
775 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700776 # Output Copyright
777 write(self.inline_copyright_message, file=self.outFile)
778 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600779 self.header = False
780 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
781 self.header = True
782 write('#pragma once', file=self.outFile)
783 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600784 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700785 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600786 else:
787 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700788 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700789 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600790 #
791 def endFile(self):
792 # Finish C++ namespace and multiple inclusion protection
793 self.newline()
794 if not self.header:
795 # Record intercepted procedures
796 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
797 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
798 write('\n'.join(self.intercepts), file=self.outFile)
799 write('};\n', file=self.outFile)
800 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600801 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600802 if self.header:
803 self.newline()
804 # Output Layer Factory Class Definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600805 self.layer_factory += '};\n\n'
806 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600807 write(self.layer_factory, file=self.outFile)
808 else:
809 write(self.inline_custom_source_postamble, file=self.outFile)
810 # Finish processing in superclass
811 OutputGenerator.endFile(self)
812
813 def beginFeature(self, interface, emit):
814 # Start processing in superclass
815 OutputGenerator.beginFeature(self, interface, emit)
816 # Get feature extra protect
817 self.featureExtraProtect = GetFeatureProtect(interface)
818 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
819 # feature. They're only printed in endFeature().
820 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
821
822 def endFeature(self):
823 # Actually write the interface to the output file.
824 if (self.emit):
825 self.newline()
826 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
827 # or move it below the 'for section...' loop.
828 if (self.featureExtraProtect != None):
829 write('#ifdef', self.featureExtraProtect, file=self.outFile)
830 for section in self.TYPE_SECTIONS:
831 contents = self.sections[section]
832 if contents:
833 write('\n'.join(contents), file=self.outFile)
834 self.newline()
835 if (self.sections['command']):
836 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
837 self.newline()
838 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600839 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600840 # Finish processing in superclass
841 OutputGenerator.endFeature(self)
842 #
843 # Append a definition to the specified section
844 def appendSection(self, section, text):
845 self.sections[section].append(text)
846 #
847 # Type generation
848 def genType(self, typeinfo, name, alias):
849 pass
850 #
851 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
852 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
853 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
854 # structs etc.)
855 def genStruct(self, typeinfo, typeName):
856 OutputGenerator.genStruct(self, typeinfo, typeName)
857 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
858 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
859 for member in typeinfo.elem.findall('.//member'):
860 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
861 body += ';\n'
862 body += '} ' + typeName + ';\n'
863 self.appendSection('struct', body)
864 #
865 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
866 def genGroup(self, groupinfo, groupName, alias):
867 pass
868 # Enumerant generation
869 # <enum> tags may specify their values in several ways, but are usually just integers.
870 def genEnum(self, enuminfo, name, alias):
871 pass
872 #
873 # Customize Cdecl for layer factory base class
874 def BaseClassCdecl(self, elem, name):
875 raw = self.makeCDecls(elem)[1]
876
877 # Toss everything before the undecorated name
878 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
879 prototype = prototype.replace(")", "", 1)
880 prototype = prototype.replace(";", " {};")
881
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600882 # Build up pre/post call virtual function declarations
883 pre_call_validate = 'virtual bool PreCallValidate' + prototype
884 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
885 pre_call_record = 'virtual void PreCallRecord' + prototype
886 post_call_record = 'virtual void PostCallRecord' + prototype
887 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
888 #
889 # Command generation
890 def genCmd(self, cmdinfo, name, alias):
891 ignore_functions = [
892 'vkEnumerateInstanceVersion'
893 ]
894
895 if name in ignore_functions:
896 return
897
898 if self.header: # In the header declare all intercepts
899 self.appendSection('command', '')
900 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
901 if (self.featureExtraProtect != None):
902 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
903 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
904 # Update base class with virtual function declarations
905 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
906 # Update function intercepts
907 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
908 if (self.featureExtraProtect != None):
909 self.intercepts += [ '#endif' ]
910 self.layer_factory += '#endif\n'
911 return
912
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700913 if name in self.manual_functions:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600914 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
915 return
916 # Record that the function will be intercepted
917 if (self.featureExtraProtect != None):
918 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
919 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
920 if (self.featureExtraProtect != None):
921 self.intercepts += [ '#endif' ]
922 OutputGenerator.genCmd(self, cmdinfo, name, alias)
923 #
924 decls = self.makeCDecls(cmdinfo.elem)
925 self.appendSection('command', '')
926 self.appendSection('command', '%s {' % decls[0][:-1])
927 # Setup common to call wrappers. First parameter is always dispatchable
928 dispatchable_type = cmdinfo.elem.find('param/type').text
929 dispatchable_name = cmdinfo.elem.find('param/name').text
930 # Default to device
931 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600932 dispatch_table_name = 'VkLayerDispatchTable'
933 # Set to instance as necessary
934 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
935 device_or_instance = 'instance'
936 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600937 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600938 api_function_name = cmdinfo.elem.attrib.get('name')
939 params = cmdinfo.elem.findall('param/name')
940 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700941 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600942
943 # Declare result variable, if any.
944 return_map = {
945 'void': 'return;',
946 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
947 'PFN_vkVoidFunction': 'return nullptr;',
948 'VkBool32': 'return VK_FALSE;',
949 }
950 resulttype = cmdinfo.elem.find('proto/type')
951 assignresult = ''
952 if (resulttype.text != 'void'):
953 assignresult = resulttype.text + ' result = '
954
955 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700956 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600957
958 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600959 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700960 self.appendSection('command', ' std::lock_guard<std::mutex> lock(intercept->layer_mutex);')
961 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
962 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
963 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600964
965 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600966 self.appendSection('command', ' %s' % self.precallrecord_loop)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700967 self.appendSection('command', ' std::lock_guard<std::mutex> lock(intercept->layer_mutex);')
968 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600969 self.appendSection('command', ' }')
970
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700971 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600972
973 # Generate post-call object processing source code
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700974 return_type_indent = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600975 if (resulttype.text == 'VkResult'):
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700976 return_type_indent = ' '
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700977 if name in self.alt_ret_codes:
Mark Lobodzinskib3c94842018-11-27 10:01:51 -0700978 self.appendSection('command', ' if ((VK_SUCCESS == result) || (VK_INCOMPLETE == result)) {')
979 else:
980 self.appendSection('command', ' if (VK_SUCCESS == result) {')
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600981
982 self.appendSection('command', '%s %s' % (return_type_indent, self.postcallrecord_loop))
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700983 self.appendSection('command', '%s std::lock_guard<std::mutex> lock(intercept->layer_mutex);' % return_type_indent)
984 self.appendSection('command', '%s intercept->PostCallRecord%s(%s);' % (return_type_indent,api_function_name[2:], paramstext))
985 self.appendSection('command', '%s }' % return_type_indent)
986 if (resulttype.text == 'VkResult'):
987 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600988
989 # Return result variable, if any.
990 if (resulttype.text != 'void'):
991 self.appendSection('command', ' return result;')
992 self.appendSection('command', '}')
993 #
994 # Override makeProtoName to drop the "vk" prefix
995 def makeProtoName(self, name, tail):
996 return self.genOpts.apientry + name[2:] + tail