blob: 56556750e5e36db2e1bf9a46dbce446facb24d2f [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 Lobodzinskiadd93232018-10-09 11:49:42 -0600126 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
127 precallrecord_loop = precallvalidate_loop
128 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600129
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700130 inline_custom_header_preamble = """
131#define NOMINMAX
132#include <mutex>
133#include <cinttypes>
134#include <stdio.h>
135#include <stdlib.h>
136#include <string.h>
137#include <unordered_map>
138#include <unordered_set>
139#include <algorithm>
140#include <memory>
141
142#include "vk_loader_platform.h"
143#include "vulkan/vulkan.h"
144#include "vk_layer_config.h"
145#include "vk_layer_data.h"
146#include "vk_layer_logging.h"
147#include "vk_object_types.h"
148#include "vulkan/vk_layer.h"
149#include "vk_enum_string_helper.h"
150#include "vk_layer_extension_utils.h"
151#include "vk_layer_utils.h"
152#include "vulkan/vk_layer.h"
153#include "vk_dispatch_table_helper.h"
154#include "vk_validation_error_messages.h"
155#include "vk_extension_helper.h"
156#include "vk_safe_struct.h"
157
158extern uint64_t global_unique_id;
159extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
160"""
161
162 inline_custom_header_class_definition = """
163
164// Layer object type identifiers
165enum LayerObjectTypeId {
166 LayerObjectTypeThreading,
167 LayerObjectTypeParameterValidation,
168 LayerObjectTypeObjectTracker,
169 LayerObjectTypeCoreValidation,
170};
171
172struct TEMPLATE_STATE {
173 VkDescriptorUpdateTemplateKHR desc_update_template;
174 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
175
176 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
177 : desc_update_template(update_template), create_info(*pCreateInfo) {}
178};
179
180// Layer chassis validation object base class definition
181class ValidationObject {
182 public:
183 uint32_t api_version;
184 debug_report_data* report_data = nullptr;
185 std::vector<VkDebugReportCallbackEXT> logging_callback;
186 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
187
188 VkLayerInstanceDispatchTable instance_dispatch_table;
189 VkLayerDispatchTable device_dispatch_table;
190
191 InstanceExtensions instance_extensions;
192 DeviceExtensions device_extensions = {};
193
194 VkInstance instance = VK_NULL_HANDLE;
195 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
196 VkDevice device = VK_NULL_HANDLE;
197
198 std::vector<ValidationObject*> object_dispatch;
199 LayerObjectTypeId container_type;
200
201 // Constructor
202 ValidationObject(){};
203 // Destructor
204 virtual ~ValidationObject() {};
205
206 std::mutex layer_mutex;
207
208 std::string layer_name = "CHASSIS";
209
210 // Handle Wrapping Data
211 // Reverse map display handles
212 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
213 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
214 std::unordered_set<std::string> device_extension_set;
215 struct SubpassesUsageStates {
216 std::unordered_set<uint32_t> subpasses_using_color_attachment;
217 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
218 };
219 // Uses unwrapped handles
220 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
221 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
222 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
223 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700224 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
225 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700226
227
228 // Unwrap a handle. Must hold lock.
229 template <typename HandleType>
230 HandleType Unwrap(HandleType wrappedHandle) {
231 // TODO: don't use operator[] here.
232 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
233 }
234
235 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
236 template <typename HandleType>
237 HandleType WrapNew(HandleType newlyCreatedHandle) {
238 auto unique_id = global_unique_id++;
239 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
240 return (HandleType)unique_id;
241 }
242
243 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
244 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
245 auto unique_id = global_unique_id++;
246 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
247 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
248 return (VkDisplayKHR)unique_id;
249 }
250
251 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
252 // creating another. Must hold lock.
253 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
254 // See if this display is already known
255 auto it = map_data->display_id_reverse_mapping.find(handle);
256 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
257 // Unknown, so wrap
258 return WrapDisplay(handle, map_data);
259 }
260
261 // Pre/post hook point declarations
262"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600263
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700264 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600265// This file is ***GENERATED***. Do Not Edit.
266// See layer_chassis_generator.py for modifications.
267
268/* Copyright (c) 2015-2018 The Khronos Group Inc.
269 * Copyright (c) 2015-2018 Valve Corporation
270 * Copyright (c) 2015-2018 LunarG, Inc.
271 * Copyright (c) 2015-2018 Google Inc.
272 *
273 * Licensed under the Apache License, Version 2.0 (the "License");
274 * you may not use this file except in compliance with the License.
275 * You may obtain a copy of the License at
276 *
277 * http://www.apache.org/licenses/LICENSE-2.0
278 *
279 * Unless required by applicable law or agreed to in writing, software
280 * distributed under the License is distributed on an "AS IS" BASIS,
281 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
282 * See the License for the specific language governing permissions and
283 * limitations under the License.
284 *
285 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700286 */"""
287
288 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600289
290#include <string.h>
291#include <mutex>
292
293#define VALIDATION_ERROR_MAP_IMPL
294
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600295#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700296#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600297
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600298std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600299
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700300// Global unique object identifier. All increments must be guarded by a lock.
301uint64_t global_unique_id = 1;
302// Map uniqueID to actual object handle
303std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
304
305// TODO: This variable controls handle wrapping -- in the future it should be hooked
306// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
307#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
308bool wrap_handles = true;
309#else
310const bool wrap_handles = false;
311#endif
312
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600313// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700314#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600315#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700316#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
317#elif BUILD_THREAD_CHECKER
318#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
319#elif BUILD_PARAMETER_VALIDATION
320#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
321#elif BUILD_CORE_VALIDATION
322#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
323#else
324#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
325#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600326
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600327namespace vulkan_layer_chassis {
328
329using std::unordered_map;
330
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600331static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700332 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600333};
334
335static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
336
337extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
338
339
340// Manually written functions
341
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700342// Check enabled instance extensions against supported instance extension whitelist
343static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
344 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
345 // Check for recognized instance extensions
346 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
347 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
348 kVUIDUndefined,
349 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
350 "results and/or produce undefined behavior.",
351 pCreateInfo->ppEnabledExtensionNames[i]);
352 }
353 }
354}
355
356// Check enabled device extensions against supported device extension whitelist
357static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
358 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
359 // Check for recognized device extensions
360 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
361 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
362 kVUIDUndefined,
363 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
364 "results and/or produce undefined behavior.",
365 pCreateInfo->ppEnabledExtensionNames[i]);
366 }
367 }
368}
369
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600370VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600371 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600372 const auto &item = name_to_funcptr_map.find(funcName);
373 if (item != name_to_funcptr_map.end()) {
374 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
375 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600376 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600377 if (!table.GetDeviceProcAddr) return nullptr;
378 return table.GetDeviceProcAddr(device, funcName);
379}
380
381VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600382 const auto &item = name_to_funcptr_map.find(funcName);
383 if (item != name_to_funcptr_map.end()) {
384 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
385 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600386 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
387 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600388 if (!table.GetInstanceProcAddr) return nullptr;
389 return table.GetInstanceProcAddr(instance, funcName);
390}
391
392VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600393 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
394 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600395 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
396 return table.GetPhysicalDeviceProcAddr(instance, funcName);
397}
398
399VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
400 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
401}
402
403VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
404 VkLayerProperties *pProperties) {
405 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
406}
407
408VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
409 VkExtensionProperties *pProperties) {
410 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
411 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
412
413 return VK_ERROR_LAYER_NOT_PRESENT;
414}
415
416VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
417 uint32_t *pCount, VkExtensionProperties *pProperties) {
418 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600419 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600420 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
421 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600422}
423
424VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
425 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600426 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600427
428 assert(chain_info->u.pLayerInfo);
429 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
430 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
431 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
432 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
433
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600434 // Create temporary dispatch vector for pre-calls until instance is created
435 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700436#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600437 auto object_tracker = new ObjectLifetimes;
438 local_object_dispatch.emplace_back(object_tracker);
439 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700440#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600441
442
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600443 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600444 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600445 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
446 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600447 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600448 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
449 }
450
451 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600452 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600453
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600454 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600455
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600456 framework->object_dispatch = local_object_dispatch;
457
458 framework->instance = *pInstance;
459 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
460 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
461 pCreateInfo->ppEnabledExtensionNames);
462 framework->api_version = framework->instance_extensions.InitFromInstanceCreateInfo(
463 (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0), pCreateInfo);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700464#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600465 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700466#else
467 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
468#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600469
470 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600471 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
472 }
473
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700474 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
475
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600476 return result;
477}
478
479VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
480 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600481 auto layer_data = GetLayerDataPtr(key, layer_data_map);
482 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700483 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600484 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
485 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600486 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700487 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600488 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
489 }
490
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600491 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600492
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600493 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700494 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600495 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
496 }
497 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600498 while (layer_data->logging_messenger.size() > 0) {
499 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
500 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
501 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600502 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600503 while (layer_data->logging_callback.size() > 0) {
504 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
505 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
506 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600507 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600508
509 layer_debug_utils_destroy_instance(layer_data->report_data);
510
511 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600512}
513
514VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
515 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600516 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600517
518 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
519
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600520 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
521 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600522 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
523 if (fpCreateDevice == NULL) {
524 return VK_ERROR_INITIALIZATION_FAILED;
525 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600526 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
527
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600528 for (auto intercept : instance_interceptor->object_dispatch) {
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->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
531 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600532 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700533 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600534 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
535 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600536
537 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600538 if (result != VK_SUCCESS) {
539 return result;
540 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600541
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600542 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
543 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
544 device_interceptor->device = *pDevice;
545 device_interceptor->physical_device = gpu;
546 device_interceptor->instance = instance_interceptor->instance;
547 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
548 device_interceptor->api_version = instance_interceptor->api_version;
549
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700550#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600551 // Create child layer objects for this key and add to dispatch vector
552 auto object_tracker = new ObjectLifetimes;
553 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
554 object_tracker->container_type = LayerObjectTypeObjectTracker;
555 object_tracker->physical_device = gpu;
556 object_tracker->instance = instance_interceptor->instance;
557 object_tracker->report_data = device_interceptor->report_data;
558 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
559 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700560#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600561
562 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700563 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600564 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
565 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600566
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700567 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
568
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600569 return result;
570}
571
572VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
573 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600574 auto layer_data = GetLayerDataPtr(key, layer_data_map);
575 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700576 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600577 intercept->PreCallValidateDestroyDevice(device, pAllocator);
578 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600579 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700580 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600581 intercept->PreCallRecordDestroyDevice(device, pAllocator);
582 }
583 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600584
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600585 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600586
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600587 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700588 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600589 intercept->PostCallRecordDestroyDevice(device, pAllocator);
590 }
591
592 FreeLayerDataPtr(key, layer_data_map);
593}
594
595VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
596 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
597 const VkAllocationCallbacks *pAllocator,
598 VkDebugReportCallbackEXT *pCallback) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600599 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
600 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700601 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600602 intercept->PreCallValidateCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
603 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600604 """ + precallrecord_loop + """
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->PreCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
607 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700608 VkResult result = DispatchCreateDebugReportCallbackEXT(layer_data, instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600609 result = layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);
610 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700611 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600612 intercept->PostCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
613 }
614 return result;
615}
616
617VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
618 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600619 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
620 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700621 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600622 intercept->PreCallValidateDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
623 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600624 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700625 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600626 intercept->PreCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
627 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700628 DispatchDestroyDebugReportCallbackEXT(layer_data, instance, callback, pAllocator);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600629 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
630 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700631 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600632 intercept->PostCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
633 }
634}
635"""
636
637 inline_custom_source_postamble = """
638// loader-layer interface v0, just wrappers since there is only a layer
639
640VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
641 VkExtensionProperties *pProperties) {
642 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
643}
644
645VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
646 VkLayerProperties *pProperties) {
647 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
648}
649
650VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
651 VkLayerProperties *pProperties) {
652 // the layer command handles VK_NULL_HANDLE just fine internally
653 assert(physicalDevice == VK_NULL_HANDLE);
654 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
655}
656
657VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
658 const char *pLayerName, uint32_t *pCount,
659 VkExtensionProperties *pProperties) {
660 // the layer command handles VK_NULL_HANDLE just fine internally
661 assert(physicalDevice == VK_NULL_HANDLE);
662 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
663}
664
665VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
666 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
667}
668
669VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
670 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
671}
672
673VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
674 const char *funcName) {
675 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
676}
677
678VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
679 assert(pVersionStruct != NULL);
680 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
681
682 // Fill in the function pointers if our version is at least capable of having the structure contain them.
683 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
684 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
685 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
686 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
687 }
688
689 return VK_SUCCESS;
690}"""
691
692
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600693 def __init__(self,
694 errFile = sys.stderr,
695 warnFile = sys.stderr,
696 diagFile = sys.stdout):
697 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
698 # Internal state - accumulators for different inner block text
699 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
700 self.intercepts = []
701 self.layer_factory = '' # String containing base layer factory class definition
702
703 # Check if the parameter passed in is a pointer to an array
704 def paramIsArray(self, param):
705 return param.attrib.get('len') is not None
706
707 # Check if the parameter passed in is a pointer
708 def paramIsPointer(self, param):
709 ispointer = False
710 for elem in param:
711 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
712 ispointer = True
713 return ispointer
714
715 # Check if an object is a non-dispatchable handle
716 def isHandleTypeNonDispatchable(self, handletype):
717 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
718 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
719 return True
720 else:
721 return False
722
723 # Check if an object is a dispatchable handle
724 def isHandleTypeDispatchable(self, handletype):
725 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
726 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
727 return True
728 else:
729 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700730 #
731 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600732 def beginFile(self, genOpts):
733 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700734 # Output Copyright
735 write(self.inline_copyright_message, file=self.outFile)
736 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600737 self.header = False
738 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
739 self.header = True
740 write('#pragma once', file=self.outFile)
741 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600742 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700743 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600744 else:
745 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700746 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700747 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600748 #
749 def endFile(self):
750 # Finish C++ namespace and multiple inclusion protection
751 self.newline()
752 if not self.header:
753 # Record intercepted procedures
754 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
755 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
756 write('\n'.join(self.intercepts), file=self.outFile)
757 write('};\n', file=self.outFile)
758 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600759 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600760 if self.header:
761 self.newline()
762 # Output Layer Factory Class Definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600763 self.layer_factory += '};\n\n'
764 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600765 write(self.layer_factory, file=self.outFile)
766 else:
767 write(self.inline_custom_source_postamble, file=self.outFile)
768 # Finish processing in superclass
769 OutputGenerator.endFile(self)
770
771 def beginFeature(self, interface, emit):
772 # Start processing in superclass
773 OutputGenerator.beginFeature(self, interface, emit)
774 # Get feature extra protect
775 self.featureExtraProtect = GetFeatureProtect(interface)
776 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
777 # feature. They're only printed in endFeature().
778 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
779
780 def endFeature(self):
781 # Actually write the interface to the output file.
782 if (self.emit):
783 self.newline()
784 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
785 # or move it below the 'for section...' loop.
786 if (self.featureExtraProtect != None):
787 write('#ifdef', self.featureExtraProtect, file=self.outFile)
788 for section in self.TYPE_SECTIONS:
789 contents = self.sections[section]
790 if contents:
791 write('\n'.join(contents), file=self.outFile)
792 self.newline()
793 if (self.sections['command']):
794 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
795 self.newline()
796 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600797 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600798 # Finish processing in superclass
799 OutputGenerator.endFeature(self)
800 #
801 # Append a definition to the specified section
802 def appendSection(self, section, text):
803 self.sections[section].append(text)
804 #
805 # Type generation
806 def genType(self, typeinfo, name, alias):
807 pass
808 #
809 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
810 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
811 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
812 # structs etc.)
813 def genStruct(self, typeinfo, typeName):
814 OutputGenerator.genStruct(self, typeinfo, typeName)
815 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
816 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
817 for member in typeinfo.elem.findall('.//member'):
818 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
819 body += ';\n'
820 body += '} ' + typeName + ';\n'
821 self.appendSection('struct', body)
822 #
823 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
824 def genGroup(self, groupinfo, groupName, alias):
825 pass
826 # Enumerant generation
827 # <enum> tags may specify their values in several ways, but are usually just integers.
828 def genEnum(self, enuminfo, name, alias):
829 pass
830 #
831 # Customize Cdecl for layer factory base class
832 def BaseClassCdecl(self, elem, name):
833 raw = self.makeCDecls(elem)[1]
834
835 # Toss everything before the undecorated name
836 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
837 prototype = prototype.replace(")", "", 1)
838 prototype = prototype.replace(";", " {};")
839
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600840 # Build up pre/post call virtual function declarations
841 pre_call_validate = 'virtual bool PreCallValidate' + prototype
842 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
843 pre_call_record = 'virtual void PreCallRecord' + prototype
844 post_call_record = 'virtual void PostCallRecord' + prototype
845 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
846 #
847 # Command generation
848 def genCmd(self, cmdinfo, name, alias):
849 ignore_functions = [
850 'vkEnumerateInstanceVersion'
851 ]
852
853 if name in ignore_functions:
854 return
855
856 if self.header: # In the header declare all intercepts
857 self.appendSection('command', '')
858 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
859 if (self.featureExtraProtect != None):
860 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
861 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
862 # Update base class with virtual function declarations
863 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
864 # Update function intercepts
865 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
866 if (self.featureExtraProtect != None):
867 self.intercepts += [ '#endif' ]
868 self.layer_factory += '#endif\n'
869 return
870
871 manual_functions = [
872 # Include functions here to be interecpted w/ manually implemented function bodies
873 'vkGetDeviceProcAddr',
874 'vkGetInstanceProcAddr',
875 'vkGetPhysicalDeviceProcAddr',
876 'vkCreateDevice',
877 'vkDestroyDevice',
878 'vkCreateInstance',
879 'vkDestroyInstance',
880 'vkCreateDebugReportCallbackEXT',
881 'vkDestroyDebugReportCallbackEXT',
882 'vkEnumerateInstanceLayerProperties',
883 'vkEnumerateInstanceExtensionProperties',
884 'vkEnumerateDeviceLayerProperties',
885 'vkEnumerateDeviceExtensionProperties',
886 ]
887 if name in manual_functions:
888 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
889 return
890 # Record that the function will be intercepted
891 if (self.featureExtraProtect != None):
892 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
893 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
894 if (self.featureExtraProtect != None):
895 self.intercepts += [ '#endif' ]
896 OutputGenerator.genCmd(self, cmdinfo, name, alias)
897 #
898 decls = self.makeCDecls(cmdinfo.elem)
899 self.appendSection('command', '')
900 self.appendSection('command', '%s {' % decls[0][:-1])
901 # Setup common to call wrappers. First parameter is always dispatchable
902 dispatchable_type = cmdinfo.elem.find('param/type').text
903 dispatchable_name = cmdinfo.elem.find('param/name').text
904 # Default to device
905 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600906 dispatch_table_name = 'VkLayerDispatchTable'
907 # Set to instance as necessary
908 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
909 device_or_instance = 'instance'
910 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600911 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600912 api_function_name = cmdinfo.elem.attrib.get('name')
913 params = cmdinfo.elem.findall('param/name')
914 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700915 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600916
917 # Declare result variable, if any.
918 return_map = {
919 'void': 'return;',
920 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
921 'PFN_vkVoidFunction': 'return nullptr;',
922 'VkBool32': 'return VK_FALSE;',
923 }
924 resulttype = cmdinfo.elem.find('proto/type')
925 assignresult = ''
926 if (resulttype.text != 'void'):
927 assignresult = resulttype.text + ' result = '
928
929 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700930 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600931
932 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600933 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700934 self.appendSection('command', ' std::lock_guard<std::mutex> lock(intercept->layer_mutex);')
935 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
936 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
937 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600938
939 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600940 self.appendSection('command', ' %s' % self.precallrecord_loop)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700941 self.appendSection('command', ' std::lock_guard<std::mutex> lock(intercept->layer_mutex);')
942 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600943 self.appendSection('command', ' }')
944
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700945 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600946
947 # Generate post-call object processing source code
Mark Lobodzinskib3c94842018-11-27 10:01:51 -0700948 alt_ret_codes = [
949 # Include functions here which must tolerate VK_INCOMPLETE as a return code
950 'vkEnumeratePhysicalDevices',
951 'vkEnumeratePhysicalDeviceGroupsKHR',
952 'vkGetValidationCacheDataEXT',
953 'vkGetPipelineCacheData',
954 'vkGetShaderInfoAMD',
955 'vkGetPhysicalDeviceDisplayPropertiesKHR',
956 'vkGetPhysicalDeviceDisplayProperties2KHR',
957 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
958 'vkGetDisplayPlaneSupportedDisplaysKHR',
959 'vkGetDisplayModePropertiesKHR',
960 'vkGetDisplayModeProperties2KHR',
961 'vkGetPhysicalDeviceSurfaceFormatsKHR',
962 'vkGetPhysicalDeviceSurfacePresentModesKHR',
963 'vkGetPhysicalDevicePresentRectanglesKHR',
964 'vkGetPastPresentationTimingGOOGLE',
965 'vkGetSwapchainImagesKHR',
966 'vkEnumerateInstanceLayerProperties',
967 'vkEnumerateDeviceLayerProperties',
968 'vkEnumerateInstanceExtensionProperties',
969 'vkEnumerateDeviceExtensionProperties',
970 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
971 ]
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700972 return_type_indent = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600973 if (resulttype.text == 'VkResult'):
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700974 return_type_indent = ' '
Mark Lobodzinskib3c94842018-11-27 10:01:51 -0700975 if name in alt_ret_codes:
976 self.appendSection('command', ' if ((VK_SUCCESS == result) || (VK_INCOMPLETE == result)) {')
977 else:
978 self.appendSection('command', ' if (VK_SUCCESS == result) {')
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600979
980 self.appendSection('command', '%s %s' % (return_type_indent, self.postcallrecord_loop))
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700981 self.appendSection('command', '%s std::lock_guard<std::mutex> lock(intercept->layer_mutex);' % return_type_indent)
982 self.appendSection('command', '%s intercept->PostCallRecord%s(%s);' % (return_type_indent,api_function_name[2:], paramstext))
983 self.appendSection('command', '%s }' % return_type_indent)
984 if (resulttype.text == 'VkResult'):
985 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600986
987 # Return result variable, if any.
988 if (resulttype.text != 'void'):
989 self.appendSection('command', ' return result;')
990 self.appendSection('command', '}')
991 #
992 # Override makeProtoName to drop the "vk" prefix
993 def makeProtoName(self, name, tail):
994 return self.genOpts.apientry + name[2:] + tail