blob: 82bab06e081b3565251ae4335bb54509245834d3 [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07003# Copyright (c) 2015-2019 Valve Corporation
4# Copyright (c) 2015-2019 LunarG, Inc.
5# Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06006#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
20# Author: Mark Lobodzinski <mark@lunarg.com>
21#
22# This script generates the dispatch portion of a factory layer which intercepts
23# all Vulkan functions. The resultant factory layer allows rapid development of
24# layers and interceptors.
25
26import os,re,sys
27from generator import *
28from common_codegen import *
29
30# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31#
32# Adds options used by LayerFactoryOutputGenerator objects during factory
33# layer generation.
34#
35# Additional members
36# prefixText - list of strings to prefix generated header with
37# (usually a copyright statement + calling convention macros).
38# protectFile - True if multiple inclusion protection should be
39# generated (based on the filename) around the entire header.
40# protectFeature - True if #ifndef..#endif protection should be
41# generated around a feature interface in the header file.
42# genFuncPointers - True if function pointer typedefs should be
43# generated
44# protectProto - If conditional protection should be generated
45# around prototype declarations, set to either '#ifdef'
46# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47# to require opt-out (#ifndef protectProtoStr). Otherwise
48# set to None.
49# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50# declarations, if protectProto is set
51# apicall - string to use for the function declaration prefix,
52# such as APICALL on Windows.
53# apientry - string to use for the calling convention macro,
54# in typedefs, such as APIENTRY.
55# apientryp - string to use for the calling convention macro
56# in function pointer typedefs, such as APIENTRYP.
57# indentFuncProto - True if prototype declarations should put each
58# parameter on a separate line
59# indentFuncPointer - True if typedefed function pointers should put each
60# parameter on a separate line
61# alignFuncParam - if nonzero and parameters are being put on a
62# separate line, align parameter names at the specified column
63class LayerChassisGeneratorOptions(GeneratorOptions):
64 def __init__(self,
Mike Schuchardt21638df2019-03-16 10:52:02 -070065 conventions = None,
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -060066 filename = None,
67 directory = '.',
68 apiname = None,
69 profile = None,
70 versions = '.*',
71 emitversions = '.*',
72 defaultExtensions = None,
73 addExtensions = None,
74 removeExtensions = None,
75 emitExtensions = None,
76 sortProcedure = regSortFeatures,
77 prefixText = "",
78 genFuncPointers = True,
79 protectFile = True,
80 protectFeature = True,
81 apicall = '',
82 apientry = '',
83 apientryp = '',
84 indentFuncProto = True,
85 indentFuncPointer = False,
86 alignFuncParam = 0,
87 helper_file_type = '',
88 expandEnumerants = True):
Mike Schuchardt21638df2019-03-16 10:52:02 -070089 GeneratorOptions.__init__(self, conventions, filename, directory, apiname, profile,
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -060090 versions, emitversions, defaultExtensions,
91 addExtensions, removeExtensions, emitExtensions, sortProcedure)
92 self.prefixText = prefixText
93 self.genFuncPointers = genFuncPointers
94 self.protectFile = protectFile
95 self.protectFeature = protectFeature
96 self.apicall = apicall
97 self.apientry = apientry
98 self.apientryp = apientryp
99 self.indentFuncProto = indentFuncProto
100 self.indentFuncPointer = indentFuncPointer
101 self.alignFuncParam = alignFuncParam
102
103# LayerChassisOutputGenerator - subclass of OutputGenerator.
104# Generates a LayerFactory layer that intercepts all API entrypoints
105# This is intended to be used as a starting point for creating custom layers
106#
107# ---- methods ----
108# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
109# OutputGenerator. Defines additional internal state.
110# ---- methods overriding base class ----
111# beginFile(genOpts)
112# endFile()
113# beginFeature(interface, emit)
114# endFeature()
115# genType(typeinfo,name)
116# genStruct(typeinfo,name)
117# genGroup(groupinfo,name)
118# genEnum(enuminfo, name)
119# genCmd(cmdinfo)
120class LayerChassisOutputGenerator(OutputGenerator):
121 """Generate specified API interfaces in a specific style, such as a C header"""
122 # This is an ordered list of sections in the header file.
123 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
124 'group', 'bitmask', 'funcpointer', 'struct']
125 ALL_SECTIONS = TYPE_SECTIONS + ['command']
126
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700127 manual_functions = [
128 # Include functions here to be interecpted w/ manually implemented function bodies
129 'vkGetDeviceProcAddr',
130 'vkGetInstanceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700131 'vkCreateDevice',
132 'vkDestroyDevice',
133 'vkCreateInstance',
134 'vkDestroyInstance',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700135 'vkEnumerateInstanceLayerProperties',
136 'vkEnumerateInstanceExtensionProperties',
137 'vkEnumerateDeviceLayerProperties',
138 'vkEnumerateDeviceExtensionProperties',
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700139 # Functions that are handled explicitly due to chassis architecture violations
140 'vkCreateGraphicsPipelines',
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700141 'vkCreateComputePipelines',
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700142 'vkCreateRayTracingPipelinesNV',
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -0700143 'vkCreatePipelineLayout',
Mark Lobodzinski1db77e82019-03-01 10:02:54 -0700144 'vkCreateShaderModule',
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -0700145 'vkAllocateDescriptorSets',
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700146 # ValidationCache functions do not get dispatched
147 'vkCreateValidationCacheEXT',
148 'vkDestroyValidationCacheEXT',
149 'vkMergeValidationCachesEXT',
150 'vkGetValidationCacheDataEXT',
Mark Lobodzinski56e88122019-03-26 10:21:48 -0600151 # We don't wanna hook this function
152 'vkGetPhysicalDeviceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700153 ]
154
155 alt_ret_codes = [
156 # Include functions here which must tolerate VK_INCOMPLETE as a return code
157 'vkEnumeratePhysicalDevices',
158 'vkEnumeratePhysicalDeviceGroupsKHR',
159 'vkGetValidationCacheDataEXT',
160 'vkGetPipelineCacheData',
161 'vkGetShaderInfoAMD',
162 'vkGetPhysicalDeviceDisplayPropertiesKHR',
163 'vkGetPhysicalDeviceDisplayProperties2KHR',
164 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
165 'vkGetDisplayPlaneSupportedDisplaysKHR',
166 'vkGetDisplayModePropertiesKHR',
167 'vkGetDisplayModeProperties2KHR',
168 'vkGetPhysicalDeviceSurfaceFormatsKHR',
169 'vkGetPhysicalDeviceSurfacePresentModesKHR',
170 'vkGetPhysicalDevicePresentRectanglesKHR',
171 'vkGetPastPresentationTimingGOOGLE',
172 'vkGetSwapchainImagesKHR',
173 'vkEnumerateInstanceLayerProperties',
174 'vkEnumerateDeviceLayerProperties',
175 'vkEnumerateInstanceExtensionProperties',
176 'vkEnumerateDeviceExtensionProperties',
177 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
178 ]
179
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700180 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700181 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
182 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700183 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
184 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700185 }
186
187 post_dispatch_debug_utils_functions = {
188 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700189 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
190 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
191 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
192 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700193 }
194
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600195 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
196 precallrecord_loop = precallvalidate_loop
197 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600198
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700199 inline_custom_header_preamble = """
200#define NOMINMAX
201#include <mutex>
202#include <cinttypes>
203#include <stdio.h>
204#include <stdlib.h>
205#include <string.h>
206#include <unordered_map>
207#include <unordered_set>
208#include <algorithm>
209#include <memory>
210
211#include "vk_loader_platform.h"
212#include "vulkan/vulkan.h"
213#include "vk_layer_config.h"
214#include "vk_layer_data.h"
215#include "vk_layer_logging.h"
216#include "vk_object_types.h"
217#include "vulkan/vk_layer.h"
218#include "vk_enum_string_helper.h"
219#include "vk_layer_extension_utils.h"
220#include "vk_layer_utils.h"
221#include "vulkan/vk_layer.h"
222#include "vk_dispatch_table_helper.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700223#include "vk_extension_helper.h"
224#include "vk_safe_struct.h"
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700225#include "vk_typemap_helper.h"
226
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700227
228extern uint64_t global_unique_id;
229extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
230"""
231
232 inline_custom_header_class_definition = """
233
234// Layer object type identifiers
235enum LayerObjectTypeId {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700236 LayerObjectTypeInstance, // Container for an instance dispatch object
237 LayerObjectTypeDevice, // Container for a device dispatch object
238 LayerObjectTypeThreading, // Instance or device threading layer object
239 LayerObjectTypeParameterValidation, // Instance or device parameter validation layer object
240 LayerObjectTypeObjectTracker, // Instance or device object tracker layer object
241 LayerObjectTypeCoreValidation, // Instance or device core validation layer object
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700242};
243
244struct TEMPLATE_STATE {
245 VkDescriptorUpdateTemplateKHR desc_update_template;
246 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
247
248 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
249 : desc_update_template(update_template), create_info(*pCreateInfo) {}
250};
251
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700252class LAYER_PHYS_DEV_PROPERTIES {
253public:
254 VkPhysicalDeviceProperties properties;
255 std::vector<VkQueueFamilyProperties> queue_family_properties;
256};
257
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600258typedef enum ValidationCheckDisables {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600259 VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600260 VALIDATION_CHECK_DISABLE_OBJECT_IN_USE,
261 VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET,
262 VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE,
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600263 VALIDATION_CHECK_DISABLE_QUERY_VALIDATION,
Matthew Ruschd7ef5482019-07-16 22:01:54 -0700264 VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600265} ValidationCheckDisables;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600266
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600267
268// CHECK_DISABLED struct is a container for bools that can block validation checks from being performed.
269// These bools are all "false" by default meaning that all checks are enabled. Enum values can be specified
270// via the vk_layer_setting.txt config file or at CreateInstance time via the VK_EXT_validation_features extension
271// that can selectively disable checks.
272struct CHECK_DISABLED {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600273 bool command_buffer_state; // Skip command buffer state validation
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600274 bool object_in_use; // Skip all object in_use checking
275 bool idle_descriptor_set; // Skip check to verify that descriptor set is not in-use
276 bool push_constant_range; // Skip push constant range checks
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600277 bool query_validation; // Disable all core validation query-related checks
Matthew Ruschd7ef5482019-07-16 22:01:54 -0700278 bool image_layout_validation; // Disable image layout validation
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600279 bool object_tracking; // Disable object lifetime validation
280 bool core_checks; // Disable core validation checks
281 bool thread_safety; // Disable thread safety validation
282 bool stateless_checks; // Disable stateless validation checks
283 bool handle_wrapping; // Disable unique handles/handle wrapping
284 bool shader_validation; // Skip validation for shaders
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700285
286 void SetAll(bool value) { std::fill(&command_buffer_state, &shader_validation + 1, value); }
287};
288
289struct CHECK_ENABLED {
290 bool gpu_validation;
291 bool gpu_validation_reserve_binding_slot;
292
293 void SetAll(bool value) { std::fill(&gpu_validation, &gpu_validation_reserve_binding_slot + 1, value); }
294};
295
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700296// Layer chassis validation object base class definition
297class ValidationObject {
298 public:
299 uint32_t api_version;
300 debug_report_data* report_data = nullptr;
301 std::vector<VkDebugReportCallbackEXT> logging_callback;
302 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
303
304 VkLayerInstanceDispatchTable instance_dispatch_table;
305 VkLayerDispatchTable device_dispatch_table;
306
307 InstanceExtensions instance_extensions;
308 DeviceExtensions device_extensions = {};
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700309 CHECK_DISABLED disabled = {};
310 CHECK_ENABLED enabled = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700311
312 VkInstance instance = VK_NULL_HANDLE;
313 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
314 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700315 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700316
317 std::vector<ValidationObject*> object_dispatch;
318 LayerObjectTypeId container_type;
319
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700320 std::string layer_name = "CHASSIS";
321
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700322 // Constructor
323 ValidationObject(){};
324 // Destructor
325 virtual ~ValidationObject() {};
326
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700327 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700328 virtual std::unique_lock<std::mutex> write_lock() {
329 return std::unique_lock<std::mutex>(validation_object_mutex);
330 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700331
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700332 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
333 for (auto validation_object : object_dispatch) {
334 if (validation_object->container_type == object_type) {
335 return validation_object;
336 }
337 }
338 return nullptr;
339 };
340
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700341 // Handle Wrapping Data
342 // Reverse map display handles
343 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
Mark Lobodzinskidd28ee22019-06-04 14:20:56 -0600344 // Wrapping Descriptor Template Update structures requires access to the template createinfo structs
345 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_createinfo_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700346 struct SubpassesUsageStates {
347 std::unordered_set<uint32_t> subpasses_using_color_attachment;
348 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
349 };
350 // Uses unwrapped handles
351 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
352 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
353 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
354 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700355 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
356 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700357
358
359 // Unwrap a handle. Must hold lock.
360 template <typename HandleType>
361 HandleType Unwrap(HandleType wrappedHandle) {
362 // TODO: don't use operator[] here.
363 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
364 }
365
366 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
367 template <typename HandleType>
368 HandleType WrapNew(HandleType newlyCreatedHandle) {
369 auto unique_id = global_unique_id++;
370 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
371 return (HandleType)unique_id;
372 }
373
374 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
375 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
376 auto unique_id = global_unique_id++;
377 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
378 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
379 return (VkDisplayKHR)unique_id;
380 }
381
382 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
383 // creating another. Must hold lock.
384 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
385 // See if this display is already known
386 auto it = map_data->display_id_reverse_mapping.find(handle);
387 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
388 // Unknown, so wrap
389 return WrapDisplay(handle, map_data);
390 }
391
392 // Pre/post hook point declarations
393"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600394
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700395 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600396// This file is ***GENERATED***. Do Not Edit.
397// See layer_chassis_generator.py for modifications.
398
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700399/* Copyright (c) 2015-2019 The Khronos Group Inc.
400 * Copyright (c) 2015-2019 Valve Corporation
401 * Copyright (c) 2015-2019 LunarG, Inc.
402 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600403 *
404 * Licensed under the Apache License, Version 2.0 (the "License");
405 * you may not use this file except in compliance with the License.
406 * You may obtain a copy of the License at
407 *
408 * http://www.apache.org/licenses/LICENSE-2.0
409 *
410 * Unless required by applicable law or agreed to in writing, software
411 * distributed under the License is distributed on an "AS IS" BASIS,
412 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
413 * See the License for the specific language governing permissions and
414 * limitations under the License.
415 *
416 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700417 */"""
418
419 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600420
421#include <string.h>
422#include <mutex>
423
424#define VALIDATION_ERROR_MAP_IMPL
425
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600426#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700427#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600428
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600429std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600430
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700431// Global unique object identifier. All increments must be guarded by a lock.
432uint64_t global_unique_id = 1;
433// Map uniqueID to actual object handle
434std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
435
436// TODO: This variable controls handle wrapping -- in the future it should be hooked
437// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
438#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
439bool wrap_handles = true;
440#else
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600441bool wrap_handles = false;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700442#endif
443
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600444// Set layer name -- Khronos layer name overrides any other defined names
Mark Lobodzinskiaa6fd7b2019-03-19 09:26:48 -0600445#if BUILD_KHRONOS_VALIDATION
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600446#define OBJECT_LAYER_NAME "VK_LAYER_KHRONOS_validation"
447#define OBJECT_LAYER_DESCRIPTION "khronos_validation"
448#elif BUILD_OBJECT_TRACKER
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700449#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600450#define OBJECT_LAYER_DESCRIPTION "lunarg_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700451#elif BUILD_THREAD_SAFETY
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700452#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600453#define OBJECT_LAYER_DESCRIPTION "google_thread_checker"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700454#elif BUILD_PARAMETER_VALIDATION
455#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600456#define OBJECT_LAYER_DESCRIPTION "lunarg_parameter_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700457#elif BUILD_CORE_VALIDATION
458#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600459#define OBJECT_LAYER_DESCRIPTION "lunarg_core_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700460#else
461#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600462#define OBJECT_LAYER_DESCRIPTION "lunarg_unique_objects"
463#endif
464
465// Include layer validation object definitions
466#if BUILD_OBJECT_TRACKER
467#include "object_lifetime_validation.h"
468#endif
469#if BUILD_THREAD_SAFETY
470#include "thread_safety.h"
471#endif
472#if BUILD_PARAMETER_VALIDATION
473#include "stateless_validation.h"
474#endif
475#if BUILD_CORE_VALIDATION
476#include "core_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700477#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600478
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600479namespace vulkan_layer_chassis {
480
481using std::unordered_map;
482
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600483static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700484 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600485};
486
John Zulauf358462e2019-04-10 11:10:32 -0600487static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION},
488 {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION}};
Lenny Komow3627f6e2019-06-19 13:54:59 -0600489static const VkExtensionProperties device_extensions[] = {
490 {VK_EXT_VALIDATION_CACHE_EXTENSION_NAME, VK_EXT_VALIDATION_CACHE_SPEC_VERSION},
491 {VK_EXT_DEBUG_MARKER_EXTENSION_NAME, VK_EXT_DEBUG_MARKER_SPEC_VERSION},
492};
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600493
Mark Lobodzinski31395512019-06-18 16:25:01 -0600494typedef struct {
495 bool is_instance_api;
496 void* funcptr;
497} function_data;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600498
Mark Lobodzinski31395512019-06-18 16:25:01 -0600499extern const std::unordered_map<std::string, function_data> name_to_funcptr_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600500
501// Manually written functions
502
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700503// Check enabled instance extensions against supported instance extension whitelist
504static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
505 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
506 // Check for recognized instance extensions
507 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
508 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
509 kVUIDUndefined,
510 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
511 "results and/or produce undefined behavior.",
512 pCreateInfo->ppEnabledExtensionNames[i]);
513 }
514 }
515}
516
517// Check enabled device extensions against supported device extension whitelist
518static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
519 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
520 // Check for recognized device extensions
521 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
522 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
523 kVUIDUndefined,
524 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
525 "results and/or produce undefined behavior.",
526 pCreateInfo->ppEnabledExtensionNames[i]);
527 }
528 }
529}
530
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600531
532// Process validation features, flags and settings specified through extensions, a layer settings file, or environment variables
533
534static const std::unordered_map<std::string, VkValidationFeatureDisableEXT> VkValFeatureDisableLookup = {
535 {"VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT", VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT},
536 {"VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT", VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT},
537 {"VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT", VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT},
538 {"VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT", VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT},
539 {"VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT", VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT},
540 {"VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT", VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT},
541 {"VK_VALIDATION_FEATURE_DISABLE_ALL_EXT", VK_VALIDATION_FEATURE_DISABLE_ALL_EXT},
542};
543
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600544static const std::unordered_map<std::string, VkValidationFeatureEnableEXT> VkValFeatureEnableLookup = {
545 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT},
546 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT},
547};
548
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600549static const std::unordered_map<std::string, ValidationCheckDisables> ValidationDisableLookup = {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600550 {"VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE", VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600551 {"VALIDATION_CHECK_DISABLE_OBJECT_IN_USE", VALIDATION_CHECK_DISABLE_OBJECT_IN_USE},
552 {"VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET", VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET},
553 {"VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE", VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE},
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600554 {"VALIDATION_CHECK_DISABLE_QUERY_VALIDATION", VALIDATION_CHECK_DISABLE_QUERY_VALIDATION},
Matthew Ruschd7ef5482019-07-16 22:01:54 -0700555 {"VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION", VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600556};
557
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600558// Set the local disable flag for the appropriate VALIDATION_CHECK_DISABLE enum
559void SetValidationDisable(CHECK_DISABLED* disable_data, const ValidationCheckDisables disable_id) {
560 switch (disable_id) {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600561 case VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE:
562 disable_data->command_buffer_state = true;
563 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600564 case VALIDATION_CHECK_DISABLE_OBJECT_IN_USE:
565 disable_data->object_in_use = true;
566 break;
567 case VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET:
568 disable_data->idle_descriptor_set = true;
569 break;
570 case VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE:
571 disable_data->push_constant_range = true;
572 break;
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600573 case VALIDATION_CHECK_DISABLE_QUERY_VALIDATION:
574 disable_data->query_validation = true;
575 break;
Matthew Ruschd7ef5482019-07-16 22:01:54 -0700576 case VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION:
577 disable_data->image_layout_validation = true;
578 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600579 default:
580 assert(true);
581 }
582}
583
584// Set the local disable flag for a single VK_VALIDATION_FEATURE_DISABLE_* flag
585void SetValidationFeatureDisable(CHECK_DISABLED* disable_data, const VkValidationFeatureDisableEXT feature_disable) {
586 switch (feature_disable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700587 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600588 disable_data->shader_validation = true;
589 break;
590 case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
591 disable_data->thread_safety = true;
592 break;
593 case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
594 disable_data->stateless_checks = true;
595 break;
596 case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
597 disable_data->object_tracking = true;
598 break;
599 case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
600 disable_data->core_checks = true;
601 break;
602 case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
603 disable_data->handle_wrapping = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700604 break;
605 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
606 // Set all disabled flags to true
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600607 disable_data->SetAll(true);
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700608 break;
609 default:
610 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700611 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600612}
613
614// Set the local enable flag for a single VK_VALIDATION_FEATURE_ENABLE_* flag
615void SetValidationFeatureEnable(CHECK_ENABLED *enable_data, const VkValidationFeatureEnableEXT feature_enable) {
616 switch (feature_enable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700617 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600618 enable_data->gpu_validation = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700619 break;
620 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600621 enable_data->gpu_validation_reserve_binding_slot = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700622 break;
623 default:
624 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700625 }
626}
627
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600628// Set the local disable flag for settings specified through the VK_EXT_validation_flags extension
629void SetValidationFlags(CHECK_DISABLED* disables, const VkValidationFlagsEXT* val_flags_struct) {
630 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
631 switch (val_flags_struct->pDisabledValidationChecks[i]) {
632 case VK_VALIDATION_CHECK_SHADERS_EXT:
633 disables->shader_validation = true;
634 break;
635 case VK_VALIDATION_CHECK_ALL_EXT:
636 // Set all disabled flags to true
637 disables->SetAll(true);
638 break;
639 default:
640 break;
641 }
642 }
643}
644
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600645// Process Validation Features flags specified through the ValidationFeature extension
646void SetValidationFeatures(CHECK_DISABLED *disable_data, CHECK_ENABLED *enable_data,
647 const VkValidationFeaturesEXT *val_features_struct) {
648 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
649 SetValidationFeatureDisable(disable_data, val_features_struct->pDisabledValidationFeatures[i]);
650 }
651 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
652 SetValidationFeatureEnable(enable_data, val_features_struct->pEnabledValidationFeatures[i]);
653 }
654}
655
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600656// Given a string representation of a list of enable enum values, call the appropriate setter function
657void SetLocalEnableSetting(std::string list_of_enables, std::string delimiter, CHECK_ENABLED* enables) {
658 size_t pos = 0;
659 std::string token;
660 while (list_of_enables.length() != 0) {
661 pos = list_of_enables.find(delimiter);
662 if (pos != std::string::npos) {
663 token = list_of_enables.substr(0, pos);
664 } else {
665 pos = list_of_enables.length() - delimiter.length();
666 token = list_of_enables;
667 }
668 if (token.find("VK_VALIDATION_FEATURE_ENABLE_") != std::string::npos) {
669 auto result = VkValFeatureEnableLookup.find(token);
670 if (result != VkValFeatureEnableLookup.end()) {
671 SetValidationFeatureEnable(enables, result->second);
672 }
673 }
674 list_of_enables.erase(0, pos + delimiter.length());
675 }
676}
677
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600678// Given a string representation of a list of disable enum values, call the appropriate setter function
679void SetLocalDisableSetting(std::string list_of_disables, std::string delimiter, CHECK_DISABLED* disables) {
680 size_t pos = 0;
681 std::string token;
682 while (list_of_disables.length() != 0) {
683 pos = list_of_disables.find(delimiter);
684 if (pos != std::string::npos) {
685 token = list_of_disables.substr(0, pos);
686 } else {
687 pos = list_of_disables.length() - delimiter.length();
688 token = list_of_disables;
689 }
690 if (token.find("VK_VALIDATION_FEATURE_DISABLE_") != std::string::npos) {
691 auto result = VkValFeatureDisableLookup.find(token);
692 if (result != VkValFeatureDisableLookup.end()) {
693 SetValidationFeatureDisable(disables, result->second);
694 }
695 }
696 if (token.find("VALIDATION_CHECK_DISABLE_") != std::string::npos) {
697 auto result = ValidationDisableLookup.find(token);
698 if (result != ValidationDisableLookup.end()) {
699 SetValidationDisable(disables, result->second);
700 }
701 }
702 list_of_disables.erase(0, pos + delimiter.length());
703 }
704}
705
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600706// Process enables and disables set though the vk_layer_settings.txt config file or through an environment variable
707void ProcessConfigAndEnvSettings(const char* layer_description, CHECK_ENABLED* enables, CHECK_DISABLED* disables) {
708 std::string enable_key = layer_description;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600709 std::string disable_key = layer_description;
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600710 enable_key.append(".enables");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600711 disable_key.append(".disables");
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600712 std::string list_of_config_enables = getLayerOption(enable_key.c_str());
713 std::string list_of_env_enables = GetLayerEnvVar("VK_LAYER_ENABLES");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600714 std::string list_of_config_disables = getLayerOption(disable_key.c_str());
715 std::string list_of_env_disables = GetLayerEnvVar("VK_LAYER_DISABLES");
716#if defined(_WIN32)
717 std::string env_delimiter = ";";
718#else
719 std::string env_delimiter = ":";
720#endif
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600721 SetLocalEnableSetting(list_of_config_enables, ",", enables);
722 SetLocalEnableSetting(list_of_env_enables, env_delimiter, enables);
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600723 SetLocalDisableSetting(list_of_config_disables, ",", disables);
724 SetLocalDisableSetting(list_of_env_disables, env_delimiter, disables);
725}
726
727
728// Non-code-generated chassis API functions
729
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600730VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600731 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskif94196f2019-07-11 11:46:09 -0600732 if (!ApiParentExtensionEnabled(funcName, &layer_data->device_extensions)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700733 return nullptr;
734 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600735 const auto &item = name_to_funcptr_map.find(funcName);
736 if (item != name_to_funcptr_map.end()) {
Mark Lobodzinski31395512019-06-18 16:25:01 -0600737 if (item->second.is_instance_api) {
738 return nullptr;
739 } else {
740 return reinterpret_cast<PFN_vkVoidFunction>(item->second.funcptr);
741 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600742 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600743 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600744 if (!table.GetDeviceProcAddr) return nullptr;
745 return table.GetDeviceProcAddr(device, funcName);
746}
747
748VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600749 const auto &item = name_to_funcptr_map.find(funcName);
750 if (item != name_to_funcptr_map.end()) {
Mark Lobodzinski31395512019-06-18 16:25:01 -0600751 return reinterpret_cast<PFN_vkVoidFunction>(item->second.funcptr);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600752 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600753 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
754 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600755 if (!table.GetInstanceProcAddr) return nullptr;
756 return table.GetInstanceProcAddr(instance, funcName);
757}
758
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600759VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
760 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
761}
762
763VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
764 VkLayerProperties *pProperties) {
765 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
766}
767
768VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
769 VkExtensionProperties *pProperties) {
770 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
John Zulauf358462e2019-04-10 11:10:32 -0600771 return util_GetExtensionProperties(ARRAY_SIZE(instance_extensions), instance_extensions, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600772
773 return VK_ERROR_LAYER_NOT_PRESENT;
774}
775
776VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
777 uint32_t *pCount, VkExtensionProperties *pProperties) {
Lenny Komow3627f6e2019-06-19 13:54:59 -0600778 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 -0600779 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600780 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
Lenny Komow7b567f72019-06-10 16:49:43 -0600781 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600782}
783
784VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
785 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600786 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600787
788 assert(chain_info->u.pLayerInfo);
789 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
790 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
791 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
792 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700793 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
794 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
795
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600796 CHECK_ENABLED local_enables {};
797 CHECK_DISABLED local_disables {};
798 const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(pCreateInfo->pNext);
799 if (validation_features_ext) {
800 SetValidationFeatures(&local_disables, &local_enables, validation_features_ext);
801 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600802 const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
803 if (validation_flags_ext) {
804 SetValidationFlags(&local_disables, validation_flags_ext);
805 }
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600806 ProcessConfigAndEnvSettings(OBJECT_LAYER_DESCRIPTION, &local_enables, &local_disables);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600807
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600808 // Create temporary dispatch vector for pre-calls until instance is created
809 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600810 // Add VOs to dispatch vector. Order here will be the validation dispatch order!
811#if BUILD_THREAD_SAFETY
812 auto thread_checker = new ThreadSafety;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600813 if (!local_disables.thread_safety) {
814 local_object_dispatch.emplace_back(thread_checker);
815 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600816 thread_checker->container_type = LayerObjectTypeThreading;
817 thread_checker->api_version = api_version;
818#endif
819#if BUILD_PARAMETER_VALIDATION
820 auto parameter_validation = new StatelessValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600821 if (!local_disables.stateless_checks) {
822 local_object_dispatch.emplace_back(parameter_validation);
823 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600824 parameter_validation->container_type = LayerObjectTypeParameterValidation;
825 parameter_validation->api_version = api_version;
826#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700827#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600828 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600829 if (!local_disables.object_tracking) {
830 local_object_dispatch.emplace_back(object_tracker);
831 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600832 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700833 object_tracker->api_version = api_version;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600834#endif
835#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700836 auto core_checks = new CoreChecks;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600837 if (!local_disables.core_checks) {
838 local_object_dispatch.emplace_back(core_checks);
839 }
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700840 core_checks->container_type = LayerObjectTypeCoreValidation;
841 core_checks->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700842#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600843
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600844 // If handle wrapping is disabled via the ValidationFeatures extension, override build flag
845 if (local_disables.handle_wrapping) {
846 wrap_handles = false;
847 }
848
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600849 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600850 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600851 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
852 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600853 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600854 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
855 }
856
857 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600858 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600859
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600860 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600861
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600862 framework->object_dispatch = local_object_dispatch;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700863 framework->container_type = LayerObjectTypeInstance;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600864 framework->disabled = local_disables;
865 framework->enabled = local_enables;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600866
867 framework->instance = *pInstance;
868 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
869 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
870 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700871 framework->api_version = api_version;
872 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
873
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600874 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, OBJECT_LAYER_DESCRIPTION);
875
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700876#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700877 object_tracker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600878 object_tracker->instance_dispatch_table = framework->instance_dispatch_table;
879 object_tracker->enabled = framework->enabled;
880 object_tracker->disabled = framework->disabled;
881#endif
882#if BUILD_THREAD_SAFETY
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700883 thread_checker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600884 thread_checker->instance_dispatch_table = framework->instance_dispatch_table;
885 thread_checker->enabled = framework->enabled;
886 thread_checker->disabled = framework->disabled;
887#endif
888#if BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700889 parameter_validation->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600890 parameter_validation->instance_dispatch_table = framework->instance_dispatch_table;
891 parameter_validation->enabled = framework->enabled;
892 parameter_validation->disabled = framework->disabled;
893#endif
894#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700895 core_checks->report_data = framework->report_data;
896 core_checks->instance_dispatch_table = framework->instance_dispatch_table;
897 core_checks->instance = *pInstance;
898 core_checks->enabled = framework->enabled;
899 core_checks->disabled = framework->disabled;
900 core_checks->instance_state = core_checks;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700901#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600902
903 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700904 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600905 }
906
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700907 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
908
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600909 return result;
910}
911
912VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
913 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600914 auto layer_data = GetLayerDataPtr(key, layer_data_map);
915 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700916 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600917 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
918 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600919 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700920 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600921 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
922 }
923
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600924 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600925
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600926 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700927 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600928 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
929 }
930 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600931 while (layer_data->logging_messenger.size() > 0) {
932 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
933 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
934 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600935 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600936 while (layer_data->logging_callback.size() > 0) {
937 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
938 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
939 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600940 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600941
942 layer_debug_utils_destroy_instance(layer_data->report_data);
943
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700944 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
945 delete *item;
946 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600947 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600948}
949
950VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
951 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600952 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600953
954 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
955
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600956 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
957 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600958 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
959 if (fpCreateDevice == NULL) {
960 return VK_ERROR_INITIALIZATION_FAILED;
961 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600962 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
963
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700964 // Get physical device limits for device
965 VkPhysicalDeviceProperties device_properties = {};
966 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
967
968 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
969 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
970
971 DeviceExtensions device_extensions = {};
972 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
973 for (auto item : instance_interceptor->object_dispatch) {
974 item->device_extensions = device_extensions;
975 }
976
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700977 std::unique_ptr<safe_VkDeviceCreateInfo> modified_create_info(new safe_VkDeviceCreateInfo(pCreateInfo));
978
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700979 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600980 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700981 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700982 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700983 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600984 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600985 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700986 auto lock = intercept->write_lock();
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700987 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, modified_create_info);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600988 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600989
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700990 VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(modified_create_info.get()), pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600991 if (result != VK_SUCCESS) {
992 return result;
993 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600994
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600995 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700996 device_interceptor->container_type = LayerObjectTypeDevice;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700997
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700998 // Save local info in device object
999 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001000 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
1001 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001002 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001003
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001004 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001005
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001006 device_interceptor->device = *pDevice;
1007 device_interceptor->physical_device = gpu;
1008 device_interceptor->instance = instance_interceptor->instance;
1009 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001010
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001011 // Note that this defines the order in which the layer validation objects are called
1012#if BUILD_THREAD_SAFETY
1013 auto thread_safety = new ThreadSafety;
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001014 thread_safety->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001015 if (!instance_interceptor->disabled.thread_safety) {
1016 device_interceptor->object_dispatch.emplace_back(thread_safety);
1017 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001018#endif
1019#if BUILD_PARAMETER_VALIDATION
1020 auto stateless_validation = new StatelessValidation;
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001021 stateless_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001022 if (!instance_interceptor->disabled.stateless_checks) {
1023 device_interceptor->object_dispatch.emplace_back(stateless_validation);
1024 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001025#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001026#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001027 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001028 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001029 if (!instance_interceptor->disabled.object_tracking) {
1030 device_interceptor->object_dispatch.emplace_back(object_tracker);
1031 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001032#endif
1033#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001034 auto core_checks = new CoreChecks;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001035 core_checks->container_type = LayerObjectTypeCoreValidation;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001036 core_checks->instance_state = reinterpret_cast<CoreChecks *>(
1037 core_checks->GetValidationObject(instance_interceptor->object_dispatch, LayerObjectTypeCoreValidation));
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001038 if (!instance_interceptor->disabled.core_checks) {
1039 device_interceptor->object_dispatch.emplace_back(core_checks);
1040 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001041#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001042
Mark Lobodzinski7314bf42019-03-28 08:54:53 -06001043 // Set per-intercept common data items
1044 for (auto dev_intercept : device_interceptor->object_dispatch) {
1045 dev_intercept->device = *pDevice;
1046 dev_intercept->physical_device = gpu;
1047 dev_intercept->instance = instance_interceptor->instance;
1048 dev_intercept->report_data = device_interceptor->report_data;
1049 dev_intercept->device_dispatch_table = device_interceptor->device_dispatch_table;
1050 dev_intercept->api_version = device_interceptor->api_version;
1051 dev_intercept->disabled = instance_interceptor->disabled;
1052 dev_intercept->enabled = instance_interceptor->enabled;
1053 dev_intercept->instance_dispatch_table = instance_interceptor->instance_dispatch_table;
1054 dev_intercept->instance_extensions = instance_interceptor->instance_extensions;
1055 dev_intercept->device_extensions = device_interceptor->device_extensions;
1056 }
1057
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001058 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001059 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001060 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001061 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001062
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001063 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
1064
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001065 return result;
1066}
1067
1068VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
1069 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001070 auto layer_data = GetLayerDataPtr(key, layer_data_map);
1071 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001072 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001073 intercept->PreCallValidateDestroyDevice(device, pAllocator);
1074 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001075 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001076 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001077 intercept->PreCallRecordDestroyDevice(device, pAllocator);
1078 }
1079 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001080
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001081 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001082
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001083 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001084 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001085 intercept->PostCallRecordDestroyDevice(device, pAllocator);
1086 }
1087
Mark Lobodzinskic5003372018-12-17 16:36:01 -07001088 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
1089 delete *item;
1090 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001091 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001092}
1093
1094
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001095// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001096
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001097VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
1098 VkDevice device,
1099 VkPipelineCache pipelineCache,
1100 uint32_t createInfoCount,
1101 const VkGraphicsPipelineCreateInfo* pCreateInfos,
1102 const VkAllocationCallbacks* pAllocator,
1103 VkPipeline* pPipelines) {
1104 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1105 bool skip = false;
1106
1107#ifdef BUILD_CORE_VALIDATION
1108 create_graphics_pipeline_api_state cgpl_state{};
1109#else
1110 struct create_graphics_pipeline_api_state {
1111 const VkGraphicsPipelineCreateInfo* pCreateInfos;
1112 } cgpl_state;
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001113#endif
Mark Lobodzinskid08e16c2019-06-11 10:22:10 -06001114 cgpl_state.pCreateInfos = pCreateInfos;
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001115
1116 for (auto intercept : layer_data->object_dispatch) {
1117 auto lock = intercept->write_lock();
1118 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1119 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1120 }
1121 for (auto intercept : layer_data->object_dispatch) {
1122 auto lock = intercept->write_lock();
1123 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1124 }
1125
Tony-LunarG152a88b2019-03-20 15:42:24 -06001126 VkResult result = DispatchCreateGraphicsPipelines(device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001127
1128 for (auto intercept : layer_data->object_dispatch) {
1129 auto lock = intercept->write_lock();
1130 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
1131 }
1132 return result;
1133}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001134
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001135// This API saves some core_validation pipeline state state on the stack for performance purposes
1136VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
1137 VkDevice device,
1138 VkPipelineCache pipelineCache,
1139 uint32_t createInfoCount,
1140 const VkComputePipelineCreateInfo* pCreateInfos,
1141 const VkAllocationCallbacks* pAllocator,
1142 VkPipeline* pPipelines) {
1143 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1144 bool skip = false;
1145
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001146#ifdef BUILD_CORE_VALIDATION
1147 create_compute_pipeline_api_state ccpl_state{};
1148#else
1149 struct create_compute_pipeline_api_state {
1150 const VkComputePipelineCreateInfo* pCreateInfos;
1151 } ccpl_state;
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001152#endif
Mark Lobodzinskid08e16c2019-06-11 10:22:10 -06001153 ccpl_state.pCreateInfos = pCreateInfos;
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001154
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001155 for (auto intercept : layer_data->object_dispatch) {
1156 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001157 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001158 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1159 }
1160 for (auto intercept : layer_data->object_dispatch) {
1161 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001162 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001163 }
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001164 VkResult result = DispatchCreateComputePipelines(device, pipelineCache, createInfoCount, ccpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001165 for (auto intercept : layer_data->object_dispatch) {
1166 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001167 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001168 }
1169 return result;
1170}
1171
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001172VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
1173 VkDevice device,
1174 VkPipelineCache pipelineCache,
1175 uint32_t createInfoCount,
1176 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
1177 const VkAllocationCallbacks* pAllocator,
1178 VkPipeline* pPipelines) {
1179 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1180 bool skip = false;
1181
Jason Macnak67407e72019-07-11 11:05:09 -07001182#ifdef BUILD_CORE_VALIDATION
1183 create_ray_tracing_pipeline_api_state crtpl_state{};
1184#else
1185 struct create_ray_tracing_pipeline_api_state {
1186 const VkRayTracingPipelineCreateInfoNV* pCreateInfos;
1187 } crtpl_state;
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001188#endif
Jason Macnak67407e72019-07-11 11:05:09 -07001189 crtpl_state.pCreateInfos = pCreateInfos;
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001190
1191 for (auto intercept : layer_data->object_dispatch) {
1192 auto lock = intercept->write_lock();
Jason Macnak67407e72019-07-11 11:05:09 -07001193 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos,
1194 pAllocator, pPipelines, &crtpl_state);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001195 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1196 }
1197 for (auto intercept : layer_data->object_dispatch) {
1198 auto lock = intercept->write_lock();
Jason Macnak67407e72019-07-11 11:05:09 -07001199 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator,
1200 pPipelines, &crtpl_state);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001201 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001202 VkResult result = DispatchCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001203 for (auto intercept : layer_data->object_dispatch) {
1204 auto lock = intercept->write_lock();
Jason Macnak67407e72019-07-11 11:05:09 -07001205 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator,
1206 pPipelines, result, &crtpl_state);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001207 }
1208 return result;
1209}
1210
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001211// This API needs the ability to modify a down-chain parameter
1212VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
1213 VkDevice device,
1214 const VkPipelineLayoutCreateInfo* pCreateInfo,
1215 const VkAllocationCallbacks* pAllocator,
1216 VkPipelineLayout* pPipelineLayout) {
1217 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1218 bool skip = false;
1219
1220#ifndef BUILD_CORE_VALIDATION
1221 struct create_pipeline_layout_api_state {
1222 VkPipelineLayoutCreateInfo modified_create_info;
1223 };
1224#endif
1225 create_pipeline_layout_api_state cpl_state{};
1226 cpl_state.modified_create_info = *pCreateInfo;
1227
1228 for (auto intercept : layer_data->object_dispatch) {
1229 auto lock = intercept->write_lock();
1230 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1231 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1232 }
1233 for (auto intercept : layer_data->object_dispatch) {
1234 auto lock = intercept->write_lock();
1235 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1236 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001237 VkResult result = DispatchCreatePipelineLayout(device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001238 for (auto intercept : layer_data->object_dispatch) {
1239 auto lock = intercept->write_lock();
1240 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1241 }
1242 return result;
1243}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001244
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001245// This API needs some local stack data for performance reasons and also may modify a parameter
1246VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1247 VkDevice device,
1248 const VkShaderModuleCreateInfo* pCreateInfo,
1249 const VkAllocationCallbacks* pAllocator,
1250 VkShaderModule* pShaderModule) {
1251 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1252 bool skip = false;
1253
1254#ifndef BUILD_CORE_VALIDATION
1255 struct create_shader_module_api_state {
1256 VkShaderModuleCreateInfo instrumented_create_info;
1257 };
1258#endif
1259 create_shader_module_api_state csm_state{};
1260 csm_state.instrumented_create_info = *pCreateInfo;
1261
1262 for (auto intercept : layer_data->object_dispatch) {
1263 auto lock = intercept->write_lock();
1264 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1265 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1266 }
1267 for (auto intercept : layer_data->object_dispatch) {
1268 auto lock = intercept->write_lock();
1269 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1270 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001271 VkResult result = DispatchCreateShaderModule(device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001272 for (auto intercept : layer_data->object_dispatch) {
1273 auto lock = intercept->write_lock();
1274 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1275 }
1276 return result;
1277}
1278
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001279VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1280 VkDevice device,
1281 const VkDescriptorSetAllocateInfo* pAllocateInfo,
1282 VkDescriptorSet* pDescriptorSets) {
1283 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1284 bool skip = false;
1285
1286#ifdef BUILD_CORE_VALIDATION
1287 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1288#else
1289 struct ads_state {} ads_state;
1290#endif
1291
1292 for (auto intercept : layer_data->object_dispatch) {
1293 auto lock = intercept->write_lock();
1294 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1295 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1296 }
1297 for (auto intercept : layer_data->object_dispatch) {
1298 auto lock = intercept->write_lock();
1299 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1300 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001301 VkResult result = DispatchAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001302 for (auto intercept : layer_data->object_dispatch) {
1303 auto lock = intercept->write_lock();
1304 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1305 }
1306 return result;
1307}
1308
1309
1310
1311
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001312
1313// ValidationCache APIs do not dispatch
1314
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001315VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1316 VkDevice device,
1317 const VkValidationCacheCreateInfoEXT* pCreateInfo,
1318 const VkAllocationCallbacks* pAllocator,
1319 VkValidationCacheEXT* pValidationCache) {
1320 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1321 VkResult result = VK_SUCCESS;
1322
1323 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1324 if (validation_data) {
1325 auto lock = validation_data->write_lock();
1326 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1327 }
1328 return result;
1329}
1330
1331VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1332 VkDevice device,
1333 VkValidationCacheEXT validationCache,
1334 const VkAllocationCallbacks* pAllocator) {
1335 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1336
1337 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1338 if (validation_data) {
1339 auto lock = validation_data->write_lock();
1340 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1341 }
1342}
1343
1344VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1345 VkDevice device,
1346 VkValidationCacheEXT dstCache,
1347 uint32_t srcCacheCount,
1348 const VkValidationCacheEXT* pSrcCaches) {
1349 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1350 VkResult result = VK_SUCCESS;
1351
1352 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1353 if (validation_data) {
1354 auto lock = validation_data->write_lock();
1355 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1356 }
1357 return result;
1358}
1359
1360VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1361 VkDevice device,
1362 VkValidationCacheEXT validationCache,
1363 size_t* pDataSize,
1364 void* pData) {
1365 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1366 VkResult result = VK_SUCCESS;
1367
1368 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1369 if (validation_data) {
1370 auto lock = validation_data->write_lock();
1371 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1372 }
1373 return result;
1374
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001375}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001376
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001377 inline_custom_validation_class_definitions = """
1378 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1379 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1380 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1381 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001382
Jason Macnak67407e72019-07-11 11:05:09 -07001383 // Allow additional state parameter for CreateGraphicsPipelines
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001384 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1385 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1386 };
1387 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1388 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1389 };
1390 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1391 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1392 };
Jason Macnak67407e72019-07-11 11:05:09 -07001393
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001394 // Allow additional state parameter for CreateComputePipelines
1395 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1396 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1397 };
Jason Macnak67407e72019-07-11 11:05:09 -07001398 virtual void PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* ccpl_state) {
1399 PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1400 };
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001401 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1402 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1403 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001404
1405 // Allow additional state parameter for CreateRayTracingPipelinesNV
1406 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1407 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1408 };
Jason Macnak67407e72019-07-11 11:05:09 -07001409 virtual void PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* ccpl_state) {
1410 PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1411 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001412 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1413 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1414 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001415
1416 // Allow modification of a down-chain parameter for CreatePipelineLayout
1417 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1418 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1419 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001420
1421 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1422 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1423 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1424 };
1425 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1426 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1427 };
1428 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1429 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1430 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001431
1432 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1433 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1434 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1435 };
1436 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1437 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1438 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001439
1440 // Modify a parameter to CreateDevice
1441 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1442 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1443 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001444"""
1445
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001446 inline_custom_source_postamble = """
1447// loader-layer interface v0, just wrappers since there is only a layer
1448
1449VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1450 VkExtensionProperties *pProperties) {
1451 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1452}
1453
1454VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1455 VkLayerProperties *pProperties) {
1456 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1457}
1458
1459VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1460 VkLayerProperties *pProperties) {
1461 // the layer command handles VK_NULL_HANDLE just fine internally
1462 assert(physicalDevice == VK_NULL_HANDLE);
1463 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1464}
1465
1466VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1467 const char *pLayerName, uint32_t *pCount,
1468 VkExtensionProperties *pProperties) {
1469 // the layer command handles VK_NULL_HANDLE just fine internally
1470 assert(physicalDevice == VK_NULL_HANDLE);
1471 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1472}
1473
1474VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1475 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1476}
1477
1478VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1479 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1480}
1481
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001482VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1483 assert(pVersionStruct != NULL);
1484 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1485
1486 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1487 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1488 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1489 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
Mark Lobodzinski56e88122019-03-26 10:21:48 -06001490 pVersionStruct->pfnGetPhysicalDeviceProcAddr = nullptr;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001491 }
1492
1493 return VK_SUCCESS;
1494}"""
1495
1496
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001497 def __init__(self,
1498 errFile = sys.stderr,
1499 warnFile = sys.stderr,
1500 diagFile = sys.stdout):
1501 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1502 # Internal state - accumulators for different inner block text
1503 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1504 self.intercepts = []
1505 self.layer_factory = '' # String containing base layer factory class definition
1506
1507 # Check if the parameter passed in is a pointer to an array
1508 def paramIsArray(self, param):
1509 return param.attrib.get('len') is not None
1510
1511 # Check if the parameter passed in is a pointer
1512 def paramIsPointer(self, param):
1513 ispointer = False
1514 for elem in param:
Raul Tambre7b300182019-05-04 11:25:14 +03001515 if elem.tag == 'type' and elem.tail is not None and '*' in elem.tail:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001516 ispointer = True
1517 return ispointer
1518
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001519 #
1520 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001521 def beginFile(self, genOpts):
1522 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001523 # Output Copyright
1524 write(self.inline_copyright_message, file=self.outFile)
1525 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001526 self.header = False
1527 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1528 self.header = True
1529 write('#pragma once', file=self.outFile)
1530 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001531 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001532 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001533 else:
1534 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001535 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001536 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001537 #
1538 def endFile(self):
1539 # Finish C++ namespace and multiple inclusion protection
1540 self.newline()
1541 if not self.header:
1542 # Record intercepted procedures
Mark Lobodzinski31395512019-06-18 16:25:01 -06001543 write('// Map of intercepted ApiName to its associated function data', file=self.outFile)
1544 write('const std::unordered_map<std::string, function_data> name_to_funcptr_map = {', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001545 write('\n'.join(self.intercepts), file=self.outFile)
1546 write('};\n', file=self.outFile)
1547 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001548 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001549 if self.header:
1550 self.newline()
1551 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001552 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001553 self.layer_factory += '};\n\n'
1554 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001555 write(self.layer_factory, file=self.outFile)
1556 else:
1557 write(self.inline_custom_source_postamble, file=self.outFile)
1558 # Finish processing in superclass
1559 OutputGenerator.endFile(self)
1560
1561 def beginFeature(self, interface, emit):
1562 # Start processing in superclass
1563 OutputGenerator.beginFeature(self, interface, emit)
1564 # Get feature extra protect
1565 self.featureExtraProtect = GetFeatureProtect(interface)
1566 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1567 # feature. They're only printed in endFeature().
1568 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1569
1570 def endFeature(self):
1571 # Actually write the interface to the output file.
1572 if (self.emit):
1573 self.newline()
1574 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1575 # or move it below the 'for section...' loop.
1576 if (self.featureExtraProtect != None):
1577 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1578 for section in self.TYPE_SECTIONS:
1579 contents = self.sections[section]
1580 if contents:
1581 write('\n'.join(contents), file=self.outFile)
1582 self.newline()
1583 if (self.sections['command']):
1584 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1585 self.newline()
1586 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001587 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001588 # Finish processing in superclass
1589 OutputGenerator.endFeature(self)
1590 #
1591 # Append a definition to the specified section
1592 def appendSection(self, section, text):
1593 self.sections[section].append(text)
1594 #
1595 # Type generation
1596 def genType(self, typeinfo, name, alias):
1597 pass
1598 #
1599 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1600 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1601 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1602 # structs etc.)
1603 def genStruct(self, typeinfo, typeName):
1604 OutputGenerator.genStruct(self, typeinfo, typeName)
1605 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1606 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1607 for member in typeinfo.elem.findall('.//member'):
1608 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1609 body += ';\n'
1610 body += '} ' + typeName + ';\n'
1611 self.appendSection('struct', body)
1612 #
1613 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1614 def genGroup(self, groupinfo, groupName, alias):
1615 pass
1616 # Enumerant generation
1617 # <enum> tags may specify their values in several ways, but are usually just integers.
1618 def genEnum(self, enuminfo, name, alias):
1619 pass
1620 #
1621 # Customize Cdecl for layer factory base class
1622 def BaseClassCdecl(self, elem, name):
1623 raw = self.makeCDecls(elem)[1]
1624
1625 # Toss everything before the undecorated name
1626 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1627 prototype = prototype.replace(")", "", 1)
1628 prototype = prototype.replace(";", " {};")
1629
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001630 # Build up pre/post call virtual function declarations
1631 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1632 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1633 pre_call_record = 'virtual void PreCallRecord' + prototype
1634 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001635 resulttype = elem.find('proto/type')
1636 if resulttype.text == 'VkResult':
1637 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001638 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1639 #
1640 # Command generation
1641 def genCmd(self, cmdinfo, name, alias):
1642 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001643 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001644 ]
1645
1646 if name in ignore_functions:
1647 return
1648
1649 if self.header: # In the header declare all intercepts
1650 self.appendSection('command', '')
1651 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1652 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001653 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1654 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001655 if 'ValidationCache' not in name:
1656 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001657 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001658 self.layer_factory += '#endif\n'
1659 return
1660
Mark Lobodzinski31395512019-06-18 16:25:01 -06001661 is_instance = 'false'
1662 dispatchable_type = cmdinfo.elem.find('param/type').text
1663 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1664 is_instance = 'true'
1665
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001666 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001667 if 'ValidationCache' not in name:
Mark Lobodzinski31395512019-06-18 16:25:01 -06001668 self.intercepts += [ ' {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001669 else:
1670 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
Mark Lobodzinski31395512019-06-18 16:25:01 -06001671
1672 self.intercepts += [ ' {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001673 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001674 return
1675 # Record that the function will be intercepted
1676 if (self.featureExtraProtect != None):
1677 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
Mark Lobodzinski31395512019-06-18 16:25:01 -06001678 self.intercepts += [ ' {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001679 if (self.featureExtraProtect != None):
1680 self.intercepts += [ '#endif' ]
1681 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1682 #
1683 decls = self.makeCDecls(cmdinfo.elem)
1684 self.appendSection('command', '')
1685 self.appendSection('command', '%s {' % decls[0][:-1])
1686 # Setup common to call wrappers. First parameter is always dispatchable
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001687 dispatchable_name = cmdinfo.elem.find('param/name').text
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001688 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001689 api_function_name = cmdinfo.elem.attrib.get('name')
1690 params = cmdinfo.elem.findall('param/name')
1691 paramstext = ', '.join([str(param.text) for param in params])
Tony-LunarG152a88b2019-03-20 15:42:24 -06001692 API = api_function_name.replace('vk','Dispatch') + '('
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001693
1694 # Declare result variable, if any.
1695 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001696 'PFN_vkVoidFunction': 'return nullptr;',
1697 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001698 'VkDeviceAddress': 'return 0;',
1699 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1700 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001701 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001702 }
1703 resulttype = cmdinfo.elem.find('proto/type')
1704 assignresult = ''
1705 if (resulttype.text != 'void'):
1706 assignresult = resulttype.text + ' result = '
1707
1708 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001709 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001710
1711 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001712 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001713 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001714 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1715 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1716 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001717
1718 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001719 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001720 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001721 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001722 self.appendSection('command', ' }')
1723
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001724 # Insert pre-dispatch debug utils function call
1725 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001726 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001727
1728 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001729 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001730
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001731 # Insert post-dispatch debug utils function call
1732 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001733 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001734
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001735 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001736 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001737 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001738 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001739 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001740 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001741 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001742 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001743 # Return result variable, if any.
1744 if (resulttype.text != 'void'):
1745 self.appendSection('command', ' return result;')
1746 self.appendSection('command', '}')
1747 #
1748 # Override makeProtoName to drop the "vk" prefix
1749 def makeProtoName(self, name, tail):
1750 return self.genOpts.apientry + name[2:] + tail