blob: e30eb1eaf05c9d32c2c9fe8e7b580cc3a2bcab71 [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,
Mike Schuchardt21638df2019-03-16 10:52:02 -070065 conventions = None,
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -060066 filename = None,
67 directory = '.',
68 apiname = None,
69 profile = None,
70 versions = '.*',
71 emitversions = '.*',
72 defaultExtensions = None,
73 addExtensions = None,
74 removeExtensions = None,
75 emitExtensions = None,
76 sortProcedure = regSortFeatures,
77 prefixText = "",
78 genFuncPointers = True,
79 protectFile = True,
80 protectFeature = True,
81 apicall = '',
82 apientry = '',
83 apientryp = '',
84 indentFuncProto = True,
85 indentFuncPointer = False,
86 alignFuncParam = 0,
87 helper_file_type = '',
88 expandEnumerants = True):
Mike Schuchardt21638df2019-03-16 10:52:02 -070089 GeneratorOptions.__init__(self, conventions, filename, directory, apiname, profile,
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -060090 versions, emitversions, defaultExtensions,
91 addExtensions, removeExtensions, emitExtensions, sortProcedure)
92 self.prefixText = prefixText
93 self.genFuncPointers = genFuncPointers
94 self.protectFile = protectFile
95 self.protectFeature = protectFeature
96 self.apicall = apicall
97 self.apientry = apientry
98 self.apientryp = apientryp
99 self.indentFuncProto = indentFuncProto
100 self.indentFuncPointer = indentFuncPointer
101 self.alignFuncParam = alignFuncParam
102
103# LayerChassisOutputGenerator - subclass of OutputGenerator.
104# Generates a LayerFactory layer that intercepts all API entrypoints
105# This is intended to be used as a starting point for creating custom layers
106#
107# ---- methods ----
108# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
109# OutputGenerator. Defines additional internal state.
110# ---- methods overriding base class ----
111# beginFile(genOpts)
112# endFile()
113# beginFeature(interface, emit)
114# endFeature()
115# genType(typeinfo,name)
116# genStruct(typeinfo,name)
117# genGroup(groupinfo,name)
118# genEnum(enuminfo, name)
119# genCmd(cmdinfo)
120class LayerChassisOutputGenerator(OutputGenerator):
121 """Generate specified API interfaces in a specific style, such as a C header"""
122 # This is an ordered list of sections in the header file.
123 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
124 'group', 'bitmask', 'funcpointer', 'struct']
125 ALL_SECTIONS = TYPE_SECTIONS + ['command']
126
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700127 manual_functions = [
128 # Include functions here to be interecpted w/ manually implemented function bodies
129 'vkGetDeviceProcAddr',
130 'vkGetInstanceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700131 'vkCreateDevice',
132 'vkDestroyDevice',
133 'vkCreateInstance',
134 'vkDestroyInstance',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700135 'vkEnumerateInstanceLayerProperties',
136 'vkEnumerateInstanceExtensionProperties',
137 'vkEnumerateDeviceLayerProperties',
138 'vkEnumerateDeviceExtensionProperties',
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700139 # Functions that are handled explicitly due to chassis architecture violations
140 'vkCreateGraphicsPipelines',
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700141 'vkCreateComputePipelines',
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700142 'vkCreateRayTracingPipelinesNV',
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -0700143 'vkCreatePipelineLayout',
Mark Lobodzinski1db77e82019-03-01 10:02:54 -0700144 'vkCreateShaderModule',
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -0700145 'vkAllocateDescriptorSets',
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700146 # ValidationCache functions do not get dispatched
147 'vkCreateValidationCacheEXT',
148 'vkDestroyValidationCacheEXT',
149 'vkMergeValidationCachesEXT',
150 'vkGetValidationCacheDataEXT',
Mark Lobodzinski56e88122019-03-26 10:21:48 -0600151 # We don't wanna hook this function
152 'vkGetPhysicalDeviceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700153 ]
154
155 alt_ret_codes = [
156 # Include functions here which must tolerate VK_INCOMPLETE as a return code
157 'vkEnumeratePhysicalDevices',
158 'vkEnumeratePhysicalDeviceGroupsKHR',
159 'vkGetValidationCacheDataEXT',
160 'vkGetPipelineCacheData',
161 'vkGetShaderInfoAMD',
162 'vkGetPhysicalDeviceDisplayPropertiesKHR',
163 'vkGetPhysicalDeviceDisplayProperties2KHR',
164 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
165 'vkGetDisplayPlaneSupportedDisplaysKHR',
166 'vkGetDisplayModePropertiesKHR',
167 'vkGetDisplayModeProperties2KHR',
168 'vkGetPhysicalDeviceSurfaceFormatsKHR',
169 'vkGetPhysicalDeviceSurfacePresentModesKHR',
170 'vkGetPhysicalDevicePresentRectanglesKHR',
171 'vkGetPastPresentationTimingGOOGLE',
172 'vkGetSwapchainImagesKHR',
173 'vkEnumerateInstanceLayerProperties',
174 'vkEnumerateDeviceLayerProperties',
175 'vkEnumerateInstanceExtensionProperties',
176 'vkEnumerateDeviceExtensionProperties',
177 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
178 ]
179
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700180 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700181 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
182 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700183 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
184 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700185 }
186
187 post_dispatch_debug_utils_functions = {
188 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700189 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
190 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
191 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
192 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700193 }
194
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600195 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
196 precallrecord_loop = precallvalidate_loop
197 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600198
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700199 inline_custom_header_preamble = """
200#define NOMINMAX
201#include <mutex>
202#include <cinttypes>
203#include <stdio.h>
204#include <stdlib.h>
205#include <string.h>
206#include <unordered_map>
207#include <unordered_set>
208#include <algorithm>
209#include <memory>
210
211#include "vk_loader_platform.h"
212#include "vulkan/vulkan.h"
213#include "vk_layer_config.h"
214#include "vk_layer_data.h"
215#include "vk_layer_logging.h"
216#include "vk_object_types.h"
217#include "vulkan/vk_layer.h"
218#include "vk_enum_string_helper.h"
219#include "vk_layer_extension_utils.h"
220#include "vk_layer_utils.h"
221#include "vulkan/vk_layer.h"
222#include "vk_dispatch_table_helper.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700223#include "vk_extension_helper.h"
224#include "vk_safe_struct.h"
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700225#include "vk_typemap_helper.h"
226
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700227
228extern uint64_t global_unique_id;
229extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
230"""
231
232 inline_custom_header_class_definition = """
233
234// Layer object type identifiers
235enum LayerObjectTypeId {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700236 LayerObjectTypeInstance, // Container for an instance dispatch object
237 LayerObjectTypeDevice, // Container for a device dispatch object
238 LayerObjectTypeThreading, // Instance or device threading layer object
239 LayerObjectTypeParameterValidation, // Instance or device parameter validation layer object
240 LayerObjectTypeObjectTracker, // Instance or device object tracker layer object
241 LayerObjectTypeCoreValidation, // Instance or device core validation layer object
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700242};
243
244struct TEMPLATE_STATE {
245 VkDescriptorUpdateTemplateKHR desc_update_template;
246 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
247
248 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
249 : desc_update_template(update_template), create_info(*pCreateInfo) {}
250};
251
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700252class LAYER_PHYS_DEV_PROPERTIES {
253public:
254 VkPhysicalDeviceProperties properties;
255 std::vector<VkQueueFamilyProperties> queue_family_properties;
256};
257
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600258typedef enum ValidationCheckDisables {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600259 VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600260 VALIDATION_CHECK_DISABLE_OBJECT_IN_USE,
261 VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET,
262 VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE,
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600263 VALIDATION_CHECK_DISABLE_QUERY_VALIDATION,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600264} ValidationCheckDisables;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600265
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600266
267// CHECK_DISABLED struct is a container for bools that can block validation checks from being performed.
268// These bools are all "false" by default meaning that all checks are enabled. Enum values can be specified
269// via the vk_layer_setting.txt config file or at CreateInstance time via the VK_EXT_validation_features extension
270// that can selectively disable checks.
271struct CHECK_DISABLED {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600272 bool command_buffer_state; // Skip command buffer state validation
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600273 bool object_in_use; // Skip all object in_use checking
274 bool idle_descriptor_set; // Skip check to verify that descriptor set is not in-use
275 bool push_constant_range; // Skip push constant range checks
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600276 bool query_validation; // Disable all core validation query-related checks
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600277 bool object_tracking; // Disable object lifetime validation
278 bool core_checks; // Disable core validation checks
279 bool thread_safety; // Disable thread safety validation
280 bool stateless_checks; // Disable stateless validation checks
281 bool handle_wrapping; // Disable unique handles/handle wrapping
282 bool shader_validation; // Skip validation for shaders
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700283
284 void SetAll(bool value) { std::fill(&command_buffer_state, &shader_validation + 1, value); }
285};
286
287struct CHECK_ENABLED {
288 bool gpu_validation;
289 bool gpu_validation_reserve_binding_slot;
290
291 void SetAll(bool value) { std::fill(&gpu_validation, &gpu_validation_reserve_binding_slot + 1, value); }
292};
293
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700294// Layer chassis validation object base class definition
295class ValidationObject {
296 public:
297 uint32_t api_version;
298 debug_report_data* report_data = nullptr;
299 std::vector<VkDebugReportCallbackEXT> logging_callback;
300 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
301
302 VkLayerInstanceDispatchTable instance_dispatch_table;
303 VkLayerDispatchTable device_dispatch_table;
304
305 InstanceExtensions instance_extensions;
306 DeviceExtensions device_extensions = {};
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700307 CHECK_DISABLED disabled = {};
308 CHECK_ENABLED enabled = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700309
310 VkInstance instance = VK_NULL_HANDLE;
311 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
312 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700313 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700314
315 std::vector<ValidationObject*> object_dispatch;
316 LayerObjectTypeId container_type;
317
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700318 std::string layer_name = "CHASSIS";
319
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700320 // Constructor
321 ValidationObject(){};
322 // Destructor
323 virtual ~ValidationObject() {};
324
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700325 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700326 virtual std::unique_lock<std::mutex> write_lock() {
327 return std::unique_lock<std::mutex>(validation_object_mutex);
328 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700329
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700330 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
331 for (auto validation_object : object_dispatch) {
332 if (validation_object->container_type == object_type) {
333 return validation_object;
334 }
335 }
336 return nullptr;
337 };
338
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700339 // Handle Wrapping Data
340 // Reverse map display handles
341 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
Mark Lobodzinskidd28ee22019-06-04 14:20:56 -0600342 // Wrapping Descriptor Template Update structures requires access to the template createinfo structs
343 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_createinfo_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700344 struct SubpassesUsageStates {
345 std::unordered_set<uint32_t> subpasses_using_color_attachment;
346 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
347 };
348 // Uses unwrapped handles
349 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
350 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
351 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
352 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700353 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
354 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700355
356
357 // Unwrap a handle. Must hold lock.
358 template <typename HandleType>
359 HandleType Unwrap(HandleType wrappedHandle) {
360 // TODO: don't use operator[] here.
361 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
362 }
363
364 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
365 template <typename HandleType>
366 HandleType WrapNew(HandleType newlyCreatedHandle) {
367 auto unique_id = global_unique_id++;
368 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
369 return (HandleType)unique_id;
370 }
371
372 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
373 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
374 auto unique_id = global_unique_id++;
375 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
376 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
377 return (VkDisplayKHR)unique_id;
378 }
379
380 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
381 // creating another. Must hold lock.
382 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
383 // See if this display is already known
384 auto it = map_data->display_id_reverse_mapping.find(handle);
385 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
386 // Unknown, so wrap
387 return WrapDisplay(handle, map_data);
388 }
389
390 // Pre/post hook point declarations
391"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600392
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700393 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600394// This file is ***GENERATED***. Do Not Edit.
395// See layer_chassis_generator.py for modifications.
396
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700397/* Copyright (c) 2015-2019 The Khronos Group Inc.
398 * Copyright (c) 2015-2019 Valve Corporation
399 * Copyright (c) 2015-2019 LunarG, Inc.
400 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600401 *
402 * Licensed under the Apache License, Version 2.0 (the "License");
403 * you may not use this file except in compliance with the License.
404 * You may obtain a copy of the License at
405 *
406 * http://www.apache.org/licenses/LICENSE-2.0
407 *
408 * Unless required by applicable law or agreed to in writing, software
409 * distributed under the License is distributed on an "AS IS" BASIS,
410 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
411 * See the License for the specific language governing permissions and
412 * limitations under the License.
413 *
414 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700415 */"""
416
417 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600418
419#include <string.h>
420#include <mutex>
421
422#define VALIDATION_ERROR_MAP_IMPL
423
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600424#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700425#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600426
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600427std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600428
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700429// Global unique object identifier. All increments must be guarded by a lock.
430uint64_t global_unique_id = 1;
431// Map uniqueID to actual object handle
432std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
433
434// TODO: This variable controls handle wrapping -- in the future it should be hooked
435// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
436#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
437bool wrap_handles = true;
438#else
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600439bool wrap_handles = false;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700440#endif
441
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600442// Set layer name -- Khronos layer name overrides any other defined names
Mark Lobodzinskiaa6fd7b2019-03-19 09:26:48 -0600443#if BUILD_KHRONOS_VALIDATION
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600444#define OBJECT_LAYER_NAME "VK_LAYER_KHRONOS_validation"
445#define OBJECT_LAYER_DESCRIPTION "khronos_validation"
446#elif BUILD_OBJECT_TRACKER
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700447#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600448#define OBJECT_LAYER_DESCRIPTION "lunarg_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700449#elif BUILD_THREAD_SAFETY
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700450#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600451#define OBJECT_LAYER_DESCRIPTION "google_thread_checker"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700452#elif BUILD_PARAMETER_VALIDATION
453#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600454#define OBJECT_LAYER_DESCRIPTION "lunarg_parameter_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700455#elif BUILD_CORE_VALIDATION
456#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600457#define OBJECT_LAYER_DESCRIPTION "lunarg_core_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700458#else
459#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600460#define OBJECT_LAYER_DESCRIPTION "lunarg_unique_objects"
461#endif
462
463// Include layer validation object definitions
464#if BUILD_OBJECT_TRACKER
465#include "object_lifetime_validation.h"
466#endif
467#if BUILD_THREAD_SAFETY
468#include "thread_safety.h"
469#endif
470#if BUILD_PARAMETER_VALIDATION
471#include "stateless_validation.h"
472#endif
473#if BUILD_CORE_VALIDATION
474#include "core_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700475#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600476
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600477namespace vulkan_layer_chassis {
478
479using std::unordered_map;
480
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600481static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700482 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600483};
484
John Zulauf358462e2019-04-10 11:10:32 -0600485static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION},
486 {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION}};
Lenny Komow3627f6e2019-06-19 13:54:59 -0600487static const VkExtensionProperties device_extensions[] = {
488 {VK_EXT_VALIDATION_CACHE_EXTENSION_NAME, VK_EXT_VALIDATION_CACHE_SPEC_VERSION},
489 {VK_EXT_DEBUG_MARKER_EXTENSION_NAME, VK_EXT_DEBUG_MARKER_SPEC_VERSION},
490};
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600491
Mark Lobodzinski31395512019-06-18 16:25:01 -0600492typedef struct {
493 bool is_instance_api;
494 void* funcptr;
495} function_data;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600496
Mark Lobodzinski31395512019-06-18 16:25:01 -0600497extern const std::unordered_map<std::string, function_data> name_to_funcptr_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600498
499// Manually written functions
500
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700501// Check enabled instance extensions against supported instance extension whitelist
502static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
503 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
504 // Check for recognized instance extensions
505 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
506 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
507 kVUIDUndefined,
508 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
509 "results and/or produce undefined behavior.",
510 pCreateInfo->ppEnabledExtensionNames[i]);
511 }
512 }
513}
514
515// Check enabled device extensions against supported device extension whitelist
516static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
517 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
518 // Check for recognized device extensions
519 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
520 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
521 kVUIDUndefined,
522 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
523 "results and/or produce undefined behavior.",
524 pCreateInfo->ppEnabledExtensionNames[i]);
525 }
526 }
527}
528
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600529
530// Process validation features, flags and settings specified through extensions, a layer settings file, or environment variables
531
532static const std::unordered_map<std::string, VkValidationFeatureDisableEXT> VkValFeatureDisableLookup = {
533 {"VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT", VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT},
534 {"VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT", VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT},
535 {"VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT", VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT},
536 {"VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT", VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT},
537 {"VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT", VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT},
538 {"VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT", VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT},
539 {"VK_VALIDATION_FEATURE_DISABLE_ALL_EXT", VK_VALIDATION_FEATURE_DISABLE_ALL_EXT},
540};
541
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600542static const std::unordered_map<std::string, VkValidationFeatureEnableEXT> VkValFeatureEnableLookup = {
543 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT},
544 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT},
545};
546
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600547static const std::unordered_map<std::string, ValidationCheckDisables> ValidationDisableLookup = {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600548 {"VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE", VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600549 {"VALIDATION_CHECK_DISABLE_OBJECT_IN_USE", VALIDATION_CHECK_DISABLE_OBJECT_IN_USE},
550 {"VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET", VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET},
551 {"VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE", VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE},
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600552 {"VALIDATION_CHECK_DISABLE_QUERY_VALIDATION", VALIDATION_CHECK_DISABLE_QUERY_VALIDATION},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600553};
554
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600555// Set the local disable flag for the appropriate VALIDATION_CHECK_DISABLE enum
556void SetValidationDisable(CHECK_DISABLED* disable_data, const ValidationCheckDisables disable_id) {
557 switch (disable_id) {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600558 case VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE:
559 disable_data->command_buffer_state = true;
560 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600561 case VALIDATION_CHECK_DISABLE_OBJECT_IN_USE:
562 disable_data->object_in_use = true;
563 break;
564 case VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET:
565 disable_data->idle_descriptor_set = true;
566 break;
567 case VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE:
568 disable_data->push_constant_range = true;
569 break;
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600570 case VALIDATION_CHECK_DISABLE_QUERY_VALIDATION:
571 disable_data->query_validation = true;
572 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600573 default:
574 assert(true);
575 }
576}
577
578// Set the local disable flag for a single VK_VALIDATION_FEATURE_DISABLE_* flag
579void SetValidationFeatureDisable(CHECK_DISABLED* disable_data, const VkValidationFeatureDisableEXT feature_disable) {
580 switch (feature_disable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700581 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600582 disable_data->shader_validation = true;
583 break;
584 case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
585 disable_data->thread_safety = true;
586 break;
587 case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
588 disable_data->stateless_checks = true;
589 break;
590 case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
591 disable_data->object_tracking = true;
592 break;
593 case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
594 disable_data->core_checks = true;
595 break;
596 case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
597 disable_data->handle_wrapping = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700598 break;
599 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
600 // Set all disabled flags to true
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600601 disable_data->SetAll(true);
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700602 break;
603 default:
604 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700605 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600606}
607
608// Set the local enable flag for a single VK_VALIDATION_FEATURE_ENABLE_* flag
609void SetValidationFeatureEnable(CHECK_ENABLED *enable_data, const VkValidationFeatureEnableEXT feature_enable) {
610 switch (feature_enable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700611 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600612 enable_data->gpu_validation = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700613 break;
614 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600615 enable_data->gpu_validation_reserve_binding_slot = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700616 break;
617 default:
618 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700619 }
620}
621
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600622// Set the local disable flag for settings specified through the VK_EXT_validation_flags extension
623void SetValidationFlags(CHECK_DISABLED* disables, const VkValidationFlagsEXT* val_flags_struct) {
624 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
625 switch (val_flags_struct->pDisabledValidationChecks[i]) {
626 case VK_VALIDATION_CHECK_SHADERS_EXT:
627 disables->shader_validation = true;
628 break;
629 case VK_VALIDATION_CHECK_ALL_EXT:
630 // Set all disabled flags to true
631 disables->SetAll(true);
632 break;
633 default:
634 break;
635 }
636 }
637}
638
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600639// Process Validation Features flags specified through the ValidationFeature extension
640void SetValidationFeatures(CHECK_DISABLED *disable_data, CHECK_ENABLED *enable_data,
641 const VkValidationFeaturesEXT *val_features_struct) {
642 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
643 SetValidationFeatureDisable(disable_data, val_features_struct->pDisabledValidationFeatures[i]);
644 }
645 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
646 SetValidationFeatureEnable(enable_data, val_features_struct->pEnabledValidationFeatures[i]);
647 }
648}
649
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600650// Given a string representation of a list of enable enum values, call the appropriate setter function
651void SetLocalEnableSetting(std::string list_of_enables, std::string delimiter, CHECK_ENABLED* enables) {
652 size_t pos = 0;
653 std::string token;
654 while (list_of_enables.length() != 0) {
655 pos = list_of_enables.find(delimiter);
656 if (pos != std::string::npos) {
657 token = list_of_enables.substr(0, pos);
658 } else {
659 pos = list_of_enables.length() - delimiter.length();
660 token = list_of_enables;
661 }
662 if (token.find("VK_VALIDATION_FEATURE_ENABLE_") != std::string::npos) {
663 auto result = VkValFeatureEnableLookup.find(token);
664 if (result != VkValFeatureEnableLookup.end()) {
665 SetValidationFeatureEnable(enables, result->second);
666 }
667 }
668 list_of_enables.erase(0, pos + delimiter.length());
669 }
670}
671
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600672// Given a string representation of a list of disable enum values, call the appropriate setter function
673void SetLocalDisableSetting(std::string list_of_disables, std::string delimiter, CHECK_DISABLED* disables) {
674 size_t pos = 0;
675 std::string token;
676 while (list_of_disables.length() != 0) {
677 pos = list_of_disables.find(delimiter);
678 if (pos != std::string::npos) {
679 token = list_of_disables.substr(0, pos);
680 } else {
681 pos = list_of_disables.length() - delimiter.length();
682 token = list_of_disables;
683 }
684 if (token.find("VK_VALIDATION_FEATURE_DISABLE_") != std::string::npos) {
685 auto result = VkValFeatureDisableLookup.find(token);
686 if (result != VkValFeatureDisableLookup.end()) {
687 SetValidationFeatureDisable(disables, result->second);
688 }
689 }
690 if (token.find("VALIDATION_CHECK_DISABLE_") != std::string::npos) {
691 auto result = ValidationDisableLookup.find(token);
692 if (result != ValidationDisableLookup.end()) {
693 SetValidationDisable(disables, result->second);
694 }
695 }
696 list_of_disables.erase(0, pos + delimiter.length());
697 }
698}
699
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600700// Process enables and disables set though the vk_layer_settings.txt config file or through an environment variable
701void ProcessConfigAndEnvSettings(const char* layer_description, CHECK_ENABLED* enables, CHECK_DISABLED* disables) {
702 std::string enable_key = layer_description;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600703 std::string disable_key = layer_description;
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600704 enable_key.append(".enables");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600705 disable_key.append(".disables");
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600706 std::string list_of_config_enables = getLayerOption(enable_key.c_str());
707 std::string list_of_env_enables = GetLayerEnvVar("VK_LAYER_ENABLES");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600708 std::string list_of_config_disables = getLayerOption(disable_key.c_str());
709 std::string list_of_env_disables = GetLayerEnvVar("VK_LAYER_DISABLES");
710#if defined(_WIN32)
711 std::string env_delimiter = ";";
712#else
713 std::string env_delimiter = ":";
714#endif
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600715 SetLocalEnableSetting(list_of_config_enables, ",", enables);
716 SetLocalEnableSetting(list_of_env_enables, env_delimiter, enables);
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600717 SetLocalDisableSetting(list_of_config_disables, ",", disables);
718 SetLocalDisableSetting(list_of_env_disables, env_delimiter, disables);
719}
720
721
722// Non-code-generated chassis API functions
723
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600724VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600725 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskif94196f2019-07-11 11:46:09 -0600726 if (!ApiParentExtensionEnabled(funcName, &layer_data->device_extensions)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700727 return nullptr;
728 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600729 const auto &item = name_to_funcptr_map.find(funcName);
730 if (item != name_to_funcptr_map.end()) {
Mark Lobodzinski31395512019-06-18 16:25:01 -0600731 if (item->second.is_instance_api) {
732 return nullptr;
733 } else {
734 return reinterpret_cast<PFN_vkVoidFunction>(item->second.funcptr);
735 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600736 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600737 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600738 if (!table.GetDeviceProcAddr) return nullptr;
739 return table.GetDeviceProcAddr(device, funcName);
740}
741
742VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600743 const auto &item = name_to_funcptr_map.find(funcName);
744 if (item != name_to_funcptr_map.end()) {
Mark Lobodzinski31395512019-06-18 16:25:01 -0600745 return reinterpret_cast<PFN_vkVoidFunction>(item->second.funcptr);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600746 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600747 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
748 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600749 if (!table.GetInstanceProcAddr) return nullptr;
750 return table.GetInstanceProcAddr(instance, funcName);
751}
752
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600753VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
754 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
755}
756
757VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
758 VkLayerProperties *pProperties) {
759 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
760}
761
762VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
763 VkExtensionProperties *pProperties) {
764 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
John Zulauf358462e2019-04-10 11:10:32 -0600765 return util_GetExtensionProperties(ARRAY_SIZE(instance_extensions), instance_extensions, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600766
767 return VK_ERROR_LAYER_NOT_PRESENT;
768}
769
770VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
771 uint32_t *pCount, VkExtensionProperties *pProperties) {
Lenny Komow3627f6e2019-06-19 13:54:59 -0600772 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(ARRAY_SIZE(device_extensions), device_extensions, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600773 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600774 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
Lenny Komow7b567f72019-06-10 16:49:43 -0600775 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600776}
777
778VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
779 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600780 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600781
782 assert(chain_info->u.pLayerInfo);
783 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
784 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
785 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
786 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700787 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
788 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
789
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600790 CHECK_ENABLED local_enables {};
791 CHECK_DISABLED local_disables {};
792 const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(pCreateInfo->pNext);
793 if (validation_features_ext) {
794 SetValidationFeatures(&local_disables, &local_enables, validation_features_ext);
795 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600796 const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
797 if (validation_flags_ext) {
798 SetValidationFlags(&local_disables, validation_flags_ext);
799 }
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600800 ProcessConfigAndEnvSettings(OBJECT_LAYER_DESCRIPTION, &local_enables, &local_disables);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600801
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600802 // Create temporary dispatch vector for pre-calls until instance is created
803 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600804 // Add VOs to dispatch vector. Order here will be the validation dispatch order!
805#if BUILD_THREAD_SAFETY
806 auto thread_checker = new ThreadSafety;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600807 if (!local_disables.thread_safety) {
808 local_object_dispatch.emplace_back(thread_checker);
809 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600810 thread_checker->container_type = LayerObjectTypeThreading;
811 thread_checker->api_version = api_version;
812#endif
813#if BUILD_PARAMETER_VALIDATION
814 auto parameter_validation = new StatelessValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600815 if (!local_disables.stateless_checks) {
816 local_object_dispatch.emplace_back(parameter_validation);
817 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600818 parameter_validation->container_type = LayerObjectTypeParameterValidation;
819 parameter_validation->api_version = api_version;
820#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700821#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600822 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600823 if (!local_disables.object_tracking) {
824 local_object_dispatch.emplace_back(object_tracker);
825 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600826 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700827 object_tracker->api_version = api_version;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600828#endif
829#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700830 auto core_checks = new CoreChecks;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600831 if (!local_disables.core_checks) {
832 local_object_dispatch.emplace_back(core_checks);
833 }
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700834 core_checks->container_type = LayerObjectTypeCoreValidation;
835 core_checks->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700836#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600837
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600838 // If handle wrapping is disabled via the ValidationFeatures extension, override build flag
839 if (local_disables.handle_wrapping) {
840 wrap_handles = false;
841 }
842
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600843 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600844 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600845 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
846 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600847 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600848 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
849 }
850
851 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600852 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600853
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600854 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600855
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600856 framework->object_dispatch = local_object_dispatch;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700857 framework->container_type = LayerObjectTypeInstance;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600858 framework->disabled = local_disables;
859 framework->enabled = local_enables;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600860
861 framework->instance = *pInstance;
862 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
863 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
864 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700865 framework->api_version = api_version;
866 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
867
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600868 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, OBJECT_LAYER_DESCRIPTION);
869
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700870#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700871 object_tracker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600872 object_tracker->instance_dispatch_table = framework->instance_dispatch_table;
873 object_tracker->enabled = framework->enabled;
874 object_tracker->disabled = framework->disabled;
875#endif
876#if BUILD_THREAD_SAFETY
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700877 thread_checker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600878 thread_checker->instance_dispatch_table = framework->instance_dispatch_table;
879 thread_checker->enabled = framework->enabled;
880 thread_checker->disabled = framework->disabled;
881#endif
882#if BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700883 parameter_validation->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600884 parameter_validation->instance_dispatch_table = framework->instance_dispatch_table;
885 parameter_validation->enabled = framework->enabled;
886 parameter_validation->disabled = framework->disabled;
887#endif
888#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700889 core_checks->report_data = framework->report_data;
890 core_checks->instance_dispatch_table = framework->instance_dispatch_table;
891 core_checks->instance = *pInstance;
892 core_checks->enabled = framework->enabled;
893 core_checks->disabled = framework->disabled;
894 core_checks->instance_state = core_checks;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700895#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600896
897 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700898 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600899 }
900
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700901 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
902
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600903 return result;
904}
905
906VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
907 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600908 auto layer_data = GetLayerDataPtr(key, layer_data_map);
909 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700910 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600911 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
912 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600913 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700914 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600915 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
916 }
917
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600918 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600919
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600920 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700921 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600922 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
923 }
924 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600925 while (layer_data->logging_messenger.size() > 0) {
926 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
927 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
928 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600929 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600930 while (layer_data->logging_callback.size() > 0) {
931 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
932 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
933 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600934 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600935
936 layer_debug_utils_destroy_instance(layer_data->report_data);
937
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700938 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
939 delete *item;
940 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600941 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600942}
943
944VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
945 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600946 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600947
948 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
949
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600950 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
951 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600952 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
953 if (fpCreateDevice == NULL) {
954 return VK_ERROR_INITIALIZATION_FAILED;
955 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600956 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
957
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700958 // Get physical device limits for device
959 VkPhysicalDeviceProperties device_properties = {};
960 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
961
962 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
963 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
964
965 DeviceExtensions device_extensions = {};
966 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
967 for (auto item : instance_interceptor->object_dispatch) {
968 item->device_extensions = device_extensions;
969 }
970
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700971 std::unique_ptr<safe_VkDeviceCreateInfo> modified_create_info(new safe_VkDeviceCreateInfo(pCreateInfo));
972
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700973 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600974 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700975 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700976 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700977 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600978 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600979 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700980 auto lock = intercept->write_lock();
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700981 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, modified_create_info);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600982 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600983
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700984 VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(modified_create_info.get()), pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600985 if (result != VK_SUCCESS) {
986 return result;
987 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600988
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600989 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700990 device_interceptor->container_type = LayerObjectTypeDevice;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700991
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700992 // Save local info in device object
993 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700994 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
995 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700996 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700997
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600998 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700999
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001000 device_interceptor->device = *pDevice;
1001 device_interceptor->physical_device = gpu;
1002 device_interceptor->instance = instance_interceptor->instance;
1003 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001004
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001005 // Note that this defines the order in which the layer validation objects are called
1006#if BUILD_THREAD_SAFETY
1007 auto thread_safety = new ThreadSafety;
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001008 thread_safety->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001009 if (!instance_interceptor->disabled.thread_safety) {
1010 device_interceptor->object_dispatch.emplace_back(thread_safety);
1011 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001012#endif
1013#if BUILD_PARAMETER_VALIDATION
1014 auto stateless_validation = new StatelessValidation;
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001015 stateless_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001016 if (!instance_interceptor->disabled.stateless_checks) {
1017 device_interceptor->object_dispatch.emplace_back(stateless_validation);
1018 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001019#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001020#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001021 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001022 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001023 if (!instance_interceptor->disabled.object_tracking) {
1024 device_interceptor->object_dispatch.emplace_back(object_tracker);
1025 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001026#endif
1027#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001028 auto core_checks = new CoreChecks;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001029 core_checks->container_type = LayerObjectTypeCoreValidation;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001030 core_checks->instance_state = reinterpret_cast<CoreChecks *>(
1031 core_checks->GetValidationObject(instance_interceptor->object_dispatch, LayerObjectTypeCoreValidation));
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001032 if (!instance_interceptor->disabled.core_checks) {
1033 device_interceptor->object_dispatch.emplace_back(core_checks);
1034 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001035#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001036
Mark Lobodzinski7314bf42019-03-28 08:54:53 -06001037 // Set per-intercept common data items
1038 for (auto dev_intercept : device_interceptor->object_dispatch) {
1039 dev_intercept->device = *pDevice;
1040 dev_intercept->physical_device = gpu;
1041 dev_intercept->instance = instance_interceptor->instance;
1042 dev_intercept->report_data = device_interceptor->report_data;
1043 dev_intercept->device_dispatch_table = device_interceptor->device_dispatch_table;
1044 dev_intercept->api_version = device_interceptor->api_version;
1045 dev_intercept->disabled = instance_interceptor->disabled;
1046 dev_intercept->enabled = instance_interceptor->enabled;
1047 dev_intercept->instance_dispatch_table = instance_interceptor->instance_dispatch_table;
1048 dev_intercept->instance_extensions = instance_interceptor->instance_extensions;
1049 dev_intercept->device_extensions = device_interceptor->device_extensions;
1050 }
1051
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001052 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001053 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001054 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001055 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001056
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001057 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
1058
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001059 return result;
1060}
1061
1062VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
1063 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001064 auto layer_data = GetLayerDataPtr(key, layer_data_map);
1065 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001066 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001067 intercept->PreCallValidateDestroyDevice(device, pAllocator);
1068 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001069 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001070 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001071 intercept->PreCallRecordDestroyDevice(device, pAllocator);
1072 }
1073 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001074
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001075 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001076
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001077 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001078 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001079 intercept->PostCallRecordDestroyDevice(device, pAllocator);
1080 }
1081
Mark Lobodzinskic5003372018-12-17 16:36:01 -07001082 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
1083 delete *item;
1084 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001085 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001086}
1087
1088
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001089// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001090
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001091VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
1092 VkDevice device,
1093 VkPipelineCache pipelineCache,
1094 uint32_t createInfoCount,
1095 const VkGraphicsPipelineCreateInfo* pCreateInfos,
1096 const VkAllocationCallbacks* pAllocator,
1097 VkPipeline* pPipelines) {
1098 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1099 bool skip = false;
1100
1101#ifdef BUILD_CORE_VALIDATION
1102 create_graphics_pipeline_api_state cgpl_state{};
1103#else
1104 struct create_graphics_pipeline_api_state {
1105 const VkGraphicsPipelineCreateInfo* pCreateInfos;
1106 } cgpl_state;
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001107#endif
Mark Lobodzinskid08e16c2019-06-11 10:22:10 -06001108 cgpl_state.pCreateInfos = pCreateInfos;
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001109
1110 for (auto intercept : layer_data->object_dispatch) {
1111 auto lock = intercept->write_lock();
1112 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1113 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1114 }
1115 for (auto intercept : layer_data->object_dispatch) {
1116 auto lock = intercept->write_lock();
1117 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1118 }
1119
Tony-LunarG152a88b2019-03-20 15:42:24 -06001120 VkResult result = DispatchCreateGraphicsPipelines(device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001121
1122 for (auto intercept : layer_data->object_dispatch) {
1123 auto lock = intercept->write_lock();
1124 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
1125 }
1126 return result;
1127}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001128
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001129// This API saves some core_validation pipeline state state on the stack for performance purposes
1130VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
1131 VkDevice device,
1132 VkPipelineCache pipelineCache,
1133 uint32_t createInfoCount,
1134 const VkComputePipelineCreateInfo* pCreateInfos,
1135 const VkAllocationCallbacks* pAllocator,
1136 VkPipeline* pPipelines) {
1137 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1138 bool skip = false;
1139
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001140#ifdef BUILD_CORE_VALIDATION
1141 create_compute_pipeline_api_state ccpl_state{};
1142#else
1143 struct create_compute_pipeline_api_state {
1144 const VkComputePipelineCreateInfo* pCreateInfos;
1145 } ccpl_state;
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001146#endif
Mark Lobodzinskid08e16c2019-06-11 10:22:10 -06001147 ccpl_state.pCreateInfos = pCreateInfos;
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001148
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001149 for (auto intercept : layer_data->object_dispatch) {
1150 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001151 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001152 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1153 }
1154 for (auto intercept : layer_data->object_dispatch) {
1155 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001156 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001157 }
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001158 VkResult result = DispatchCreateComputePipelines(device, pipelineCache, createInfoCount, ccpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001159 for (auto intercept : layer_data->object_dispatch) {
1160 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001161 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001162 }
1163 return result;
1164}
1165
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001166VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
1167 VkDevice device,
1168 VkPipelineCache pipelineCache,
1169 uint32_t createInfoCount,
1170 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
1171 const VkAllocationCallbacks* pAllocator,
1172 VkPipeline* pPipelines) {
1173 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1174 bool skip = false;
1175
Jason Macnak67407e72019-07-11 11:05:09 -07001176#ifdef BUILD_CORE_VALIDATION
1177 create_ray_tracing_pipeline_api_state crtpl_state{};
1178#else
1179 struct create_ray_tracing_pipeline_api_state {
1180 const VkRayTracingPipelineCreateInfoNV* pCreateInfos;
1181 } crtpl_state;
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001182#endif
Jason Macnak67407e72019-07-11 11:05:09 -07001183 crtpl_state.pCreateInfos = pCreateInfos;
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001184
1185 for (auto intercept : layer_data->object_dispatch) {
1186 auto lock = intercept->write_lock();
Jason Macnak67407e72019-07-11 11:05:09 -07001187 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos,
1188 pAllocator, pPipelines, &crtpl_state);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001189 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1190 }
1191 for (auto intercept : layer_data->object_dispatch) {
1192 auto lock = intercept->write_lock();
Jason Macnak67407e72019-07-11 11:05:09 -07001193 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator,
1194 pPipelines, &crtpl_state);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001195 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001196 VkResult result = DispatchCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001197 for (auto intercept : layer_data->object_dispatch) {
1198 auto lock = intercept->write_lock();
Jason Macnak67407e72019-07-11 11:05:09 -07001199 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator,
1200 pPipelines, result, &crtpl_state);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001201 }
1202 return result;
1203}
1204
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001205// This API needs the ability to modify a down-chain parameter
1206VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
1207 VkDevice device,
1208 const VkPipelineLayoutCreateInfo* pCreateInfo,
1209 const VkAllocationCallbacks* pAllocator,
1210 VkPipelineLayout* pPipelineLayout) {
1211 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1212 bool skip = false;
1213
1214#ifndef BUILD_CORE_VALIDATION
1215 struct create_pipeline_layout_api_state {
1216 VkPipelineLayoutCreateInfo modified_create_info;
1217 };
1218#endif
1219 create_pipeline_layout_api_state cpl_state{};
1220 cpl_state.modified_create_info = *pCreateInfo;
1221
1222 for (auto intercept : layer_data->object_dispatch) {
1223 auto lock = intercept->write_lock();
1224 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1225 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1226 }
1227 for (auto intercept : layer_data->object_dispatch) {
1228 auto lock = intercept->write_lock();
1229 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1230 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001231 VkResult result = DispatchCreatePipelineLayout(device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001232 for (auto intercept : layer_data->object_dispatch) {
1233 auto lock = intercept->write_lock();
1234 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1235 }
1236 return result;
1237}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001238
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001239// This API needs some local stack data for performance reasons and also may modify a parameter
1240VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1241 VkDevice device,
1242 const VkShaderModuleCreateInfo* pCreateInfo,
1243 const VkAllocationCallbacks* pAllocator,
1244 VkShaderModule* pShaderModule) {
1245 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1246 bool skip = false;
1247
1248#ifndef BUILD_CORE_VALIDATION
1249 struct create_shader_module_api_state {
1250 VkShaderModuleCreateInfo instrumented_create_info;
1251 };
1252#endif
1253 create_shader_module_api_state csm_state{};
1254 csm_state.instrumented_create_info = *pCreateInfo;
1255
1256 for (auto intercept : layer_data->object_dispatch) {
1257 auto lock = intercept->write_lock();
1258 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1259 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1260 }
1261 for (auto intercept : layer_data->object_dispatch) {
1262 auto lock = intercept->write_lock();
1263 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1264 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001265 VkResult result = DispatchCreateShaderModule(device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001266 for (auto intercept : layer_data->object_dispatch) {
1267 auto lock = intercept->write_lock();
1268 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1269 }
1270 return result;
1271}
1272
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001273VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1274 VkDevice device,
1275 const VkDescriptorSetAllocateInfo* pAllocateInfo,
1276 VkDescriptorSet* pDescriptorSets) {
1277 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1278 bool skip = false;
1279
1280#ifdef BUILD_CORE_VALIDATION
1281 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1282#else
1283 struct ads_state {} ads_state;
1284#endif
1285
1286 for (auto intercept : layer_data->object_dispatch) {
1287 auto lock = intercept->write_lock();
1288 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1289 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1290 }
1291 for (auto intercept : layer_data->object_dispatch) {
1292 auto lock = intercept->write_lock();
1293 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1294 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001295 VkResult result = DispatchAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001296 for (auto intercept : layer_data->object_dispatch) {
1297 auto lock = intercept->write_lock();
1298 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1299 }
1300 return result;
1301}
1302
1303
1304
1305
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001306
1307// ValidationCache APIs do not dispatch
1308
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001309VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1310 VkDevice device,
1311 const VkValidationCacheCreateInfoEXT* pCreateInfo,
1312 const VkAllocationCallbacks* pAllocator,
1313 VkValidationCacheEXT* pValidationCache) {
1314 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1315 VkResult result = VK_SUCCESS;
1316
1317 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1318 if (validation_data) {
1319 auto lock = validation_data->write_lock();
1320 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1321 }
1322 return result;
1323}
1324
1325VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1326 VkDevice device,
1327 VkValidationCacheEXT validationCache,
1328 const VkAllocationCallbacks* pAllocator) {
1329 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1330
1331 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1332 if (validation_data) {
1333 auto lock = validation_data->write_lock();
1334 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1335 }
1336}
1337
1338VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1339 VkDevice device,
1340 VkValidationCacheEXT dstCache,
1341 uint32_t srcCacheCount,
1342 const VkValidationCacheEXT* pSrcCaches) {
1343 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1344 VkResult result = VK_SUCCESS;
1345
1346 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1347 if (validation_data) {
1348 auto lock = validation_data->write_lock();
1349 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1350 }
1351 return result;
1352}
1353
1354VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1355 VkDevice device,
1356 VkValidationCacheEXT validationCache,
1357 size_t* pDataSize,
1358 void* pData) {
1359 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1360 VkResult result = VK_SUCCESS;
1361
1362 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1363 if (validation_data) {
1364 auto lock = validation_data->write_lock();
1365 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1366 }
1367 return result;
1368
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001369}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001370
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001371 inline_custom_validation_class_definitions = """
1372 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1373 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1374 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1375 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001376
Jason Macnak67407e72019-07-11 11:05:09 -07001377 // Allow additional state parameter for CreateGraphicsPipelines
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001378 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1379 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1380 };
1381 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1382 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1383 };
1384 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1385 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1386 };
Jason Macnak67407e72019-07-11 11:05:09 -07001387
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001388 // Allow additional state parameter for CreateComputePipelines
1389 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1390 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1391 };
Jason Macnak67407e72019-07-11 11:05:09 -07001392 virtual void PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* ccpl_state) {
1393 PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1394 };
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001395 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1396 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1397 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001398
1399 // Allow additional state parameter for CreateRayTracingPipelinesNV
1400 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1401 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1402 };
Jason Macnak67407e72019-07-11 11:05:09 -07001403 virtual void PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* ccpl_state) {
1404 PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1405 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001406 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1407 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1408 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001409
1410 // Allow modification of a down-chain parameter for CreatePipelineLayout
1411 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1412 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1413 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001414
1415 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1416 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1417 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1418 };
1419 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1420 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1421 };
1422 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1423 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1424 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001425
1426 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1427 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1428 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1429 };
1430 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1431 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1432 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001433
1434 // Modify a parameter to CreateDevice
1435 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1436 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1437 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001438"""
1439
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001440 inline_custom_source_postamble = """
1441// loader-layer interface v0, just wrappers since there is only a layer
1442
1443VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1444 VkExtensionProperties *pProperties) {
1445 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1446}
1447
1448VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1449 VkLayerProperties *pProperties) {
1450 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1451}
1452
1453VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1454 VkLayerProperties *pProperties) {
1455 // the layer command handles VK_NULL_HANDLE just fine internally
1456 assert(physicalDevice == VK_NULL_HANDLE);
1457 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1458}
1459
1460VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1461 const char *pLayerName, uint32_t *pCount,
1462 VkExtensionProperties *pProperties) {
1463 // the layer command handles VK_NULL_HANDLE just fine internally
1464 assert(physicalDevice == VK_NULL_HANDLE);
1465 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1466}
1467
1468VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1469 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1470}
1471
1472VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1473 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1474}
1475
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001476VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1477 assert(pVersionStruct != NULL);
1478 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1479
1480 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1481 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1482 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1483 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
Mark Lobodzinski56e88122019-03-26 10:21:48 -06001484 pVersionStruct->pfnGetPhysicalDeviceProcAddr = nullptr;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001485 }
1486
1487 return VK_SUCCESS;
1488}"""
1489
1490
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001491 def __init__(self,
1492 errFile = sys.stderr,
1493 warnFile = sys.stderr,
1494 diagFile = sys.stdout):
1495 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1496 # Internal state - accumulators for different inner block text
1497 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1498 self.intercepts = []
1499 self.layer_factory = '' # String containing base layer factory class definition
1500
1501 # Check if the parameter passed in is a pointer to an array
1502 def paramIsArray(self, param):
1503 return param.attrib.get('len') is not None
1504
1505 # Check if the parameter passed in is a pointer
1506 def paramIsPointer(self, param):
1507 ispointer = False
1508 for elem in param:
Raul Tambre7b300182019-05-04 11:25:14 +03001509 if elem.tag == 'type' and elem.tail is not None and '*' in elem.tail:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001510 ispointer = True
1511 return ispointer
1512
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001513 #
1514 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001515 def beginFile(self, genOpts):
1516 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001517 # Output Copyright
1518 write(self.inline_copyright_message, file=self.outFile)
1519 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001520 self.header = False
1521 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1522 self.header = True
1523 write('#pragma once', file=self.outFile)
1524 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001525 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001526 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001527 else:
1528 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001529 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001530 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001531 #
1532 def endFile(self):
1533 # Finish C++ namespace and multiple inclusion protection
1534 self.newline()
1535 if not self.header:
1536 # Record intercepted procedures
Mark Lobodzinski31395512019-06-18 16:25:01 -06001537 write('// Map of intercepted ApiName to its associated function data', file=self.outFile)
1538 write('const std::unordered_map<std::string, function_data> name_to_funcptr_map = {', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001539 write('\n'.join(self.intercepts), file=self.outFile)
1540 write('};\n', file=self.outFile)
1541 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001542 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001543 if self.header:
1544 self.newline()
1545 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001546 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001547 self.layer_factory += '};\n\n'
1548 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001549 write(self.layer_factory, file=self.outFile)
1550 else:
1551 write(self.inline_custom_source_postamble, file=self.outFile)
1552 # Finish processing in superclass
1553 OutputGenerator.endFile(self)
1554
1555 def beginFeature(self, interface, emit):
1556 # Start processing in superclass
1557 OutputGenerator.beginFeature(self, interface, emit)
1558 # Get feature extra protect
1559 self.featureExtraProtect = GetFeatureProtect(interface)
1560 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1561 # feature. They're only printed in endFeature().
1562 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1563
1564 def endFeature(self):
1565 # Actually write the interface to the output file.
1566 if (self.emit):
1567 self.newline()
1568 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1569 # or move it below the 'for section...' loop.
1570 if (self.featureExtraProtect != None):
1571 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1572 for section in self.TYPE_SECTIONS:
1573 contents = self.sections[section]
1574 if contents:
1575 write('\n'.join(contents), file=self.outFile)
1576 self.newline()
1577 if (self.sections['command']):
1578 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1579 self.newline()
1580 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001581 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001582 # Finish processing in superclass
1583 OutputGenerator.endFeature(self)
1584 #
1585 # Append a definition to the specified section
1586 def appendSection(self, section, text):
1587 self.sections[section].append(text)
1588 #
1589 # Type generation
1590 def genType(self, typeinfo, name, alias):
1591 pass
1592 #
1593 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1594 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1595 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1596 # structs etc.)
1597 def genStruct(self, typeinfo, typeName):
1598 OutputGenerator.genStruct(self, typeinfo, typeName)
1599 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1600 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1601 for member in typeinfo.elem.findall('.//member'):
1602 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1603 body += ';\n'
1604 body += '} ' + typeName + ';\n'
1605 self.appendSection('struct', body)
1606 #
1607 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1608 def genGroup(self, groupinfo, groupName, alias):
1609 pass
1610 # Enumerant generation
1611 # <enum> tags may specify their values in several ways, but are usually just integers.
1612 def genEnum(self, enuminfo, name, alias):
1613 pass
1614 #
1615 # Customize Cdecl for layer factory base class
1616 def BaseClassCdecl(self, elem, name):
1617 raw = self.makeCDecls(elem)[1]
1618
1619 # Toss everything before the undecorated name
1620 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1621 prototype = prototype.replace(")", "", 1)
1622 prototype = prototype.replace(";", " {};")
1623
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001624 # Build up pre/post call virtual function declarations
1625 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1626 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1627 pre_call_record = 'virtual void PreCallRecord' + prototype
1628 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001629 resulttype = elem.find('proto/type')
1630 if resulttype.text == 'VkResult':
1631 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001632 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1633 #
1634 # Command generation
1635 def genCmd(self, cmdinfo, name, alias):
1636 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001637 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001638 ]
1639
1640 if name in ignore_functions:
1641 return
1642
1643 if self.header: # In the header declare all intercepts
1644 self.appendSection('command', '')
1645 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1646 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001647 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1648 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001649 if 'ValidationCache' not in name:
1650 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001651 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001652 self.layer_factory += '#endif\n'
1653 return
1654
Mark Lobodzinski31395512019-06-18 16:25:01 -06001655 is_instance = 'false'
1656 dispatchable_type = cmdinfo.elem.find('param/type').text
1657 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1658 is_instance = 'true'
1659
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001660 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001661 if 'ValidationCache' not in name:
Mark Lobodzinski31395512019-06-18 16:25:01 -06001662 self.intercepts += [ ' {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001663 else:
1664 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
Mark Lobodzinski31395512019-06-18 16:25:01 -06001665
1666 self.intercepts += [ ' {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001667 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001668 return
1669 # Record that the function will be intercepted
1670 if (self.featureExtraProtect != None):
1671 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
Mark Lobodzinski31395512019-06-18 16:25:01 -06001672 self.intercepts += [ ' {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001673 if (self.featureExtraProtect != None):
1674 self.intercepts += [ '#endif' ]
1675 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1676 #
1677 decls = self.makeCDecls(cmdinfo.elem)
1678 self.appendSection('command', '')
1679 self.appendSection('command', '%s {' % decls[0][:-1])
1680 # Setup common to call wrappers. First parameter is always dispatchable
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001681 dispatchable_name = cmdinfo.elem.find('param/name').text
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001682 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001683 api_function_name = cmdinfo.elem.attrib.get('name')
1684 params = cmdinfo.elem.findall('param/name')
1685 paramstext = ', '.join([str(param.text) for param in params])
Tony-LunarG152a88b2019-03-20 15:42:24 -06001686 API = api_function_name.replace('vk','Dispatch') + '('
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001687
1688 # Declare result variable, if any.
1689 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001690 'PFN_vkVoidFunction': 'return nullptr;',
1691 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001692 'VkDeviceAddress': 'return 0;',
1693 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1694 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001695 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001696 }
1697 resulttype = cmdinfo.elem.find('proto/type')
1698 assignresult = ''
1699 if (resulttype.text != 'void'):
1700 assignresult = resulttype.text + ' result = '
1701
1702 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001703 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001704
1705 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001706 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001707 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001708 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1709 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1710 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001711
1712 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001713 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001714 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001715 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001716 self.appendSection('command', ' }')
1717
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001718 # Insert pre-dispatch debug utils function call
1719 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001720 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001721
1722 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001723 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001724
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001725 # Insert post-dispatch debug utils function call
1726 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001727 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001728
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001729 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001730 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001731 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001732 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001733 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001734 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001735 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001736 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001737 # Return result variable, if any.
1738 if (resulttype.text != 'void'):
1739 self.appendSection('command', ' return result;')
1740 self.appendSection('command', '}')
1741 #
1742 # Override makeProtoName to drop the "vk" prefix
1743 def makeProtoName(self, name, tail):
1744 return self.genOpts.apientry + name[2:] + tail