blob: 956313c79b642e7b53a131c091b4e5d11d68ce01 [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07003# Copyright (c) 2015-2019 Valve Corporation
4# Copyright (c) 2015-2019 LunarG, Inc.
5# Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06006#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
20# Author: Mark Lobodzinski <mark@lunarg.com>
21#
22# This script generates the dispatch portion of a factory layer which intercepts
23# all Vulkan functions. The resultant factory layer allows rapid development of
24# layers and interceptors.
25
26import os,re,sys
27from generator import *
28from common_codegen import *
29
30# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31#
32# Adds options used by LayerFactoryOutputGenerator objects during factory
33# layer generation.
34#
35# Additional members
36# prefixText - list of strings to prefix generated header with
37# (usually a copyright statement + calling convention macros).
38# protectFile - True if multiple inclusion protection should be
39# generated (based on the filename) around the entire header.
40# protectFeature - True if #ifndef..#endif protection should be
41# generated around a feature interface in the header file.
42# genFuncPointers - True if function pointer typedefs should be
43# generated
44# protectProto - If conditional protection should be generated
45# around prototype declarations, set to either '#ifdef'
46# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47# to require opt-out (#ifndef protectProtoStr). Otherwise
48# set to None.
49# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50# declarations, if protectProto is set
51# apicall - string to use for the function declaration prefix,
52# such as APICALL on Windows.
53# apientry - string to use for the calling convention macro,
54# in typedefs, such as APIENTRY.
55# apientryp - string to use for the calling convention macro
56# in function pointer typedefs, such as APIENTRYP.
57# indentFuncProto - True if prototype declarations should put each
58# parameter on a separate line
59# indentFuncPointer - True if typedefed function pointers should put each
60# parameter on a separate line
61# alignFuncParam - if nonzero and parameters are being put on a
62# separate line, align parameter names at the specified column
63class LayerChassisGeneratorOptions(GeneratorOptions):
64 def __init__(self,
65 filename = None,
66 directory = '.',
67 apiname = None,
68 profile = None,
69 versions = '.*',
70 emitversions = '.*',
71 defaultExtensions = None,
72 addExtensions = None,
73 removeExtensions = None,
74 emitExtensions = None,
75 sortProcedure = regSortFeatures,
76 prefixText = "",
77 genFuncPointers = True,
78 protectFile = True,
79 protectFeature = True,
80 apicall = '',
81 apientry = '',
82 apientryp = '',
83 indentFuncProto = True,
84 indentFuncPointer = False,
85 alignFuncParam = 0,
86 helper_file_type = '',
87 expandEnumerants = True):
88 GeneratorOptions.__init__(self, filename, directory, apiname, profile,
89 versions, emitversions, defaultExtensions,
90 addExtensions, removeExtensions, emitExtensions, sortProcedure)
91 self.prefixText = prefixText
92 self.genFuncPointers = genFuncPointers
93 self.protectFile = protectFile
94 self.protectFeature = protectFeature
95 self.apicall = apicall
96 self.apientry = apientry
97 self.apientryp = apientryp
98 self.indentFuncProto = indentFuncProto
99 self.indentFuncPointer = indentFuncPointer
100 self.alignFuncParam = alignFuncParam
101
102# LayerChassisOutputGenerator - subclass of OutputGenerator.
103# Generates a LayerFactory layer that intercepts all API entrypoints
104# This is intended to be used as a starting point for creating custom layers
105#
106# ---- methods ----
107# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
108# OutputGenerator. Defines additional internal state.
109# ---- methods overriding base class ----
110# beginFile(genOpts)
111# endFile()
112# beginFeature(interface, emit)
113# endFeature()
114# genType(typeinfo,name)
115# genStruct(typeinfo,name)
116# genGroup(groupinfo,name)
117# genEnum(enuminfo, name)
118# genCmd(cmdinfo)
119class LayerChassisOutputGenerator(OutputGenerator):
120 """Generate specified API interfaces in a specific style, such as a C header"""
121 # This is an ordered list of sections in the header file.
122 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
123 'group', 'bitmask', 'funcpointer', 'struct']
124 ALL_SECTIONS = TYPE_SECTIONS + ['command']
125
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700126 manual_functions = [
127 # Include functions here to be interecpted w/ manually implemented function bodies
128 'vkGetDeviceProcAddr',
129 'vkGetInstanceProcAddr',
130 'vkGetPhysicalDeviceProcAddr',
131 'vkCreateDevice',
132 'vkDestroyDevice',
133 'vkCreateInstance',
134 'vkDestroyInstance',
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 Lobodzinski09f86362018-12-13 14:07:20 -0700151 ]
152
153 alt_ret_codes = [
154 # Include functions here which must tolerate VK_INCOMPLETE as a return code
155 'vkEnumeratePhysicalDevices',
156 'vkEnumeratePhysicalDeviceGroupsKHR',
157 'vkGetValidationCacheDataEXT',
158 'vkGetPipelineCacheData',
159 'vkGetShaderInfoAMD',
160 'vkGetPhysicalDeviceDisplayPropertiesKHR',
161 'vkGetPhysicalDeviceDisplayProperties2KHR',
162 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
163 'vkGetDisplayPlaneSupportedDisplaysKHR',
164 'vkGetDisplayModePropertiesKHR',
165 'vkGetDisplayModeProperties2KHR',
166 'vkGetPhysicalDeviceSurfaceFormatsKHR',
167 'vkGetPhysicalDeviceSurfacePresentModesKHR',
168 'vkGetPhysicalDevicePresentRectanglesKHR',
169 'vkGetPastPresentationTimingGOOGLE',
170 'vkGetSwapchainImagesKHR',
171 'vkEnumerateInstanceLayerProperties',
172 'vkEnumerateDeviceLayerProperties',
173 'vkEnumerateInstanceExtensionProperties',
174 'vkEnumerateDeviceExtensionProperties',
175 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
176 ]
177
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700178 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700179 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
180 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700181 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
182 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
183 'vkCmdBeginDebugUtilsLabelEXT' : 'BeginCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
184 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
185 }
186
187 post_dispatch_debug_utils_functions = {
188 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
189 'vkCmdEndDebugUtilsLabelEXT' : 'EndCmdDebugUtilsLabel(layer_data->report_data, commandBuffer);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700190 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
191 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
192 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
193 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
194 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700195 }
196
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600197 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
198 precallrecord_loop = precallvalidate_loop
199 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600200
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700201 inline_custom_header_preamble = """
202#define NOMINMAX
203#include <mutex>
204#include <cinttypes>
205#include <stdio.h>
206#include <stdlib.h>
207#include <string.h>
208#include <unordered_map>
209#include <unordered_set>
210#include <algorithm>
211#include <memory>
212
213#include "vk_loader_platform.h"
214#include "vulkan/vulkan.h"
215#include "vk_layer_config.h"
216#include "vk_layer_data.h"
217#include "vk_layer_logging.h"
218#include "vk_object_types.h"
219#include "vulkan/vk_layer.h"
220#include "vk_enum_string_helper.h"
221#include "vk_layer_extension_utils.h"
222#include "vk_layer_utils.h"
223#include "vulkan/vk_layer.h"
224#include "vk_dispatch_table_helper.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700225#include "vk_extension_helper.h"
226#include "vk_safe_struct.h"
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700227#include "vk_typemap_helper.h"
228
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700229
230extern uint64_t global_unique_id;
231extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
232"""
233
234 inline_custom_header_class_definition = """
235
236// Layer object type identifiers
237enum LayerObjectTypeId {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700238 LayerObjectTypeInstance, // Container for an instance dispatch object
239 LayerObjectTypeDevice, // Container for a device dispatch object
240 LayerObjectTypeThreading, // Instance or device threading layer object
241 LayerObjectTypeParameterValidation, // Instance or device parameter validation layer object
242 LayerObjectTypeObjectTracker, // Instance or device object tracker layer object
243 LayerObjectTypeCoreValidation, // Instance or device core validation layer object
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700244};
245
246struct TEMPLATE_STATE {
247 VkDescriptorUpdateTemplateKHR desc_update_template;
248 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
249
250 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
251 : desc_update_template(update_template), create_info(*pCreateInfo) {}
252};
253
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700254class LAYER_PHYS_DEV_PROPERTIES {
255public:
256 VkPhysicalDeviceProperties properties;
257 std::vector<VkQueueFamilyProperties> queue_family_properties;
258};
259
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600260typedef enum ValidationCheckDisables {
261 VALIDATION_CHECK_DISABLE_DESTROY_PIPELINE,
262 VALIDATION_CHECK_DISABLE_DESTROY_SAMPLER,
263 VALIDATION_CHECK_DISABLE_DESTROY_COMMAND_POOL,
264 VALIDATION_CHECK_DISABLE_DESTROY_SEMAPHORE,
265 VALIDATION_CHECK_DISABLE_DESTROY_DESCRIPTOR_POOL,
266 VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE,
267 VALIDATION_CHECK_DISABLE_CREATE_DESCRIPTOR_SET_LAYOUT,
268 VALIDATION_CHECK_DISABLE_OBJECT_IN_USE,
269 VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET,
270 VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE,
271 VALIDATION_CHECK_DISABLE_ALLOCATE_DESCRIPTOR_SETS,
272 VALIDATION_CHECK_DISABLE_UPDATE_DESCRIPTOR_SETS,
273 VALIDATION_CHECK_DISABLE_WAIT_FOR_FENCES,
274 VALIDATION_CHECK_DISABLE_QUEUE_WAIT_IDLE,
275 VALIDATION_CHECK_DISABLE_DEVICE_WAIT_IDLE,
276} ValidationCheckDisables;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600277
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600278
279// CHECK_DISABLED struct is a container for bools that can block validation checks from being performed.
280// These bools are all "false" by default meaning that all checks are enabled. Enum values can be specified
281// via the vk_layer_setting.txt config file or at CreateInstance time via the VK_EXT_validation_features extension
282// that can selectively disable checks.
283struct CHECK_DISABLED {
284 bool destroy_pipeline; // Skip validation at DestroyPipeline time
285 bool destroy_sampler; // Skip validation at DestroySampler time
286 bool destroy_command_pool; // Skip validation at DestroyCommandPool time
287 bool destroy_semaphore; // Skip validation at DestroySemaphore time
288 bool destroy_descriptor_pool; // Skip validation at DestroyDescriptorPool time
289 bool command_buffer_state; // Skip command buffer state validation
290 bool create_descriptor_set_layout; // Skip validation at CreateDescSetLayout time
291 bool object_in_use; // Skip all object in_use checking
292 bool idle_descriptor_set; // Skip check to verify that descriptor set is not in-use
293 bool push_constant_range; // Skip push constant range checks
294 bool allocate_descriptor_sets; // Skip validation prior to vkAllocateDescriptorSets()
295 bool update_descriptor_sets; // Skip validation prior to vkUpdateDescriptorSets()
296 bool wait_for_fences; // Skip validation at WaitForFences time
297 bool queue_wait_idle; // Skip validation at QueueWaitIdle time
298 bool device_wait_idle; // Skip validation at DeviceWaitIdle time
299 bool object_tracking; // Disable object lifetime validation
300 bool core_checks; // Disable core validation checks
301 bool thread_safety; // Disable thread safety validation
302 bool stateless_checks; // Disable stateless validation checks
303 bool handle_wrapping; // Disable unique handles/handle wrapping
304 bool shader_validation; // Skip validation for shaders
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700305
306 void SetAll(bool value) { std::fill(&command_buffer_state, &shader_validation + 1, value); }
307};
308
309struct CHECK_ENABLED {
310 bool gpu_validation;
311 bool gpu_validation_reserve_binding_slot;
312
313 void SetAll(bool value) { std::fill(&gpu_validation, &gpu_validation_reserve_binding_slot + 1, value); }
314};
315
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700316// Layer chassis validation object base class definition
317class ValidationObject {
318 public:
319 uint32_t api_version;
320 debug_report_data* report_data = nullptr;
321 std::vector<VkDebugReportCallbackEXT> logging_callback;
322 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
323
324 VkLayerInstanceDispatchTable instance_dispatch_table;
325 VkLayerDispatchTable device_dispatch_table;
326
327 InstanceExtensions instance_extensions;
328 DeviceExtensions device_extensions = {};
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700329 CHECK_DISABLED disabled = {};
330 CHECK_ENABLED enabled = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700331
332 VkInstance instance = VK_NULL_HANDLE;
333 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
334 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700335 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700336
337 std::vector<ValidationObject*> object_dispatch;
338 LayerObjectTypeId container_type;
339
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700340 std::string layer_name = "CHASSIS";
341
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700342 // Constructor
343 ValidationObject(){};
344 // Destructor
345 virtual ~ValidationObject() {};
346
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700347 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700348 virtual std::unique_lock<std::mutex> write_lock() {
349 return std::unique_lock<std::mutex>(validation_object_mutex);
350 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700351
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700352 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
353 for (auto validation_object : object_dispatch) {
354 if (validation_object->container_type == object_type) {
355 return validation_object;
356 }
357 }
358 return nullptr;
359 };
360
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700361 // Handle Wrapping Data
362 // Reverse map display handles
363 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
364 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700365 struct SubpassesUsageStates {
366 std::unordered_set<uint32_t> subpasses_using_color_attachment;
367 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
368 };
369 // Uses unwrapped handles
370 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
371 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
372 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
373 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700374 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
375 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700376
377
378 // Unwrap a handle. Must hold lock.
379 template <typename HandleType>
380 HandleType Unwrap(HandleType wrappedHandle) {
381 // TODO: don't use operator[] here.
382 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
383 }
384
385 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
386 template <typename HandleType>
387 HandleType WrapNew(HandleType newlyCreatedHandle) {
388 auto unique_id = global_unique_id++;
389 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
390 return (HandleType)unique_id;
391 }
392
393 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
394 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
395 auto unique_id = global_unique_id++;
396 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
397 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
398 return (VkDisplayKHR)unique_id;
399 }
400
401 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
402 // creating another. Must hold lock.
403 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
404 // See if this display is already known
405 auto it = map_data->display_id_reverse_mapping.find(handle);
406 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
407 // Unknown, so wrap
408 return WrapDisplay(handle, map_data);
409 }
410
411 // Pre/post hook point declarations
412"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600413
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700414 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600415// This file is ***GENERATED***. Do Not Edit.
416// See layer_chassis_generator.py for modifications.
417
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700418/* Copyright (c) 2015-2019 The Khronos Group Inc.
419 * Copyright (c) 2015-2019 Valve Corporation
420 * Copyright (c) 2015-2019 LunarG, Inc.
421 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600422 *
423 * Licensed under the Apache License, Version 2.0 (the "License");
424 * you may not use this file except in compliance with the License.
425 * You may obtain a copy of the License at
426 *
427 * http://www.apache.org/licenses/LICENSE-2.0
428 *
429 * Unless required by applicable law or agreed to in writing, software
430 * distributed under the License is distributed on an "AS IS" BASIS,
431 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
432 * See the License for the specific language governing permissions and
433 * limitations under the License.
434 *
435 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700436 */"""
437
438 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600439
440#include <string.h>
441#include <mutex>
442
443#define VALIDATION_ERROR_MAP_IMPL
444
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600445#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700446#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600447
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600448std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600449
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700450// Global unique object identifier. All increments must be guarded by a lock.
451uint64_t global_unique_id = 1;
452// Map uniqueID to actual object handle
453std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
454
455// TODO: This variable controls handle wrapping -- in the future it should be hooked
456// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
457#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
458bool wrap_handles = true;
459#else
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600460bool wrap_handles = false;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700461#endif
462
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600463// Set layer name -- Khronos layer name overrides any other defined names
Mark Lobodzinskiaa6fd7b2019-03-19 09:26:48 -0600464#if BUILD_KHRONOS_VALIDATION
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600465#define OBJECT_LAYER_NAME "VK_LAYER_KHRONOS_validation"
466#define OBJECT_LAYER_DESCRIPTION "khronos_validation"
467#elif BUILD_OBJECT_TRACKER
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700468#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600469#define OBJECT_LAYER_DESCRIPTION "lunarg_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700470#elif BUILD_THREAD_SAFETY
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700471#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600472#define OBJECT_LAYER_DESCRIPTION "google_thread_checker"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700473#elif BUILD_PARAMETER_VALIDATION
474#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600475#define OBJECT_LAYER_DESCRIPTION "lunarg_parameter_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700476#elif BUILD_CORE_VALIDATION
477#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600478#define OBJECT_LAYER_DESCRIPTION "lunarg_core_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700479#else
480#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600481#define OBJECT_LAYER_DESCRIPTION "lunarg_unique_objects"
482#endif
483
484// Include layer validation object definitions
485#if BUILD_OBJECT_TRACKER
486#include "object_lifetime_validation.h"
487#endif
488#if BUILD_THREAD_SAFETY
489#include "thread_safety.h"
490#endif
491#if BUILD_PARAMETER_VALIDATION
492#include "stateless_validation.h"
493#endif
494#if BUILD_CORE_VALIDATION
495#include "core_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700496#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600497
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600498namespace vulkan_layer_chassis {
499
500using std::unordered_map;
501
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600502static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700503 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600504};
505
506static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
507
508extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
509
510
511// Manually written functions
512
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700513// Check enabled instance extensions against supported instance extension whitelist
514static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
515 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
516 // Check for recognized instance extensions
517 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
518 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
519 kVUIDUndefined,
520 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
521 "results and/or produce undefined behavior.",
522 pCreateInfo->ppEnabledExtensionNames[i]);
523 }
524 }
525}
526
527// Check enabled device extensions against supported device extension whitelist
528static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
529 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
530 // Check for recognized device extensions
531 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
532 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
533 kVUIDUndefined,
534 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
535 "results and/or produce undefined behavior.",
536 pCreateInfo->ppEnabledExtensionNames[i]);
537 }
538 }
539}
540
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600541
542// Process validation features, flags and settings specified through extensions, a layer settings file, or environment variables
543
544static const std::unordered_map<std::string, VkValidationFeatureDisableEXT> VkValFeatureDisableLookup = {
545 {"VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT", VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT},
546 {"VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT", VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT},
547 {"VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT", VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT},
548 {"VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT", VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT},
549 {"VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT", VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT},
550 {"VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT", VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT},
551 {"VK_VALIDATION_FEATURE_DISABLE_ALL_EXT", VK_VALIDATION_FEATURE_DISABLE_ALL_EXT},
552};
553
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600554static const std::unordered_map<std::string, VkValidationFeatureEnableEXT> VkValFeatureEnableLookup = {
555 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT},
556 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT},
557};
558
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600559static const std::unordered_map<std::string, ValidationCheckDisables> ValidationDisableLookup = {
560 {"VALIDATION_CHECK_DISABLE_DESTROY_PIPELINE", VALIDATION_CHECK_DISABLE_DESTROY_PIPELINE},
561 {"VALIDATION_CHECK_DISABLE_DESTROY_SAMPLER", VALIDATION_CHECK_DISABLE_DESTROY_SAMPLER},
562 {"VALIDATION_CHECK_DISABLE_DESTROY_COMMAND_POOL", VALIDATION_CHECK_DISABLE_DESTROY_COMMAND_POOL},
563 {"VALIDATION_CHECK_DISABLE_DESTROY_SEMAPHORE", VALIDATION_CHECK_DISABLE_DESTROY_SEMAPHORE},
564 {"VALIDATION_CHECK_DISABLE_DESTROY_DESCRIPTOR_POOL", VALIDATION_CHECK_DISABLE_DESTROY_DESCRIPTOR_POOL},
565 {"VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE", VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE},
566 {"VALIDATION_CHECK_DISABLE_CREATE_DESCRIPTOR_SET_LAYOUT", VALIDATION_CHECK_DISABLE_CREATE_DESCRIPTOR_SET_LAYOUT},
567 {"VALIDATION_CHECK_DISABLE_OBJECT_IN_USE", VALIDATION_CHECK_DISABLE_OBJECT_IN_USE},
568 {"VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET", VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET},
569 {"VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE", VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE},
570 {"VALIDATION_CHECK_DISABLE_ALLOCATE_DESCRIPTOR_SETS", VALIDATION_CHECK_DISABLE_ALLOCATE_DESCRIPTOR_SETS},
571 {"VALIDATION_CHECK_DISABLE_UPDATE_DESCRIPTOR_SETS", VALIDATION_CHECK_DISABLE_UPDATE_DESCRIPTOR_SETS},
572 {"VALIDATION_CHECK_DISABLE_WAIT_FOR_FENCES", VALIDATION_CHECK_DISABLE_WAIT_FOR_FENCES},
573 {"VALIDATION_CHECK_DISABLE_QUEUE_WAIT_IDLE", VALIDATION_CHECK_DISABLE_QUEUE_WAIT_IDLE},
574 {"VALIDATION_CHECK_DISABLE_DEVICE_WAIT_IDLE", VALIDATION_CHECK_DISABLE_DEVICE_WAIT_IDLE},
575};
576
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600577// Set the local disable flag for the appropriate VALIDATION_CHECK_DISABLE enum
578void SetValidationDisable(CHECK_DISABLED* disable_data, const ValidationCheckDisables disable_id) {
579 switch (disable_id) {
580 case VALIDATION_CHECK_DISABLE_DESTROY_PIPELINE:
581 disable_data->destroy_pipeline = true;
582 break;
583 case VALIDATION_CHECK_DISABLE_DESTROY_SAMPLER:
584 disable_data->destroy_sampler = true;
585 break;
586 case VALIDATION_CHECK_DISABLE_DESTROY_COMMAND_POOL:
587 disable_data->destroy_command_pool = true;
588 break;
589 case VALIDATION_CHECK_DISABLE_DESTROY_SEMAPHORE:
590 disable_data->destroy_semaphore = true;
591 break;
592 case VALIDATION_CHECK_DISABLE_DESTROY_DESCRIPTOR_POOL:
593 disable_data->destroy_descriptor_pool = true;
594 break;
595 case VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE:
596 disable_data->command_buffer_state = true;
597 break;
598 case VALIDATION_CHECK_DISABLE_CREATE_DESCRIPTOR_SET_LAYOUT:
599 disable_data->create_descriptor_set_layout = true;
600 break;
601 case VALIDATION_CHECK_DISABLE_OBJECT_IN_USE:
602 disable_data->object_in_use = true;
603 break;
604 case VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET:
605 disable_data->idle_descriptor_set = true;
606 break;
607 case VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE:
608 disable_data->push_constant_range = true;
609 break;
610 case VALIDATION_CHECK_DISABLE_ALLOCATE_DESCRIPTOR_SETS:
611 disable_data->allocate_descriptor_sets = true;
612 break;
613 case VALIDATION_CHECK_DISABLE_UPDATE_DESCRIPTOR_SETS:
614 disable_data->update_descriptor_sets = true;
615 break;
616 case VALIDATION_CHECK_DISABLE_WAIT_FOR_FENCES:
617 disable_data->wait_for_fences = true;
618 break;
619 case VALIDATION_CHECK_DISABLE_QUEUE_WAIT_IDLE:
620 disable_data->queue_wait_idle = true;
621 break;
622 case VALIDATION_CHECK_DISABLE_DEVICE_WAIT_IDLE:
623 disable_data->device_wait_idle = true;
624 break;
625 default:
626 assert(true);
627 }
628}
629
630// Set the local disable flag for a single VK_VALIDATION_FEATURE_DISABLE_* flag
631void SetValidationFeatureDisable(CHECK_DISABLED* disable_data, const VkValidationFeatureDisableEXT feature_disable) {
632 switch (feature_disable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700633 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600634 disable_data->shader_validation = true;
635 break;
636 case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
637 disable_data->thread_safety = true;
638 break;
639 case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
640 disable_data->stateless_checks = true;
641 break;
642 case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
643 disable_data->object_tracking = true;
644 break;
645 case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
646 disable_data->core_checks = true;
647 break;
648 case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
649 disable_data->handle_wrapping = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700650 break;
651 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
652 // Set all disabled flags to true
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600653 disable_data->SetAll(true);
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700654 break;
655 default:
656 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700657 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600658}
659
660// Set the local enable flag for a single VK_VALIDATION_FEATURE_ENABLE_* flag
661void SetValidationFeatureEnable(CHECK_ENABLED *enable_data, const VkValidationFeatureEnableEXT feature_enable) {
662 switch (feature_enable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700663 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600664 enable_data->gpu_validation = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700665 break;
666 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600667 enable_data->gpu_validation_reserve_binding_slot = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700668 break;
669 default:
670 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700671 }
672}
673
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600674// Set the local disable flag for settings specified through the VK_EXT_validation_flags extension
675void SetValidationFlags(CHECK_DISABLED* disables, const VkValidationFlagsEXT* val_flags_struct) {
676 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
677 switch (val_flags_struct->pDisabledValidationChecks[i]) {
678 case VK_VALIDATION_CHECK_SHADERS_EXT:
679 disables->shader_validation = true;
680 break;
681 case VK_VALIDATION_CHECK_ALL_EXT:
682 // Set all disabled flags to true
683 disables->SetAll(true);
684 break;
685 default:
686 break;
687 }
688 }
689}
690
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600691// Process Validation Features flags specified through the ValidationFeature extension
692void SetValidationFeatures(CHECK_DISABLED *disable_data, CHECK_ENABLED *enable_data,
693 const VkValidationFeaturesEXT *val_features_struct) {
694 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
695 SetValidationFeatureDisable(disable_data, val_features_struct->pDisabledValidationFeatures[i]);
696 }
697 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
698 SetValidationFeatureEnable(enable_data, val_features_struct->pEnabledValidationFeatures[i]);
699 }
700}
701
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600702// Given a string representation of a list of enable enum values, call the appropriate setter function
703void SetLocalEnableSetting(std::string list_of_enables, std::string delimiter, CHECK_ENABLED* enables) {
704 size_t pos = 0;
705 std::string token;
706 while (list_of_enables.length() != 0) {
707 pos = list_of_enables.find(delimiter);
708 if (pos != std::string::npos) {
709 token = list_of_enables.substr(0, pos);
710 } else {
711 pos = list_of_enables.length() - delimiter.length();
712 token = list_of_enables;
713 }
714 if (token.find("VK_VALIDATION_FEATURE_ENABLE_") != std::string::npos) {
715 auto result = VkValFeatureEnableLookup.find(token);
716 if (result != VkValFeatureEnableLookup.end()) {
717 SetValidationFeatureEnable(enables, result->second);
718 }
719 }
720 list_of_enables.erase(0, pos + delimiter.length());
721 }
722}
723
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600724// Given a string representation of a list of disable enum values, call the appropriate setter function
725void SetLocalDisableSetting(std::string list_of_disables, std::string delimiter, CHECK_DISABLED* disables) {
726 size_t pos = 0;
727 std::string token;
728 while (list_of_disables.length() != 0) {
729 pos = list_of_disables.find(delimiter);
730 if (pos != std::string::npos) {
731 token = list_of_disables.substr(0, pos);
732 } else {
733 pos = list_of_disables.length() - delimiter.length();
734 token = list_of_disables;
735 }
736 if (token.find("VK_VALIDATION_FEATURE_DISABLE_") != std::string::npos) {
737 auto result = VkValFeatureDisableLookup.find(token);
738 if (result != VkValFeatureDisableLookup.end()) {
739 SetValidationFeatureDisable(disables, result->second);
740 }
741 }
742 if (token.find("VALIDATION_CHECK_DISABLE_") != std::string::npos) {
743 auto result = ValidationDisableLookup.find(token);
744 if (result != ValidationDisableLookup.end()) {
745 SetValidationDisable(disables, result->second);
746 }
747 }
748 list_of_disables.erase(0, pos + delimiter.length());
749 }
750}
751
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600752// Process enables and disables set though the vk_layer_settings.txt config file or through an environment variable
753void ProcessConfigAndEnvSettings(const char* layer_description, CHECK_ENABLED* enables, CHECK_DISABLED* disables) {
754 std::string enable_key = layer_description;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600755 std::string disable_key = layer_description;
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600756 enable_key.append(".enables");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600757 disable_key.append(".disables");
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600758 std::string list_of_config_enables = getLayerOption(enable_key.c_str());
759 std::string list_of_env_enables = GetLayerEnvVar("VK_LAYER_ENABLES");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600760 std::string list_of_config_disables = getLayerOption(disable_key.c_str());
761 std::string list_of_env_disables = GetLayerEnvVar("VK_LAYER_DISABLES");
762#if defined(_WIN32)
763 std::string env_delimiter = ";";
764#else
765 std::string env_delimiter = ":";
766#endif
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600767 SetLocalEnableSetting(list_of_config_enables, ",", enables);
768 SetLocalEnableSetting(list_of_env_enables, env_delimiter, enables);
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600769 SetLocalDisableSetting(list_of_config_disables, ",", disables);
770 SetLocalDisableSetting(list_of_env_disables, env_delimiter, disables);
771}
772
773
774// Non-code-generated chassis API functions
775
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600776VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600777 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700778 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700779 return nullptr;
780 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600781 const auto &item = name_to_funcptr_map.find(funcName);
782 if (item != name_to_funcptr_map.end()) {
783 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
784 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600785 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600786 if (!table.GetDeviceProcAddr) return nullptr;
787 return table.GetDeviceProcAddr(device, funcName);
788}
789
790VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600791 const auto &item = name_to_funcptr_map.find(funcName);
792 if (item != name_to_funcptr_map.end()) {
793 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
794 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600795 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
796 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600797 if (!table.GetInstanceProcAddr) return nullptr;
798 return table.GetInstanceProcAddr(instance, funcName);
799}
800
801VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600802 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
803 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600804 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
805 return table.GetPhysicalDeviceProcAddr(instance, funcName);
806}
807
808VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
809 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
810}
811
812VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
813 VkLayerProperties *pProperties) {
814 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
815}
816
817VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
818 VkExtensionProperties *pProperties) {
819 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
820 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
821
822 return VK_ERROR_LAYER_NOT_PRESENT;
823}
824
825VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
826 uint32_t *pCount, VkExtensionProperties *pProperties) {
827 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600828 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600829 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
830 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600831}
832
833VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
834 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600835 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600836
837 assert(chain_info->u.pLayerInfo);
838 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
839 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
840 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
841 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700842 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
843 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
844
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600845 CHECK_ENABLED local_enables {};
846 CHECK_DISABLED local_disables {};
847 const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(pCreateInfo->pNext);
848 if (validation_features_ext) {
849 SetValidationFeatures(&local_disables, &local_enables, validation_features_ext);
850 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600851 const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
852 if (validation_flags_ext) {
853 SetValidationFlags(&local_disables, validation_flags_ext);
854 }
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600855 ProcessConfigAndEnvSettings(OBJECT_LAYER_DESCRIPTION, &local_enables, &local_disables);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600856
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600857 // Create temporary dispatch vector for pre-calls until instance is created
858 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600859 // Add VOs to dispatch vector. Order here will be the validation dispatch order!
860#if BUILD_THREAD_SAFETY
861 auto thread_checker = new ThreadSafety;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600862 if (!local_disables.thread_safety) {
863 local_object_dispatch.emplace_back(thread_checker);
864 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600865 thread_checker->container_type = LayerObjectTypeThreading;
866 thread_checker->api_version = api_version;
867#endif
868#if BUILD_PARAMETER_VALIDATION
869 auto parameter_validation = new StatelessValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600870 if (!local_disables.stateless_checks) {
871 local_object_dispatch.emplace_back(parameter_validation);
872 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600873 parameter_validation->container_type = LayerObjectTypeParameterValidation;
874 parameter_validation->api_version = api_version;
875#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700876#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600877 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600878 if (!local_disables.object_tracking) {
879 local_object_dispatch.emplace_back(object_tracker);
880 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600881 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700882 object_tracker->api_version = api_version;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600883#endif
884#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700885 auto core_checks = new CoreChecks;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600886 if (!local_disables.core_checks) {
887 local_object_dispatch.emplace_back(core_checks);
888 }
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700889 core_checks->container_type = LayerObjectTypeCoreValidation;
890 core_checks->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700891#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600892
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600893 // If handle wrapping is disabled via the ValidationFeatures extension, override build flag
894 if (local_disables.handle_wrapping) {
895 wrap_handles = false;
896 }
897
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600898 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600899 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600900 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
901 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600902 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600903 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
904 }
905
906 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600907 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600908
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600909 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600910
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600911 framework->object_dispatch = local_object_dispatch;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700912 framework->container_type = LayerObjectTypeInstance;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600913 framework->disabled = local_disables;
914 framework->enabled = local_enables;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600915
916 framework->instance = *pInstance;
917 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
918 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
919 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700920 framework->api_version = api_version;
921 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
922
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600923 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, OBJECT_LAYER_DESCRIPTION);
924
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700925#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700926 object_tracker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600927 object_tracker->instance_dispatch_table = framework->instance_dispatch_table;
928 object_tracker->enabled = framework->enabled;
929 object_tracker->disabled = framework->disabled;
930#endif
931#if BUILD_THREAD_SAFETY
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700932 thread_checker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600933 thread_checker->instance_dispatch_table = framework->instance_dispatch_table;
934 thread_checker->enabled = framework->enabled;
935 thread_checker->disabled = framework->disabled;
936#endif
937#if BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700938 parameter_validation->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600939 parameter_validation->instance_dispatch_table = framework->instance_dispatch_table;
940 parameter_validation->enabled = framework->enabled;
941 parameter_validation->disabled = framework->disabled;
942#endif
943#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700944 core_checks->report_data = framework->report_data;
945 core_checks->instance_dispatch_table = framework->instance_dispatch_table;
946 core_checks->instance = *pInstance;
947 core_checks->enabled = framework->enabled;
948 core_checks->disabled = framework->disabled;
949 core_checks->instance_state = core_checks;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700950#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600951
952 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700953 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600954 }
955
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700956 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
957
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600958 return result;
959}
960
961VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
962 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600963 auto layer_data = GetLayerDataPtr(key, layer_data_map);
964 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700965 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600966 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
967 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600968 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700969 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600970 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
971 }
972
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600973 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600974
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600975 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700976 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600977 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
978 }
979 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600980 while (layer_data->logging_messenger.size() > 0) {
981 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
982 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
983 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600984 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600985 while (layer_data->logging_callback.size() > 0) {
986 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
987 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
988 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600989 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600990
991 layer_debug_utils_destroy_instance(layer_data->report_data);
992
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700993 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
994 delete *item;
995 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600996 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600997}
998
999VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
1000 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001001 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001002
1003 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
1004
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001005 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
1006 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001007 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
1008 if (fpCreateDevice == NULL) {
1009 return VK_ERROR_INITIALIZATION_FAILED;
1010 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001011 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
1012
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001013 // Get physical device limits for device
1014 VkPhysicalDeviceProperties device_properties = {};
1015 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
1016
1017 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
1018 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
1019
1020 DeviceExtensions device_extensions = {};
1021 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
1022 for (auto item : instance_interceptor->object_dispatch) {
1023 item->device_extensions = device_extensions;
1024 }
1025
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001026 std::unique_ptr<safe_VkDeviceCreateInfo> modified_create_info(new safe_VkDeviceCreateInfo(pCreateInfo));
1027
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001028 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001029 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001030 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001031 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001032 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001033 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001034 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001035 auto lock = intercept->write_lock();
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001036 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, modified_create_info);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001037 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001038
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001039 VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(modified_create_info.get()), pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001040 if (result != VK_SUCCESS) {
1041 return result;
1042 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001043
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001044 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001045 device_interceptor->container_type = LayerObjectTypeDevice;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001046
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001047 // Save local info in device object
1048 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001049 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
1050 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001051 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001052
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001053 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001054
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001055 device_interceptor->device = *pDevice;
1056 device_interceptor->physical_device = gpu;
1057 device_interceptor->instance = instance_interceptor->instance;
1058 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001059
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001060 // Note that this defines the order in which the layer validation objects are called
1061#if BUILD_THREAD_SAFETY
1062 auto thread_safety = new ThreadSafety;
1063 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
1064 thread_safety->container_type = LayerObjectTypeThreading;
1065 thread_safety->physical_device = gpu;
1066 thread_safety->instance = instance_interceptor->instance;
1067 thread_safety->report_data = device_interceptor->report_data;
1068 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
1069 thread_safety->api_version = device_interceptor->api_version;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001070 if (!instance_interceptor->disabled.thread_safety) {
1071 device_interceptor->object_dispatch.emplace_back(thread_safety);
1072 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001073#endif
1074#if BUILD_PARAMETER_VALIDATION
1075 auto stateless_validation = new StatelessValidation;
1076 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
1077 stateless_validation->container_type = LayerObjectTypeParameterValidation;
1078 stateless_validation->physical_device = gpu;
1079 stateless_validation->instance = instance_interceptor->instance;
1080 stateless_validation->report_data = device_interceptor->report_data;
1081 stateless_validation->device_dispatch_table = device_interceptor->device_dispatch_table;
1082 stateless_validation->api_version = device_interceptor->api_version;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001083 if (!instance_interceptor->disabled.stateless_checks) {
1084 device_interceptor->object_dispatch.emplace_back(stateless_validation);
1085 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001086#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001087#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001088 // Create child layer objects for this key and add to dispatch vector
1089 auto object_tracker = new ObjectLifetimes;
1090 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
1091 object_tracker->container_type = LayerObjectTypeObjectTracker;
1092 object_tracker->physical_device = gpu;
1093 object_tracker->instance = instance_interceptor->instance;
1094 object_tracker->report_data = device_interceptor->report_data;
1095 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -07001096 object_tracker->api_version = device_interceptor->api_version;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001097 if (!instance_interceptor->disabled.object_tracking) {
1098 device_interceptor->object_dispatch.emplace_back(object_tracker);
1099 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001100#endif
1101#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001102 auto core_checks = new CoreChecks;
1103 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
1104 core_checks->container_type = LayerObjectTypeCoreValidation;
1105 core_checks->physical_device = gpu;
1106 core_checks->instance = instance_interceptor->instance;
1107 core_checks->report_data = device_interceptor->report_data;
1108 core_checks->device_dispatch_table = device_interceptor->device_dispatch_table;
1109 core_checks->instance_dispatch_table = instance_interceptor->instance_dispatch_table;
1110 core_checks->api_version = device_interceptor->api_version;
1111 core_checks->instance_extensions = instance_interceptor->instance_extensions;
1112 core_checks->device_extensions = device_interceptor->device_extensions;
1113 core_checks->instance_state = reinterpret_cast<CoreChecks *>(
1114 core_checks->GetValidationObject(instance_interceptor->object_dispatch, LayerObjectTypeCoreValidation));
1115 core_checks->device = *pDevice;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001116 if (!instance_interceptor->disabled.core_checks) {
1117 device_interceptor->object_dispatch.emplace_back(core_checks);
1118 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001119#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001120
1121 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001122 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001123 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001124 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001125
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001126 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
1127
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001128 return result;
1129}
1130
1131VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
1132 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001133 auto layer_data = GetLayerDataPtr(key, layer_data_map);
1134 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001135 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001136 intercept->PreCallValidateDestroyDevice(device, pAllocator);
1137 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001138 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001139 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001140 intercept->PreCallRecordDestroyDevice(device, pAllocator);
1141 }
1142 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001143
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001144 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001145
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001146 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001147 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001148 intercept->PostCallRecordDestroyDevice(device, pAllocator);
1149 }
1150
Mark Lobodzinskic5003372018-12-17 16:36:01 -07001151 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
1152 delete *item;
1153 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001154 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001155}
1156
1157
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001158// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001159
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001160VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
1161 VkDevice device,
1162 VkPipelineCache pipelineCache,
1163 uint32_t createInfoCount,
1164 const VkGraphicsPipelineCreateInfo* pCreateInfos,
1165 const VkAllocationCallbacks* pAllocator,
1166 VkPipeline* pPipelines) {
1167 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1168 bool skip = false;
1169
1170#ifdef BUILD_CORE_VALIDATION
1171 create_graphics_pipeline_api_state cgpl_state{};
1172#else
1173 struct create_graphics_pipeline_api_state {
1174 const VkGraphicsPipelineCreateInfo* pCreateInfos;
1175 } cgpl_state;
1176 cgpl_state.pCreateInfos = pCreateInfos;
1177#endif
1178
1179 for (auto intercept : layer_data->object_dispatch) {
1180 auto lock = intercept->write_lock();
1181 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1182 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1183 }
1184 for (auto intercept : layer_data->object_dispatch) {
1185 auto lock = intercept->write_lock();
1186 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1187 }
1188
Tony-LunarG152a88b2019-03-20 15:42:24 -06001189 VkResult result = DispatchCreateGraphicsPipelines(device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001190
1191 for (auto intercept : layer_data->object_dispatch) {
1192 auto lock = intercept->write_lock();
1193 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
1194 }
1195 return result;
1196}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001197
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001198// This API saves some core_validation pipeline state state on the stack for performance purposes
1199VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
1200 VkDevice device,
1201 VkPipelineCache pipelineCache,
1202 uint32_t createInfoCount,
1203 const VkComputePipelineCreateInfo* pCreateInfos,
1204 const VkAllocationCallbacks* pAllocator,
1205 VkPipeline* pPipelines) {
1206 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1207 bool skip = false;
1208
1209#ifndef BUILD_CORE_VALIDATION
1210 struct PIPELINE_STATE {};
1211#endif
1212
1213 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
1214
1215 for (auto intercept : layer_data->object_dispatch) {
1216 auto lock = intercept->write_lock();
1217 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
1218 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1219 }
1220 for (auto intercept : layer_data->object_dispatch) {
1221 auto lock = intercept->write_lock();
1222 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1223 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001224 VkResult result = DispatchCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001225 for (auto intercept : layer_data->object_dispatch) {
1226 auto lock = intercept->write_lock();
1227 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1228 }
1229 return result;
1230}
1231
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001232VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
1233 VkDevice device,
1234 VkPipelineCache pipelineCache,
1235 uint32_t createInfoCount,
1236 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
1237 const VkAllocationCallbacks* pAllocator,
1238 VkPipeline* pPipelines) {
1239 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1240 bool skip = false;
1241
1242#ifndef BUILD_CORE_VALIDATION
1243 struct PIPELINE_STATE {};
1244#endif
1245
1246 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
1247
1248 for (auto intercept : layer_data->object_dispatch) {
1249 auto lock = intercept->write_lock();
1250 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
1251 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1252 }
1253 for (auto intercept : layer_data->object_dispatch) {
1254 auto lock = intercept->write_lock();
1255 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1256 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001257 VkResult result = DispatchCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001258 for (auto intercept : layer_data->object_dispatch) {
1259 auto lock = intercept->write_lock();
1260 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1261 }
1262 return result;
1263}
1264
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001265// This API needs the ability to modify a down-chain parameter
1266VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
1267 VkDevice device,
1268 const VkPipelineLayoutCreateInfo* pCreateInfo,
1269 const VkAllocationCallbacks* pAllocator,
1270 VkPipelineLayout* pPipelineLayout) {
1271 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1272 bool skip = false;
1273
1274#ifndef BUILD_CORE_VALIDATION
1275 struct create_pipeline_layout_api_state {
1276 VkPipelineLayoutCreateInfo modified_create_info;
1277 };
1278#endif
1279 create_pipeline_layout_api_state cpl_state{};
1280 cpl_state.modified_create_info = *pCreateInfo;
1281
1282 for (auto intercept : layer_data->object_dispatch) {
1283 auto lock = intercept->write_lock();
1284 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1285 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1286 }
1287 for (auto intercept : layer_data->object_dispatch) {
1288 auto lock = intercept->write_lock();
1289 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1290 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001291 VkResult result = DispatchCreatePipelineLayout(device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001292 for (auto intercept : layer_data->object_dispatch) {
1293 auto lock = intercept->write_lock();
1294 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1295 }
1296 return result;
1297}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001298
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001299// This API needs some local stack data for performance reasons and also may modify a parameter
1300VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1301 VkDevice device,
1302 const VkShaderModuleCreateInfo* pCreateInfo,
1303 const VkAllocationCallbacks* pAllocator,
1304 VkShaderModule* pShaderModule) {
1305 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1306 bool skip = false;
1307
1308#ifndef BUILD_CORE_VALIDATION
1309 struct create_shader_module_api_state {
1310 VkShaderModuleCreateInfo instrumented_create_info;
1311 };
1312#endif
1313 create_shader_module_api_state csm_state{};
1314 csm_state.instrumented_create_info = *pCreateInfo;
1315
1316 for (auto intercept : layer_data->object_dispatch) {
1317 auto lock = intercept->write_lock();
1318 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1319 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1320 }
1321 for (auto intercept : layer_data->object_dispatch) {
1322 auto lock = intercept->write_lock();
1323 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1324 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001325 VkResult result = DispatchCreateShaderModule(device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001326 for (auto intercept : layer_data->object_dispatch) {
1327 auto lock = intercept->write_lock();
1328 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1329 }
1330 return result;
1331}
1332
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001333VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1334 VkDevice device,
1335 const VkDescriptorSetAllocateInfo* pAllocateInfo,
1336 VkDescriptorSet* pDescriptorSets) {
1337 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1338 bool skip = false;
1339
1340#ifdef BUILD_CORE_VALIDATION
1341 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1342#else
1343 struct ads_state {} ads_state;
1344#endif
1345
1346 for (auto intercept : layer_data->object_dispatch) {
1347 auto lock = intercept->write_lock();
1348 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1349 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1350 }
1351 for (auto intercept : layer_data->object_dispatch) {
1352 auto lock = intercept->write_lock();
1353 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1354 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001355 VkResult result = DispatchAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001356 for (auto intercept : layer_data->object_dispatch) {
1357 auto lock = intercept->write_lock();
1358 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1359 }
1360 return result;
1361}
1362
1363
1364
1365
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001366
1367// ValidationCache APIs do not dispatch
1368
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001369VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1370 VkDevice device,
1371 const VkValidationCacheCreateInfoEXT* pCreateInfo,
1372 const VkAllocationCallbacks* pAllocator,
1373 VkValidationCacheEXT* pValidationCache) {
1374 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1375 VkResult result = VK_SUCCESS;
1376
1377 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1378 if (validation_data) {
1379 auto lock = validation_data->write_lock();
1380 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1381 }
1382 return result;
1383}
1384
1385VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1386 VkDevice device,
1387 VkValidationCacheEXT validationCache,
1388 const VkAllocationCallbacks* pAllocator) {
1389 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1390
1391 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1392 if (validation_data) {
1393 auto lock = validation_data->write_lock();
1394 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1395 }
1396}
1397
1398VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1399 VkDevice device,
1400 VkValidationCacheEXT dstCache,
1401 uint32_t srcCacheCount,
1402 const VkValidationCacheEXT* pSrcCaches) {
1403 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1404 VkResult result = VK_SUCCESS;
1405
1406 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1407 if (validation_data) {
1408 auto lock = validation_data->write_lock();
1409 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1410 }
1411 return result;
1412}
1413
1414VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1415 VkDevice device,
1416 VkValidationCacheEXT validationCache,
1417 size_t* pDataSize,
1418 void* pData) {
1419 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1420 VkResult result = VK_SUCCESS;
1421
1422 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1423 if (validation_data) {
1424 auto lock = validation_data->write_lock();
1425 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1426 }
1427 return result;
1428
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001429}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001430
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001431 inline_custom_validation_class_definitions = """
1432 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1433 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1434 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1435 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001436
1437 // Allow additional parameter for CreateGraphicsPipelines
1438 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1439 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1440 };
1441 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1442 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1443 };
1444 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1445 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1446 };
1447
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001448 // Allow additional state parameter for CreateComputePipelines
1449 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1450 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1451 };
1452 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1453 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1454 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001455
1456 // Allow additional state parameter for CreateRayTracingPipelinesNV
1457 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1458 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1459 };
1460 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1461 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1462 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001463
1464 // Allow modification of a down-chain parameter for CreatePipelineLayout
1465 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1466 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1467 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001468
1469 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1470 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1471 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1472 };
1473 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1474 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1475 };
1476 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1477 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1478 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001479
1480 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1481 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1482 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1483 };
1484 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1485 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1486 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001487
1488 // Modify a parameter to CreateDevice
1489 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1490 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1491 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001492"""
1493
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001494 inline_custom_source_postamble = """
1495// loader-layer interface v0, just wrappers since there is only a layer
1496
1497VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1498 VkExtensionProperties *pProperties) {
1499 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1500}
1501
1502VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1503 VkLayerProperties *pProperties) {
1504 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1505}
1506
1507VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1508 VkLayerProperties *pProperties) {
1509 // the layer command handles VK_NULL_HANDLE just fine internally
1510 assert(physicalDevice == VK_NULL_HANDLE);
1511 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1512}
1513
1514VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1515 const char *pLayerName, uint32_t *pCount,
1516 VkExtensionProperties *pProperties) {
1517 // the layer command handles VK_NULL_HANDLE just fine internally
1518 assert(physicalDevice == VK_NULL_HANDLE);
1519 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1520}
1521
1522VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1523 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1524}
1525
1526VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1527 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1528}
1529
1530VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
1531 const char *funcName) {
1532 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
1533}
1534
1535VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1536 assert(pVersionStruct != NULL);
1537 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1538
1539 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1540 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1541 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1542 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
1543 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
1544 }
1545
1546 return VK_SUCCESS;
1547}"""
1548
1549
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001550 def __init__(self,
1551 errFile = sys.stderr,
1552 warnFile = sys.stderr,
1553 diagFile = sys.stdout):
1554 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1555 # Internal state - accumulators for different inner block text
1556 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1557 self.intercepts = []
1558 self.layer_factory = '' # String containing base layer factory class definition
1559
1560 # Check if the parameter passed in is a pointer to an array
1561 def paramIsArray(self, param):
1562 return param.attrib.get('len') is not None
1563
1564 # Check if the parameter passed in is a pointer
1565 def paramIsPointer(self, param):
1566 ispointer = False
1567 for elem in param:
1568 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
1569 ispointer = True
1570 return ispointer
1571
1572 # Check if an object is a non-dispatchable handle
1573 def isHandleTypeNonDispatchable(self, handletype):
1574 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1575 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1576 return True
1577 else:
1578 return False
1579
1580 # Check if an object is a dispatchable handle
1581 def isHandleTypeDispatchable(self, handletype):
1582 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1583 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
1584 return True
1585 else:
1586 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001587 #
1588 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001589 def beginFile(self, genOpts):
1590 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001591 # Output Copyright
1592 write(self.inline_copyright_message, file=self.outFile)
1593 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001594 self.header = False
1595 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1596 self.header = True
1597 write('#pragma once', file=self.outFile)
1598 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001599 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001600 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001601 else:
1602 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001603 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001604 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001605 #
1606 def endFile(self):
1607 # Finish C++ namespace and multiple inclusion protection
1608 self.newline()
1609 if not self.header:
1610 # Record intercepted procedures
1611 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
1612 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
1613 write('\n'.join(self.intercepts), file=self.outFile)
1614 write('};\n', file=self.outFile)
1615 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001616 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001617 if self.header:
1618 self.newline()
1619 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001620 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001621 self.layer_factory += '};\n\n'
1622 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001623 write(self.layer_factory, file=self.outFile)
1624 else:
1625 write(self.inline_custom_source_postamble, file=self.outFile)
1626 # Finish processing in superclass
1627 OutputGenerator.endFile(self)
1628
1629 def beginFeature(self, interface, emit):
1630 # Start processing in superclass
1631 OutputGenerator.beginFeature(self, interface, emit)
1632 # Get feature extra protect
1633 self.featureExtraProtect = GetFeatureProtect(interface)
1634 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1635 # feature. They're only printed in endFeature().
1636 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1637
1638 def endFeature(self):
1639 # Actually write the interface to the output file.
1640 if (self.emit):
1641 self.newline()
1642 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1643 # or move it below the 'for section...' loop.
1644 if (self.featureExtraProtect != None):
1645 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1646 for section in self.TYPE_SECTIONS:
1647 contents = self.sections[section]
1648 if contents:
1649 write('\n'.join(contents), file=self.outFile)
1650 self.newline()
1651 if (self.sections['command']):
1652 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1653 self.newline()
1654 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001655 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001656 # Finish processing in superclass
1657 OutputGenerator.endFeature(self)
1658 #
1659 # Append a definition to the specified section
1660 def appendSection(self, section, text):
1661 self.sections[section].append(text)
1662 #
1663 # Type generation
1664 def genType(self, typeinfo, name, alias):
1665 pass
1666 #
1667 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1668 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1669 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1670 # structs etc.)
1671 def genStruct(self, typeinfo, typeName):
1672 OutputGenerator.genStruct(self, typeinfo, typeName)
1673 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1674 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1675 for member in typeinfo.elem.findall('.//member'):
1676 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1677 body += ';\n'
1678 body += '} ' + typeName + ';\n'
1679 self.appendSection('struct', body)
1680 #
1681 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1682 def genGroup(self, groupinfo, groupName, alias):
1683 pass
1684 # Enumerant generation
1685 # <enum> tags may specify their values in several ways, but are usually just integers.
1686 def genEnum(self, enuminfo, name, alias):
1687 pass
1688 #
1689 # Customize Cdecl for layer factory base class
1690 def BaseClassCdecl(self, elem, name):
1691 raw = self.makeCDecls(elem)[1]
1692
1693 # Toss everything before the undecorated name
1694 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1695 prototype = prototype.replace(")", "", 1)
1696 prototype = prototype.replace(";", " {};")
1697
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001698 # Build up pre/post call virtual function declarations
1699 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1700 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1701 pre_call_record = 'virtual void PreCallRecord' + prototype
1702 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001703 resulttype = elem.find('proto/type')
1704 if resulttype.text == 'VkResult':
1705 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001706 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1707 #
1708 # Command generation
1709 def genCmd(self, cmdinfo, name, alias):
1710 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001711 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001712 ]
1713
1714 if name in ignore_functions:
1715 return
1716
1717 if self.header: # In the header declare all intercepts
1718 self.appendSection('command', '')
1719 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1720 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001721 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1722 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001723 if 'ValidationCache' not in name:
1724 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001725 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001726 self.layer_factory += '#endif\n'
1727 return
1728
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001729 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001730 if 'ValidationCache' not in name:
1731 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1732 else:
1733 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1734 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1735 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001736 return
1737 # Record that the function will be intercepted
1738 if (self.featureExtraProtect != None):
1739 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1740 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1741 if (self.featureExtraProtect != None):
1742 self.intercepts += [ '#endif' ]
1743 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1744 #
1745 decls = self.makeCDecls(cmdinfo.elem)
1746 self.appendSection('command', '')
1747 self.appendSection('command', '%s {' % decls[0][:-1])
1748 # Setup common to call wrappers. First parameter is always dispatchable
1749 dispatchable_type = cmdinfo.elem.find('param/type').text
1750 dispatchable_name = cmdinfo.elem.find('param/name').text
1751 # Default to device
1752 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001753 dispatch_table_name = 'VkLayerDispatchTable'
1754 # Set to instance as necessary
1755 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1756 device_or_instance = 'instance'
1757 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001758 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001759 api_function_name = cmdinfo.elem.attrib.get('name')
1760 params = cmdinfo.elem.findall('param/name')
1761 paramstext = ', '.join([str(param.text) for param in params])
Tony-LunarG152a88b2019-03-20 15:42:24 -06001762 API = api_function_name.replace('vk','Dispatch') + '('
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001763
1764 # Declare result variable, if any.
1765 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001766 'PFN_vkVoidFunction': 'return nullptr;',
1767 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001768 'VkDeviceAddress': 'return 0;',
1769 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1770 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001771 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001772 }
1773 resulttype = cmdinfo.elem.find('proto/type')
1774 assignresult = ''
1775 if (resulttype.text != 'void'):
1776 assignresult = resulttype.text + ' result = '
1777
1778 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001779 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001780
1781 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001782 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001783 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001784 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1785 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1786 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001787
1788 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001789 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001790 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001791 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001792 self.appendSection('command', ' }')
1793
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001794 # Insert pre-dispatch debug utils function call
1795 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001796 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001797
1798 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001799 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001800
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001801 # Insert post-dispatch debug utils function call
1802 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001803 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001804
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001805 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001806 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001807 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001808 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001809 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001810 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001811 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001812 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001813 # Return result variable, if any.
1814 if (resulttype.text != 'void'):
1815 self.appendSection('command', ' return result;')
1816 self.appendSection('command', '}')
1817 #
1818 # Override makeProtoName to drop the "vk" prefix
1819 def makeProtoName(self, name, tail):
1820 return self.genOpts.apientry + name[2:] + tail