blob: 8f31fe3ae8952b9f967e83ab7f5f70d7af0f50a9 [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
3# Copyright (c) 2015-2016 Valve Corporation
4# Copyright (c) 2015-2016 LunarG, Inc.
5# Copyright (c) 2015-2016 Google Inc.
6#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
20# Author: Mark Lobodzinski <mark@lunarg.com>
21#
22# This script generates the dispatch portion of a factory layer which intercepts
23# all Vulkan functions. The resultant factory layer allows rapid development of
24# layers and interceptors.
25
26import os,re,sys
27from generator import *
28from common_codegen import *
29
30# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31#
32# Adds options used by LayerFactoryOutputGenerator objects during factory
33# layer generation.
34#
35# Additional members
36# prefixText - list of strings to prefix generated header with
37# (usually a copyright statement + calling convention macros).
38# protectFile - True if multiple inclusion protection should be
39# generated (based on the filename) around the entire header.
40# protectFeature - True if #ifndef..#endif protection should be
41# generated around a feature interface in the header file.
42# genFuncPointers - True if function pointer typedefs should be
43# generated
44# protectProto - If conditional protection should be generated
45# around prototype declarations, set to either '#ifdef'
46# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47# to require opt-out (#ifndef protectProtoStr). Otherwise
48# set to None.
49# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50# declarations, if protectProto is set
51# apicall - string to use for the function declaration prefix,
52# such as APICALL on Windows.
53# apientry - string to use for the calling convention macro,
54# in typedefs, such as APIENTRY.
55# apientryp - string to use for the calling convention macro
56# in function pointer typedefs, such as APIENTRYP.
57# indentFuncProto - True if prototype declarations should put each
58# parameter on a separate line
59# indentFuncPointer - True if typedefed function pointers should put each
60# parameter on a separate line
61# alignFuncParam - if nonzero and parameters are being put on a
62# separate line, align parameter names at the specified column
63class LayerChassisGeneratorOptions(GeneratorOptions):
64 def __init__(self,
65 filename = None,
66 directory = '.',
67 apiname = None,
68 profile = None,
69 versions = '.*',
70 emitversions = '.*',
71 defaultExtensions = None,
72 addExtensions = None,
73 removeExtensions = None,
74 emitExtensions = None,
75 sortProcedure = regSortFeatures,
76 prefixText = "",
77 genFuncPointers = True,
78 protectFile = True,
79 protectFeature = True,
80 apicall = '',
81 apientry = '',
82 apientryp = '',
83 indentFuncProto = True,
84 indentFuncPointer = False,
85 alignFuncParam = 0,
86 helper_file_type = '',
87 expandEnumerants = True):
88 GeneratorOptions.__init__(self, filename, directory, apiname, profile,
89 versions, emitversions, defaultExtensions,
90 addExtensions, removeExtensions, emitExtensions, sortProcedure)
91 self.prefixText = prefixText
92 self.genFuncPointers = genFuncPointers
93 self.protectFile = protectFile
94 self.protectFeature = protectFeature
95 self.apicall = apicall
96 self.apientry = apientry
97 self.apientryp = apientryp
98 self.indentFuncProto = indentFuncProto
99 self.indentFuncPointer = indentFuncPointer
100 self.alignFuncParam = alignFuncParam
101
102# LayerChassisOutputGenerator - subclass of OutputGenerator.
103# Generates a LayerFactory layer that intercepts all API entrypoints
104# This is intended to be used as a starting point for creating custom layers
105#
106# ---- methods ----
107# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
108# OutputGenerator. Defines additional internal state.
109# ---- methods overriding base class ----
110# beginFile(genOpts)
111# endFile()
112# beginFeature(interface, emit)
113# endFeature()
114# genType(typeinfo,name)
115# genStruct(typeinfo,name)
116# genGroup(groupinfo,name)
117# genEnum(enuminfo, name)
118# genCmd(cmdinfo)
119class LayerChassisOutputGenerator(OutputGenerator):
120 """Generate specified API interfaces in a specific style, such as a C header"""
121 # This is an ordered list of sections in the header file.
122 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
123 'group', 'bitmask', 'funcpointer', 'struct']
124 ALL_SECTIONS = TYPE_SECTIONS + ['command']
125
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700126 manual_functions = [
127 # Include functions here to be interecpted w/ manually implemented function bodies
128 'vkGetDeviceProcAddr',
129 'vkGetInstanceProcAddr',
130 'vkGetPhysicalDeviceProcAddr',
131 'vkCreateDevice',
132 'vkDestroyDevice',
133 'vkCreateInstance',
134 'vkDestroyInstance',
135 'vkCreateDebugReportCallbackEXT',
136 'vkDestroyDebugReportCallbackEXT',
137 'vkEnumerateInstanceLayerProperties',
138 'vkEnumerateInstanceExtensionProperties',
139 'vkEnumerateDeviceLayerProperties',
140 'vkEnumerateDeviceExtensionProperties',
141 ]
142
143 alt_ret_codes = [
144 # Include functions here which must tolerate VK_INCOMPLETE as a return code
145 'vkEnumeratePhysicalDevices',
146 'vkEnumeratePhysicalDeviceGroupsKHR',
147 'vkGetValidationCacheDataEXT',
148 'vkGetPipelineCacheData',
149 'vkGetShaderInfoAMD',
150 'vkGetPhysicalDeviceDisplayPropertiesKHR',
151 'vkGetPhysicalDeviceDisplayProperties2KHR',
152 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
153 'vkGetDisplayPlaneSupportedDisplaysKHR',
154 'vkGetDisplayModePropertiesKHR',
155 'vkGetDisplayModeProperties2KHR',
156 'vkGetPhysicalDeviceSurfaceFormatsKHR',
157 'vkGetPhysicalDeviceSurfacePresentModesKHR',
158 'vkGetPhysicalDevicePresentRectanglesKHR',
159 'vkGetPastPresentationTimingGOOGLE',
160 'vkGetSwapchainImagesKHR',
161 'vkEnumerateInstanceLayerProperties',
162 'vkEnumerateDeviceLayerProperties',
163 'vkEnumerateInstanceExtensionProperties',
164 'vkEnumerateDeviceExtensionProperties',
165 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
166 ]
167
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700168 pre_dispatch_debug_utils_functions = {
169 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->debugUtilsObjectNameMap->insert(std::make_pair<uint64_t, std::string>((uint64_t &&) pNameInfo->objectHandle, pNameInfo->pObjectName));',
170 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
171 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
172 'vkCmdBeginDebugUtilsLabelEXT' : 'BeginCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
173 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
174 }
175
176 post_dispatch_debug_utils_functions = {
177 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
178 'vkCmdEndDebugUtilsLabelEXT' : 'EndCmdDebugUtilsLabel(layer_data->report_data, commandBuffer);',
179 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
180 }
181
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600182 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
183 precallrecord_loop = precallvalidate_loop
184 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600185
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700186 inline_custom_header_preamble = """
187#define NOMINMAX
188#include <mutex>
189#include <cinttypes>
190#include <stdio.h>
191#include <stdlib.h>
192#include <string.h>
193#include <unordered_map>
194#include <unordered_set>
195#include <algorithm>
196#include <memory>
197
198#include "vk_loader_platform.h"
199#include "vulkan/vulkan.h"
200#include "vk_layer_config.h"
201#include "vk_layer_data.h"
202#include "vk_layer_logging.h"
203#include "vk_object_types.h"
204#include "vulkan/vk_layer.h"
205#include "vk_enum_string_helper.h"
206#include "vk_layer_extension_utils.h"
207#include "vk_layer_utils.h"
208#include "vulkan/vk_layer.h"
209#include "vk_dispatch_table_helper.h"
210#include "vk_validation_error_messages.h"
211#include "vk_extension_helper.h"
212#include "vk_safe_struct.h"
213
214extern uint64_t global_unique_id;
215extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
216"""
217
218 inline_custom_header_class_definition = """
219
220// Layer object type identifiers
221enum LayerObjectTypeId {
222 LayerObjectTypeThreading,
223 LayerObjectTypeParameterValidation,
224 LayerObjectTypeObjectTracker,
225 LayerObjectTypeCoreValidation,
226};
227
228struct TEMPLATE_STATE {
229 VkDescriptorUpdateTemplateKHR desc_update_template;
230 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
231
232 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
233 : desc_update_template(update_template), create_info(*pCreateInfo) {}
234};
235
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700236class LAYER_PHYS_DEV_PROPERTIES {
237public:
238 VkPhysicalDeviceProperties properties;
239 std::vector<VkQueueFamilyProperties> queue_family_properties;
240};
241
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700242// Layer chassis validation object base class definition
243class ValidationObject {
244 public:
245 uint32_t api_version;
246 debug_report_data* report_data = nullptr;
247 std::vector<VkDebugReportCallbackEXT> logging_callback;
248 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
249
250 VkLayerInstanceDispatchTable instance_dispatch_table;
251 VkLayerDispatchTable device_dispatch_table;
252
253 InstanceExtensions instance_extensions;
254 DeviceExtensions device_extensions = {};
255
256 VkInstance instance = VK_NULL_HANDLE;
257 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
258 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700259 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700260
261 std::vector<ValidationObject*> object_dispatch;
262 LayerObjectTypeId container_type;
263
264 // Constructor
265 ValidationObject(){};
266 // Destructor
267 virtual ~ValidationObject() {};
268
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700269 std::mutex validation_object_mutex;
270 virtual void write_lock() { validation_object_mutex.lock(); }
271 virtual void write_unlock() { validation_object_mutex.unlock(); }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700272
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700273 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
274 for (auto validation_object : object_dispatch) {
275 if (validation_object->container_type == object_type) {
276 return validation_object;
277 }
278 }
279 return nullptr;
280 };
281
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700282 std::string layer_name = "CHASSIS";
283
284 // Handle Wrapping Data
285 // Reverse map display handles
286 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
287 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700288 struct SubpassesUsageStates {
289 std::unordered_set<uint32_t> subpasses_using_color_attachment;
290 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
291 };
292 // Uses unwrapped handles
293 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
294 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
295 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
296 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700297 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
298 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700299
300
301 // Unwrap a handle. Must hold lock.
302 template <typename HandleType>
303 HandleType Unwrap(HandleType wrappedHandle) {
304 // TODO: don't use operator[] here.
305 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
306 }
307
308 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
309 template <typename HandleType>
310 HandleType WrapNew(HandleType newlyCreatedHandle) {
311 auto unique_id = global_unique_id++;
312 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
313 return (HandleType)unique_id;
314 }
315
316 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
317 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
318 auto unique_id = global_unique_id++;
319 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
320 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
321 return (VkDisplayKHR)unique_id;
322 }
323
324 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
325 // creating another. Must hold lock.
326 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
327 // See if this display is already known
328 auto it = map_data->display_id_reverse_mapping.find(handle);
329 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
330 // Unknown, so wrap
331 return WrapDisplay(handle, map_data);
332 }
333
334 // Pre/post hook point declarations
335"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600336
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700337 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600338// This file is ***GENERATED***. Do Not Edit.
339// See layer_chassis_generator.py for modifications.
340
341/* Copyright (c) 2015-2018 The Khronos Group Inc.
342 * Copyright (c) 2015-2018 Valve Corporation
343 * Copyright (c) 2015-2018 LunarG, Inc.
344 * Copyright (c) 2015-2018 Google Inc.
345 *
346 * Licensed under the Apache License, Version 2.0 (the "License");
347 * you may not use this file except in compliance with the License.
348 * You may obtain a copy of the License at
349 *
350 * http://www.apache.org/licenses/LICENSE-2.0
351 *
352 * Unless required by applicable law or agreed to in writing, software
353 * distributed under the License is distributed on an "AS IS" BASIS,
354 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
355 * See the License for the specific language governing permissions and
356 * limitations under the License.
357 *
358 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700359 */"""
360
361 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600362
363#include <string.h>
364#include <mutex>
365
366#define VALIDATION_ERROR_MAP_IMPL
367
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600368#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700369#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600370
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600371std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600372
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700373// Global unique object identifier. All increments must be guarded by a lock.
374uint64_t global_unique_id = 1;
375// Map uniqueID to actual object handle
376std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
377
378// TODO: This variable controls handle wrapping -- in the future it should be hooked
379// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
380#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
381bool wrap_handles = true;
382#else
383const bool wrap_handles = false;
384#endif
385
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600386// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700387#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600388#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700389#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700390#elif BUILD_THREAD_SAFETY
Mark Lobodzinski706e52b2018-12-11 13:21:52 -0700391#include "thread_safety.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700392#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
393#elif BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700394#include "stateless_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700395#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
396#elif BUILD_CORE_VALIDATION
397#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
398#else
399#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
400#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600401
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600402namespace vulkan_layer_chassis {
403
404using std::unordered_map;
405
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600406static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700407 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600408};
409
410static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
411
412extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
413
414
415// Manually written functions
416
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700417// Check enabled instance extensions against supported instance extension whitelist
418static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
419 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
420 // Check for recognized instance extensions
421 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
422 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
423 kVUIDUndefined,
424 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
425 "results and/or produce undefined behavior.",
426 pCreateInfo->ppEnabledExtensionNames[i]);
427 }
428 }
429}
430
431// Check enabled device extensions against supported device extension whitelist
432static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
433 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
434 // Check for recognized device extensions
435 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
436 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
437 kVUIDUndefined,
438 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
439 "results and/or produce undefined behavior.",
440 pCreateInfo->ppEnabledExtensionNames[i]);
441 }
442 }
443}
444
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600445VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600446 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700447 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700448 return nullptr;
449 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600450 const auto &item = name_to_funcptr_map.find(funcName);
451 if (item != name_to_funcptr_map.end()) {
452 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
453 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600454 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600455 if (!table.GetDeviceProcAddr) return nullptr;
456 return table.GetDeviceProcAddr(device, funcName);
457}
458
459VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600460 const auto &item = name_to_funcptr_map.find(funcName);
461 if (item != name_to_funcptr_map.end()) {
462 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
463 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600464 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
465 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600466 if (!table.GetInstanceProcAddr) return nullptr;
467 return table.GetInstanceProcAddr(instance, funcName);
468}
469
470VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600471 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
472 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600473 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
474 return table.GetPhysicalDeviceProcAddr(instance, funcName);
475}
476
477VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
478 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
479}
480
481VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
482 VkLayerProperties *pProperties) {
483 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
484}
485
486VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
487 VkExtensionProperties *pProperties) {
488 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
489 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
490
491 return VK_ERROR_LAYER_NOT_PRESENT;
492}
493
494VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
495 uint32_t *pCount, VkExtensionProperties *pProperties) {
496 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600497 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600498 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
499 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600500}
501
502VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
503 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600504 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600505
506 assert(chain_info->u.pLayerInfo);
507 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
508 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
509 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
510 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
511
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600512 // Create temporary dispatch vector for pre-calls until instance is created
513 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700514#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600515 auto object_tracker = new ObjectLifetimes;
516 local_object_dispatch.emplace_back(object_tracker);
517 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700518#elif BUILD_THREAD_SAFETY
519 auto thread_checker = new ThreadSafety;
520 local_object_dispatch.emplace_back(thread_checker);
521 thread_checker->container_type = LayerObjectTypeThreading;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700522#elif BUILD_PARAMETER_VALIDATION
523 auto parameter_validation = new StatelessValidation;
524 local_object_dispatch.emplace_back(parameter_validation);
525 parameter_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700526#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600527
528
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600529 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600530 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600531 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
532 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600533 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600534 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
535 }
536
537 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600538 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600539
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600540 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600541
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600542 framework->object_dispatch = local_object_dispatch;
543
544 framework->instance = *pInstance;
545 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
546 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
547 pCreateInfo->ppEnabledExtensionNames);
548 framework->api_version = framework->instance_extensions.InitFromInstanceCreateInfo(
549 (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0), pCreateInfo);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700550#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600551 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700552 object_tracker->report_data = framework->report_data;
553 object_tracker->api_version = framework->api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700554#elif BUILD_THREAD_SAFETY
555 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "google_thread_checker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700556 thread_checker->report_data = framework->report_data;
557 thread_checker->api_version = framework->api_version;
558#elif BUILD_PARAMETER_VALIDATION
559 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_parameter_validation");
560 parameter_validation->report_data = framework->report_data;
561 parameter_validation->api_version = framework->api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700562#else
563 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
564#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600565
566 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600567 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
568 }
569
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700570 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
571
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600572 return result;
573}
574
575VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
576 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600577 auto layer_data = GetLayerDataPtr(key, layer_data_map);
578 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700579 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600580 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700581 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600582 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600583 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700584 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600585 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700586 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600587 }
588
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600589 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600590
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600591 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700592 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600593 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700594 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600595 }
596 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600597 while (layer_data->logging_messenger.size() > 0) {
598 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
599 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
600 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600601 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600602 while (layer_data->logging_callback.size() > 0) {
603 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
604 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
605 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600606 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600607
608 layer_debug_utils_destroy_instance(layer_data->report_data);
609
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700610 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
611 delete *item;
612 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600613 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600614}
615
616VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
617 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600618 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600619
620 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
621
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600622 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
623 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600624 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
625 if (fpCreateDevice == NULL) {
626 return VK_ERROR_INITIALIZATION_FAILED;
627 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600628 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
629
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700630 // Get physical device limits for device
631 VkPhysicalDeviceProperties device_properties = {};
632 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
633
634 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
635 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
636
637 DeviceExtensions device_extensions = {};
638 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
639 for (auto item : instance_interceptor->object_dispatch) {
640 item->device_extensions = device_extensions;
641 }
642
643 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600644 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700645 intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700646 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700647 intercept->write_unlock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700648 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600649 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600650 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700651 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600652 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700653 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600654 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600655
656 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600657 if (result != VK_SUCCESS) {
658 return result;
659 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600660
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600661 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700662
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700663 // Save local info in device object
664 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700665 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
666 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700667 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700668
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600669 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700670
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600671 device_interceptor->device = *pDevice;
672 device_interceptor->physical_device = gpu;
673 device_interceptor->instance = instance_interceptor->instance;
674 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600675
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700676#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600677 // Create child layer objects for this key and add to dispatch vector
678 auto object_tracker = new ObjectLifetimes;
679 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
680 object_tracker->container_type = LayerObjectTypeObjectTracker;
681 object_tracker->physical_device = gpu;
682 object_tracker->instance = instance_interceptor->instance;
683 object_tracker->report_data = device_interceptor->report_data;
684 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700685 object_tracker->api_version = device_interceptor->api_version;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600686 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700687#elif BUILD_THREAD_SAFETY
688 auto thread_safety = new ThreadSafety;
689 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
690 thread_safety->container_type = LayerObjectTypeThreading;
691 thread_safety->physical_device = gpu;
692 thread_safety->instance = instance_interceptor->instance;
693 thread_safety->report_data = device_interceptor->report_data;
694 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700695 thread_safety->api_version = device_interceptor->api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700696 device_interceptor->object_dispatch.emplace_back(thread_safety);
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700697#elif BUILD_PARAMETER_VALIDATION
698 auto stateless_validation = new StatelessValidation;
699 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
700 stateless_validation->container_type = LayerObjectTypeParameterValidation;
701 stateless_validation->physical_device = gpu;
702 stateless_validation->instance = instance_interceptor->instance;
703 stateless_validation->report_data = device_interceptor->report_data;
704 stateless_validation->device_dispatch_table = device_interceptor->device_dispatch_table;
705 stateless_validation->api_version = device_interceptor->api_version;
706 device_interceptor->object_dispatch.emplace_back(stateless_validation);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700707#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600708
709 for (auto intercept : instance_interceptor->object_dispatch) {
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700710 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600711 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700712 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600713 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600714
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700715 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
716
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600717 return result;
718}
719
720VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
721 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600722 auto layer_data = GetLayerDataPtr(key, layer_data_map);
723 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700724 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600725 intercept->PreCallValidateDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700726 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600727 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600728 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700729 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600730 intercept->PreCallRecordDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700731 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600732 }
733 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600734
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600735 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600736
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600737 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700738 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600739 intercept->PostCallRecordDestroyDevice(device, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700740 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600741 }
742
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700743 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
744 delete *item;
745 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600746 FreeLayerDataPtr(key, layer_data_map);
747}
748
749VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
750 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
751 const VkAllocationCallbacks *pAllocator,
752 VkDebugReportCallbackEXT *pCallback) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600753 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
754 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700755 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600756 intercept->PreCallValidateCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700757 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600758 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600759 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700760 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600761 intercept->PreCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700762 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600763 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700764 VkResult result = DispatchCreateDebugReportCallbackEXT(layer_data, instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600765 result = layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);
766 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700767 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600768 intercept->PostCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700769 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600770 }
771 return result;
772}
773
774VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
775 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600776 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
777 """ + precallvalidate_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700778 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600779 intercept->PreCallValidateDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700780 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600781 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600782 """ + precallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700783 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600784 intercept->PreCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700785 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600786 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700787 DispatchDestroyDebugReportCallbackEXT(layer_data, instance, callback, pAllocator);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600788 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
789 """ + postcallrecord_loop + """
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700790 intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600791 intercept->PostCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700792 intercept->write_unlock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600793 }
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700794}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600795
796 inline_custom_source_postamble = """
797// loader-layer interface v0, just wrappers since there is only a layer
798
799VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
800 VkExtensionProperties *pProperties) {
801 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
802}
803
804VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
805 VkLayerProperties *pProperties) {
806 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
807}
808
809VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
810 VkLayerProperties *pProperties) {
811 // the layer command handles VK_NULL_HANDLE just fine internally
812 assert(physicalDevice == VK_NULL_HANDLE);
813 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
814}
815
816VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
817 const char *pLayerName, uint32_t *pCount,
818 VkExtensionProperties *pProperties) {
819 // the layer command handles VK_NULL_HANDLE just fine internally
820 assert(physicalDevice == VK_NULL_HANDLE);
821 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
822}
823
824VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
825 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
826}
827
828VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
829 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
830}
831
832VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
833 const char *funcName) {
834 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
835}
836
837VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
838 assert(pVersionStruct != NULL);
839 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
840
841 // Fill in the function pointers if our version is at least capable of having the structure contain them.
842 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
843 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
844 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
845 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
846 }
847
848 return VK_SUCCESS;
849}"""
850
851
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600852 def __init__(self,
853 errFile = sys.stderr,
854 warnFile = sys.stderr,
855 diagFile = sys.stdout):
856 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
857 # Internal state - accumulators for different inner block text
858 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
859 self.intercepts = []
860 self.layer_factory = '' # String containing base layer factory class definition
861
862 # Check if the parameter passed in is a pointer to an array
863 def paramIsArray(self, param):
864 return param.attrib.get('len') is not None
865
866 # Check if the parameter passed in is a pointer
867 def paramIsPointer(self, param):
868 ispointer = False
869 for elem in param:
870 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
871 ispointer = True
872 return ispointer
873
874 # Check if an object is a non-dispatchable handle
875 def isHandleTypeNonDispatchable(self, handletype):
876 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
877 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
878 return True
879 else:
880 return False
881
882 # Check if an object is a dispatchable handle
883 def isHandleTypeDispatchable(self, handletype):
884 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
885 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
886 return True
887 else:
888 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700889 #
890 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600891 def beginFile(self, genOpts):
892 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700893 # Output Copyright
894 write(self.inline_copyright_message, file=self.outFile)
895 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600896 self.header = False
897 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
898 self.header = True
899 write('#pragma once', file=self.outFile)
900 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600901 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700902 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600903 else:
904 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700905 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700906 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600907 #
908 def endFile(self):
909 # Finish C++ namespace and multiple inclusion protection
910 self.newline()
911 if not self.header:
912 # Record intercepted procedures
913 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
914 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
915 write('\n'.join(self.intercepts), file=self.outFile)
916 write('};\n', file=self.outFile)
917 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600918 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600919 if self.header:
920 self.newline()
921 # Output Layer Factory Class Definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600922 self.layer_factory += '};\n\n'
923 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600924 write(self.layer_factory, file=self.outFile)
925 else:
926 write(self.inline_custom_source_postamble, file=self.outFile)
927 # Finish processing in superclass
928 OutputGenerator.endFile(self)
929
930 def beginFeature(self, interface, emit):
931 # Start processing in superclass
932 OutputGenerator.beginFeature(self, interface, emit)
933 # Get feature extra protect
934 self.featureExtraProtect = GetFeatureProtect(interface)
935 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
936 # feature. They're only printed in endFeature().
937 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
938
939 def endFeature(self):
940 # Actually write the interface to the output file.
941 if (self.emit):
942 self.newline()
943 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
944 # or move it below the 'for section...' loop.
945 if (self.featureExtraProtect != None):
946 write('#ifdef', self.featureExtraProtect, file=self.outFile)
947 for section in self.TYPE_SECTIONS:
948 contents = self.sections[section]
949 if contents:
950 write('\n'.join(contents), file=self.outFile)
951 self.newline()
952 if (self.sections['command']):
953 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
954 self.newline()
955 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600956 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600957 # Finish processing in superclass
958 OutputGenerator.endFeature(self)
959 #
960 # Append a definition to the specified section
961 def appendSection(self, section, text):
962 self.sections[section].append(text)
963 #
964 # Type generation
965 def genType(self, typeinfo, name, alias):
966 pass
967 #
968 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
969 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
970 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
971 # structs etc.)
972 def genStruct(self, typeinfo, typeName):
973 OutputGenerator.genStruct(self, typeinfo, typeName)
974 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
975 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
976 for member in typeinfo.elem.findall('.//member'):
977 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
978 body += ';\n'
979 body += '} ' + typeName + ';\n'
980 self.appendSection('struct', body)
981 #
982 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
983 def genGroup(self, groupinfo, groupName, alias):
984 pass
985 # Enumerant generation
986 # <enum> tags may specify their values in several ways, but are usually just integers.
987 def genEnum(self, enuminfo, name, alias):
988 pass
989 #
990 # Customize Cdecl for layer factory base class
991 def BaseClassCdecl(self, elem, name):
992 raw = self.makeCDecls(elem)[1]
993
994 # Toss everything before the undecorated name
995 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
996 prototype = prototype.replace(")", "", 1)
997 prototype = prototype.replace(";", " {};")
998
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600999 # Build up pre/post call virtual function declarations
1000 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1001 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1002 pre_call_record = 'virtual void PreCallRecord' + prototype
1003 post_call_record = 'virtual void PostCallRecord' + prototype
1004 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1005 #
1006 # Command generation
1007 def genCmd(self, cmdinfo, name, alias):
1008 ignore_functions = [
1009 'vkEnumerateInstanceVersion'
1010 ]
1011
1012 if name in ignore_functions:
1013 return
1014
1015 if self.header: # In the header declare all intercepts
1016 self.appendSection('command', '')
1017 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1018 if (self.featureExtraProtect != None):
1019 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1020 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1021 # Update base class with virtual function declarations
1022 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
1023 # Update function intercepts
1024 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1025 if (self.featureExtraProtect != None):
1026 self.intercepts += [ '#endif' ]
1027 self.layer_factory += '#endif\n'
1028 return
1029
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001030 if name in self.manual_functions:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001031 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1032 return
1033 # Record that the function will be intercepted
1034 if (self.featureExtraProtect != None):
1035 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1036 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1037 if (self.featureExtraProtect != None):
1038 self.intercepts += [ '#endif' ]
1039 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1040 #
1041 decls = self.makeCDecls(cmdinfo.elem)
1042 self.appendSection('command', '')
1043 self.appendSection('command', '%s {' % decls[0][:-1])
1044 # Setup common to call wrappers. First parameter is always dispatchable
1045 dispatchable_type = cmdinfo.elem.find('param/type').text
1046 dispatchable_name = cmdinfo.elem.find('param/name').text
1047 # Default to device
1048 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001049 dispatch_table_name = 'VkLayerDispatchTable'
1050 # Set to instance as necessary
1051 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1052 device_or_instance = 'instance'
1053 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001054 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001055 api_function_name = cmdinfo.elem.attrib.get('name')
1056 params = cmdinfo.elem.findall('param/name')
1057 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001058 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001059
1060 # Declare result variable, if any.
1061 return_map = {
1062 'void': 'return;',
1063 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1064 'PFN_vkVoidFunction': 'return nullptr;',
1065 'VkBool32': 'return VK_FALSE;',
1066 }
1067 resulttype = cmdinfo.elem.find('proto/type')
1068 assignresult = ''
1069 if (resulttype.text != 'void'):
1070 assignresult = resulttype.text + ' result = '
1071
1072 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001073 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001074
1075 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001076 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001077 self.appendSection('command', ' intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001078 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001079 self.appendSection('command', ' intercept->write_unlock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001080 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1081 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001082
1083 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001084 self.appendSection('command', ' %s' % self.precallrecord_loop)
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001085 self.appendSection('command', ' intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001086 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001087 self.appendSection('command', ' intercept->write_unlock();')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001088 self.appendSection('command', ' }')
1089
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001090 # Insert pre-dispatch debug utils function call
1091 if name in self.pre_dispatch_debug_utils_functions:
1092 self.appendSection('command', ' {')
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001093 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->validation_object_mutex);')
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001094 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
1095 self.appendSection('command', ' }')
1096
1097 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001098 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001099
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001100 # Insert post-dispatch debug utils function call
1101 if name in self.post_dispatch_debug_utils_functions:
1102 self.appendSection('command', ' {')
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001103 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->validation_object_mutex);')
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001104 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
1105 self.appendSection('command', ' }')
1106
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001107 # Generate post-call object processing source code
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001108 return_type_indent = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001109 if (resulttype.text == 'VkResult'):
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001110 return_type_indent = ' '
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001111 if name in self.alt_ret_codes:
Mark Lobodzinskib3c94842018-11-27 10:01:51 -07001112 self.appendSection('command', ' if ((VK_SUCCESS == result) || (VK_INCOMPLETE == result)) {')
1113 else:
1114 self.appendSection('command', ' if (VK_SUCCESS == result) {')
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001115
1116 self.appendSection('command', '%s %s' % (return_type_indent, self.postcallrecord_loop))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001117 self.appendSection('command', '%s intercept->write_lock();' % return_type_indent)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001118 self.appendSection('command', '%s intercept->PostCallRecord%s(%s);' % (return_type_indent,api_function_name[2:], paramstext))
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001119 self.appendSection('command', '%s intercept->write_unlock();' % return_type_indent)
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001120 self.appendSection('command', '%s }' % return_type_indent)
1121 if (resulttype.text == 'VkResult'):
1122 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001123
1124 # Return result variable, if any.
1125 if (resulttype.text != 'void'):
1126 self.appendSection('command', ' return result;')
1127 self.appendSection('command', '}')
1128 #
1129 # Override makeProtoName to drop the "vk" prefix
1130 def makeProtoName(self, name, tail):
1131 return self.genOpts.apientry + name[2:] + tail