blob: 82a24865217d763f7644c7916287fceea63b68f6 [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 Lobodzinskicc4e4a22018-12-18 16:16:21 -0700726 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
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
1176#ifndef BUILD_CORE_VALIDATION
1177 struct PIPELINE_STATE {};
1178#endif
1179
1180 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
1181
1182 for (auto intercept : layer_data->object_dispatch) {
1183 auto lock = intercept->write_lock();
1184 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
1185 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1186 }
1187 for (auto intercept : layer_data->object_dispatch) {
1188 auto lock = intercept->write_lock();
1189 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1190 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001191 VkResult result = DispatchCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001192 for (auto intercept : layer_data->object_dispatch) {
1193 auto lock = intercept->write_lock();
1194 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1195 }
1196 return result;
1197}
1198
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001199// This API needs the ability to modify a down-chain parameter
1200VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
1201 VkDevice device,
1202 const VkPipelineLayoutCreateInfo* pCreateInfo,
1203 const VkAllocationCallbacks* pAllocator,
1204 VkPipelineLayout* pPipelineLayout) {
1205 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1206 bool skip = false;
1207
1208#ifndef BUILD_CORE_VALIDATION
1209 struct create_pipeline_layout_api_state {
1210 VkPipelineLayoutCreateInfo modified_create_info;
1211 };
1212#endif
1213 create_pipeline_layout_api_state cpl_state{};
1214 cpl_state.modified_create_info = *pCreateInfo;
1215
1216 for (auto intercept : layer_data->object_dispatch) {
1217 auto lock = intercept->write_lock();
1218 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1219 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1220 }
1221 for (auto intercept : layer_data->object_dispatch) {
1222 auto lock = intercept->write_lock();
1223 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1224 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001225 VkResult result = DispatchCreatePipelineLayout(device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001226 for (auto intercept : layer_data->object_dispatch) {
1227 auto lock = intercept->write_lock();
1228 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1229 }
1230 return result;
1231}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001232
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001233// This API needs some local stack data for performance reasons and also may modify a parameter
1234VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1235 VkDevice device,
1236 const VkShaderModuleCreateInfo* pCreateInfo,
1237 const VkAllocationCallbacks* pAllocator,
1238 VkShaderModule* pShaderModule) {
1239 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1240 bool skip = false;
1241
1242#ifndef BUILD_CORE_VALIDATION
1243 struct create_shader_module_api_state {
1244 VkShaderModuleCreateInfo instrumented_create_info;
1245 };
1246#endif
1247 create_shader_module_api_state csm_state{};
1248 csm_state.instrumented_create_info = *pCreateInfo;
1249
1250 for (auto intercept : layer_data->object_dispatch) {
1251 auto lock = intercept->write_lock();
1252 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1253 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1254 }
1255 for (auto intercept : layer_data->object_dispatch) {
1256 auto lock = intercept->write_lock();
1257 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1258 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001259 VkResult result = DispatchCreateShaderModule(device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001260 for (auto intercept : layer_data->object_dispatch) {
1261 auto lock = intercept->write_lock();
1262 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1263 }
1264 return result;
1265}
1266
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001267VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1268 VkDevice device,
1269 const VkDescriptorSetAllocateInfo* pAllocateInfo,
1270 VkDescriptorSet* pDescriptorSets) {
1271 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1272 bool skip = false;
1273
1274#ifdef BUILD_CORE_VALIDATION
1275 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1276#else
1277 struct ads_state {} ads_state;
1278#endif
1279
1280 for (auto intercept : layer_data->object_dispatch) {
1281 auto lock = intercept->write_lock();
1282 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1283 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1284 }
1285 for (auto intercept : layer_data->object_dispatch) {
1286 auto lock = intercept->write_lock();
1287 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1288 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001289 VkResult result = DispatchAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001290 for (auto intercept : layer_data->object_dispatch) {
1291 auto lock = intercept->write_lock();
1292 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1293 }
1294 return result;
1295}
1296
1297
1298
1299
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001300
1301// ValidationCache APIs do not dispatch
1302
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001303VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1304 VkDevice device,
1305 const VkValidationCacheCreateInfoEXT* pCreateInfo,
1306 const VkAllocationCallbacks* pAllocator,
1307 VkValidationCacheEXT* pValidationCache) {
1308 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1309 VkResult result = VK_SUCCESS;
1310
1311 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1312 if (validation_data) {
1313 auto lock = validation_data->write_lock();
1314 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1315 }
1316 return result;
1317}
1318
1319VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1320 VkDevice device,
1321 VkValidationCacheEXT validationCache,
1322 const VkAllocationCallbacks* pAllocator) {
1323 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1324
1325 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1326 if (validation_data) {
1327 auto lock = validation_data->write_lock();
1328 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1329 }
1330}
1331
1332VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1333 VkDevice device,
1334 VkValidationCacheEXT dstCache,
1335 uint32_t srcCacheCount,
1336 const VkValidationCacheEXT* pSrcCaches) {
1337 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1338 VkResult result = VK_SUCCESS;
1339
1340 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1341 if (validation_data) {
1342 auto lock = validation_data->write_lock();
1343 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1344 }
1345 return result;
1346}
1347
1348VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1349 VkDevice device,
1350 VkValidationCacheEXT validationCache,
1351 size_t* pDataSize,
1352 void* pData) {
1353 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1354 VkResult result = VK_SUCCESS;
1355
1356 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1357 if (validation_data) {
1358 auto lock = validation_data->write_lock();
1359 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1360 }
1361 return result;
1362
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001363}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001364
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001365 inline_custom_validation_class_definitions = """
1366 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1367 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1368 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1369 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001370
1371 // Allow additional parameter for CreateGraphicsPipelines
1372 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1373 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1374 };
1375 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1376 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1377 };
1378 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1379 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1380 };
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001381 virtual void PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* ccpl_state) {
1382 PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1383 };
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001384 // Allow additional state parameter for CreateComputePipelines
1385 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1386 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1387 };
1388 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1389 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1390 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001391
1392 // Allow additional state parameter for CreateRayTracingPipelinesNV
1393 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1394 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1395 };
1396 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1397 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1398 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001399
1400 // Allow modification of a down-chain parameter for CreatePipelineLayout
1401 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1402 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1403 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001404
1405 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1406 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1407 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1408 };
1409 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1410 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1411 };
1412 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1413 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1414 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001415
1416 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1417 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1418 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1419 };
1420 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1421 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1422 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001423
1424 // Modify a parameter to CreateDevice
1425 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1426 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1427 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001428"""
1429
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001430 inline_custom_source_postamble = """
1431// loader-layer interface v0, just wrappers since there is only a layer
1432
1433VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1434 VkExtensionProperties *pProperties) {
1435 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1436}
1437
1438VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1439 VkLayerProperties *pProperties) {
1440 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1441}
1442
1443VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1444 VkLayerProperties *pProperties) {
1445 // the layer command handles VK_NULL_HANDLE just fine internally
1446 assert(physicalDevice == VK_NULL_HANDLE);
1447 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1448}
1449
1450VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1451 const char *pLayerName, uint32_t *pCount,
1452 VkExtensionProperties *pProperties) {
1453 // the layer command handles VK_NULL_HANDLE just fine internally
1454 assert(physicalDevice == VK_NULL_HANDLE);
1455 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1456}
1457
1458VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1459 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1460}
1461
1462VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1463 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1464}
1465
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001466VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1467 assert(pVersionStruct != NULL);
1468 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1469
1470 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1471 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1472 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1473 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
Mark Lobodzinski56e88122019-03-26 10:21:48 -06001474 pVersionStruct->pfnGetPhysicalDeviceProcAddr = nullptr;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001475 }
1476
1477 return VK_SUCCESS;
1478}"""
1479
1480
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001481 def __init__(self,
1482 errFile = sys.stderr,
1483 warnFile = sys.stderr,
1484 diagFile = sys.stdout):
1485 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1486 # Internal state - accumulators for different inner block text
1487 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1488 self.intercepts = []
1489 self.layer_factory = '' # String containing base layer factory class definition
1490
1491 # Check if the parameter passed in is a pointer to an array
1492 def paramIsArray(self, param):
1493 return param.attrib.get('len') is not None
1494
1495 # Check if the parameter passed in is a pointer
1496 def paramIsPointer(self, param):
1497 ispointer = False
1498 for elem in param:
Raul Tambre7b300182019-05-04 11:25:14 +03001499 if elem.tag == 'type' and elem.tail is not None and '*' in elem.tail:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001500 ispointer = True
1501 return ispointer
1502
1503 # Check if an object is a non-dispatchable handle
1504 def isHandleTypeNonDispatchable(self, handletype):
1505 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1506 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1507 return True
1508 else:
1509 return False
1510
1511 # Check if an object is a dispatchable handle
1512 def isHandleTypeDispatchable(self, handletype):
1513 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1514 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
1515 return True
1516 else:
1517 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001518 #
1519 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001520 def beginFile(self, genOpts):
1521 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001522 # Output Copyright
1523 write(self.inline_copyright_message, file=self.outFile)
1524 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001525 self.header = False
1526 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1527 self.header = True
1528 write('#pragma once', file=self.outFile)
1529 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001530 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001531 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001532 else:
1533 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001534 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001535 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001536 #
1537 def endFile(self):
1538 # Finish C++ namespace and multiple inclusion protection
1539 self.newline()
1540 if not self.header:
1541 # Record intercepted procedures
Mark Lobodzinski31395512019-06-18 16:25:01 -06001542 write('// Map of intercepted ApiName to its associated function data', file=self.outFile)
1543 write('const std::unordered_map<std::string, function_data> name_to_funcptr_map = {', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001544 write('\n'.join(self.intercepts), file=self.outFile)
1545 write('};\n', file=self.outFile)
1546 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001547 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001548 if self.header:
1549 self.newline()
1550 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001551 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001552 self.layer_factory += '};\n\n'
1553 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001554 write(self.layer_factory, file=self.outFile)
1555 else:
1556 write(self.inline_custom_source_postamble, file=self.outFile)
1557 # Finish processing in superclass
1558 OutputGenerator.endFile(self)
1559
1560 def beginFeature(self, interface, emit):
1561 # Start processing in superclass
1562 OutputGenerator.beginFeature(self, interface, emit)
1563 # Get feature extra protect
1564 self.featureExtraProtect = GetFeatureProtect(interface)
1565 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1566 # feature. They're only printed in endFeature().
1567 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1568
1569 def endFeature(self):
1570 # Actually write the interface to the output file.
1571 if (self.emit):
1572 self.newline()
1573 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1574 # or move it below the 'for section...' loop.
1575 if (self.featureExtraProtect != None):
1576 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1577 for section in self.TYPE_SECTIONS:
1578 contents = self.sections[section]
1579 if contents:
1580 write('\n'.join(contents), file=self.outFile)
1581 self.newline()
1582 if (self.sections['command']):
1583 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1584 self.newline()
1585 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001586 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001587 # Finish processing in superclass
1588 OutputGenerator.endFeature(self)
1589 #
1590 # Append a definition to the specified section
1591 def appendSection(self, section, text):
1592 self.sections[section].append(text)
1593 #
1594 # Type generation
1595 def genType(self, typeinfo, name, alias):
1596 pass
1597 #
1598 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1599 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1600 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1601 # structs etc.)
1602 def genStruct(self, typeinfo, typeName):
1603 OutputGenerator.genStruct(self, typeinfo, typeName)
1604 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1605 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1606 for member in typeinfo.elem.findall('.//member'):
1607 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1608 body += ';\n'
1609 body += '} ' + typeName + ';\n'
1610 self.appendSection('struct', body)
1611 #
1612 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1613 def genGroup(self, groupinfo, groupName, alias):
1614 pass
1615 # Enumerant generation
1616 # <enum> tags may specify their values in several ways, but are usually just integers.
1617 def genEnum(self, enuminfo, name, alias):
1618 pass
1619 #
1620 # Customize Cdecl for layer factory base class
1621 def BaseClassCdecl(self, elem, name):
1622 raw = self.makeCDecls(elem)[1]
1623
1624 # Toss everything before the undecorated name
1625 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1626 prototype = prototype.replace(")", "", 1)
1627 prototype = prototype.replace(";", " {};")
1628
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001629 # Build up pre/post call virtual function declarations
1630 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1631 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1632 pre_call_record = 'virtual void PreCallRecord' + prototype
1633 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001634 resulttype = elem.find('proto/type')
1635 if resulttype.text == 'VkResult':
1636 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001637 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1638 #
1639 # Command generation
1640 def genCmd(self, cmdinfo, name, alias):
1641 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001642 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001643 ]
1644
1645 if name in ignore_functions:
1646 return
1647
1648 if self.header: # In the header declare all intercepts
1649 self.appendSection('command', '')
1650 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1651 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001652 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1653 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001654 if 'ValidationCache' not in name:
1655 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001656 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001657 self.layer_factory += '#endif\n'
1658 return
1659
Mark Lobodzinski31395512019-06-18 16:25:01 -06001660 is_instance = 'false'
1661 dispatchable_type = cmdinfo.elem.find('param/type').text
1662 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1663 is_instance = 'true'
1664
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001665 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001666 if 'ValidationCache' not in name:
Mark Lobodzinski31395512019-06-18 16:25:01 -06001667 self.intercepts += [ ' {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001668 else:
1669 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
Mark Lobodzinski31395512019-06-18 16:25:01 -06001670
1671 self.intercepts += [ ' {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001672 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001673 return
1674 # Record that the function will be intercepted
1675 if (self.featureExtraProtect != None):
1676 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
Mark Lobodzinski31395512019-06-18 16:25:01 -06001677 self.intercepts += [ ' {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001678 if (self.featureExtraProtect != None):
1679 self.intercepts += [ '#endif' ]
1680 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1681 #
1682 decls = self.makeCDecls(cmdinfo.elem)
1683 self.appendSection('command', '')
1684 self.appendSection('command', '%s {' % decls[0][:-1])
1685 # Setup common to call wrappers. First parameter is always dispatchable
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001686 dispatchable_name = cmdinfo.elem.find('param/name').text
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001687 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001688 api_function_name = cmdinfo.elem.attrib.get('name')
1689 params = cmdinfo.elem.findall('param/name')
1690 paramstext = ', '.join([str(param.text) for param in params])
Tony-LunarG152a88b2019-03-20 15:42:24 -06001691 API = api_function_name.replace('vk','Dispatch') + '('
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001692
1693 # Declare result variable, if any.
1694 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001695 'PFN_vkVoidFunction': 'return nullptr;',
1696 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001697 'VkDeviceAddress': 'return 0;',
1698 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1699 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001700 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001701 }
1702 resulttype = cmdinfo.elem.find('proto/type')
1703 assignresult = ''
1704 if (resulttype.text != 'void'):
1705 assignresult = resulttype.text + ' result = '
1706
1707 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001708 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001709
1710 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001711 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001712 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001713 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1714 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1715 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001716
1717 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001718 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001719 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001720 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001721 self.appendSection('command', ' }')
1722
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001723 # Insert pre-dispatch debug utils function call
1724 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001725 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001726
1727 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001728 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001729
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001730 # Insert post-dispatch debug utils function call
1731 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001732 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001733
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001734 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001735 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001736 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001737 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001738 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001739 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001740 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001741 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001742 # Return result variable, if any.
1743 if (resulttype.text != 'void'):
1744 self.appendSection('command', ' return result;')
1745 self.appendSection('command', '}')
1746 #
1747 # Override makeProtoName to drop the "vk" prefix
1748 def makeProtoName(self, name, tail):
1749 return self.genOpts.apientry + name[2:] + tail