blob: ec06c8f3f2ede52620dbc34493af485bdf1db8df [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
262 inline_custom_source_preamble = """
263// 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>
284 */
285
286#include <string.h>
287#include <mutex>
288
289#define VALIDATION_ERROR_MAP_IMPL
290
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600291#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700292#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600293
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600294std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600295
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700296// Global unique object identifier. All increments must be guarded by a lock.
297uint64_t global_unique_id = 1;
298// Map uniqueID to actual object handle
299std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
300
301// TODO: This variable controls handle wrapping -- in the future it should be hooked
302// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
303#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
304bool wrap_handles = true;
305#else
306const bool wrap_handles = false;
307#endif
308
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600309// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700310#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600311#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700312#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
313#elif BUILD_THREAD_CHECKER
314#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
315#elif BUILD_PARAMETER_VALIDATION
316#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
317#elif BUILD_CORE_VALIDATION
318#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
319#else
320#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
321#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600322
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600323namespace vulkan_layer_chassis {
324
325using std::unordered_map;
326
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600327static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700328 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600329};
330
331static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
332
333extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
334
335
336// Manually written functions
337
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700338// Check enabled instance extensions against supported instance extension whitelist
339static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
340 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
341 // Check for recognized instance extensions
342 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
343 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
344 kVUIDUndefined,
345 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
346 "results and/or produce undefined behavior.",
347 pCreateInfo->ppEnabledExtensionNames[i]);
348 }
349 }
350}
351
352// Check enabled device extensions against supported device extension whitelist
353static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
354 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
355 // Check for recognized device extensions
356 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
357 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
358 kVUIDUndefined,
359 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
360 "results and/or produce undefined behavior.",
361 pCreateInfo->ppEnabledExtensionNames[i]);
362 }
363 }
364}
365
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600366VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600367 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600368 const auto &item = name_to_funcptr_map.find(funcName);
369 if (item != name_to_funcptr_map.end()) {
370 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
371 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600372 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600373 if (!table.GetDeviceProcAddr) return nullptr;
374 return table.GetDeviceProcAddr(device, funcName);
375}
376
377VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600378 const auto &item = name_to_funcptr_map.find(funcName);
379 if (item != name_to_funcptr_map.end()) {
380 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
381 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600382 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
383 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600384 if (!table.GetInstanceProcAddr) return nullptr;
385 return table.GetInstanceProcAddr(instance, funcName);
386}
387
388VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600389 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
390 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600391 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
392 return table.GetPhysicalDeviceProcAddr(instance, funcName);
393}
394
395VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
396 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
397}
398
399VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
400 VkLayerProperties *pProperties) {
401 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
402}
403
404VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
405 VkExtensionProperties *pProperties) {
406 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
407 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
408
409 return VK_ERROR_LAYER_NOT_PRESENT;
410}
411
412VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
413 uint32_t *pCount, VkExtensionProperties *pProperties) {
414 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600415 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600416 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
417 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600418}
419
420VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
421 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600422 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600423
424 assert(chain_info->u.pLayerInfo);
425 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
426 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
427 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
428 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
429
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600430 // Create temporary dispatch vector for pre-calls until instance is created
431 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700432#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600433 auto object_tracker = new ObjectLifetimes;
434 local_object_dispatch.emplace_back(object_tracker);
435 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700436#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600437
438
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600439 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600440 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600441 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
442 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600443 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600444 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
445 }
446
447 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600448 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600449
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600450 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600451
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600452 framework->object_dispatch = local_object_dispatch;
453
454 framework->instance = *pInstance;
455 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
456 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
457 pCreateInfo->ppEnabledExtensionNames);
458 framework->api_version = framework->instance_extensions.InitFromInstanceCreateInfo(
459 (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0), pCreateInfo);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700460#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600461 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700462#else
463 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
464#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600465
466 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600467 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
468 }
469
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700470 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
471
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600472 return result;
473}
474
475VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
476 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600477 auto layer_data = GetLayerDataPtr(key, layer_data_map);
478 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700479 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600480 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
481 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600482 """ + precallrecord_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->PreCallRecordDestroyInstance(instance, pAllocator);
485 }
486
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600487 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600488
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600489 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700490 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600491 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
492 }
493 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600494 while (layer_data->logging_messenger.size() > 0) {
495 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
496 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
497 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600498 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600499 while (layer_data->logging_callback.size() > 0) {
500 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
501 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
502 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600503 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600504
505 layer_debug_utils_destroy_instance(layer_data->report_data);
506
507 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600508}
509
510VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
511 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600512 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600513
514 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
515
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600516 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
517 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600518 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
519 if (fpCreateDevice == NULL) {
520 return VK_ERROR_INITIALIZATION_FAILED;
521 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600522 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
523
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600524 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700525 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600526 intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
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->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
531 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600532
533 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600534 if (result != VK_SUCCESS) {
535 return result;
536 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600537
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600538 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
539 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
540 device_interceptor->device = *pDevice;
541 device_interceptor->physical_device = gpu;
542 device_interceptor->instance = instance_interceptor->instance;
543 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
544 device_interceptor->api_version = instance_interceptor->api_version;
545
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700546#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600547 // Create child layer objects for this key and add to dispatch vector
548 auto object_tracker = new ObjectLifetimes;
549 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
550 object_tracker->container_type = LayerObjectTypeObjectTracker;
551 object_tracker->physical_device = gpu;
552 object_tracker->instance = instance_interceptor->instance;
553 object_tracker->report_data = device_interceptor->report_data;
554 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
555 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700556#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600557
558 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700559 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600560 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
561 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600562
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700563 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
564
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600565 return result;
566}
567
568VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
569 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600570 auto layer_data = GetLayerDataPtr(key, layer_data_map);
571 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700572 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600573 intercept->PreCallValidateDestroyDevice(device, pAllocator);
574 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600575 """ + precallrecord_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->PreCallRecordDestroyDevice(device, pAllocator);
578 }
579 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600580
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600581 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600582
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600583 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700584 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600585 intercept->PostCallRecordDestroyDevice(device, pAllocator);
586 }
587
588 FreeLayerDataPtr(key, layer_data_map);
589}
590
591VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
592 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
593 const VkAllocationCallbacks *pAllocator,
594 VkDebugReportCallbackEXT *pCallback) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600595 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
596 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700597 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600598 intercept->PreCallValidateCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
599 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600600 """ + precallrecord_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->PreCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
603 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700604 VkResult result = DispatchCreateDebugReportCallbackEXT(layer_data, instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600605 result = layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);
606 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700607 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600608 intercept->PostCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
609 }
610 return result;
611}
612
613VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
614 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600615 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
616 """ + precallvalidate_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700617 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600618 intercept->PreCallValidateDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
619 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600620 """ + precallrecord_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->PreCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
623 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700624 DispatchDestroyDebugReportCallbackEXT(layer_data, instance, callback, pAllocator);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600625 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
626 """ + postcallrecord_loop + """
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700627 std::lock_guard<std::mutex> lock(intercept->layer_mutex);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600628 intercept->PostCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
629 }
630}
631"""
632
633 inline_custom_source_postamble = """
634// loader-layer interface v0, just wrappers since there is only a layer
635
636VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
637 VkExtensionProperties *pProperties) {
638 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
639}
640
641VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
642 VkLayerProperties *pProperties) {
643 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
644}
645
646VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
647 VkLayerProperties *pProperties) {
648 // the layer command handles VK_NULL_HANDLE just fine internally
649 assert(physicalDevice == VK_NULL_HANDLE);
650 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
651}
652
653VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
654 const char *pLayerName, uint32_t *pCount,
655 VkExtensionProperties *pProperties) {
656 // the layer command handles VK_NULL_HANDLE just fine internally
657 assert(physicalDevice == VK_NULL_HANDLE);
658 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
659}
660
661VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
662 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
663}
664
665VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
666 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
667}
668
669VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
670 const char *funcName) {
671 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
672}
673
674VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
675 assert(pVersionStruct != NULL);
676 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
677
678 // Fill in the function pointers if our version is at least capable of having the structure contain them.
679 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
680 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
681 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
682 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
683 }
684
685 return VK_SUCCESS;
686}"""
687
688
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600689 def __init__(self,
690 errFile = sys.stderr,
691 warnFile = sys.stderr,
692 diagFile = sys.stdout):
693 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
694 # Internal state - accumulators for different inner block text
695 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
696 self.intercepts = []
697 self.layer_factory = '' # String containing base layer factory class definition
698
699 # Check if the parameter passed in is a pointer to an array
700 def paramIsArray(self, param):
701 return param.attrib.get('len') is not None
702
703 # Check if the parameter passed in is a pointer
704 def paramIsPointer(self, param):
705 ispointer = False
706 for elem in param:
707 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
708 ispointer = True
709 return ispointer
710
711 # Check if an object is a non-dispatchable handle
712 def isHandleTypeNonDispatchable(self, handletype):
713 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
714 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
715 return True
716 else:
717 return False
718
719 # Check if an object is a dispatchable handle
720 def isHandleTypeDispatchable(self, handletype):
721 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
722 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
723 return True
724 else:
725 return False
726
727 def beginFile(self, genOpts):
728 OutputGenerator.beginFile(self, genOpts)
729 # Multiple inclusion protection & C++ namespace.
730 self.header = False
731 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
732 self.header = True
733 write('#pragma once', file=self.outFile)
734 self.newline()
735 # User-supplied prefix text, if any (list of strings)
736 if self.header:
737 if (genOpts.prefixText):
738 for s in genOpts.prefixText:
739 write(s, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700740 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600741 else:
742 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700743 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600744
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600745 #
746 def endFile(self):
747 # Finish C++ namespace and multiple inclusion protection
748 self.newline()
749 if not self.header:
750 # Record intercepted procedures
751 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
752 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
753 write('\n'.join(self.intercepts), file=self.outFile)
754 write('};\n', file=self.outFile)
755 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600756 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600757 if self.header:
758 self.newline()
759 # Output Layer Factory Class Definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600760 self.layer_factory += '};\n\n'
761 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600762 write(self.layer_factory, file=self.outFile)
763 else:
764 write(self.inline_custom_source_postamble, file=self.outFile)
765 # Finish processing in superclass
766 OutputGenerator.endFile(self)
767
768 def beginFeature(self, interface, emit):
769 # Start processing in superclass
770 OutputGenerator.beginFeature(self, interface, emit)
771 # Get feature extra protect
772 self.featureExtraProtect = GetFeatureProtect(interface)
773 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
774 # feature. They're only printed in endFeature().
775 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
776
777 def endFeature(self):
778 # Actually write the interface to the output file.
779 if (self.emit):
780 self.newline()
781 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
782 # or move it below the 'for section...' loop.
783 if (self.featureExtraProtect != None):
784 write('#ifdef', self.featureExtraProtect, file=self.outFile)
785 for section in self.TYPE_SECTIONS:
786 contents = self.sections[section]
787 if contents:
788 write('\n'.join(contents), file=self.outFile)
789 self.newline()
790 if (self.sections['command']):
791 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
792 self.newline()
793 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600794 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600795 # Finish processing in superclass
796 OutputGenerator.endFeature(self)
797 #
798 # Append a definition to the specified section
799 def appendSection(self, section, text):
800 self.sections[section].append(text)
801 #
802 # Type generation
803 def genType(self, typeinfo, name, alias):
804 pass
805 #
806 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
807 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
808 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
809 # structs etc.)
810 def genStruct(self, typeinfo, typeName):
811 OutputGenerator.genStruct(self, typeinfo, typeName)
812 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
813 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
814 for member in typeinfo.elem.findall('.//member'):
815 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
816 body += ';\n'
817 body += '} ' + typeName + ';\n'
818 self.appendSection('struct', body)
819 #
820 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
821 def genGroup(self, groupinfo, groupName, alias):
822 pass
823 # Enumerant generation
824 # <enum> tags may specify their values in several ways, but are usually just integers.
825 def genEnum(self, enuminfo, name, alias):
826 pass
827 #
828 # Customize Cdecl for layer factory base class
829 def BaseClassCdecl(self, elem, name):
830 raw = self.makeCDecls(elem)[1]
831
832 # Toss everything before the undecorated name
833 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
834 prototype = prototype.replace(")", "", 1)
835 prototype = prototype.replace(";", " {};")
836
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600837 # Build up pre/post call virtual function declarations
838 pre_call_validate = 'virtual bool PreCallValidate' + prototype
839 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
840 pre_call_record = 'virtual void PreCallRecord' + prototype
841 post_call_record = 'virtual void PostCallRecord' + prototype
842 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
843 #
844 # Command generation
845 def genCmd(self, cmdinfo, name, alias):
846 ignore_functions = [
847 'vkEnumerateInstanceVersion'
848 ]
849
850 if name in ignore_functions:
851 return
852
853 if self.header: # In the header declare all intercepts
854 self.appendSection('command', '')
855 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
856 if (self.featureExtraProtect != None):
857 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
858 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
859 # Update base class with virtual function declarations
860 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
861 # Update function intercepts
862 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
863 if (self.featureExtraProtect != None):
864 self.intercepts += [ '#endif' ]
865 self.layer_factory += '#endif\n'
866 return
867
868 manual_functions = [
869 # Include functions here to be interecpted w/ manually implemented function bodies
870 'vkGetDeviceProcAddr',
871 'vkGetInstanceProcAddr',
872 'vkGetPhysicalDeviceProcAddr',
873 'vkCreateDevice',
874 'vkDestroyDevice',
875 'vkCreateInstance',
876 'vkDestroyInstance',
877 'vkCreateDebugReportCallbackEXT',
878 'vkDestroyDebugReportCallbackEXT',
879 'vkEnumerateInstanceLayerProperties',
880 'vkEnumerateInstanceExtensionProperties',
881 'vkEnumerateDeviceLayerProperties',
882 'vkEnumerateDeviceExtensionProperties',
883 ]
884 if name in manual_functions:
885 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
886 return
887 # Record that the function will be intercepted
888 if (self.featureExtraProtect != None):
889 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
890 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
891 if (self.featureExtraProtect != None):
892 self.intercepts += [ '#endif' ]
893 OutputGenerator.genCmd(self, cmdinfo, name, alias)
894 #
895 decls = self.makeCDecls(cmdinfo.elem)
896 self.appendSection('command', '')
897 self.appendSection('command', '%s {' % decls[0][:-1])
898 # Setup common to call wrappers. First parameter is always dispatchable
899 dispatchable_type = cmdinfo.elem.find('param/type').text
900 dispatchable_name = cmdinfo.elem.find('param/name').text
901 # Default to device
902 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600903 dispatch_table_name = 'VkLayerDispatchTable'
904 # Set to instance as necessary
905 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
906 device_or_instance = 'instance'
907 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600908 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600909 api_function_name = cmdinfo.elem.attrib.get('name')
910 params = cmdinfo.elem.findall('param/name')
911 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700912 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600913
914 # Declare result variable, if any.
915 return_map = {
916 'void': 'return;',
917 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
918 'PFN_vkVoidFunction': 'return nullptr;',
919 'VkBool32': 'return VK_FALSE;',
920 }
921 resulttype = cmdinfo.elem.find('proto/type')
922 assignresult = ''
923 if (resulttype.text != 'void'):
924 assignresult = resulttype.text + ' result = '
925
926 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700927 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600928
929 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600930 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700931 self.appendSection('command', ' std::lock_guard<std::mutex> lock(intercept->layer_mutex);')
932 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
933 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
934 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600935
936 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600937 self.appendSection('command', ' %s' % self.precallrecord_loop)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700938 self.appendSection('command', ' std::lock_guard<std::mutex> lock(intercept->layer_mutex);')
939 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600940 self.appendSection('command', ' }')
941
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700942 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600943
944 # Generate post-call object processing source code
Mark Lobodzinskib3c94842018-11-27 10:01:51 -0700945 alt_ret_codes = [
946 # Include functions here which must tolerate VK_INCOMPLETE as a return code
947 'vkEnumeratePhysicalDevices',
948 'vkEnumeratePhysicalDeviceGroupsKHR',
949 'vkGetValidationCacheDataEXT',
950 'vkGetPipelineCacheData',
951 'vkGetShaderInfoAMD',
952 'vkGetPhysicalDeviceDisplayPropertiesKHR',
953 'vkGetPhysicalDeviceDisplayProperties2KHR',
954 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
955 'vkGetDisplayPlaneSupportedDisplaysKHR',
956 'vkGetDisplayModePropertiesKHR',
957 'vkGetDisplayModeProperties2KHR',
958 'vkGetPhysicalDeviceSurfaceFormatsKHR',
959 'vkGetPhysicalDeviceSurfacePresentModesKHR',
960 'vkGetPhysicalDevicePresentRectanglesKHR',
961 'vkGetPastPresentationTimingGOOGLE',
962 'vkGetSwapchainImagesKHR',
963 'vkEnumerateInstanceLayerProperties',
964 'vkEnumerateDeviceLayerProperties',
965 'vkEnumerateInstanceExtensionProperties',
966 'vkEnumerateDeviceExtensionProperties',
967 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
968 ]
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700969 return_type_indent = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600970 if (resulttype.text == 'VkResult'):
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700971 return_type_indent = ' '
Mark Lobodzinskib3c94842018-11-27 10:01:51 -0700972 if name in alt_ret_codes:
973 self.appendSection('command', ' if ((VK_SUCCESS == result) || (VK_INCOMPLETE == result)) {')
974 else:
975 self.appendSection('command', ' if (VK_SUCCESS == result) {')
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600976
977 self.appendSection('command', '%s %s' % (return_type_indent, self.postcallrecord_loop))
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -0700978 self.appendSection('command', '%s std::lock_guard<std::mutex> lock(intercept->layer_mutex);' % return_type_indent)
979 self.appendSection('command', '%s intercept->PostCallRecord%s(%s);' % (return_type_indent,api_function_name[2:], paramstext))
980 self.appendSection('command', '%s }' % return_type_indent)
981 if (resulttype.text == 'VkResult'):
982 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600983
984 # Return result variable, if any.
985 if (resulttype.text != 'void'):
986 self.appendSection('command', ' return result;')
987 self.appendSection('command', '}')
988 #
989 # Override makeProtoName to drop the "vk" prefix
990 def makeProtoName(self, name, tail):
991 return self.genOpts.apientry + name[2:] + tail