blob: 8bf1b10771b68b6b3a49cdf3d48f9125ce0fdc0b [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07003# Copyright (c) 2015-2019 Valve Corporation
4# Copyright (c) 2015-2019 LunarG, Inc.
5# Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06006#
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;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700270 virtual std::unique_lock<std::mutex> write_lock() {
271 return std::unique_lock<std::mutex>(validation_object_mutex);
272 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700273
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700274 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
275 for (auto validation_object : object_dispatch) {
276 if (validation_object->container_type == object_type) {
277 return validation_object;
278 }
279 }
280 return nullptr;
281 };
282
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700283 std::string layer_name = "CHASSIS";
284
285 // Handle Wrapping Data
286 // Reverse map display handles
287 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
288 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700289 struct SubpassesUsageStates {
290 std::unordered_set<uint32_t> subpasses_using_color_attachment;
291 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
292 };
293 // Uses unwrapped handles
294 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
295 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
296 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
297 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700298 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
299 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700300
301
302 // Unwrap a handle. Must hold lock.
303 template <typename HandleType>
304 HandleType Unwrap(HandleType wrappedHandle) {
305 // TODO: don't use operator[] here.
306 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
307 }
308
309 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
310 template <typename HandleType>
311 HandleType WrapNew(HandleType newlyCreatedHandle) {
312 auto unique_id = global_unique_id++;
313 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
314 return (HandleType)unique_id;
315 }
316
317 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
318 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
319 auto unique_id = global_unique_id++;
320 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
321 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
322 return (VkDisplayKHR)unique_id;
323 }
324
325 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
326 // creating another. Must hold lock.
327 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
328 // See if this display is already known
329 auto it = map_data->display_id_reverse_mapping.find(handle);
330 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
331 // Unknown, so wrap
332 return WrapDisplay(handle, map_data);
333 }
334
335 // Pre/post hook point declarations
336"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600337
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700338 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600339// This file is ***GENERATED***. Do Not Edit.
340// See layer_chassis_generator.py for modifications.
341
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700342/* Copyright (c) 2015-2019 The Khronos Group Inc.
343 * Copyright (c) 2015-2019 Valve Corporation
344 * Copyright (c) 2015-2019 LunarG, Inc.
345 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600346 *
347 * Licensed under the Apache License, Version 2.0 (the "License");
348 * you may not use this file except in compliance with the License.
349 * You may obtain a copy of the License at
350 *
351 * http://www.apache.org/licenses/LICENSE-2.0
352 *
353 * Unless required by applicable law or agreed to in writing, software
354 * distributed under the License is distributed on an "AS IS" BASIS,
355 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
356 * See the License for the specific language governing permissions and
357 * limitations under the License.
358 *
359 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700360 */"""
361
362 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600363
364#include <string.h>
365#include <mutex>
366
367#define VALIDATION_ERROR_MAP_IMPL
368
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600369#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700370#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600371
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600372std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600373
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700374// Global unique object identifier. All increments must be guarded by a lock.
375uint64_t global_unique_id = 1;
376// Map uniqueID to actual object handle
377std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
378
379// TODO: This variable controls handle wrapping -- in the future it should be hooked
380// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
381#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
382bool wrap_handles = true;
383#else
384const bool wrap_handles = false;
385#endif
386
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600387// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700388#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600389#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700390#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700391#elif BUILD_THREAD_SAFETY
Mark Lobodzinski706e52b2018-12-11 13:21:52 -0700392#include "thread_safety.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700393#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
394#elif BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700395#include "stateless_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700396#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
397#elif BUILD_CORE_VALIDATION
398#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
399#else
400#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
401#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600402
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600403namespace vulkan_layer_chassis {
404
405using std::unordered_map;
406
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600407static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700408 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600409};
410
411static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
412
413extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
414
415
416// Manually written functions
417
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700418// Check enabled instance extensions against supported instance extension whitelist
419static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
420 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
421 // Check for recognized instance extensions
422 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
423 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
424 kVUIDUndefined,
425 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
426 "results and/or produce undefined behavior.",
427 pCreateInfo->ppEnabledExtensionNames[i]);
428 }
429 }
430}
431
432// Check enabled device extensions against supported device extension whitelist
433static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
434 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
435 // Check for recognized device extensions
436 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
437 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
438 kVUIDUndefined,
439 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
440 "results and/or produce undefined behavior.",
441 pCreateInfo->ppEnabledExtensionNames[i]);
442 }
443 }
444}
445
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600446VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600447 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700448 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700449 return nullptr;
450 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600451 const auto &item = name_to_funcptr_map.find(funcName);
452 if (item != name_to_funcptr_map.end()) {
453 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
454 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600455 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600456 if (!table.GetDeviceProcAddr) return nullptr;
457 return table.GetDeviceProcAddr(device, funcName);
458}
459
460VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600461 const auto &item = name_to_funcptr_map.find(funcName);
462 if (item != name_to_funcptr_map.end()) {
463 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
464 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600465 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
466 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600467 if (!table.GetInstanceProcAddr) return nullptr;
468 return table.GetInstanceProcAddr(instance, funcName);
469}
470
471VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600472 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
473 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600474 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
475 return table.GetPhysicalDeviceProcAddr(instance, funcName);
476}
477
478VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
479 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
480}
481
482VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
483 VkLayerProperties *pProperties) {
484 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
485}
486
487VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
488 VkExtensionProperties *pProperties) {
489 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
490 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
491
492 return VK_ERROR_LAYER_NOT_PRESENT;
493}
494
495VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
496 uint32_t *pCount, VkExtensionProperties *pProperties) {
497 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600498 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600499 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
500 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600501}
502
503VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
504 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600505 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600506
507 assert(chain_info->u.pLayerInfo);
508 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
509 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
510 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
511 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700512 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
513 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
514
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600515
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600516 // Create temporary dispatch vector for pre-calls until instance is created
517 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700518#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600519 auto object_tracker = new ObjectLifetimes;
520 local_object_dispatch.emplace_back(object_tracker);
521 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700522 object_tracker->api_version = api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700523#elif BUILD_THREAD_SAFETY
524 auto thread_checker = new ThreadSafety;
525 local_object_dispatch.emplace_back(thread_checker);
526 thread_checker->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700527 thread_checker->api_version = api_version;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700528#elif BUILD_PARAMETER_VALIDATION
529 auto parameter_validation = new StatelessValidation;
530 local_object_dispatch.emplace_back(parameter_validation);
531 parameter_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700532 parameter_validation->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700533#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600534
535
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600536 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600537 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600538 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
539 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600540 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600541 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
542 }
543
544 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600545 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600546
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600547 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600548
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600549 framework->object_dispatch = local_object_dispatch;
550
551 framework->instance = *pInstance;
552 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
553 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
554 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700555 framework->api_version = api_version;
556 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
557
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700558#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600559 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700560 object_tracker->report_data = framework->report_data;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700561#elif BUILD_THREAD_SAFETY
562 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "google_thread_checker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700563 thread_checker->report_data = framework->report_data;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700564#elif BUILD_PARAMETER_VALIDATION
565 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_parameter_validation");
566 parameter_validation->report_data = framework->report_data;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700567#else
568 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
569#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600570
571 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700572 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600573 }
574
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700575 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
576
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600577 return result;
578}
579
580VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
581 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600582 auto layer_data = GetLayerDataPtr(key, layer_data_map);
583 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700584 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600585 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
586 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600587 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700588 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600589 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
590 }
591
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600592 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600593
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600594 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700595 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600596 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
597 }
598 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600599 while (layer_data->logging_messenger.size() > 0) {
600 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
601 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
602 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600603 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600604 while (layer_data->logging_callback.size() > 0) {
605 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
606 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
607 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600608 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600609
610 layer_debug_utils_destroy_instance(layer_data->report_data);
611
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700612 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
613 delete *item;
614 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600615 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600616}
617
618VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
619 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600620 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600621
622 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
623
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600624 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
625 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600626 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
627 if (fpCreateDevice == NULL) {
628 return VK_ERROR_INITIALIZATION_FAILED;
629 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600630 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
631
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700632 // Get physical device limits for device
633 VkPhysicalDeviceProperties device_properties = {};
634 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
635
636 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
637 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
638
639 DeviceExtensions device_extensions = {};
640 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
641 for (auto item : instance_interceptor->object_dispatch) {
642 item->device_extensions = device_extensions;
643 }
644
645 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600646 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700647 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700648 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700649 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600650 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600651 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700652 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600653 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
654 }
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) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700710 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700711 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600712 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600713
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700714 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
715
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600716 return result;
717}
718
719VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
720 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600721 auto layer_data = GetLayerDataPtr(key, layer_data_map);
722 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700723 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600724 intercept->PreCallValidateDestroyDevice(device, pAllocator);
725 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600726 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700727 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600728 intercept->PreCallRecordDestroyDevice(device, pAllocator);
729 }
730 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600731
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600732 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600733
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600734 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700735 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600736 intercept->PostCallRecordDestroyDevice(device, pAllocator);
737 }
738
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700739 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
740 delete *item;
741 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600742 FreeLayerDataPtr(key, layer_data_map);
743}
744
745VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
746 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
747 const VkAllocationCallbacks *pAllocator,
748 VkDebugReportCallbackEXT *pCallback) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600749 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
750 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700751 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600752 intercept->PreCallValidateCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
753 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600754 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700755 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600756 intercept->PreCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
757 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700758 VkResult result = DispatchCreateDebugReportCallbackEXT(layer_data, instance, pCreateInfo, pAllocator, pCallback);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600759 result = layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);
760 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700761 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700762 intercept->PostCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600763 }
764 return result;
765}
766
767VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
768 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600769 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
770 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700771 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600772 intercept->PreCallValidateDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
773 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600774 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700775 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600776 intercept->PreCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
777 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700778 DispatchDestroyDebugReportCallbackEXT(layer_data, instance, callback, pAllocator);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600779 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
780 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700781 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600782 intercept->PostCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
783 }
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700784}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600785
786 inline_custom_source_postamble = """
787// loader-layer interface v0, just wrappers since there is only a layer
788
789VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
790 VkExtensionProperties *pProperties) {
791 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
792}
793
794VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
795 VkLayerProperties *pProperties) {
796 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
797}
798
799VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
800 VkLayerProperties *pProperties) {
801 // the layer command handles VK_NULL_HANDLE just fine internally
802 assert(physicalDevice == VK_NULL_HANDLE);
803 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
804}
805
806VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
807 const char *pLayerName, uint32_t *pCount,
808 VkExtensionProperties *pProperties) {
809 // the layer command handles VK_NULL_HANDLE just fine internally
810 assert(physicalDevice == VK_NULL_HANDLE);
811 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
812}
813
814VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
815 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
816}
817
818VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
819 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
820}
821
822VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
823 const char *funcName) {
824 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
825}
826
827VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
828 assert(pVersionStruct != NULL);
829 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
830
831 // Fill in the function pointers if our version is at least capable of having the structure contain them.
832 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
833 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
834 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
835 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
836 }
837
838 return VK_SUCCESS;
839}"""
840
841
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600842 def __init__(self,
843 errFile = sys.stderr,
844 warnFile = sys.stderr,
845 diagFile = sys.stdout):
846 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
847 # Internal state - accumulators for different inner block text
848 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
849 self.intercepts = []
850 self.layer_factory = '' # String containing base layer factory class definition
851
852 # Check if the parameter passed in is a pointer to an array
853 def paramIsArray(self, param):
854 return param.attrib.get('len') is not None
855
856 # Check if the parameter passed in is a pointer
857 def paramIsPointer(self, param):
858 ispointer = False
859 for elem in param:
860 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
861 ispointer = True
862 return ispointer
863
864 # Check if an object is a non-dispatchable handle
865 def isHandleTypeNonDispatchable(self, handletype):
866 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
867 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
868 return True
869 else:
870 return False
871
872 # Check if an object is a dispatchable handle
873 def isHandleTypeDispatchable(self, handletype):
874 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
875 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
876 return True
877 else:
878 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700879 #
880 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600881 def beginFile(self, genOpts):
882 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700883 # Output Copyright
884 write(self.inline_copyright_message, file=self.outFile)
885 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600886 self.header = False
887 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
888 self.header = True
889 write('#pragma once', file=self.outFile)
890 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600891 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700892 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600893 else:
894 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700895 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700896 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600897 #
898 def endFile(self):
899 # Finish C++ namespace and multiple inclusion protection
900 self.newline()
901 if not self.header:
902 # Record intercepted procedures
903 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
904 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
905 write('\n'.join(self.intercepts), file=self.outFile)
906 write('};\n', file=self.outFile)
907 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600908 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600909 if self.header:
910 self.newline()
911 # Output Layer Factory Class Definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600912 self.layer_factory += '};\n\n'
913 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600914 write(self.layer_factory, file=self.outFile)
915 else:
916 write(self.inline_custom_source_postamble, file=self.outFile)
917 # Finish processing in superclass
918 OutputGenerator.endFile(self)
919
920 def beginFeature(self, interface, emit):
921 # Start processing in superclass
922 OutputGenerator.beginFeature(self, interface, emit)
923 # Get feature extra protect
924 self.featureExtraProtect = GetFeatureProtect(interface)
925 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
926 # feature. They're only printed in endFeature().
927 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
928
929 def endFeature(self):
930 # Actually write the interface to the output file.
931 if (self.emit):
932 self.newline()
933 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
934 # or move it below the 'for section...' loop.
935 if (self.featureExtraProtect != None):
936 write('#ifdef', self.featureExtraProtect, file=self.outFile)
937 for section in self.TYPE_SECTIONS:
938 contents = self.sections[section]
939 if contents:
940 write('\n'.join(contents), file=self.outFile)
941 self.newline()
942 if (self.sections['command']):
943 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
944 self.newline()
945 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600946 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600947 # Finish processing in superclass
948 OutputGenerator.endFeature(self)
949 #
950 # Append a definition to the specified section
951 def appendSection(self, section, text):
952 self.sections[section].append(text)
953 #
954 # Type generation
955 def genType(self, typeinfo, name, alias):
956 pass
957 #
958 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
959 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
960 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
961 # structs etc.)
962 def genStruct(self, typeinfo, typeName):
963 OutputGenerator.genStruct(self, typeinfo, typeName)
964 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
965 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
966 for member in typeinfo.elem.findall('.//member'):
967 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
968 body += ';\n'
969 body += '} ' + typeName + ';\n'
970 self.appendSection('struct', body)
971 #
972 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
973 def genGroup(self, groupinfo, groupName, alias):
974 pass
975 # Enumerant generation
976 # <enum> tags may specify their values in several ways, but are usually just integers.
977 def genEnum(self, enuminfo, name, alias):
978 pass
979 #
980 # Customize Cdecl for layer factory base class
981 def BaseClassCdecl(self, elem, name):
982 raw = self.makeCDecls(elem)[1]
983
984 # Toss everything before the undecorated name
985 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
986 prototype = prototype.replace(")", "", 1)
987 prototype = prototype.replace(";", " {};")
988
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600989 # Build up pre/post call virtual function declarations
990 pre_call_validate = 'virtual bool PreCallValidate' + prototype
991 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
992 pre_call_record = 'virtual void PreCallRecord' + prototype
993 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700994 resulttype = elem.find('proto/type')
995 if resulttype.text == 'VkResult':
996 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600997 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
998 #
999 # Command generation
1000 def genCmd(self, cmdinfo, name, alias):
1001 ignore_functions = [
1002 'vkEnumerateInstanceVersion'
1003 ]
1004
1005 if name in ignore_functions:
1006 return
1007
1008 if self.header: # In the header declare all intercepts
1009 self.appendSection('command', '')
1010 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1011 if (self.featureExtraProtect != None):
1012 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1013 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1014 # Update base class with virtual function declarations
1015 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
1016 # Update function intercepts
1017 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1018 if (self.featureExtraProtect != None):
1019 self.intercepts += [ '#endif' ]
1020 self.layer_factory += '#endif\n'
1021 return
1022
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001023 if name in self.manual_functions:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001024 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1025 return
1026 # Record that the function will be intercepted
1027 if (self.featureExtraProtect != None):
1028 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1029 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1030 if (self.featureExtraProtect != None):
1031 self.intercepts += [ '#endif' ]
1032 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1033 #
1034 decls = self.makeCDecls(cmdinfo.elem)
1035 self.appendSection('command', '')
1036 self.appendSection('command', '%s {' % decls[0][:-1])
1037 # Setup common to call wrappers. First parameter is always dispatchable
1038 dispatchable_type = cmdinfo.elem.find('param/type').text
1039 dispatchable_name = cmdinfo.elem.find('param/name').text
1040 # Default to device
1041 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001042 dispatch_table_name = 'VkLayerDispatchTable'
1043 # Set to instance as necessary
1044 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1045 device_or_instance = 'instance'
1046 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001047 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001048 api_function_name = cmdinfo.elem.attrib.get('name')
1049 params = cmdinfo.elem.findall('param/name')
1050 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001051 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001052
1053 # Declare result variable, if any.
1054 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001055 'PFN_vkVoidFunction': 'return nullptr;',
1056 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001057 'VkDeviceAddress': 'return 0;',
1058 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1059 'void': 'return;',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001060 }
1061 resulttype = cmdinfo.elem.find('proto/type')
1062 assignresult = ''
1063 if (resulttype.text != 'void'):
1064 assignresult = resulttype.text + ' result = '
1065
1066 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001067 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001068
1069 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001070 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001071 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001072 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1073 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1074 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001075
1076 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001077 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001078 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001079 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001080 self.appendSection('command', ' }')
1081
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001082 # Insert pre-dispatch debug utils function call
1083 if name in self.pre_dispatch_debug_utils_functions:
1084 self.appendSection('command', ' {')
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001085 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->validation_object_mutex);')
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001086 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
1087 self.appendSection('command', ' }')
1088
1089 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001090 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001091
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001092 # Insert post-dispatch debug utils function call
1093 if name in self.post_dispatch_debug_utils_functions:
1094 self.appendSection('command', ' {')
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -07001095 self.appendSection('command', ' std::lock_guard<std::mutex> lock(layer_data->validation_object_mutex);')
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001096 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
1097 self.appendSection('command', ' }')
1098
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001099 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001100 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001101 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001102 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001103 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001104 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001105 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001106 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001107 # Return result variable, if any.
1108 if (resulttype.text != 'void'):
1109 self.appendSection('command', ' return result;')
1110 self.appendSection('command', '}')
1111 #
1112 # Override makeProtoName to drop the "vk" prefix
1113 def makeProtoName(self, name, tail):
1114 return self.genOpts.apientry + name[2:] + tail