blob: 1b6e9d998aab6fba008f9bd7819783bce8531184 [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07003# Copyright (c) 2015-2019 Valve Corporation
4# Copyright (c) 2015-2019 LunarG, Inc.
5# Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06006#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
20# Author: Mark Lobodzinski <mark@lunarg.com>
21#
22# This script generates the dispatch portion of a factory layer which intercepts
23# all Vulkan functions. The resultant factory layer allows rapid development of
24# layers and interceptors.
25
26import os,re,sys
27from generator import *
28from common_codegen import *
29
30# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31#
32# Adds options used by LayerFactoryOutputGenerator objects during factory
33# layer generation.
34#
35# Additional members
36# prefixText - list of strings to prefix generated header with
37# (usually a copyright statement + calling convention macros).
38# protectFile - True if multiple inclusion protection should be
39# generated (based on the filename) around the entire header.
40# protectFeature - True if #ifndef..#endif protection should be
41# generated around a feature interface in the header file.
42# genFuncPointers - True if function pointer typedefs should be
43# generated
44# protectProto - If conditional protection should be generated
45# around prototype declarations, set to either '#ifdef'
46# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47# to require opt-out (#ifndef protectProtoStr). Otherwise
48# set to None.
49# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50# declarations, if protectProto is set
51# apicall - string to use for the function declaration prefix,
52# such as APICALL on Windows.
53# apientry - string to use for the calling convention macro,
54# in typedefs, such as APIENTRY.
55# apientryp - string to use for the calling convention macro
56# in function pointer typedefs, such as APIENTRYP.
57# indentFuncProto - True if prototype declarations should put each
58# parameter on a separate line
59# indentFuncPointer - True if typedefed function pointers should put each
60# parameter on a separate line
61# alignFuncParam - if nonzero and parameters are being put on a
62# separate line, align parameter names at the specified column
63class LayerChassisGeneratorOptions(GeneratorOptions):
64 def __init__(self,
Mike Schuchardt21638df2019-03-16 10:52:02 -070065 conventions = None,
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -060066 filename = None,
67 directory = '.',
68 apiname = None,
69 profile = None,
70 versions = '.*',
71 emitversions = '.*',
72 defaultExtensions = None,
73 addExtensions = None,
74 removeExtensions = None,
75 emitExtensions = None,
76 sortProcedure = regSortFeatures,
77 prefixText = "",
78 genFuncPointers = True,
79 protectFile = True,
80 protectFeature = True,
81 apicall = '',
82 apientry = '',
83 apientryp = '',
84 indentFuncProto = True,
85 indentFuncPointer = False,
86 alignFuncParam = 0,
87 helper_file_type = '',
88 expandEnumerants = True):
Mike Schuchardt21638df2019-03-16 10:52:02 -070089 GeneratorOptions.__init__(self, conventions, filename, directory, apiname, profile,
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -060090 versions, emitversions, defaultExtensions,
91 addExtensions, removeExtensions, emitExtensions, sortProcedure)
92 self.prefixText = prefixText
93 self.genFuncPointers = genFuncPointers
94 self.protectFile = protectFile
95 self.protectFeature = protectFeature
96 self.apicall = apicall
97 self.apientry = apientry
98 self.apientryp = apientryp
99 self.indentFuncProto = indentFuncProto
100 self.indentFuncPointer = indentFuncPointer
101 self.alignFuncParam = alignFuncParam
102
103# LayerChassisOutputGenerator - subclass of OutputGenerator.
104# Generates a LayerFactory layer that intercepts all API entrypoints
105# This is intended to be used as a starting point for creating custom layers
106#
107# ---- methods ----
108# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
109# OutputGenerator. Defines additional internal state.
110# ---- methods overriding base class ----
111# beginFile(genOpts)
112# endFile()
113# beginFeature(interface, emit)
114# endFeature()
115# genType(typeinfo,name)
116# genStruct(typeinfo,name)
117# genGroup(groupinfo,name)
118# genEnum(enuminfo, name)
119# genCmd(cmdinfo)
120class LayerChassisOutputGenerator(OutputGenerator):
121 """Generate specified API interfaces in a specific style, such as a C header"""
122 # This is an ordered list of sections in the header file.
123 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
124 'group', 'bitmask', 'funcpointer', 'struct']
125 ALL_SECTIONS = TYPE_SECTIONS + ['command']
126
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700127 manual_functions = [
128 # Include functions here to be interecpted w/ manually implemented function bodies
129 'vkGetDeviceProcAddr',
130 'vkGetInstanceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700131 'vkCreateDevice',
132 'vkDestroyDevice',
133 'vkCreateInstance',
134 'vkDestroyInstance',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700135 'vkEnumerateInstanceLayerProperties',
136 'vkEnumerateInstanceExtensionProperties',
137 'vkEnumerateDeviceLayerProperties',
138 'vkEnumerateDeviceExtensionProperties',
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700139 # Functions that are handled explicitly due to chassis architecture violations
140 'vkCreateGraphicsPipelines',
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700141 'vkCreateComputePipelines',
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700142 'vkCreateRayTracingPipelinesNV',
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -0700143 'vkCreatePipelineLayout',
Mark Lobodzinski1db77e82019-03-01 10:02:54 -0700144 'vkCreateShaderModule',
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -0700145 'vkAllocateDescriptorSets',
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700146 # ValidationCache functions do not get dispatched
147 'vkCreateValidationCacheEXT',
148 'vkDestroyValidationCacheEXT',
149 'vkMergeValidationCachesEXT',
150 'vkGetValidationCacheDataEXT',
Mark Lobodzinski56e88122019-03-26 10:21:48 -0600151 # We don't wanna hook this function
152 'vkGetPhysicalDeviceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700153 ]
154
155 alt_ret_codes = [
156 # Include functions here which must tolerate VK_INCOMPLETE as a return code
157 'vkEnumeratePhysicalDevices',
158 'vkEnumeratePhysicalDeviceGroupsKHR',
159 'vkGetValidationCacheDataEXT',
160 'vkGetPipelineCacheData',
161 'vkGetShaderInfoAMD',
162 'vkGetPhysicalDeviceDisplayPropertiesKHR',
163 'vkGetPhysicalDeviceDisplayProperties2KHR',
164 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
165 'vkGetDisplayPlaneSupportedDisplaysKHR',
166 'vkGetDisplayModePropertiesKHR',
167 'vkGetDisplayModeProperties2KHR',
168 'vkGetPhysicalDeviceSurfaceFormatsKHR',
169 'vkGetPhysicalDeviceSurfacePresentModesKHR',
170 'vkGetPhysicalDevicePresentRectanglesKHR',
171 'vkGetPastPresentationTimingGOOGLE',
172 'vkGetSwapchainImagesKHR',
173 'vkEnumerateInstanceLayerProperties',
174 'vkEnumerateDeviceLayerProperties',
175 'vkEnumerateInstanceExtensionProperties',
176 'vkEnumerateDeviceExtensionProperties',
177 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
178 ]
179
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700180 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700181 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
182 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700183 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
184 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700185 }
186
187 post_dispatch_debug_utils_functions = {
188 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700189 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
190 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
191 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
192 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700193 }
194
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600195 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
196 precallrecord_loop = precallvalidate_loop
197 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600198
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700199 inline_custom_header_preamble = """
200#define NOMINMAX
201#include <mutex>
202#include <cinttypes>
203#include <stdio.h>
204#include <stdlib.h>
205#include <string.h>
206#include <unordered_map>
207#include <unordered_set>
208#include <algorithm>
209#include <memory>
210
211#include "vk_loader_platform.h"
212#include "vulkan/vulkan.h"
213#include "vk_layer_config.h"
214#include "vk_layer_data.h"
215#include "vk_layer_logging.h"
216#include "vk_object_types.h"
217#include "vulkan/vk_layer.h"
218#include "vk_enum_string_helper.h"
219#include "vk_layer_extension_utils.h"
220#include "vk_layer_utils.h"
221#include "vulkan/vk_layer.h"
222#include "vk_dispatch_table_helper.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700223#include "vk_extension_helper.h"
224#include "vk_safe_struct.h"
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700225#include "vk_typemap_helper.h"
226
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700227
228extern uint64_t global_unique_id;
229extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
230"""
231
232 inline_custom_header_class_definition = """
233
234// Layer object type identifiers
235enum LayerObjectTypeId {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700236 LayerObjectTypeInstance, // Container for an instance dispatch object
237 LayerObjectTypeDevice, // Container for a device dispatch object
238 LayerObjectTypeThreading, // Instance or device threading layer object
239 LayerObjectTypeParameterValidation, // Instance or device parameter validation layer object
240 LayerObjectTypeObjectTracker, // Instance or device object tracker layer object
241 LayerObjectTypeCoreValidation, // Instance or device core validation layer object
Camdeneaa86ea2019-07-26 11:00:09 -0600242 LayerObjectTypeBestPractices, // Instance or device best practices layer object
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700243};
244
245struct TEMPLATE_STATE {
246 VkDescriptorUpdateTemplateKHR desc_update_template;
247 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
248
249 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
250 : desc_update_template(update_template), create_info(*pCreateInfo) {}
251};
252
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700253class LAYER_PHYS_DEV_PROPERTIES {
254public:
255 VkPhysicalDeviceProperties properties;
256 std::vector<VkQueueFamilyProperties> queue_family_properties;
257};
258
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600259typedef enum ValidationCheckDisables {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600260 VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600261 VALIDATION_CHECK_DISABLE_OBJECT_IN_USE,
262 VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET,
263 VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE,
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600264 VALIDATION_CHECK_DISABLE_QUERY_VALIDATION,
Matthew Ruschd7ef5482019-07-16 22:01:54 -0700265 VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600266} ValidationCheckDisables;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600267
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600268
269// CHECK_DISABLED struct is a container for bools that can block validation checks from being performed.
270// These bools are all "false" by default meaning that all checks are enabled. Enum values can be specified
271// via the vk_layer_setting.txt config file or at CreateInstance time via the VK_EXT_validation_features extension
272// that can selectively disable checks.
273struct CHECK_DISABLED {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600274 bool command_buffer_state; // Skip command buffer state validation
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600275 bool object_in_use; // Skip all object in_use checking
276 bool idle_descriptor_set; // Skip check to verify that descriptor set is not in-use
277 bool push_constant_range; // Skip push constant range checks
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600278 bool query_validation; // Disable all core validation query-related checks
Matthew Ruschd7ef5482019-07-16 22:01:54 -0700279 bool image_layout_validation; // Disable image layout validation
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600280 bool object_tracking; // Disable object lifetime validation
281 bool core_checks; // Disable core validation checks
282 bool thread_safety; // Disable thread safety validation
283 bool stateless_checks; // Disable stateless validation checks
284 bool handle_wrapping; // Disable unique handles/handle wrapping
285 bool shader_validation; // Skip validation for shaders
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700286
287 void SetAll(bool value) { std::fill(&command_buffer_state, &shader_validation + 1, value); }
288};
289
290struct CHECK_ENABLED {
291 bool gpu_validation;
292 bool gpu_validation_reserve_binding_slot;
Camdeneaa86ea2019-07-26 11:00:09 -0600293 bool best_practices;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700294
295 void SetAll(bool value) { std::fill(&gpu_validation, &gpu_validation_reserve_binding_slot + 1, value); }
296};
297
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700298// Layer chassis validation object base class definition
299class ValidationObject {
300 public:
301 uint32_t api_version;
302 debug_report_data* report_data = nullptr;
303 std::vector<VkDebugReportCallbackEXT> logging_callback;
304 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
305
306 VkLayerInstanceDispatchTable instance_dispatch_table;
307 VkLayerDispatchTable device_dispatch_table;
308
309 InstanceExtensions instance_extensions;
310 DeviceExtensions device_extensions = {};
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700311 CHECK_DISABLED disabled = {};
312 CHECK_ENABLED enabled = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700313
314 VkInstance instance = VK_NULL_HANDLE;
315 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
316 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700317 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700318
319 std::vector<ValidationObject*> object_dispatch;
320 LayerObjectTypeId container_type;
321
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700322 std::string layer_name = "CHASSIS";
323
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700324 // Constructor
325 ValidationObject(){};
326 // Destructor
327 virtual ~ValidationObject() {};
328
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700329 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700330 virtual std::unique_lock<std::mutex> write_lock() {
331 return std::unique_lock<std::mutex>(validation_object_mutex);
332 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700333
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700334 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
335 for (auto validation_object : object_dispatch) {
336 if (validation_object->container_type == object_type) {
337 return validation_object;
338 }
339 }
340 return nullptr;
341 };
342
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700343 // Handle Wrapping Data
344 // Reverse map display handles
345 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
Mark Lobodzinskidd28ee22019-06-04 14:20:56 -0600346 // Wrapping Descriptor Template Update structures requires access to the template createinfo structs
347 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_createinfo_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700348 struct SubpassesUsageStates {
349 std::unordered_set<uint32_t> subpasses_using_color_attachment;
350 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
351 };
352 // Uses unwrapped handles
353 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
354 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
355 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
356 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700357 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
358 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700359
360
361 // Unwrap a handle. Must hold lock.
362 template <typename HandleType>
363 HandleType Unwrap(HandleType wrappedHandle) {
364 // TODO: don't use operator[] here.
365 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
366 }
367
368 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
369 template <typename HandleType>
370 HandleType WrapNew(HandleType newlyCreatedHandle) {
371 auto unique_id = global_unique_id++;
372 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
373 return (HandleType)unique_id;
374 }
375
376 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
377 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
378 auto unique_id = global_unique_id++;
379 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
380 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
381 return (VkDisplayKHR)unique_id;
382 }
383
384 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
385 // creating another. Must hold lock.
386 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
387 // See if this display is already known
388 auto it = map_data->display_id_reverse_mapping.find(handle);
389 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
390 // Unknown, so wrap
391 return WrapDisplay(handle, map_data);
392 }
393
394 // Pre/post hook point declarations
395"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600396
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700397 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600398// This file is ***GENERATED***. Do Not Edit.
399// See layer_chassis_generator.py for modifications.
400
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700401/* Copyright (c) 2015-2019 The Khronos Group Inc.
402 * Copyright (c) 2015-2019 Valve Corporation
403 * Copyright (c) 2015-2019 LunarG, Inc.
404 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600405 *
406 * Licensed under the Apache License, Version 2.0 (the "License");
407 * you may not use this file except in compliance with the License.
408 * You may obtain a copy of the License at
409 *
410 * http://www.apache.org/licenses/LICENSE-2.0
411 *
412 * Unless required by applicable law or agreed to in writing, software
413 * distributed under the License is distributed on an "AS IS" BASIS,
414 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
415 * See the License for the specific language governing permissions and
416 * limitations under the License.
417 *
418 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700419 */"""
420
421 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600422
423#include <string.h>
424#include <mutex>
425
426#define VALIDATION_ERROR_MAP_IMPL
427
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600428#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700429#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600430
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600431std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600432
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700433// Global unique object identifier. All increments must be guarded by a lock.
434uint64_t global_unique_id = 1;
435// Map uniqueID to actual object handle
436std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
437
438// TODO: This variable controls handle wrapping -- in the future it should be hooked
439// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
440#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
441bool wrap_handles = true;
442#else
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600443bool wrap_handles = false;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700444#endif
445
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600446// Set layer name -- Khronos layer name overrides any other defined names
Mark Lobodzinskiaa6fd7b2019-03-19 09:26:48 -0600447#if BUILD_KHRONOS_VALIDATION
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600448#define OBJECT_LAYER_NAME "VK_LAYER_KHRONOS_validation"
449#define OBJECT_LAYER_DESCRIPTION "khronos_validation"
450#elif BUILD_OBJECT_TRACKER
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700451#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600452#define OBJECT_LAYER_DESCRIPTION "lunarg_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700453#elif BUILD_THREAD_SAFETY
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700454#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600455#define OBJECT_LAYER_DESCRIPTION "google_thread_checker"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700456#elif BUILD_PARAMETER_VALIDATION
457#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600458#define OBJECT_LAYER_DESCRIPTION "lunarg_parameter_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700459#elif BUILD_CORE_VALIDATION
460#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600461#define OBJECT_LAYER_DESCRIPTION "lunarg_core_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700462#else
463#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600464#define OBJECT_LAYER_DESCRIPTION "lunarg_unique_objects"
465#endif
466
467// Include layer validation object definitions
468#if BUILD_OBJECT_TRACKER
469#include "object_lifetime_validation.h"
470#endif
471#if BUILD_THREAD_SAFETY
472#include "thread_safety.h"
473#endif
474#if BUILD_PARAMETER_VALIDATION
475#include "stateless_validation.h"
476#endif
477#if BUILD_CORE_VALIDATION
478#include "core_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700479#endif
Camdeneaa86ea2019-07-26 11:00:09 -0600480#if BUILD_BEST_PRACTICES
481#include "best_practices.h"
482#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600483
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600484namespace vulkan_layer_chassis {
485
486using std::unordered_map;
487
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600488static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700489 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600490};
491
John Zulauf358462e2019-04-10 11:10:32 -0600492static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION},
493 {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION}};
Lenny Komow3627f6e2019-06-19 13:54:59 -0600494static const VkExtensionProperties device_extensions[] = {
495 {VK_EXT_VALIDATION_CACHE_EXTENSION_NAME, VK_EXT_VALIDATION_CACHE_SPEC_VERSION},
496 {VK_EXT_DEBUG_MARKER_EXTENSION_NAME, VK_EXT_DEBUG_MARKER_SPEC_VERSION},
497};
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600498
Mark Lobodzinski31395512019-06-18 16:25:01 -0600499typedef struct {
500 bool is_instance_api;
501 void* funcptr;
502} function_data;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600503
Mark Lobodzinski31395512019-06-18 16:25:01 -0600504extern const std::unordered_map<std::string, function_data> name_to_funcptr_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600505
506// Manually written functions
507
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700508// Check enabled instance extensions against supported instance extension whitelist
509static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
510 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
511 // Check for recognized instance extensions
512 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
Ricardo Garcia0072a572019-08-01 12:19:23 +0200513 log_msg(layer_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700514 kVUIDUndefined,
515 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
516 "results and/or produce undefined behavior.",
517 pCreateInfo->ppEnabledExtensionNames[i]);
518 }
519 }
520}
521
522// Check enabled device extensions against supported device extension whitelist
523static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
524 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
525 // Check for recognized device extensions
526 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
Ricardo Garcia0072a572019-08-01 12:19:23 +0200527 log_msg(layer_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700528 kVUIDUndefined,
529 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
530 "results and/or produce undefined behavior.",
531 pCreateInfo->ppEnabledExtensionNames[i]);
532 }
533 }
534}
535
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600536
537// Process validation features, flags and settings specified through extensions, a layer settings file, or environment variables
538
539static const std::unordered_map<std::string, VkValidationFeatureDisableEXT> VkValFeatureDisableLookup = {
540 {"VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT", VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT},
541 {"VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT", VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT},
542 {"VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT", VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT},
543 {"VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT", VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT},
544 {"VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT", VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT},
545 {"VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT", VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT},
546 {"VK_VALIDATION_FEATURE_DISABLE_ALL_EXT", VK_VALIDATION_FEATURE_DISABLE_ALL_EXT},
547};
548
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600549static const std::unordered_map<std::string, VkValidationFeatureEnableEXT> VkValFeatureEnableLookup = {
550 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT},
551 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT},
552};
553
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600554static const std::unordered_map<std::string, ValidationCheckDisables> ValidationDisableLookup = {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600555 {"VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE", VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600556 {"VALIDATION_CHECK_DISABLE_OBJECT_IN_USE", VALIDATION_CHECK_DISABLE_OBJECT_IN_USE},
557 {"VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET", VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET},
558 {"VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE", VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE},
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600559 {"VALIDATION_CHECK_DISABLE_QUERY_VALIDATION", VALIDATION_CHECK_DISABLE_QUERY_VALIDATION},
Matthew Ruschd7ef5482019-07-16 22:01:54 -0700560 {"VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION", VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600561};
562
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600563// Set the local disable flag for the appropriate VALIDATION_CHECK_DISABLE enum
564void SetValidationDisable(CHECK_DISABLED* disable_data, const ValidationCheckDisables disable_id) {
565 switch (disable_id) {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600566 case VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE:
567 disable_data->command_buffer_state = true;
568 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600569 case VALIDATION_CHECK_DISABLE_OBJECT_IN_USE:
570 disable_data->object_in_use = true;
571 break;
572 case VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET:
573 disable_data->idle_descriptor_set = true;
574 break;
575 case VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE:
576 disable_data->push_constant_range = true;
577 break;
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600578 case VALIDATION_CHECK_DISABLE_QUERY_VALIDATION:
579 disable_data->query_validation = true;
580 break;
Matthew Ruschd7ef5482019-07-16 22:01:54 -0700581 case VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION:
582 disable_data->image_layout_validation = true;
583 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600584 default:
585 assert(true);
586 }
587}
588
589// Set the local disable flag for a single VK_VALIDATION_FEATURE_DISABLE_* flag
590void SetValidationFeatureDisable(CHECK_DISABLED* disable_data, const VkValidationFeatureDisableEXT feature_disable) {
591 switch (feature_disable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700592 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600593 disable_data->shader_validation = true;
594 break;
595 case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
596 disable_data->thread_safety = true;
597 break;
598 case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
599 disable_data->stateless_checks = true;
600 break;
601 case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
602 disable_data->object_tracking = true;
603 break;
604 case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
605 disable_data->core_checks = true;
606 break;
607 case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
608 disable_data->handle_wrapping = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700609 break;
610 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
611 // Set all disabled flags to true
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600612 disable_data->SetAll(true);
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700613 break;
614 default:
615 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700616 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600617}
618
619// Set the local enable flag for a single VK_VALIDATION_FEATURE_ENABLE_* flag
620void SetValidationFeatureEnable(CHECK_ENABLED *enable_data, const VkValidationFeatureEnableEXT feature_enable) {
621 switch (feature_enable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700622 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600623 enable_data->gpu_validation = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700624 break;
625 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600626 enable_data->gpu_validation_reserve_binding_slot = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700627 break;
628 default:
629 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700630 }
631}
632
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600633// Set the local disable flag for settings specified through the VK_EXT_validation_flags extension
634void SetValidationFlags(CHECK_DISABLED* disables, const VkValidationFlagsEXT* val_flags_struct) {
635 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
636 switch (val_flags_struct->pDisabledValidationChecks[i]) {
637 case VK_VALIDATION_CHECK_SHADERS_EXT:
638 disables->shader_validation = true;
639 break;
640 case VK_VALIDATION_CHECK_ALL_EXT:
641 // Set all disabled flags to true
642 disables->SetAll(true);
643 break;
644 default:
645 break;
646 }
647 }
648}
649
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600650// Process Validation Features flags specified through the ValidationFeature extension
651void SetValidationFeatures(CHECK_DISABLED *disable_data, CHECK_ENABLED *enable_data,
652 const VkValidationFeaturesEXT *val_features_struct) {
653 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
654 SetValidationFeatureDisable(disable_data, val_features_struct->pDisabledValidationFeatures[i]);
655 }
656 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
657 SetValidationFeatureEnable(enable_data, val_features_struct->pEnabledValidationFeatures[i]);
658 }
659}
660
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600661// Given a string representation of a list of enable enum values, call the appropriate setter function
662void SetLocalEnableSetting(std::string list_of_enables, std::string delimiter, CHECK_ENABLED* enables) {
663 size_t pos = 0;
664 std::string token;
665 while (list_of_enables.length() != 0) {
666 pos = list_of_enables.find(delimiter);
667 if (pos != std::string::npos) {
668 token = list_of_enables.substr(0, pos);
669 } else {
670 pos = list_of_enables.length() - delimiter.length();
671 token = list_of_enables;
672 }
673 if (token.find("VK_VALIDATION_FEATURE_ENABLE_") != std::string::npos) {
674 auto result = VkValFeatureEnableLookup.find(token);
675 if (result != VkValFeatureEnableLookup.end()) {
676 SetValidationFeatureEnable(enables, result->second);
677 }
678 }
679 list_of_enables.erase(0, pos + delimiter.length());
680 }
681}
682
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600683// Given a string representation of a list of disable enum values, call the appropriate setter function
684void SetLocalDisableSetting(std::string list_of_disables, std::string delimiter, CHECK_DISABLED* disables) {
685 size_t pos = 0;
686 std::string token;
687 while (list_of_disables.length() != 0) {
688 pos = list_of_disables.find(delimiter);
689 if (pos != std::string::npos) {
690 token = list_of_disables.substr(0, pos);
691 } else {
692 pos = list_of_disables.length() - delimiter.length();
693 token = list_of_disables;
694 }
695 if (token.find("VK_VALIDATION_FEATURE_DISABLE_") != std::string::npos) {
696 auto result = VkValFeatureDisableLookup.find(token);
697 if (result != VkValFeatureDisableLookup.end()) {
698 SetValidationFeatureDisable(disables, result->second);
699 }
700 }
701 if (token.find("VALIDATION_CHECK_DISABLE_") != std::string::npos) {
702 auto result = ValidationDisableLookup.find(token);
703 if (result != ValidationDisableLookup.end()) {
704 SetValidationDisable(disables, result->second);
705 }
706 }
707 list_of_disables.erase(0, pos + delimiter.length());
708 }
709}
710
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600711// Process enables and disables set though the vk_layer_settings.txt config file or through an environment variable
712void ProcessConfigAndEnvSettings(const char* layer_description, CHECK_ENABLED* enables, CHECK_DISABLED* disables) {
713 std::string enable_key = layer_description;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600714 std::string disable_key = layer_description;
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600715 enable_key.append(".enables");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600716 disable_key.append(".disables");
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600717 std::string list_of_config_enables = getLayerOption(enable_key.c_str());
718 std::string list_of_env_enables = GetLayerEnvVar("VK_LAYER_ENABLES");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600719 std::string list_of_config_disables = getLayerOption(disable_key.c_str());
720 std::string list_of_env_disables = GetLayerEnvVar("VK_LAYER_DISABLES");
721#if defined(_WIN32)
722 std::string env_delimiter = ";";
723#else
724 std::string env_delimiter = ":";
725#endif
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600726 SetLocalEnableSetting(list_of_config_enables, ",", enables);
727 SetLocalEnableSetting(list_of_env_enables, env_delimiter, enables);
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600728 SetLocalDisableSetting(list_of_config_disables, ",", disables);
729 SetLocalDisableSetting(list_of_env_disables, env_delimiter, disables);
730}
731
732
733// Non-code-generated chassis API functions
734
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600735VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600736 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskif94196f2019-07-11 11:46:09 -0600737 if (!ApiParentExtensionEnabled(funcName, &layer_data->device_extensions)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700738 return nullptr;
739 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600740 const auto &item = name_to_funcptr_map.find(funcName);
741 if (item != name_to_funcptr_map.end()) {
Mark Lobodzinski31395512019-06-18 16:25:01 -0600742 if (item->second.is_instance_api) {
743 return nullptr;
744 } else {
745 return reinterpret_cast<PFN_vkVoidFunction>(item->second.funcptr);
746 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600747 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600748 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600749 if (!table.GetDeviceProcAddr) return nullptr;
750 return table.GetDeviceProcAddr(device, funcName);
751}
752
753VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600754 const auto &item = name_to_funcptr_map.find(funcName);
755 if (item != name_to_funcptr_map.end()) {
Mark Lobodzinski31395512019-06-18 16:25:01 -0600756 return reinterpret_cast<PFN_vkVoidFunction>(item->second.funcptr);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600757 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600758 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
759 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600760 if (!table.GetInstanceProcAddr) return nullptr;
761 return table.GetInstanceProcAddr(instance, funcName);
762}
763
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600764VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
765 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
766}
767
768VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
769 VkLayerProperties *pProperties) {
770 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
771}
772
773VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
774 VkExtensionProperties *pProperties) {
775 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
John Zulauf358462e2019-04-10 11:10:32 -0600776 return util_GetExtensionProperties(ARRAY_SIZE(instance_extensions), instance_extensions, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600777
778 return VK_ERROR_LAYER_NOT_PRESENT;
779}
780
781VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
782 uint32_t *pCount, VkExtensionProperties *pProperties) {
Lenny Komow3627f6e2019-06-19 13:54:59 -0600783 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(ARRAY_SIZE(device_extensions), device_extensions, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600784 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600785 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
Lenny Komow7b567f72019-06-10 16:49:43 -0600786 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600787}
788
789VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
790 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600791 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600792
793 assert(chain_info->u.pLayerInfo);
794 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
795 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
796 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
797 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700798 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
799 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
800
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600801 CHECK_ENABLED local_enables {};
802 CHECK_DISABLED local_disables {};
803 const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(pCreateInfo->pNext);
804 if (validation_features_ext) {
805 SetValidationFeatures(&local_disables, &local_enables, validation_features_ext);
806 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600807 const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
808 if (validation_flags_ext) {
809 SetValidationFlags(&local_disables, validation_flags_ext);
810 }
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600811 ProcessConfigAndEnvSettings(OBJECT_LAYER_DESCRIPTION, &local_enables, &local_disables);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600812
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600813 // Create temporary dispatch vector for pre-calls until instance is created
814 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600815 // Add VOs to dispatch vector. Order here will be the validation dispatch order!
816#if BUILD_THREAD_SAFETY
817 auto thread_checker = new ThreadSafety;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600818 if (!local_disables.thread_safety) {
819 local_object_dispatch.emplace_back(thread_checker);
820 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600821 thread_checker->container_type = LayerObjectTypeThreading;
822 thread_checker->api_version = api_version;
823#endif
824#if BUILD_PARAMETER_VALIDATION
825 auto parameter_validation = new StatelessValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600826 if (!local_disables.stateless_checks) {
827 local_object_dispatch.emplace_back(parameter_validation);
828 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600829 parameter_validation->container_type = LayerObjectTypeParameterValidation;
830 parameter_validation->api_version = api_version;
831#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700832#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600833 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600834 if (!local_disables.object_tracking) {
835 local_object_dispatch.emplace_back(object_tracker);
836 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600837 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700838 object_tracker->api_version = api_version;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600839#endif
840#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700841 auto core_checks = new CoreChecks;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600842 if (!local_disables.core_checks) {
843 local_object_dispatch.emplace_back(core_checks);
844 }
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700845 core_checks->container_type = LayerObjectTypeCoreValidation;
846 core_checks->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700847#endif
Camdeneaa86ea2019-07-26 11:00:09 -0600848#if BUILD_BEST_PRACTICES
849 auto best_practices = new BestPractices;
850 if (local_enables.best_practices) {
851 local_object_dispatch.emplace_back(best_practices);
852 }
853 best_practices->container_type = LayerObjectTypeBestPractices;
854 best_practices->api_version = api_version;
855#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600856
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600857 // If handle wrapping is disabled via the ValidationFeatures extension, override build flag
858 if (local_disables.handle_wrapping) {
859 wrap_handles = false;
860 }
861
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600862 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600863 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600864 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
865 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600866 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600867 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
868 }
869
870 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600871 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600872
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600873 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600874
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600875 framework->object_dispatch = local_object_dispatch;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700876 framework->container_type = LayerObjectTypeInstance;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600877 framework->disabled = local_disables;
878 framework->enabled = local_enables;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600879
880 framework->instance = *pInstance;
881 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
882 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
883 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700884 framework->api_version = api_version;
885 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
886
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600887 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, OBJECT_LAYER_DESCRIPTION);
888
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700889#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700890 object_tracker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600891 object_tracker->instance_dispatch_table = framework->instance_dispatch_table;
892 object_tracker->enabled = framework->enabled;
893 object_tracker->disabled = framework->disabled;
894#endif
895#if BUILD_THREAD_SAFETY
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700896 thread_checker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600897 thread_checker->instance_dispatch_table = framework->instance_dispatch_table;
898 thread_checker->enabled = framework->enabled;
899 thread_checker->disabled = framework->disabled;
900#endif
901#if BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700902 parameter_validation->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600903 parameter_validation->instance_dispatch_table = framework->instance_dispatch_table;
904 parameter_validation->enabled = framework->enabled;
905 parameter_validation->disabled = framework->disabled;
906#endif
907#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700908 core_checks->report_data = framework->report_data;
909 core_checks->instance_dispatch_table = framework->instance_dispatch_table;
910 core_checks->instance = *pInstance;
911 core_checks->enabled = framework->enabled;
912 core_checks->disabled = framework->disabled;
913 core_checks->instance_state = core_checks;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700914#endif
Camdeneaa86ea2019-07-26 11:00:09 -0600915#if BUILD_BEST_PRACTICES
916 best_practices->report_data = framework->report_data;
917 best_practices->instance_dispatch_table = framework->instance_dispatch_table;
918 best_practices->enabled = framework->enabled;
919 best_practices->disabled = framework->disabled;
920#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600921
922 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700923 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600924 }
925
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700926 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
927
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600928 return result;
929}
930
931VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
932 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600933 auto layer_data = GetLayerDataPtr(key, layer_data_map);
934 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700935 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600936 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
937 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600938 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700939 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600940 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
941 }
942
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600943 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600944
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600945 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700946 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600947 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
948 }
949 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600950 while (layer_data->logging_messenger.size() > 0) {
951 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
952 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
953 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600954 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600955 while (layer_data->logging_callback.size() > 0) {
956 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
957 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
958 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600959 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600960
961 layer_debug_utils_destroy_instance(layer_data->report_data);
962
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700963 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
964 delete *item;
965 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600966 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600967}
968
969VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
970 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600971 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600972
973 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
974
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600975 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
976 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600977 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
978 if (fpCreateDevice == NULL) {
979 return VK_ERROR_INITIALIZATION_FAILED;
980 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600981 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
982
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700983 // Get physical device limits for device
984 VkPhysicalDeviceProperties device_properties = {};
985 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
986
987 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
988 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
989
990 DeviceExtensions device_extensions = {};
991 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
992 for (auto item : instance_interceptor->object_dispatch) {
993 item->device_extensions = device_extensions;
994 }
995
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700996 std::unique_ptr<safe_VkDeviceCreateInfo> modified_create_info(new safe_VkDeviceCreateInfo(pCreateInfo));
997
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700998 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600999 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001000 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001001 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001002 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001003 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001004 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001005 auto lock = intercept->write_lock();
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001006 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, modified_create_info);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001007 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001008
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001009 VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(modified_create_info.get()), pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001010 if (result != VK_SUCCESS) {
1011 return result;
1012 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001013
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001014 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001015 device_interceptor->container_type = LayerObjectTypeDevice;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001016
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001017 // Save local info in device object
1018 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001019 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
1020 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001021 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001022
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001023 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001024
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001025 device_interceptor->device = *pDevice;
1026 device_interceptor->physical_device = gpu;
1027 device_interceptor->instance = instance_interceptor->instance;
1028 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001029
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001030 // Note that this defines the order in which the layer validation objects are called
1031#if BUILD_THREAD_SAFETY
1032 auto thread_safety = new ThreadSafety;
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001033 thread_safety->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001034 if (!instance_interceptor->disabled.thread_safety) {
1035 device_interceptor->object_dispatch.emplace_back(thread_safety);
1036 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001037#endif
1038#if BUILD_PARAMETER_VALIDATION
1039 auto stateless_validation = new StatelessValidation;
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001040 stateless_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001041 if (!instance_interceptor->disabled.stateless_checks) {
1042 device_interceptor->object_dispatch.emplace_back(stateless_validation);
1043 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001044#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001045#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001046 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001047 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001048 if (!instance_interceptor->disabled.object_tracking) {
1049 device_interceptor->object_dispatch.emplace_back(object_tracker);
1050 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001051#endif
1052#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001053 auto core_checks = new CoreChecks;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001054 core_checks->container_type = LayerObjectTypeCoreValidation;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001055 core_checks->instance_state = reinterpret_cast<CoreChecks *>(
1056 core_checks->GetValidationObject(instance_interceptor->object_dispatch, LayerObjectTypeCoreValidation));
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001057 if (!instance_interceptor->disabled.core_checks) {
1058 device_interceptor->object_dispatch.emplace_back(core_checks);
1059 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001060#endif
Camdeneaa86ea2019-07-26 11:00:09 -06001061#if BUILD_BEST_PRACTICES
1062 auto best_practices = new BestPractices;
1063 best_practices->container_type = LayerObjectTypeBestPractices;
1064 if (instance_interceptor->enabled.best_practices) {
1065 device_interceptor->object_dispatch.emplace_back(best_practices);
1066 }
1067#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001068
Mark Lobodzinski7314bf42019-03-28 08:54:53 -06001069 // Set per-intercept common data items
1070 for (auto dev_intercept : device_interceptor->object_dispatch) {
1071 dev_intercept->device = *pDevice;
1072 dev_intercept->physical_device = gpu;
1073 dev_intercept->instance = instance_interceptor->instance;
1074 dev_intercept->report_data = device_interceptor->report_data;
1075 dev_intercept->device_dispatch_table = device_interceptor->device_dispatch_table;
1076 dev_intercept->api_version = device_interceptor->api_version;
1077 dev_intercept->disabled = instance_interceptor->disabled;
1078 dev_intercept->enabled = instance_interceptor->enabled;
1079 dev_intercept->instance_dispatch_table = instance_interceptor->instance_dispatch_table;
1080 dev_intercept->instance_extensions = instance_interceptor->instance_extensions;
1081 dev_intercept->device_extensions = device_interceptor->device_extensions;
1082 }
1083
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001084 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001085 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001086 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001087 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001088
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001089 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
1090
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001091 return result;
1092}
1093
1094VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
1095 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001096 auto layer_data = GetLayerDataPtr(key, layer_data_map);
1097 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001098 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001099 intercept->PreCallValidateDestroyDevice(device, pAllocator);
1100 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001101 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001102 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001103 intercept->PreCallRecordDestroyDevice(device, pAllocator);
1104 }
1105 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001106
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001107 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001108
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001109 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001110 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001111 intercept->PostCallRecordDestroyDevice(device, pAllocator);
1112 }
1113
Mark Lobodzinskic5003372018-12-17 16:36:01 -07001114 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
1115 delete *item;
1116 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001117 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001118}
1119
1120
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001121// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001122
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001123VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
1124 VkDevice device,
1125 VkPipelineCache pipelineCache,
1126 uint32_t createInfoCount,
1127 const VkGraphicsPipelineCreateInfo* pCreateInfos,
1128 const VkAllocationCallbacks* pAllocator,
1129 VkPipeline* pPipelines) {
1130 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1131 bool skip = false;
1132
1133#ifdef BUILD_CORE_VALIDATION
1134 create_graphics_pipeline_api_state cgpl_state{};
1135#else
1136 struct create_graphics_pipeline_api_state {
1137 const VkGraphicsPipelineCreateInfo* pCreateInfos;
1138 } cgpl_state;
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001139#endif
Mark Lobodzinskid08e16c2019-06-11 10:22:10 -06001140 cgpl_state.pCreateInfos = pCreateInfos;
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001141
1142 for (auto intercept : layer_data->object_dispatch) {
1143 auto lock = intercept->write_lock();
1144 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1145 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1146 }
1147 for (auto intercept : layer_data->object_dispatch) {
1148 auto lock = intercept->write_lock();
1149 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1150 }
1151
Tony-LunarG152a88b2019-03-20 15:42:24 -06001152 VkResult result = DispatchCreateGraphicsPipelines(device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001153
1154 for (auto intercept : layer_data->object_dispatch) {
1155 auto lock = intercept->write_lock();
1156 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
1157 }
1158 return result;
1159}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001160
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001161// This API saves some core_validation pipeline state state on the stack for performance purposes
1162VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
1163 VkDevice device,
1164 VkPipelineCache pipelineCache,
1165 uint32_t createInfoCount,
1166 const VkComputePipelineCreateInfo* pCreateInfos,
1167 const VkAllocationCallbacks* pAllocator,
1168 VkPipeline* pPipelines) {
1169 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1170 bool skip = false;
1171
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001172#ifdef BUILD_CORE_VALIDATION
1173 create_compute_pipeline_api_state ccpl_state{};
1174#else
1175 struct create_compute_pipeline_api_state {
1176 const VkComputePipelineCreateInfo* pCreateInfos;
1177 } ccpl_state;
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001178#endif
Mark Lobodzinskid08e16c2019-06-11 10:22:10 -06001179 ccpl_state.pCreateInfos = pCreateInfos;
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001180
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001181 for (auto intercept : layer_data->object_dispatch) {
1182 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001183 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001184 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1185 }
1186 for (auto intercept : layer_data->object_dispatch) {
1187 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001188 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001189 }
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001190 VkResult result = DispatchCreateComputePipelines(device, pipelineCache, createInfoCount, ccpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001191 for (auto intercept : layer_data->object_dispatch) {
1192 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001193 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001194 }
1195 return result;
1196}
1197
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001198VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
1199 VkDevice device,
1200 VkPipelineCache pipelineCache,
1201 uint32_t createInfoCount,
1202 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
1203 const VkAllocationCallbacks* pAllocator,
1204 VkPipeline* pPipelines) {
1205 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1206 bool skip = false;
1207
Jason Macnak67407e72019-07-11 11:05:09 -07001208#ifdef BUILD_CORE_VALIDATION
1209 create_ray_tracing_pipeline_api_state crtpl_state{};
1210#else
1211 struct create_ray_tracing_pipeline_api_state {
1212 const VkRayTracingPipelineCreateInfoNV* pCreateInfos;
1213 } crtpl_state;
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001214#endif
Jason Macnak67407e72019-07-11 11:05:09 -07001215 crtpl_state.pCreateInfos = pCreateInfos;
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001216
1217 for (auto intercept : layer_data->object_dispatch) {
1218 auto lock = intercept->write_lock();
Jason Macnak67407e72019-07-11 11:05:09 -07001219 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos,
1220 pAllocator, pPipelines, &crtpl_state);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001221 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1222 }
1223 for (auto intercept : layer_data->object_dispatch) {
1224 auto lock = intercept->write_lock();
Jason Macnak67407e72019-07-11 11:05:09 -07001225 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator,
1226 pPipelines, &crtpl_state);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001227 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001228 VkResult result = DispatchCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001229 for (auto intercept : layer_data->object_dispatch) {
1230 auto lock = intercept->write_lock();
Jason Macnak67407e72019-07-11 11:05:09 -07001231 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator,
1232 pPipelines, result, &crtpl_state);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001233 }
1234 return result;
1235}
1236
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001237// This API needs the ability to modify a down-chain parameter
1238VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
1239 VkDevice device,
1240 const VkPipelineLayoutCreateInfo* pCreateInfo,
1241 const VkAllocationCallbacks* pAllocator,
1242 VkPipelineLayout* pPipelineLayout) {
1243 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1244 bool skip = false;
1245
1246#ifndef BUILD_CORE_VALIDATION
1247 struct create_pipeline_layout_api_state {
1248 VkPipelineLayoutCreateInfo modified_create_info;
1249 };
1250#endif
1251 create_pipeline_layout_api_state cpl_state{};
1252 cpl_state.modified_create_info = *pCreateInfo;
1253
1254 for (auto intercept : layer_data->object_dispatch) {
1255 auto lock = intercept->write_lock();
1256 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1257 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1258 }
1259 for (auto intercept : layer_data->object_dispatch) {
1260 auto lock = intercept->write_lock();
1261 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1262 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001263 VkResult result = DispatchCreatePipelineLayout(device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001264 for (auto intercept : layer_data->object_dispatch) {
1265 auto lock = intercept->write_lock();
1266 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1267 }
1268 return result;
1269}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001270
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001271// This API needs some local stack data for performance reasons and also may modify a parameter
1272VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1273 VkDevice device,
1274 const VkShaderModuleCreateInfo* pCreateInfo,
1275 const VkAllocationCallbacks* pAllocator,
1276 VkShaderModule* pShaderModule) {
1277 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1278 bool skip = false;
1279
1280#ifndef BUILD_CORE_VALIDATION
1281 struct create_shader_module_api_state {
1282 VkShaderModuleCreateInfo instrumented_create_info;
1283 };
1284#endif
1285 create_shader_module_api_state csm_state{};
1286 csm_state.instrumented_create_info = *pCreateInfo;
1287
1288 for (auto intercept : layer_data->object_dispatch) {
1289 auto lock = intercept->write_lock();
1290 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1291 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1292 }
1293 for (auto intercept : layer_data->object_dispatch) {
1294 auto lock = intercept->write_lock();
1295 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1296 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001297 VkResult result = DispatchCreateShaderModule(device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001298 for (auto intercept : layer_data->object_dispatch) {
1299 auto lock = intercept->write_lock();
1300 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1301 }
1302 return result;
1303}
1304
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001305VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1306 VkDevice device,
1307 const VkDescriptorSetAllocateInfo* pAllocateInfo,
1308 VkDescriptorSet* pDescriptorSets) {
1309 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1310 bool skip = false;
1311
1312#ifdef BUILD_CORE_VALIDATION
1313 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1314#else
1315 struct ads_state {} ads_state;
1316#endif
1317
1318 for (auto intercept : layer_data->object_dispatch) {
1319 auto lock = intercept->write_lock();
1320 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1321 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1322 }
1323 for (auto intercept : layer_data->object_dispatch) {
1324 auto lock = intercept->write_lock();
1325 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1326 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001327 VkResult result = DispatchAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001328 for (auto intercept : layer_data->object_dispatch) {
1329 auto lock = intercept->write_lock();
1330 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1331 }
1332 return result;
1333}
1334
1335
1336
1337
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001338
1339// ValidationCache APIs do not dispatch
1340
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001341VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1342 VkDevice device,
1343 const VkValidationCacheCreateInfoEXT* pCreateInfo,
1344 const VkAllocationCallbacks* pAllocator,
1345 VkValidationCacheEXT* pValidationCache) {
1346 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1347 VkResult result = VK_SUCCESS;
1348
1349 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1350 if (validation_data) {
1351 auto lock = validation_data->write_lock();
1352 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1353 }
1354 return result;
1355}
1356
1357VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1358 VkDevice device,
1359 VkValidationCacheEXT validationCache,
1360 const VkAllocationCallbacks* pAllocator) {
1361 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1362
1363 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1364 if (validation_data) {
1365 auto lock = validation_data->write_lock();
1366 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1367 }
1368}
1369
1370VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1371 VkDevice device,
1372 VkValidationCacheEXT dstCache,
1373 uint32_t srcCacheCount,
1374 const VkValidationCacheEXT* pSrcCaches) {
1375 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1376 VkResult result = VK_SUCCESS;
1377
1378 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1379 if (validation_data) {
1380 auto lock = validation_data->write_lock();
1381 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1382 }
1383 return result;
1384}
1385
1386VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1387 VkDevice device,
1388 VkValidationCacheEXT validationCache,
1389 size_t* pDataSize,
1390 void* pData) {
1391 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1392 VkResult result = VK_SUCCESS;
1393
1394 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1395 if (validation_data) {
1396 auto lock = validation_data->write_lock();
1397 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1398 }
1399 return result;
1400
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001401}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001402
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001403 inline_custom_validation_class_definitions = """
1404 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1405 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1406 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1407 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001408
Jason Macnak67407e72019-07-11 11:05:09 -07001409 // Allow additional state parameter for CreateGraphicsPipelines
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001410 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1411 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1412 };
1413 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1414 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1415 };
1416 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1417 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1418 };
Jason Macnak67407e72019-07-11 11:05:09 -07001419
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001420 // Allow additional state parameter for CreateComputePipelines
1421 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1422 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1423 };
Jason Macnak67407e72019-07-11 11:05:09 -07001424 virtual void PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* ccpl_state) {
1425 PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1426 };
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001427 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1428 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1429 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001430
1431 // Allow additional state parameter for CreateRayTracingPipelinesNV
1432 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1433 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1434 };
Jason Macnak67407e72019-07-11 11:05:09 -07001435 virtual void PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* ccpl_state) {
1436 PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1437 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001438 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1439 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1440 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001441
1442 // Allow modification of a down-chain parameter for CreatePipelineLayout
1443 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1444 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1445 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001446
1447 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1448 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1449 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1450 };
1451 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1452 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1453 };
1454 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1455 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1456 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001457
1458 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1459 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1460 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1461 };
1462 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1463 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1464 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001465
1466 // Modify a parameter to CreateDevice
1467 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1468 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1469 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001470"""
1471
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001472 inline_custom_source_postamble = """
1473// loader-layer interface v0, just wrappers since there is only a layer
1474
1475VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1476 VkExtensionProperties *pProperties) {
1477 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1478}
1479
1480VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1481 VkLayerProperties *pProperties) {
1482 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1483}
1484
1485VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1486 VkLayerProperties *pProperties) {
1487 // the layer command handles VK_NULL_HANDLE just fine internally
1488 assert(physicalDevice == VK_NULL_HANDLE);
1489 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1490}
1491
1492VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1493 const char *pLayerName, uint32_t *pCount,
1494 VkExtensionProperties *pProperties) {
1495 // the layer command handles VK_NULL_HANDLE just fine internally
1496 assert(physicalDevice == VK_NULL_HANDLE);
1497 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1498}
1499
1500VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1501 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1502}
1503
1504VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1505 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1506}
1507
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001508VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1509 assert(pVersionStruct != NULL);
1510 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1511
1512 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1513 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1514 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1515 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
Mark Lobodzinski56e88122019-03-26 10:21:48 -06001516 pVersionStruct->pfnGetPhysicalDeviceProcAddr = nullptr;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001517 }
1518
1519 return VK_SUCCESS;
1520}"""
1521
1522
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001523 def __init__(self,
1524 errFile = sys.stderr,
1525 warnFile = sys.stderr,
1526 diagFile = sys.stdout):
1527 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1528 # Internal state - accumulators for different inner block text
1529 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1530 self.intercepts = []
1531 self.layer_factory = '' # String containing base layer factory class definition
1532
1533 # Check if the parameter passed in is a pointer to an array
1534 def paramIsArray(self, param):
1535 return param.attrib.get('len') is not None
1536
1537 # Check if the parameter passed in is a pointer
1538 def paramIsPointer(self, param):
1539 ispointer = False
1540 for elem in param:
Raul Tambre7b300182019-05-04 11:25:14 +03001541 if elem.tag == 'type' and elem.tail is not None and '*' in elem.tail:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001542 ispointer = True
1543 return ispointer
1544
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001545 #
1546 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001547 def beginFile(self, genOpts):
1548 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001549 # Output Copyright
1550 write(self.inline_copyright_message, file=self.outFile)
1551 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001552 self.header = False
1553 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1554 self.header = True
1555 write('#pragma once', file=self.outFile)
1556 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001557 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001558 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001559 else:
1560 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001561 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001562 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001563 #
1564 def endFile(self):
1565 # Finish C++ namespace and multiple inclusion protection
1566 self.newline()
1567 if not self.header:
1568 # Record intercepted procedures
Mark Lobodzinski31395512019-06-18 16:25:01 -06001569 write('// Map of intercepted ApiName to its associated function data', file=self.outFile)
1570 write('const std::unordered_map<std::string, function_data> name_to_funcptr_map = {', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001571 write('\n'.join(self.intercepts), file=self.outFile)
1572 write('};\n', file=self.outFile)
1573 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001574 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001575 if self.header:
1576 self.newline()
1577 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001578 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001579 self.layer_factory += '};\n\n'
1580 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001581 write(self.layer_factory, file=self.outFile)
1582 else:
1583 write(self.inline_custom_source_postamble, file=self.outFile)
1584 # Finish processing in superclass
1585 OutputGenerator.endFile(self)
1586
1587 def beginFeature(self, interface, emit):
1588 # Start processing in superclass
1589 OutputGenerator.beginFeature(self, interface, emit)
1590 # Get feature extra protect
1591 self.featureExtraProtect = GetFeatureProtect(interface)
1592 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1593 # feature. They're only printed in endFeature().
1594 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1595
1596 def endFeature(self):
1597 # Actually write the interface to the output file.
1598 if (self.emit):
1599 self.newline()
1600 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1601 # or move it below the 'for section...' loop.
1602 if (self.featureExtraProtect != None):
1603 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1604 for section in self.TYPE_SECTIONS:
1605 contents = self.sections[section]
1606 if contents:
1607 write('\n'.join(contents), file=self.outFile)
1608 self.newline()
1609 if (self.sections['command']):
1610 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1611 self.newline()
1612 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001613 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001614 # Finish processing in superclass
1615 OutputGenerator.endFeature(self)
1616 #
1617 # Append a definition to the specified section
1618 def appendSection(self, section, text):
1619 self.sections[section].append(text)
1620 #
1621 # Type generation
1622 def genType(self, typeinfo, name, alias):
1623 pass
1624 #
1625 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1626 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1627 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1628 # structs etc.)
1629 def genStruct(self, typeinfo, typeName):
1630 OutputGenerator.genStruct(self, typeinfo, typeName)
1631 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1632 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1633 for member in typeinfo.elem.findall('.//member'):
1634 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1635 body += ';\n'
1636 body += '} ' + typeName + ';\n'
1637 self.appendSection('struct', body)
1638 #
1639 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1640 def genGroup(self, groupinfo, groupName, alias):
1641 pass
1642 # Enumerant generation
1643 # <enum> tags may specify their values in several ways, but are usually just integers.
1644 def genEnum(self, enuminfo, name, alias):
1645 pass
1646 #
1647 # Customize Cdecl for layer factory base class
1648 def BaseClassCdecl(self, elem, name):
1649 raw = self.makeCDecls(elem)[1]
1650
1651 # Toss everything before the undecorated name
1652 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1653 prototype = prototype.replace(")", "", 1)
1654 prototype = prototype.replace(";", " {};")
1655
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001656 # Build up pre/post call virtual function declarations
1657 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1658 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1659 pre_call_record = 'virtual void PreCallRecord' + prototype
1660 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001661 resulttype = elem.find('proto/type')
1662 if resulttype.text == 'VkResult':
1663 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001664 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1665 #
1666 # Command generation
1667 def genCmd(self, cmdinfo, name, alias):
1668 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001669 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001670 ]
1671
1672 if name in ignore_functions:
1673 return
1674
1675 if self.header: # In the header declare all intercepts
1676 self.appendSection('command', '')
1677 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1678 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001679 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1680 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001681 if 'ValidationCache' not in name:
1682 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001683 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001684 self.layer_factory += '#endif\n'
1685 return
1686
Mark Lobodzinski31395512019-06-18 16:25:01 -06001687 is_instance = 'false'
1688 dispatchable_type = cmdinfo.elem.find('param/type').text
1689 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1690 is_instance = 'true'
1691
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001692 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001693 if 'ValidationCache' not in name:
Mark Lobodzinski31395512019-06-18 16:25:01 -06001694 self.intercepts += [ ' {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001695 else:
1696 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
Mark Lobodzinski31395512019-06-18 16:25:01 -06001697
1698 self.intercepts += [ ' {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001699 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001700 return
1701 # Record that the function will be intercepted
1702 if (self.featureExtraProtect != None):
1703 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
Mark Lobodzinski31395512019-06-18 16:25:01 -06001704 self.intercepts += [ ' {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001705 if (self.featureExtraProtect != None):
1706 self.intercepts += [ '#endif' ]
1707 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1708 #
1709 decls = self.makeCDecls(cmdinfo.elem)
1710 self.appendSection('command', '')
1711 self.appendSection('command', '%s {' % decls[0][:-1])
1712 # Setup common to call wrappers. First parameter is always dispatchable
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001713 dispatchable_name = cmdinfo.elem.find('param/name').text
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001714 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001715 api_function_name = cmdinfo.elem.attrib.get('name')
1716 params = cmdinfo.elem.findall('param/name')
1717 paramstext = ', '.join([str(param.text) for param in params])
Tony-LunarG152a88b2019-03-20 15:42:24 -06001718 API = api_function_name.replace('vk','Dispatch') + '('
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001719
1720 # Declare result variable, if any.
1721 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001722 'PFN_vkVoidFunction': 'return nullptr;',
1723 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001724 'VkDeviceAddress': 'return 0;',
1725 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1726 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001727 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001728 }
1729 resulttype = cmdinfo.elem.find('proto/type')
1730 assignresult = ''
1731 if (resulttype.text != 'void'):
1732 assignresult = resulttype.text + ' result = '
1733
1734 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001735 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001736
1737 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001738 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001739 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001740 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1741 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1742 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001743
1744 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001745 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001746 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001747 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001748 self.appendSection('command', ' }')
1749
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001750 # Insert pre-dispatch debug utils function call
1751 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001752 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001753
1754 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001755 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001756
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001757 # Insert post-dispatch debug utils function call
1758 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001759 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001760
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001761 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001762 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001763 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001764 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001765 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001766 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001767 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001768 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001769 # Return result variable, if any.
1770 if (resulttype.text != 'void'):
1771 self.appendSection('command', ' return result;')
1772 self.appendSection('command', '}')
1773 #
1774 # Override makeProtoName to drop the "vk" prefix
1775 def makeProtoName(self, name, tail):
1776 return self.genOpts.apientry + name[2:] + tail