blob: 1e18937c0c27ad67a8c9c7033aa5d1ea4167ad1a [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;
224
225
226 // Unwrap a handle. Must hold lock.
227 template <typename HandleType>
228 HandleType Unwrap(HandleType wrappedHandle) {
229 // TODO: don't use operator[] here.
230 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
231 }
232
233 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
234 template <typename HandleType>
235 HandleType WrapNew(HandleType newlyCreatedHandle) {
236 auto unique_id = global_unique_id++;
237 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
238 return (HandleType)unique_id;
239 }
240
241 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
242 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
243 auto unique_id = global_unique_id++;
244 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
245 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
246 return (VkDisplayKHR)unique_id;
247 }
248
249 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
250 // creating another. Must hold lock.
251 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
252 // See if this display is already known
253 auto it = map_data->display_id_reverse_mapping.find(handle);
254 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
255 // Unknown, so wrap
256 return WrapDisplay(handle, map_data);
257 }
258
259 // Pre/post hook point declarations
260"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600261
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700262 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600263// This file is ***GENERATED***. Do Not Edit.
264// See layer_chassis_generator.py for modifications.
265
266/* Copyright (c) 2015-2018 The Khronos Group Inc.
267 * Copyright (c) 2015-2018 Valve Corporation
268 * Copyright (c) 2015-2018 LunarG, Inc.
269 * Copyright (c) 2015-2018 Google Inc.
270 *
271 * Licensed under the Apache License, Version 2.0 (the "License");
272 * you may not use this file except in compliance with the License.
273 * You may obtain a copy of the License at
274 *
275 * http://www.apache.org/licenses/LICENSE-2.0
276 *
277 * Unless required by applicable law or agreed to in writing, software
278 * distributed under the License is distributed on an "AS IS" BASIS,
279 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
280 * See the License for the specific language governing permissions and
281 * limitations under the License.
282 *
283 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700284 */"""
285
286 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600287
288#include <string.h>
289#include <mutex>
290
291#define VALIDATION_ERROR_MAP_IMPL
292
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600293#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700294#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600295
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600296std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600297
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700298// Global unique object identifier. All increments must be guarded by a lock.
299uint64_t global_unique_id = 1;
300// Map uniqueID to actual object handle
301std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
302
303// TODO: This variable controls handle wrapping -- in the future it should be hooked
304// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
305#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
306bool wrap_handles = true;
307#else
308const bool wrap_handles = false;
309#endif
310
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600311// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700312#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600313#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700314#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
315#elif BUILD_THREAD_CHECKER
316#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
317#elif BUILD_PARAMETER_VALIDATION
318#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
319#elif BUILD_CORE_VALIDATION
320#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
321#else
322#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
323#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600324
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600325namespace vulkan_layer_chassis {
326
327using std::unordered_map;
328
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600329static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700330 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600331};
332
333static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
334
335extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
336
337
338// Manually written functions
339
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700340// Check enabled instance extensions against supported instance extension whitelist
341static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
342 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
343 // Check for recognized instance extensions
344 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
345 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
346 kVUIDUndefined,
347 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
348 "results and/or produce undefined behavior.",
349 pCreateInfo->ppEnabledExtensionNames[i]);
350 }
351 }
352}
353
354// Check enabled device extensions against supported device extension whitelist
355static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
356 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
357 // Check for recognized device extensions
358 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
359 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
360 kVUIDUndefined,
361 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
362 "results and/or produce undefined behavior.",
363 pCreateInfo->ppEnabledExtensionNames[i]);
364 }
365 }
366}
367
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600368VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600369 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600370 const auto &item = name_to_funcptr_map.find(funcName);
371 if (item != name_to_funcptr_map.end()) {
372 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
373 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600374 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600375 if (!table.GetDeviceProcAddr) return nullptr;
376 return table.GetDeviceProcAddr(device, funcName);
377}
378
379VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600380 const auto &item = name_to_funcptr_map.find(funcName);
381 if (item != name_to_funcptr_map.end()) {
382 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
383 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600384 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
385 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600386 if (!table.GetInstanceProcAddr) return nullptr;
387 return table.GetInstanceProcAddr(instance, funcName);
388}
389
390VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600391 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
392 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600393 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
394 return table.GetPhysicalDeviceProcAddr(instance, funcName);
395}
396
397VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
398 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
399}
400
401VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
402 VkLayerProperties *pProperties) {
403 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
404}
405
406VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
407 VkExtensionProperties *pProperties) {
408 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
409 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
410
411 return VK_ERROR_LAYER_NOT_PRESENT;
412}
413
414VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
415 uint32_t *pCount, VkExtensionProperties *pProperties) {
416 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600417 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600418 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
419 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600420}
421
422VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
423 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600424 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600425
426 assert(chain_info->u.pLayerInfo);
427 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
428 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
429 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
430 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
431
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600432 // Create temporary dispatch vector for pre-calls until instance is created
433 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700434#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600435 auto object_tracker = new ObjectLifetimes;
436 local_object_dispatch.emplace_back(object_tracker);
437 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700438#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600439
440
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600441 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600442 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600443 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
444 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600445 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600446 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
447 }
448
449 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600450 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600451
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600452 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600453
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600454 framework->object_dispatch = local_object_dispatch;
455
456 framework->instance = *pInstance;
457 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
458 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
459 pCreateInfo->ppEnabledExtensionNames);
460 framework->api_version = framework->instance_extensions.InitFromInstanceCreateInfo(
461 (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0), pCreateInfo);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700462#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600463 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700464#else
465 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
466#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600467
468 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600469 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
470 }
471
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700472 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
473
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600474 return result;
475}
476
477VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
478 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600479 auto layer_data = GetLayerDataPtr(key, layer_data_map);
480 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700481 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600482 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
483 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600484 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700485 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600486 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
487 }
488
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600489 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600490
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600491 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700492 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600493 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
494 }
495 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600496 while (layer_data->logging_messenger.size() > 0) {
497 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
498 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
499 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600500 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600501 while (layer_data->logging_callback.size() > 0) {
502 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
503 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
504 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600505 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600506
507 layer_debug_utils_destroy_instance(layer_data->report_data);
508
509 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600510}
511
512VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
513 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600514 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600515
516 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
517
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600518 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
519 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600520 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
521 if (fpCreateDevice == NULL) {
522 return VK_ERROR_INITIALIZATION_FAILED;
523 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600524 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
525
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600526 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700527 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600528 intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
529 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600530 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700531 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600532 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
533 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600534
535 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600536 if (result != VK_SUCCESS) {
537 return result;
538 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600539
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600540 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
541 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
542 device_interceptor->device = *pDevice;
543 device_interceptor->physical_device = gpu;
544 device_interceptor->instance = instance_interceptor->instance;
545 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
546 device_interceptor->api_version = instance_interceptor->api_version;
547
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700548#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600549 // Create child layer objects for this key and add to dispatch vector
550 auto object_tracker = new ObjectLifetimes;
551 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
552 object_tracker->container_type = LayerObjectTypeObjectTracker;
553 object_tracker->physical_device = gpu;
554 object_tracker->instance = instance_interceptor->instance;
555 object_tracker->report_data = device_interceptor->report_data;
556 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
557 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700558#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600559
560 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700561 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600562 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
563 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600564
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700565 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
566
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600567 return result;
568}
569
570VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
571 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600572 auto layer_data = GetLayerDataPtr(key, layer_data_map);
573 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700574 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600575 intercept->PreCallValidateDestroyDevice(device, pAllocator);
576 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600577 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700578 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600579 intercept->PreCallRecordDestroyDevice(device, pAllocator);
580 }
581 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600582
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600583 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600584
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600585 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700586 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600587 intercept->PostCallRecordDestroyDevice(device, pAllocator);
588 }
589
590 FreeLayerDataPtr(key, layer_data_map);
591}
592
593VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
594 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
595 const VkAllocationCallbacks *pAllocator,
596 VkDebugReportCallbackEXT *pCallback) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600597 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
598 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700599 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600600 intercept->PreCallValidateCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
601 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600602 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700603 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600604 intercept->PreCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
605 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700606 VkResult result = DispatchCreateDebugReportCallbackEXT(layer_data, instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600607 result = layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);
608 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700609 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600610 intercept->PostCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
611 }
612 return result;
613}
614
615VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
616 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600617 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
618 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700619 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600620 intercept->PreCallValidateDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
621 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600622 """ + precallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700623 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600624 intercept->PreCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
625 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700626 DispatchDestroyDebugReportCallbackEXT(layer_data, instance, callback, pAllocator);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600627 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
628 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700629 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600630 intercept->PostCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
631 }
632}
633"""
634
635 inline_custom_source_postamble = """
636// loader-layer interface v0, just wrappers since there is only a layer
637
638VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
639 VkExtensionProperties *pProperties) {
640 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
641}
642
643VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
644 VkLayerProperties *pProperties) {
645 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
646}
647
648VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
649 VkLayerProperties *pProperties) {
650 // the layer command handles VK_NULL_HANDLE just fine internally
651 assert(physicalDevice == VK_NULL_HANDLE);
652 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
653}
654
655VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
656 const char *pLayerName, uint32_t *pCount,
657 VkExtensionProperties *pProperties) {
658 // the layer command handles VK_NULL_HANDLE just fine internally
659 assert(physicalDevice == VK_NULL_HANDLE);
660 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
661}
662
663VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
664 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
665}
666
667VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
668 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
669}
670
671VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
672 const char *funcName) {
673 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
674}
675
676VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
677 assert(pVersionStruct != NULL);
678 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
679
680 // Fill in the function pointers if our version is at least capable of having the structure contain them.
681 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
682 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
683 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
684 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
685 }
686
687 return VK_SUCCESS;
688}"""
689
690
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600691 def __init__(self,
692 errFile = sys.stderr,
693 warnFile = sys.stderr,
694 diagFile = sys.stdout):
695 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
696 # Internal state - accumulators for different inner block text
697 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
698 self.intercepts = []
699 self.layer_factory = '' # String containing base layer factory class definition
700
701 # Check if the parameter passed in is a pointer to an array
702 def paramIsArray(self, param):
703 return param.attrib.get('len') is not None
704
705 # Check if the parameter passed in is a pointer
706 def paramIsPointer(self, param):
707 ispointer = False
708 for elem in param:
709 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
710 ispointer = True
711 return ispointer
712
713 # Check if an object is a non-dispatchable handle
714 def isHandleTypeNonDispatchable(self, handletype):
715 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
716 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
717 return True
718 else:
719 return False
720
721 # Check if an object is a dispatchable handle
722 def isHandleTypeDispatchable(self, handletype):
723 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
724 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
725 return True
726 else:
727 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700728 #
729 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600730 def beginFile(self, genOpts):
731 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700732 # Output Copyright
733 write(self.inline_copyright_message, file=self.outFile)
734 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600735 self.header = False
736 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
737 self.header = True
738 write('#pragma once', file=self.outFile)
739 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600740 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700741 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600742 else:
743 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700744 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700745 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600746 #
747 def endFile(self):
748 # Finish C++ namespace and multiple inclusion protection
749 self.newline()
750 if not self.header:
751 # Record intercepted procedures
752 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
753 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
754 write('\n'.join(self.intercepts), file=self.outFile)
755 write('};\n', file=self.outFile)
756 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600757 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600758 if self.header:
759 self.newline()
760 # Output Layer Factory Class Definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600761 self.layer_factory += '};\n\n'
762 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600763 write(self.layer_factory, file=self.outFile)
764 else:
765 write(self.inline_custom_source_postamble, file=self.outFile)
766 # Finish processing in superclass
767 OutputGenerator.endFile(self)
768
769 def beginFeature(self, interface, emit):
770 # Start processing in superclass
771 OutputGenerator.beginFeature(self, interface, emit)
772 # Get feature extra protect
773 self.featureExtraProtect = GetFeatureProtect(interface)
774 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
775 # feature. They're only printed in endFeature().
776 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
777
778 def endFeature(self):
779 # Actually write the interface to the output file.
780 if (self.emit):
781 self.newline()
782 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
783 # or move it below the 'for section...' loop.
784 if (self.featureExtraProtect != None):
785 write('#ifdef', self.featureExtraProtect, file=self.outFile)
786 for section in self.TYPE_SECTIONS:
787 contents = self.sections[section]
788 if contents:
789 write('\n'.join(contents), file=self.outFile)
790 self.newline()
791 if (self.sections['command']):
792 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
793 self.newline()
794 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600795 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600796 # Finish processing in superclass
797 OutputGenerator.endFeature(self)
798 #
799 # Append a definition to the specified section
800 def appendSection(self, section, text):
801 self.sections[section].append(text)
802 #
803 # Type generation
804 def genType(self, typeinfo, name, alias):
805 pass
806 #
807 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
808 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
809 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
810 # structs etc.)
811 def genStruct(self, typeinfo, typeName):
812 OutputGenerator.genStruct(self, typeinfo, typeName)
813 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
814 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
815 for member in typeinfo.elem.findall('.//member'):
816 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
817 body += ';\n'
818 body += '} ' + typeName + ';\n'
819 self.appendSection('struct', body)
820 #
821 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
822 def genGroup(self, groupinfo, groupName, alias):
823 pass
824 # Enumerant generation
825 # <enum> tags may specify their values in several ways, but are usually just integers.
826 def genEnum(self, enuminfo, name, alias):
827 pass
828 #
829 # Customize Cdecl for layer factory base class
830 def BaseClassCdecl(self, elem, name):
831 raw = self.makeCDecls(elem)[1]
832
833 # Toss everything before the undecorated name
834 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
835 prototype = prototype.replace(")", "", 1)
836 prototype = prototype.replace(";", " {};")
837
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600838 # Build up pre/post call virtual function declarations
839 pre_call_validate = 'virtual bool PreCallValidate' + prototype
840 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
841 pre_call_record = 'virtual void PreCallRecord' + prototype
842 post_call_record = 'virtual void PostCallRecord' + prototype
843 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
844 #
845 # Command generation
846 def genCmd(self, cmdinfo, name, alias):
847 ignore_functions = [
848 'vkEnumerateInstanceVersion'
849 ]
850
851 if name in ignore_functions:
852 return
853
854 if self.header: # In the header declare all intercepts
855 self.appendSection('command', '')
856 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
857 if (self.featureExtraProtect != None):
858 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
859 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
860 # Update base class with virtual function declarations
861 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
862 # Update function intercepts
863 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
864 if (self.featureExtraProtect != None):
865 self.intercepts += [ '#endif' ]
866 self.layer_factory += '#endif\n'
867 return
868
869 manual_functions = [
870 # Include functions here to be interecpted w/ manually implemented function bodies
871 'vkGetDeviceProcAddr',
872 'vkGetInstanceProcAddr',
873 'vkGetPhysicalDeviceProcAddr',
874 'vkCreateDevice',
875 'vkDestroyDevice',
876 'vkCreateInstance',
877 'vkDestroyInstance',
878 'vkCreateDebugReportCallbackEXT',
879 'vkDestroyDebugReportCallbackEXT',
880 'vkEnumerateInstanceLayerProperties',
881 'vkEnumerateInstanceExtensionProperties',
882 'vkEnumerateDeviceLayerProperties',
883 'vkEnumerateDeviceExtensionProperties',
884 ]
885 if name in manual_functions:
886 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
887 return
888 # Record that the function will be intercepted
889 if (self.featureExtraProtect != None):
890 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
891 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
892 if (self.featureExtraProtect != None):
893 self.intercepts += [ '#endif' ]
894 OutputGenerator.genCmd(self, cmdinfo, name, alias)
895 #
896 decls = self.makeCDecls(cmdinfo.elem)
897 self.appendSection('command', '')
898 self.appendSection('command', '%s {' % decls[0][:-1])
899 # Setup common to call wrappers. First parameter is always dispatchable
900 dispatchable_type = cmdinfo.elem.find('param/type').text
901 dispatchable_name = cmdinfo.elem.find('param/name').text
902 # Default to device
903 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600904 dispatch_table_name = 'VkLayerDispatchTable'
905 # Set to instance as necessary
906 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
907 device_or_instance = 'instance'
908 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600909 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600910 api_function_name = cmdinfo.elem.attrib.get('name')
911 params = cmdinfo.elem.findall('param/name')
912 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700913 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600914
915 # Declare result variable, if any.
916 return_map = {
917 'void': 'return;',
918 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
919 'PFN_vkVoidFunction': 'return nullptr;',
920 'VkBool32': 'return VK_FALSE;',
921 }
922 resulttype = cmdinfo.elem.find('proto/type')
923 assignresult = ''
924 if (resulttype.text != 'void'):
925 assignresult = resulttype.text + ' result = '
926
927 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700928 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600929
930 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600931 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700932 self.appendSection('command', ' std::lock_guard<std::mutex> lock(intercept->layer_mutex);')
933 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
934 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
935 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600936
937 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600938 self.appendSection('command', ' %s' % self.precallrecord_loop)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700939 self.appendSection('command', ' std::lock_guard<std::mutex> lock(intercept->layer_mutex);')
940 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600941 self.appendSection('command', ' }')
942
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700943 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600944
945 # Generate post-call object processing source code
Mark Lobodzinskib3c94842018-11-27 10:01:51 -0700946 alt_ret_codes = [
947 # Include functions here which must tolerate VK_INCOMPLETE as a return code
948 'vkEnumeratePhysicalDevices',
949 'vkEnumeratePhysicalDeviceGroupsKHR',
950 'vkGetValidationCacheDataEXT',
951 'vkGetPipelineCacheData',
952 'vkGetShaderInfoAMD',
953 'vkGetPhysicalDeviceDisplayPropertiesKHR',
954 'vkGetPhysicalDeviceDisplayProperties2KHR',
955 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
956 'vkGetDisplayPlaneSupportedDisplaysKHR',
957 'vkGetDisplayModePropertiesKHR',
958 'vkGetDisplayModeProperties2KHR',
959 'vkGetPhysicalDeviceSurfaceFormatsKHR',
960 'vkGetPhysicalDeviceSurfacePresentModesKHR',
961 'vkGetPhysicalDevicePresentRectanglesKHR',
962 'vkGetPastPresentationTimingGOOGLE',
963 'vkGetSwapchainImagesKHR',
964 'vkEnumerateInstanceLayerProperties',
965 'vkEnumerateDeviceLayerProperties',
966 'vkEnumerateInstanceExtensionProperties',
967 'vkEnumerateDeviceExtensionProperties',
968 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
969 ]
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700970 return_type_indent = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600971 if (resulttype.text == 'VkResult'):
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700972 return_type_indent = ' '
Mark Lobodzinskib3c94842018-11-27 10:01:51 -0700973 if name in alt_ret_codes:
974 self.appendSection('command', ' if ((VK_SUCCESS == result) || (VK_INCOMPLETE == result)) {')
975 else:
976 self.appendSection('command', ' if (VK_SUCCESS == result) {')
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600977
978 self.appendSection('command', '%s %s' % (return_type_indent, self.postcallrecord_loop))
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700979 self.appendSection('command', '%s std::lock_guard<std::mutex> lock(intercept->layer_mutex);' % return_type_indent)
980 self.appendSection('command', '%s intercept->PostCallRecord%s(%s);' % (return_type_indent,api_function_name[2:], paramstext))
981 self.appendSection('command', '%s }' % return_type_indent)
982 if (resulttype.text == 'VkResult'):
983 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600984
985 # Return result variable, if any.
986 if (resulttype.text != 'void'):
987 self.appendSection('command', ' return result;')
988 self.appendSection('command', '}')
989 #
990 # Override makeProtoName to drop the "vk" prefix
991 def makeProtoName(self, name, tail):
992 return self.genOpts.apientry + name[2:] + tail