blob: 332363f8017c82cafd84fbe4a1bc043d24611693 [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07003# Copyright (c) 2015-2019 Valve Corporation
4# Copyright (c) 2015-2019 LunarG, Inc.
5# Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06006#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
20# Author: Mark Lobodzinski <mark@lunarg.com>
21#
22# This script generates the dispatch portion of a factory layer which intercepts
23# all Vulkan functions. The resultant factory layer allows rapid development of
24# layers and interceptors.
25
26import os,re,sys
27from generator import *
28from common_codegen import *
29
30# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31#
32# Adds options used by LayerFactoryOutputGenerator objects during factory
33# layer generation.
34#
35# Additional members
36# prefixText - list of strings to prefix generated header with
37# (usually a copyright statement + calling convention macros).
38# protectFile - True if multiple inclusion protection should be
39# generated (based on the filename) around the entire header.
40# protectFeature - True if #ifndef..#endif protection should be
41# generated around a feature interface in the header file.
42# genFuncPointers - True if function pointer typedefs should be
43# generated
44# protectProto - If conditional protection should be generated
45# around prototype declarations, set to either '#ifdef'
46# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47# to require opt-out (#ifndef protectProtoStr). Otherwise
48# set to None.
49# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50# declarations, if protectProto is set
51# apicall - string to use for the function declaration prefix,
52# such as APICALL on Windows.
53# apientry - string to use for the calling convention macro,
54# in typedefs, such as APIENTRY.
55# apientryp - string to use for the calling convention macro
56# in function pointer typedefs, such as APIENTRYP.
57# indentFuncProto - True if prototype declarations should put each
58# parameter on a separate line
59# indentFuncPointer - True if typedefed function pointers should put each
60# parameter on a separate line
61# alignFuncParam - if nonzero and parameters are being put on a
62# separate line, align parameter names at the specified column
63class LayerChassisGeneratorOptions(GeneratorOptions):
64 def __init__(self,
Mike Schuchardt21638df2019-03-16 10:52:02 -070065 conventions = None,
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -060066 filename = None,
67 directory = '.',
68 apiname = None,
69 profile = None,
70 versions = '.*',
71 emitversions = '.*',
72 defaultExtensions = None,
73 addExtensions = None,
74 removeExtensions = None,
75 emitExtensions = None,
76 sortProcedure = regSortFeatures,
77 prefixText = "",
78 genFuncPointers = True,
79 protectFile = True,
80 protectFeature = True,
81 apicall = '',
82 apientry = '',
83 apientryp = '',
84 indentFuncProto = True,
85 indentFuncPointer = False,
86 alignFuncParam = 0,
87 helper_file_type = '',
88 expandEnumerants = True):
Mike Schuchardt21638df2019-03-16 10:52:02 -070089 GeneratorOptions.__init__(self, conventions, filename, directory, apiname, profile,
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -060090 versions, emitversions, defaultExtensions,
91 addExtensions, removeExtensions, emitExtensions, sortProcedure)
92 self.prefixText = prefixText
93 self.genFuncPointers = genFuncPointers
94 self.protectFile = protectFile
95 self.protectFeature = protectFeature
96 self.apicall = apicall
97 self.apientry = apientry
98 self.apientryp = apientryp
99 self.indentFuncProto = indentFuncProto
100 self.indentFuncPointer = indentFuncPointer
101 self.alignFuncParam = alignFuncParam
102
103# LayerChassisOutputGenerator - subclass of OutputGenerator.
104# Generates a LayerFactory layer that intercepts all API entrypoints
105# This is intended to be used as a starting point for creating custom layers
106#
107# ---- methods ----
108# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
109# OutputGenerator. Defines additional internal state.
110# ---- methods overriding base class ----
111# beginFile(genOpts)
112# endFile()
113# beginFeature(interface, emit)
114# endFeature()
115# genType(typeinfo,name)
116# genStruct(typeinfo,name)
117# genGroup(groupinfo,name)
118# genEnum(enuminfo, name)
119# genCmd(cmdinfo)
120class LayerChassisOutputGenerator(OutputGenerator):
121 """Generate specified API interfaces in a specific style, such as a C header"""
122 # This is an ordered list of sections in the header file.
123 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
124 'group', 'bitmask', 'funcpointer', 'struct']
125 ALL_SECTIONS = TYPE_SECTIONS + ['command']
126
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700127 manual_functions = [
128 # Include functions here to be interecpted w/ manually implemented function bodies
129 'vkGetDeviceProcAddr',
130 'vkGetInstanceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700131 'vkCreateDevice',
132 'vkDestroyDevice',
133 'vkCreateInstance',
134 'vkDestroyInstance',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700135 'vkEnumerateInstanceLayerProperties',
136 'vkEnumerateInstanceExtensionProperties',
137 'vkEnumerateDeviceLayerProperties',
138 'vkEnumerateDeviceExtensionProperties',
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700139 # Functions that are handled explicitly due to chassis architecture violations
140 'vkCreateGraphicsPipelines',
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700141 'vkCreateComputePipelines',
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700142 'vkCreateRayTracingPipelinesNV',
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -0700143 'vkCreatePipelineLayout',
Mark Lobodzinski1db77e82019-03-01 10:02:54 -0700144 'vkCreateShaderModule',
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -0700145 'vkAllocateDescriptorSets',
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700146 # ValidationCache functions do not get dispatched
147 'vkCreateValidationCacheEXT',
148 'vkDestroyValidationCacheEXT',
149 'vkMergeValidationCachesEXT',
150 'vkGetValidationCacheDataEXT',
Mark Lobodzinski56e88122019-03-26 10:21:48 -0600151 # We don't wanna hook this function
152 'vkGetPhysicalDeviceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700153 ]
154
155 alt_ret_codes = [
156 # Include functions here which must tolerate VK_INCOMPLETE as a return code
157 'vkEnumeratePhysicalDevices',
158 'vkEnumeratePhysicalDeviceGroupsKHR',
159 'vkGetValidationCacheDataEXT',
160 'vkGetPipelineCacheData',
161 'vkGetShaderInfoAMD',
162 'vkGetPhysicalDeviceDisplayPropertiesKHR',
163 'vkGetPhysicalDeviceDisplayProperties2KHR',
164 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
165 'vkGetDisplayPlaneSupportedDisplaysKHR',
166 'vkGetDisplayModePropertiesKHR',
167 'vkGetDisplayModeProperties2KHR',
168 'vkGetPhysicalDeviceSurfaceFormatsKHR',
169 'vkGetPhysicalDeviceSurfacePresentModesKHR',
170 'vkGetPhysicalDevicePresentRectanglesKHR',
171 'vkGetPastPresentationTimingGOOGLE',
172 'vkGetSwapchainImagesKHR',
173 'vkEnumerateInstanceLayerProperties',
174 'vkEnumerateDeviceLayerProperties',
175 'vkEnumerateInstanceExtensionProperties',
176 'vkEnumerateDeviceExtensionProperties',
177 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
178 ]
179
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700180 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700181 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
182 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700183 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
184 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700185 }
186
187 post_dispatch_debug_utils_functions = {
188 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700189 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
190 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
191 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
192 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700193 }
194
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600195 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
196 precallrecord_loop = precallvalidate_loop
197 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600198
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700199 inline_custom_header_preamble = """
200#define NOMINMAX
201#include <mutex>
202#include <cinttypes>
203#include <stdio.h>
204#include <stdlib.h>
205#include <string.h>
206#include <unordered_map>
207#include <unordered_set>
208#include <algorithm>
209#include <memory>
210
211#include "vk_loader_platform.h"
212#include "vulkan/vulkan.h"
213#include "vk_layer_config.h"
214#include "vk_layer_data.h"
215#include "vk_layer_logging.h"
216#include "vk_object_types.h"
217#include "vulkan/vk_layer.h"
218#include "vk_enum_string_helper.h"
219#include "vk_layer_extension_utils.h"
220#include "vk_layer_utils.h"
221#include "vulkan/vk_layer.h"
222#include "vk_dispatch_table_helper.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700223#include "vk_extension_helper.h"
224#include "vk_safe_struct.h"
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700225#include "vk_typemap_helper.h"
226
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700227
228extern uint64_t global_unique_id;
229extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
230"""
231
232 inline_custom_header_class_definition = """
233
234// Layer object type identifiers
235enum LayerObjectTypeId {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700236 LayerObjectTypeInstance, // Container for an instance dispatch object
237 LayerObjectTypeDevice, // Container for a device dispatch object
238 LayerObjectTypeThreading, // Instance or device threading layer object
239 LayerObjectTypeParameterValidation, // Instance or device parameter validation layer object
240 LayerObjectTypeObjectTracker, // Instance or device object tracker layer object
241 LayerObjectTypeCoreValidation, // Instance or device core validation layer object
Camdeneaa86ea2019-07-26 11:00:09 -0600242 LayerObjectTypeBestPractices, // Instance or device best practices layer object
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700243};
244
245struct TEMPLATE_STATE {
246 VkDescriptorUpdateTemplateKHR desc_update_template;
247 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
248
249 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
250 : desc_update_template(update_template), create_info(*pCreateInfo) {}
251};
252
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700253class LAYER_PHYS_DEV_PROPERTIES {
254public:
255 VkPhysicalDeviceProperties properties;
256 std::vector<VkQueueFamilyProperties> queue_family_properties;
257};
258
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600259typedef enum ValidationCheckDisables {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600260 VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600261 VALIDATION_CHECK_DISABLE_OBJECT_IN_USE,
262 VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET,
263 VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE,
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600264 VALIDATION_CHECK_DISABLE_QUERY_VALIDATION,
Matthew Ruschd7ef5482019-07-16 22:01:54 -0700265 VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600266} ValidationCheckDisables;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600267
Camden3231dcc2019-08-05 11:28:57 -0600268typedef enum VkValidationFeatureEnable {
269 VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES,
270} VkValidationFeatureEnable;
271
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600272
273// CHECK_DISABLED struct is a container for bools that can block validation checks from being performed.
274// These bools are all "false" by default meaning that all checks are enabled. Enum values can be specified
275// via the vk_layer_setting.txt config file or at CreateInstance time via the VK_EXT_validation_features extension
276// that can selectively disable checks.
277struct CHECK_DISABLED {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600278 bool command_buffer_state; // Skip command buffer state validation
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600279 bool object_in_use; // Skip all object in_use checking
280 bool idle_descriptor_set; // Skip check to verify that descriptor set is not in-use
281 bool push_constant_range; // Skip push constant range checks
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600282 bool query_validation; // Disable all core validation query-related checks
Matthew Ruschd7ef5482019-07-16 22:01:54 -0700283 bool image_layout_validation; // Disable image layout validation
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600284 bool object_tracking; // Disable object lifetime validation
285 bool core_checks; // Disable core validation checks
286 bool thread_safety; // Disable thread safety validation
287 bool stateless_checks; // Disable stateless validation checks
288 bool handle_wrapping; // Disable unique handles/handle wrapping
289 bool shader_validation; // Skip validation for shaders
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700290
291 void SetAll(bool value) { std::fill(&command_buffer_state, &shader_validation + 1, value); }
292};
293
294struct CHECK_ENABLED {
295 bool gpu_validation;
296 bool gpu_validation_reserve_binding_slot;
Camdeneaa86ea2019-07-26 11:00:09 -0600297 bool best_practices;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700298
299 void SetAll(bool value) { std::fill(&gpu_validation, &gpu_validation_reserve_binding_slot + 1, value); }
300};
301
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700302// Layer chassis validation object base class definition
303class ValidationObject {
304 public:
305 uint32_t api_version;
306 debug_report_data* report_data = nullptr;
307 std::vector<VkDebugReportCallbackEXT> logging_callback;
308 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
309
310 VkLayerInstanceDispatchTable instance_dispatch_table;
311 VkLayerDispatchTable device_dispatch_table;
312
313 InstanceExtensions instance_extensions;
314 DeviceExtensions device_extensions = {};
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700315 CHECK_DISABLED disabled = {};
316 CHECK_ENABLED enabled = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700317
318 VkInstance instance = VK_NULL_HANDLE;
319 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
320 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700321 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700322
323 std::vector<ValidationObject*> object_dispatch;
324 LayerObjectTypeId container_type;
325
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700326 std::string layer_name = "CHASSIS";
327
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700328 // Constructor
329 ValidationObject(){};
330 // Destructor
331 virtual ~ValidationObject() {};
332
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700333 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700334 virtual std::unique_lock<std::mutex> write_lock() {
335 return std::unique_lock<std::mutex>(validation_object_mutex);
336 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700337
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700338 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
339 for (auto validation_object : object_dispatch) {
340 if (validation_object->container_type == object_type) {
341 return validation_object;
342 }
343 }
344 return nullptr;
345 };
346
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700347 // Handle Wrapping Data
348 // Reverse map display handles
349 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
Mark Lobodzinskidd28ee22019-06-04 14:20:56 -0600350 // Wrapping Descriptor Template Update structures requires access to the template createinfo structs
351 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_createinfo_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700352 struct SubpassesUsageStates {
353 std::unordered_set<uint32_t> subpasses_using_color_attachment;
354 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
355 };
356 // Uses unwrapped handles
357 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
358 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
359 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
360 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700361 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
362 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700363
364
365 // Unwrap a handle. Must hold lock.
366 template <typename HandleType>
367 HandleType Unwrap(HandleType wrappedHandle) {
368 // TODO: don't use operator[] here.
369 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
370 }
371
372 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
373 template <typename HandleType>
374 HandleType WrapNew(HandleType newlyCreatedHandle) {
375 auto unique_id = global_unique_id++;
376 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
377 return (HandleType)unique_id;
378 }
379
380 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
381 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
382 auto unique_id = global_unique_id++;
383 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
384 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
385 return (VkDisplayKHR)unique_id;
386 }
387
388 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
389 // creating another. Must hold lock.
390 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
391 // See if this display is already known
392 auto it = map_data->display_id_reverse_mapping.find(handle);
393 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
394 // Unknown, so wrap
395 return WrapDisplay(handle, map_data);
396 }
397
398 // Pre/post hook point declarations
399"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600400
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700401 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600402// This file is ***GENERATED***. Do Not Edit.
403// See layer_chassis_generator.py for modifications.
404
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700405/* Copyright (c) 2015-2019 The Khronos Group Inc.
406 * Copyright (c) 2015-2019 Valve Corporation
407 * Copyright (c) 2015-2019 LunarG, Inc.
408 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600409 *
410 * Licensed under the Apache License, Version 2.0 (the "License");
411 * you may not use this file except in compliance with the License.
412 * You may obtain a copy of the License at
413 *
414 * http://www.apache.org/licenses/LICENSE-2.0
415 *
416 * Unless required by applicable law or agreed to in writing, software
417 * distributed under the License is distributed on an "AS IS" BASIS,
418 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
419 * See the License for the specific language governing permissions and
420 * limitations under the License.
421 *
422 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700423 */"""
424
425 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600426
427#include <string.h>
428#include <mutex>
429
430#define VALIDATION_ERROR_MAP_IMPL
431
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600432#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700433#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600434
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600435std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600436
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700437// Global unique object identifier. All increments must be guarded by a lock.
438uint64_t global_unique_id = 1;
439// Map uniqueID to actual object handle
440std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
441
442// TODO: This variable controls handle wrapping -- in the future it should be hooked
443// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
444#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
445bool wrap_handles = true;
446#else
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600447bool wrap_handles = false;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700448#endif
449
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600450// Set layer name -- Khronos layer name overrides any other defined names
Mark Lobodzinskiaa6fd7b2019-03-19 09:26:48 -0600451#if BUILD_KHRONOS_VALIDATION
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600452#define OBJECT_LAYER_NAME "VK_LAYER_KHRONOS_validation"
453#define OBJECT_LAYER_DESCRIPTION "khronos_validation"
454#elif BUILD_OBJECT_TRACKER
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700455#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600456#define OBJECT_LAYER_DESCRIPTION "lunarg_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700457#elif BUILD_THREAD_SAFETY
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700458#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600459#define OBJECT_LAYER_DESCRIPTION "google_thread_checker"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700460#elif BUILD_PARAMETER_VALIDATION
461#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600462#define OBJECT_LAYER_DESCRIPTION "lunarg_parameter_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700463#elif BUILD_CORE_VALIDATION
464#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600465#define OBJECT_LAYER_DESCRIPTION "lunarg_core_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700466#else
467#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600468#define OBJECT_LAYER_DESCRIPTION "lunarg_unique_objects"
469#endif
470
471// Include layer validation object definitions
472#if BUILD_OBJECT_TRACKER
473#include "object_lifetime_validation.h"
474#endif
475#if BUILD_THREAD_SAFETY
476#include "thread_safety.h"
477#endif
478#if BUILD_PARAMETER_VALIDATION
479#include "stateless_validation.h"
480#endif
481#if BUILD_CORE_VALIDATION
482#include "core_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700483#endif
Camdeneaa86ea2019-07-26 11:00:09 -0600484#if BUILD_BEST_PRACTICES
485#include "best_practices.h"
486#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600487
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600488namespace vulkan_layer_chassis {
489
490using std::unordered_map;
491
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600492static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700493 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600494};
495
John Zulauf358462e2019-04-10 11:10:32 -0600496static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION},
497 {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION}};
Lenny Komow3627f6e2019-06-19 13:54:59 -0600498static const VkExtensionProperties device_extensions[] = {
499 {VK_EXT_VALIDATION_CACHE_EXTENSION_NAME, VK_EXT_VALIDATION_CACHE_SPEC_VERSION},
500 {VK_EXT_DEBUG_MARKER_EXTENSION_NAME, VK_EXT_DEBUG_MARKER_SPEC_VERSION},
501};
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600502
Mark Lobodzinski31395512019-06-18 16:25:01 -0600503typedef struct {
504 bool is_instance_api;
505 void* funcptr;
506} function_data;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600507
Mark Lobodzinski31395512019-06-18 16:25:01 -0600508extern const std::unordered_map<std::string, function_data> name_to_funcptr_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600509
510// Manually written functions
511
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700512// Check enabled instance extensions against supported instance extension whitelist
513static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
514 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
515 // Check for recognized instance extensions
516 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
Ricardo Garcia0072a572019-08-01 12:19:23 +0200517 log_msg(layer_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700518 kVUIDUndefined,
519 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
520 "results and/or produce undefined behavior.",
521 pCreateInfo->ppEnabledExtensionNames[i]);
522 }
523 }
524}
525
526// Check enabled device extensions against supported device extension whitelist
527static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
528 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
529 // Check for recognized device extensions
530 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
Ricardo Garcia0072a572019-08-01 12:19:23 +0200531 log_msg(layer_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700532 kVUIDUndefined,
533 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
534 "results and/or produce undefined behavior.",
535 pCreateInfo->ppEnabledExtensionNames[i]);
536 }
537 }
538}
539
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600540
541// Process validation features, flags and settings specified through extensions, a layer settings file, or environment variables
542
543static const std::unordered_map<std::string, VkValidationFeatureDisableEXT> VkValFeatureDisableLookup = {
544 {"VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT", VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT},
545 {"VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT", VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT},
546 {"VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT", VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT},
547 {"VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT", VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT},
548 {"VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT", VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT},
549 {"VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT", VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT},
550 {"VK_VALIDATION_FEATURE_DISABLE_ALL_EXT", VK_VALIDATION_FEATURE_DISABLE_ALL_EXT},
551};
552
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600553static const std::unordered_map<std::string, VkValidationFeatureEnableEXT> VkValFeatureEnableLookup = {
554 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT},
555 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT},
556};
557
Camden3231dcc2019-08-05 11:28:57 -0600558static const std::unordered_map<std::string, VkValidationFeatureEnable> VkValFeatureEnableLookup2 = {
559 {"VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES", VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES},
560};
561
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600562static const std::unordered_map<std::string, ValidationCheckDisables> ValidationDisableLookup = {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600563 {"VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE", VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600564 {"VALIDATION_CHECK_DISABLE_OBJECT_IN_USE", VALIDATION_CHECK_DISABLE_OBJECT_IN_USE},
565 {"VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET", VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET},
566 {"VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE", VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE},
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600567 {"VALIDATION_CHECK_DISABLE_QUERY_VALIDATION", VALIDATION_CHECK_DISABLE_QUERY_VALIDATION},
Matthew Ruschd7ef5482019-07-16 22:01:54 -0700568 {"VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION", VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600569};
570
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600571// Set the local disable flag for the appropriate VALIDATION_CHECK_DISABLE enum
572void SetValidationDisable(CHECK_DISABLED* disable_data, const ValidationCheckDisables disable_id) {
573 switch (disable_id) {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600574 case VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE:
575 disable_data->command_buffer_state = true;
576 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600577 case VALIDATION_CHECK_DISABLE_OBJECT_IN_USE:
578 disable_data->object_in_use = true;
579 break;
580 case VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET:
581 disable_data->idle_descriptor_set = true;
582 break;
583 case VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE:
584 disable_data->push_constant_range = true;
585 break;
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600586 case VALIDATION_CHECK_DISABLE_QUERY_VALIDATION:
587 disable_data->query_validation = true;
588 break;
Matthew Ruschd7ef5482019-07-16 22:01:54 -0700589 case VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION:
590 disable_data->image_layout_validation = true;
591 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600592 default:
593 assert(true);
594 }
595}
596
597// Set the local disable flag for a single VK_VALIDATION_FEATURE_DISABLE_* flag
598void SetValidationFeatureDisable(CHECK_DISABLED* disable_data, const VkValidationFeatureDisableEXT feature_disable) {
599 switch (feature_disable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700600 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600601 disable_data->shader_validation = true;
602 break;
603 case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
604 disable_data->thread_safety = true;
605 break;
606 case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
607 disable_data->stateless_checks = true;
608 break;
609 case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
610 disable_data->object_tracking = true;
611 break;
612 case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
613 disable_data->core_checks = true;
614 break;
615 case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
616 disable_data->handle_wrapping = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700617 break;
618 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
619 // Set all disabled flags to true
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600620 disable_data->SetAll(true);
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700621 break;
622 default:
623 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700624 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600625}
626
627// Set the local enable flag for a single VK_VALIDATION_FEATURE_ENABLE_* flag
628void SetValidationFeatureEnable(CHECK_ENABLED *enable_data, const VkValidationFeatureEnableEXT feature_enable) {
629 switch (feature_enable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700630 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600631 enable_data->gpu_validation = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700632 break;
633 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600634 enable_data->gpu_validation_reserve_binding_slot = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700635 break;
636 default:
637 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700638 }
639}
640
Camden3231dcc2019-08-05 11:28:57 -0600641void SetValidationFeatureEnable(CHECK_ENABLED *enable_data, const VkValidationFeatureEnable feature_enable) {
642 switch(feature_enable) {
643 case VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES:
644 enable_data->best_practices = true;
645 break;
646 default:
647 break;
648 }
649}
650
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600651// Set the local disable flag for settings specified through the VK_EXT_validation_flags extension
652void SetValidationFlags(CHECK_DISABLED* disables, const VkValidationFlagsEXT* val_flags_struct) {
653 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
654 switch (val_flags_struct->pDisabledValidationChecks[i]) {
655 case VK_VALIDATION_CHECK_SHADERS_EXT:
656 disables->shader_validation = true;
657 break;
658 case VK_VALIDATION_CHECK_ALL_EXT:
659 // Set all disabled flags to true
660 disables->SetAll(true);
661 break;
662 default:
663 break;
664 }
665 }
666}
667
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600668// Process Validation Features flags specified through the ValidationFeature extension
669void SetValidationFeatures(CHECK_DISABLED *disable_data, CHECK_ENABLED *enable_data,
670 const VkValidationFeaturesEXT *val_features_struct) {
671 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
672 SetValidationFeatureDisable(disable_data, val_features_struct->pDisabledValidationFeatures[i]);
673 }
674 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
675 SetValidationFeatureEnable(enable_data, val_features_struct->pEnabledValidationFeatures[i]);
676 }
677}
678
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600679// Given a string representation of a list of enable enum values, call the appropriate setter function
680void SetLocalEnableSetting(std::string list_of_enables, std::string delimiter, CHECK_ENABLED* enables) {
681 size_t pos = 0;
682 std::string token;
683 while (list_of_enables.length() != 0) {
684 pos = list_of_enables.find(delimiter);
685 if (pos != std::string::npos) {
686 token = list_of_enables.substr(0, pos);
687 } else {
688 pos = list_of_enables.length() - delimiter.length();
689 token = list_of_enables;
690 }
691 if (token.find("VK_VALIDATION_FEATURE_ENABLE_") != std::string::npos) {
692 auto result = VkValFeatureEnableLookup.find(token);
693 if (result != VkValFeatureEnableLookup.end()) {
694 SetValidationFeatureEnable(enables, result->second);
Camden3231dcc2019-08-05 11:28:57 -0600695 } else {
696 auto result2 = VkValFeatureEnableLookup2.find(token);
697 if (result2 != VkValFeatureEnableLookup2.end()) {
698 SetValidationFeatureEnable(enables, result2->second);
699 }
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600700 }
701 }
702 list_of_enables.erase(0, pos + delimiter.length());
703 }
704}
705
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600706// Given a string representation of a list of disable enum values, call the appropriate setter function
707void SetLocalDisableSetting(std::string list_of_disables, std::string delimiter, CHECK_DISABLED* disables) {
708 size_t pos = 0;
709 std::string token;
710 while (list_of_disables.length() != 0) {
711 pos = list_of_disables.find(delimiter);
712 if (pos != std::string::npos) {
713 token = list_of_disables.substr(0, pos);
714 } else {
715 pos = list_of_disables.length() - delimiter.length();
716 token = list_of_disables;
717 }
718 if (token.find("VK_VALIDATION_FEATURE_DISABLE_") != std::string::npos) {
719 auto result = VkValFeatureDisableLookup.find(token);
720 if (result != VkValFeatureDisableLookup.end()) {
721 SetValidationFeatureDisable(disables, result->second);
722 }
723 }
724 if (token.find("VALIDATION_CHECK_DISABLE_") != std::string::npos) {
725 auto result = ValidationDisableLookup.find(token);
726 if (result != ValidationDisableLookup.end()) {
727 SetValidationDisable(disables, result->second);
728 }
729 }
730 list_of_disables.erase(0, pos + delimiter.length());
731 }
732}
733
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600734// Process enables and disables set though the vk_layer_settings.txt config file or through an environment variable
735void ProcessConfigAndEnvSettings(const char* layer_description, CHECK_ENABLED* enables, CHECK_DISABLED* disables) {
736 std::string enable_key = layer_description;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600737 std::string disable_key = layer_description;
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600738 enable_key.append(".enables");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600739 disable_key.append(".disables");
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600740 std::string list_of_config_enables = getLayerOption(enable_key.c_str());
741 std::string list_of_env_enables = GetLayerEnvVar("VK_LAYER_ENABLES");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600742 std::string list_of_config_disables = getLayerOption(disable_key.c_str());
743 std::string list_of_env_disables = GetLayerEnvVar("VK_LAYER_DISABLES");
744#if defined(_WIN32)
745 std::string env_delimiter = ";";
746#else
747 std::string env_delimiter = ":";
748#endif
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600749 SetLocalEnableSetting(list_of_config_enables, ",", enables);
750 SetLocalEnableSetting(list_of_env_enables, env_delimiter, enables);
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600751 SetLocalDisableSetting(list_of_config_disables, ",", disables);
752 SetLocalDisableSetting(list_of_env_disables, env_delimiter, disables);
753}
754
755
756// Non-code-generated chassis API functions
757
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600758VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600759 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskif94196f2019-07-11 11:46:09 -0600760 if (!ApiParentExtensionEnabled(funcName, &layer_data->device_extensions)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700761 return nullptr;
762 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600763 const auto &item = name_to_funcptr_map.find(funcName);
764 if (item != name_to_funcptr_map.end()) {
Mark Lobodzinski31395512019-06-18 16:25:01 -0600765 if (item->second.is_instance_api) {
766 return nullptr;
767 } else {
768 return reinterpret_cast<PFN_vkVoidFunction>(item->second.funcptr);
769 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600770 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600771 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600772 if (!table.GetDeviceProcAddr) return nullptr;
773 return table.GetDeviceProcAddr(device, funcName);
774}
775
776VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600777 const auto &item = name_to_funcptr_map.find(funcName);
778 if (item != name_to_funcptr_map.end()) {
Mark Lobodzinski31395512019-06-18 16:25:01 -0600779 return reinterpret_cast<PFN_vkVoidFunction>(item->second.funcptr);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600780 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600781 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
782 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600783 if (!table.GetInstanceProcAddr) return nullptr;
784 return table.GetInstanceProcAddr(instance, funcName);
785}
786
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600787VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
788 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
789}
790
791VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
792 VkLayerProperties *pProperties) {
793 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
794}
795
796VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
797 VkExtensionProperties *pProperties) {
798 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
John Zulauf358462e2019-04-10 11:10:32 -0600799 return util_GetExtensionProperties(ARRAY_SIZE(instance_extensions), instance_extensions, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600800
801 return VK_ERROR_LAYER_NOT_PRESENT;
802}
803
804VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
805 uint32_t *pCount, VkExtensionProperties *pProperties) {
Lenny Komow3627f6e2019-06-19 13:54:59 -0600806 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 -0600807 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600808 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
Lenny Komow7b567f72019-06-10 16:49:43 -0600809 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600810}
811
812VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
813 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600814 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600815
816 assert(chain_info->u.pLayerInfo);
817 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
818 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
819 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
820 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700821 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
822 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
823
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600824 CHECK_ENABLED local_enables {};
825 CHECK_DISABLED local_disables {};
826 const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(pCreateInfo->pNext);
827 if (validation_features_ext) {
828 SetValidationFeatures(&local_disables, &local_enables, validation_features_ext);
829 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600830 const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
831 if (validation_flags_ext) {
832 SetValidationFlags(&local_disables, validation_flags_ext);
833 }
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600834 ProcessConfigAndEnvSettings(OBJECT_LAYER_DESCRIPTION, &local_enables, &local_disables);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600835
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600836 // Create temporary dispatch vector for pre-calls until instance is created
837 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600838 // Add VOs to dispatch vector. Order here will be the validation dispatch order!
839#if BUILD_THREAD_SAFETY
840 auto thread_checker = new ThreadSafety;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600841 if (!local_disables.thread_safety) {
842 local_object_dispatch.emplace_back(thread_checker);
843 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600844 thread_checker->container_type = LayerObjectTypeThreading;
845 thread_checker->api_version = api_version;
846#endif
847#if BUILD_PARAMETER_VALIDATION
848 auto parameter_validation = new StatelessValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600849 if (!local_disables.stateless_checks) {
850 local_object_dispatch.emplace_back(parameter_validation);
851 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600852 parameter_validation->container_type = LayerObjectTypeParameterValidation;
853 parameter_validation->api_version = api_version;
854#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700855#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600856 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600857 if (!local_disables.object_tracking) {
858 local_object_dispatch.emplace_back(object_tracker);
859 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600860 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700861 object_tracker->api_version = api_version;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600862#endif
863#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700864 auto core_checks = new CoreChecks;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600865 if (!local_disables.core_checks) {
866 local_object_dispatch.emplace_back(core_checks);
867 }
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700868 core_checks->container_type = LayerObjectTypeCoreValidation;
869 core_checks->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700870#endif
Camdeneaa86ea2019-07-26 11:00:09 -0600871#if BUILD_BEST_PRACTICES
872 auto best_practices = new BestPractices;
873 if (local_enables.best_practices) {
874 local_object_dispatch.emplace_back(best_practices);
875 }
876 best_practices->container_type = LayerObjectTypeBestPractices;
877 best_practices->api_version = api_version;
878#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600879
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600880 // If handle wrapping is disabled via the ValidationFeatures extension, override build flag
881 if (local_disables.handle_wrapping) {
882 wrap_handles = false;
883 }
884
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600885 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600886 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600887 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
888 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600889 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600890 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
891 }
892
893 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600894 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600895
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600896 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600897
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600898 framework->object_dispatch = local_object_dispatch;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700899 framework->container_type = LayerObjectTypeInstance;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600900 framework->disabled = local_disables;
901 framework->enabled = local_enables;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600902
903 framework->instance = *pInstance;
904 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
905 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
906 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700907 framework->api_version = api_version;
908 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
909
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600910 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, OBJECT_LAYER_DESCRIPTION);
911
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700912#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700913 object_tracker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600914 object_tracker->instance_dispatch_table = framework->instance_dispatch_table;
915 object_tracker->enabled = framework->enabled;
916 object_tracker->disabled = framework->disabled;
917#endif
918#if BUILD_THREAD_SAFETY
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700919 thread_checker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600920 thread_checker->instance_dispatch_table = framework->instance_dispatch_table;
921 thread_checker->enabled = framework->enabled;
922 thread_checker->disabled = framework->disabled;
923#endif
924#if BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700925 parameter_validation->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600926 parameter_validation->instance_dispatch_table = framework->instance_dispatch_table;
927 parameter_validation->enabled = framework->enabled;
928 parameter_validation->disabled = framework->disabled;
929#endif
930#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700931 core_checks->report_data = framework->report_data;
932 core_checks->instance_dispatch_table = framework->instance_dispatch_table;
933 core_checks->instance = *pInstance;
934 core_checks->enabled = framework->enabled;
935 core_checks->disabled = framework->disabled;
936 core_checks->instance_state = core_checks;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700937#endif
Camdeneaa86ea2019-07-26 11:00:09 -0600938#if BUILD_BEST_PRACTICES
939 best_practices->report_data = framework->report_data;
940 best_practices->instance_dispatch_table = framework->instance_dispatch_table;
941 best_practices->enabled = framework->enabled;
942 best_practices->disabled = framework->disabled;
943#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600944
945 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700946 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600947 }
948
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700949 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
950
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600951 return result;
952}
953
954VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
955 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600956 auto layer_data = GetLayerDataPtr(key, layer_data_map);
957 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700958 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600959 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
960 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600961 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700962 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600963 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
964 }
965
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600966 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600967
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600968 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700969 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600970 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
971 }
972 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600973 while (layer_data->logging_messenger.size() > 0) {
974 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
975 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
976 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600977 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600978 while (layer_data->logging_callback.size() > 0) {
979 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
980 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
981 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600982 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600983
984 layer_debug_utils_destroy_instance(layer_data->report_data);
985
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700986 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
987 delete *item;
988 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600989 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600990}
991
992VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
993 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600994 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600995
996 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
997
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600998 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
999 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001000 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
1001 if (fpCreateDevice == NULL) {
1002 return VK_ERROR_INITIALIZATION_FAILED;
1003 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001004 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
1005
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001006 // Get physical device limits for device
1007 VkPhysicalDeviceProperties device_properties = {};
1008 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
1009
1010 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
1011 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
1012
1013 DeviceExtensions device_extensions = {};
1014 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
1015 for (auto item : instance_interceptor->object_dispatch) {
1016 item->device_extensions = device_extensions;
1017 }
1018
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001019 std::unique_ptr<safe_VkDeviceCreateInfo> modified_create_info(new safe_VkDeviceCreateInfo(pCreateInfo));
1020
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001021 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001022 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001023 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001024 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001025 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001026 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001027 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001028 auto lock = intercept->write_lock();
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001029 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, modified_create_info);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001030 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001031
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001032 VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(modified_create_info.get()), pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001033 if (result != VK_SUCCESS) {
1034 return result;
1035 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001036
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001037 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001038 device_interceptor->container_type = LayerObjectTypeDevice;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001039
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001040 // Save local info in device object
1041 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001042 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
1043 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -07001044 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001045
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001046 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -07001047
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001048 device_interceptor->device = *pDevice;
1049 device_interceptor->physical_device = gpu;
1050 device_interceptor->instance = instance_interceptor->instance;
1051 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001052
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001053 // Note that this defines the order in which the layer validation objects are called
1054#if BUILD_THREAD_SAFETY
1055 auto thread_safety = new ThreadSafety;
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001056 thread_safety->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001057 if (!instance_interceptor->disabled.thread_safety) {
1058 device_interceptor->object_dispatch.emplace_back(thread_safety);
1059 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001060#endif
1061#if BUILD_PARAMETER_VALIDATION
1062 auto stateless_validation = new StatelessValidation;
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001063 stateless_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001064 if (!instance_interceptor->disabled.stateless_checks) {
1065 device_interceptor->object_dispatch.emplace_back(stateless_validation);
1066 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001067#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001068#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001069 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001070 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001071 if (!instance_interceptor->disabled.object_tracking) {
1072 device_interceptor->object_dispatch.emplace_back(object_tracker);
1073 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001074#endif
1075#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001076 auto core_checks = new CoreChecks;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001077 core_checks->container_type = LayerObjectTypeCoreValidation;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001078 core_checks->instance_state = reinterpret_cast<CoreChecks *>(
1079 core_checks->GetValidationObject(instance_interceptor->object_dispatch, LayerObjectTypeCoreValidation));
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001080 if (!instance_interceptor->disabled.core_checks) {
1081 device_interceptor->object_dispatch.emplace_back(core_checks);
1082 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001083#endif
Camdeneaa86ea2019-07-26 11:00:09 -06001084#if BUILD_BEST_PRACTICES
1085 auto best_practices = new BestPractices;
1086 best_practices->container_type = LayerObjectTypeBestPractices;
1087 if (instance_interceptor->enabled.best_practices) {
1088 device_interceptor->object_dispatch.emplace_back(best_practices);
1089 }
1090#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001091
Mark Lobodzinski7314bf42019-03-28 08:54:53 -06001092 // Set per-intercept common data items
1093 for (auto dev_intercept : device_interceptor->object_dispatch) {
1094 dev_intercept->device = *pDevice;
1095 dev_intercept->physical_device = gpu;
1096 dev_intercept->instance = instance_interceptor->instance;
1097 dev_intercept->report_data = device_interceptor->report_data;
1098 dev_intercept->device_dispatch_table = device_interceptor->device_dispatch_table;
1099 dev_intercept->api_version = device_interceptor->api_version;
1100 dev_intercept->disabled = instance_interceptor->disabled;
1101 dev_intercept->enabled = instance_interceptor->enabled;
1102 dev_intercept->instance_dispatch_table = instance_interceptor->instance_dispatch_table;
1103 dev_intercept->instance_extensions = instance_interceptor->instance_extensions;
1104 dev_intercept->device_extensions = device_interceptor->device_extensions;
1105 }
1106
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001107 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001108 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001109 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001110 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001111
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001112 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
1113
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001114 return result;
1115}
1116
1117VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
1118 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001119 auto layer_data = GetLayerDataPtr(key, layer_data_map);
1120 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001121 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001122 intercept->PreCallValidateDestroyDevice(device, pAllocator);
1123 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001124 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001125 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001126 intercept->PreCallRecordDestroyDevice(device, pAllocator);
1127 }
1128 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001129
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001130 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001131
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001132 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001133 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001134 intercept->PostCallRecordDestroyDevice(device, pAllocator);
1135 }
1136
Mark Lobodzinskic5003372018-12-17 16:36:01 -07001137 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
1138 delete *item;
1139 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001140 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001141}
1142
1143
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001144// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001145
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001146VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
1147 VkDevice device,
1148 VkPipelineCache pipelineCache,
1149 uint32_t createInfoCount,
1150 const VkGraphicsPipelineCreateInfo* pCreateInfos,
1151 const VkAllocationCallbacks* pAllocator,
1152 VkPipeline* pPipelines) {
1153 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1154 bool skip = false;
1155
1156#ifdef BUILD_CORE_VALIDATION
1157 create_graphics_pipeline_api_state cgpl_state{};
1158#else
1159 struct create_graphics_pipeline_api_state {
1160 const VkGraphicsPipelineCreateInfo* pCreateInfos;
1161 } cgpl_state;
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001162#endif
Mark Lobodzinskid08e16c2019-06-11 10:22:10 -06001163 cgpl_state.pCreateInfos = pCreateInfos;
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001164
1165 for (auto intercept : layer_data->object_dispatch) {
1166 auto lock = intercept->write_lock();
1167 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1168 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1169 }
1170 for (auto intercept : layer_data->object_dispatch) {
1171 auto lock = intercept->write_lock();
1172 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1173 }
1174
Tony-LunarG152a88b2019-03-20 15:42:24 -06001175 VkResult result = DispatchCreateGraphicsPipelines(device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001176
1177 for (auto intercept : layer_data->object_dispatch) {
1178 auto lock = intercept->write_lock();
1179 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
1180 }
1181 return result;
1182}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001183
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001184// This API saves some core_validation pipeline state state on the stack for performance purposes
1185VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
1186 VkDevice device,
1187 VkPipelineCache pipelineCache,
1188 uint32_t createInfoCount,
1189 const VkComputePipelineCreateInfo* pCreateInfos,
1190 const VkAllocationCallbacks* pAllocator,
1191 VkPipeline* pPipelines) {
1192 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1193 bool skip = false;
1194
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001195#ifdef BUILD_CORE_VALIDATION
1196 create_compute_pipeline_api_state ccpl_state{};
1197#else
1198 struct create_compute_pipeline_api_state {
1199 const VkComputePipelineCreateInfo* pCreateInfos;
1200 } ccpl_state;
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001201#endif
Mark Lobodzinskid08e16c2019-06-11 10:22:10 -06001202 ccpl_state.pCreateInfos = pCreateInfos;
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001203
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001204 for (auto intercept : layer_data->object_dispatch) {
1205 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001206 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001207 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1208 }
1209 for (auto intercept : layer_data->object_dispatch) {
1210 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001211 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001212 }
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001213 VkResult result = DispatchCreateComputePipelines(device, pipelineCache, createInfoCount, ccpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001214 for (auto intercept : layer_data->object_dispatch) {
1215 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001216 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001217 }
1218 return result;
1219}
1220
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001221VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
1222 VkDevice device,
1223 VkPipelineCache pipelineCache,
1224 uint32_t createInfoCount,
1225 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
1226 const VkAllocationCallbacks* pAllocator,
1227 VkPipeline* pPipelines) {
1228 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1229 bool skip = false;
1230
Jason Macnak67407e72019-07-11 11:05:09 -07001231#ifdef BUILD_CORE_VALIDATION
1232 create_ray_tracing_pipeline_api_state crtpl_state{};
1233#else
1234 struct create_ray_tracing_pipeline_api_state {
1235 const VkRayTracingPipelineCreateInfoNV* pCreateInfos;
1236 } crtpl_state;
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001237#endif
Jason Macnak67407e72019-07-11 11:05:09 -07001238 crtpl_state.pCreateInfos = pCreateInfos;
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001239
1240 for (auto intercept : layer_data->object_dispatch) {
1241 auto lock = intercept->write_lock();
Jason Macnak67407e72019-07-11 11:05:09 -07001242 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos,
1243 pAllocator, pPipelines, &crtpl_state);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001244 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1245 }
1246 for (auto intercept : layer_data->object_dispatch) {
1247 auto lock = intercept->write_lock();
Jason Macnak67407e72019-07-11 11:05:09 -07001248 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator,
1249 pPipelines, &crtpl_state);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001250 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001251 VkResult result = DispatchCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001252 for (auto intercept : layer_data->object_dispatch) {
1253 auto lock = intercept->write_lock();
Jason Macnak67407e72019-07-11 11:05:09 -07001254 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator,
1255 pPipelines, result, &crtpl_state);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001256 }
1257 return result;
1258}
1259
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001260// This API needs the ability to modify a down-chain parameter
1261VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
1262 VkDevice device,
1263 const VkPipelineLayoutCreateInfo* pCreateInfo,
1264 const VkAllocationCallbacks* pAllocator,
1265 VkPipelineLayout* pPipelineLayout) {
1266 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1267 bool skip = false;
1268
1269#ifndef BUILD_CORE_VALIDATION
1270 struct create_pipeline_layout_api_state {
1271 VkPipelineLayoutCreateInfo modified_create_info;
1272 };
1273#endif
1274 create_pipeline_layout_api_state cpl_state{};
1275 cpl_state.modified_create_info = *pCreateInfo;
1276
1277 for (auto intercept : layer_data->object_dispatch) {
1278 auto lock = intercept->write_lock();
1279 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1280 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1281 }
1282 for (auto intercept : layer_data->object_dispatch) {
1283 auto lock = intercept->write_lock();
1284 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1285 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001286 VkResult result = DispatchCreatePipelineLayout(device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001287 for (auto intercept : layer_data->object_dispatch) {
1288 auto lock = intercept->write_lock();
1289 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1290 }
1291 return result;
1292}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001293
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001294// This API needs some local stack data for performance reasons and also may modify a parameter
1295VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1296 VkDevice device,
1297 const VkShaderModuleCreateInfo* pCreateInfo,
1298 const VkAllocationCallbacks* pAllocator,
1299 VkShaderModule* pShaderModule) {
1300 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1301 bool skip = false;
1302
1303#ifndef BUILD_CORE_VALIDATION
1304 struct create_shader_module_api_state {
1305 VkShaderModuleCreateInfo instrumented_create_info;
1306 };
1307#endif
1308 create_shader_module_api_state csm_state{};
1309 csm_state.instrumented_create_info = *pCreateInfo;
1310
1311 for (auto intercept : layer_data->object_dispatch) {
1312 auto lock = intercept->write_lock();
1313 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1314 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1315 }
1316 for (auto intercept : layer_data->object_dispatch) {
1317 auto lock = intercept->write_lock();
1318 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1319 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001320 VkResult result = DispatchCreateShaderModule(device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001321 for (auto intercept : layer_data->object_dispatch) {
1322 auto lock = intercept->write_lock();
1323 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1324 }
1325 return result;
1326}
1327
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001328VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1329 VkDevice device,
1330 const VkDescriptorSetAllocateInfo* pAllocateInfo,
1331 VkDescriptorSet* pDescriptorSets) {
1332 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1333 bool skip = false;
1334
1335#ifdef BUILD_CORE_VALIDATION
1336 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1337#else
1338 struct ads_state {} ads_state;
1339#endif
1340
1341 for (auto intercept : layer_data->object_dispatch) {
1342 auto lock = intercept->write_lock();
1343 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1344 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1345 }
1346 for (auto intercept : layer_data->object_dispatch) {
1347 auto lock = intercept->write_lock();
1348 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1349 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001350 VkResult result = DispatchAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001351 for (auto intercept : layer_data->object_dispatch) {
1352 auto lock = intercept->write_lock();
1353 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1354 }
1355 return result;
1356}
1357
1358
1359
1360
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001361
1362// ValidationCache APIs do not dispatch
1363
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001364VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1365 VkDevice device,
1366 const VkValidationCacheCreateInfoEXT* pCreateInfo,
1367 const VkAllocationCallbacks* pAllocator,
1368 VkValidationCacheEXT* pValidationCache) {
1369 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1370 VkResult result = VK_SUCCESS;
1371
1372 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1373 if (validation_data) {
1374 auto lock = validation_data->write_lock();
1375 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1376 }
1377 return result;
1378}
1379
1380VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1381 VkDevice device,
1382 VkValidationCacheEXT validationCache,
1383 const VkAllocationCallbacks* pAllocator) {
1384 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1385
1386 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1387 if (validation_data) {
1388 auto lock = validation_data->write_lock();
1389 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1390 }
1391}
1392
1393VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1394 VkDevice device,
1395 VkValidationCacheEXT dstCache,
1396 uint32_t srcCacheCount,
1397 const VkValidationCacheEXT* pSrcCaches) {
1398 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1399 VkResult result = VK_SUCCESS;
1400
1401 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1402 if (validation_data) {
1403 auto lock = validation_data->write_lock();
1404 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1405 }
1406 return result;
1407}
1408
1409VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1410 VkDevice device,
1411 VkValidationCacheEXT validationCache,
1412 size_t* pDataSize,
1413 void* pData) {
1414 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1415 VkResult result = VK_SUCCESS;
1416
1417 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1418 if (validation_data) {
1419 auto lock = validation_data->write_lock();
1420 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1421 }
1422 return result;
1423
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001424}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001425
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001426 inline_custom_validation_class_definitions = """
1427 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1428 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1429 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1430 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001431
Jason Macnak67407e72019-07-11 11:05:09 -07001432 // Allow additional state parameter for CreateGraphicsPipelines
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001433 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1434 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1435 };
1436 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1437 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1438 };
1439 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1440 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1441 };
Jason Macnak67407e72019-07-11 11:05:09 -07001442
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001443 // Allow additional state parameter for CreateComputePipelines
1444 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1445 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1446 };
Jason Macnak67407e72019-07-11 11:05:09 -07001447 virtual void PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* ccpl_state) {
1448 PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1449 };
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001450 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1451 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1452 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001453
1454 // Allow additional state parameter for CreateRayTracingPipelinesNV
1455 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1456 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1457 };
Jason Macnak67407e72019-07-11 11:05:09 -07001458 virtual void PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* ccpl_state) {
1459 PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1460 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001461 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1462 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1463 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001464
1465 // Allow modification of a down-chain parameter for CreatePipelineLayout
1466 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1467 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1468 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001469
1470 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1471 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1472 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1473 };
1474 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1475 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1476 };
1477 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1478 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1479 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001480
1481 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1482 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1483 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1484 };
1485 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1486 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1487 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001488
1489 // Modify a parameter to CreateDevice
1490 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1491 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1492 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001493"""
1494
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001495 inline_custom_source_postamble = """
1496// loader-layer interface v0, just wrappers since there is only a layer
1497
1498VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1499 VkExtensionProperties *pProperties) {
1500 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1501}
1502
1503VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1504 VkLayerProperties *pProperties) {
1505 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1506}
1507
1508VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1509 VkLayerProperties *pProperties) {
1510 // the layer command handles VK_NULL_HANDLE just fine internally
1511 assert(physicalDevice == VK_NULL_HANDLE);
1512 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1513}
1514
1515VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1516 const char *pLayerName, uint32_t *pCount,
1517 VkExtensionProperties *pProperties) {
1518 // the layer command handles VK_NULL_HANDLE just fine internally
1519 assert(physicalDevice == VK_NULL_HANDLE);
1520 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1521}
1522
1523VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1524 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1525}
1526
1527VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1528 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1529}
1530
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001531VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1532 assert(pVersionStruct != NULL);
1533 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1534
1535 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1536 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1537 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1538 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
Mark Lobodzinski56e88122019-03-26 10:21:48 -06001539 pVersionStruct->pfnGetPhysicalDeviceProcAddr = nullptr;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001540 }
1541
1542 return VK_SUCCESS;
1543}"""
1544
1545
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001546 def __init__(self,
1547 errFile = sys.stderr,
1548 warnFile = sys.stderr,
1549 diagFile = sys.stdout):
1550 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1551 # Internal state - accumulators for different inner block text
1552 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1553 self.intercepts = []
1554 self.layer_factory = '' # String containing base layer factory class definition
1555
1556 # Check if the parameter passed in is a pointer to an array
1557 def paramIsArray(self, param):
1558 return param.attrib.get('len') is not None
1559
1560 # Check if the parameter passed in is a pointer
1561 def paramIsPointer(self, param):
1562 ispointer = False
1563 for elem in param:
Raul Tambre7b300182019-05-04 11:25:14 +03001564 if elem.tag == 'type' and elem.tail is not None and '*' in elem.tail:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001565 ispointer = True
1566 return ispointer
1567
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001568 #
1569 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001570 def beginFile(self, genOpts):
1571 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001572 # Output Copyright
1573 write(self.inline_copyright_message, file=self.outFile)
1574 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001575 self.header = False
1576 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1577 self.header = True
1578 write('#pragma once', file=self.outFile)
1579 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001580 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001581 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001582 else:
1583 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001584 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001585 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001586 #
1587 def endFile(self):
1588 # Finish C++ namespace and multiple inclusion protection
1589 self.newline()
1590 if not self.header:
1591 # Record intercepted procedures
Mark Lobodzinski31395512019-06-18 16:25:01 -06001592 write('// Map of intercepted ApiName to its associated function data', file=self.outFile)
1593 write('const std::unordered_map<std::string, function_data> name_to_funcptr_map = {', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001594 write('\n'.join(self.intercepts), file=self.outFile)
1595 write('};\n', file=self.outFile)
1596 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001597 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001598 if self.header:
1599 self.newline()
1600 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001601 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001602 self.layer_factory += '};\n\n'
1603 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001604 write(self.layer_factory, file=self.outFile)
1605 else:
1606 write(self.inline_custom_source_postamble, file=self.outFile)
1607 # Finish processing in superclass
1608 OutputGenerator.endFile(self)
1609
1610 def beginFeature(self, interface, emit):
1611 # Start processing in superclass
1612 OutputGenerator.beginFeature(self, interface, emit)
1613 # Get feature extra protect
1614 self.featureExtraProtect = GetFeatureProtect(interface)
1615 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1616 # feature. They're only printed in endFeature().
1617 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1618
1619 def endFeature(self):
1620 # Actually write the interface to the output file.
1621 if (self.emit):
1622 self.newline()
1623 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1624 # or move it below the 'for section...' loop.
1625 if (self.featureExtraProtect != None):
1626 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1627 for section in self.TYPE_SECTIONS:
1628 contents = self.sections[section]
1629 if contents:
1630 write('\n'.join(contents), file=self.outFile)
1631 self.newline()
1632 if (self.sections['command']):
1633 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1634 self.newline()
1635 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001636 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001637 # Finish processing in superclass
1638 OutputGenerator.endFeature(self)
1639 #
1640 # Append a definition to the specified section
1641 def appendSection(self, section, text):
1642 self.sections[section].append(text)
1643 #
1644 # Type generation
1645 def genType(self, typeinfo, name, alias):
1646 pass
1647 #
1648 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1649 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1650 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1651 # structs etc.)
1652 def genStruct(self, typeinfo, typeName):
1653 OutputGenerator.genStruct(self, typeinfo, typeName)
1654 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1655 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1656 for member in typeinfo.elem.findall('.//member'):
1657 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1658 body += ';\n'
1659 body += '} ' + typeName + ';\n'
1660 self.appendSection('struct', body)
1661 #
1662 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1663 def genGroup(self, groupinfo, groupName, alias):
1664 pass
1665 # Enumerant generation
1666 # <enum> tags may specify their values in several ways, but are usually just integers.
1667 def genEnum(self, enuminfo, name, alias):
1668 pass
1669 #
1670 # Customize Cdecl for layer factory base class
1671 def BaseClassCdecl(self, elem, name):
1672 raw = self.makeCDecls(elem)[1]
1673
1674 # Toss everything before the undecorated name
1675 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1676 prototype = prototype.replace(")", "", 1)
1677 prototype = prototype.replace(";", " {};")
1678
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001679 # Build up pre/post call virtual function declarations
1680 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1681 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1682 pre_call_record = 'virtual void PreCallRecord' + prototype
1683 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001684 resulttype = elem.find('proto/type')
1685 if resulttype.text == 'VkResult':
1686 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001687 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1688 #
1689 # Command generation
1690 def genCmd(self, cmdinfo, name, alias):
1691 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001692 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001693 ]
1694
1695 if name in ignore_functions:
1696 return
1697
1698 if self.header: # In the header declare all intercepts
1699 self.appendSection('command', '')
1700 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1701 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001702 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1703 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001704 if 'ValidationCache' not in name:
1705 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001706 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001707 self.layer_factory += '#endif\n'
1708 return
1709
Mark Lobodzinski31395512019-06-18 16:25:01 -06001710 is_instance = 'false'
1711 dispatchable_type = cmdinfo.elem.find('param/type').text
1712 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1713 is_instance = 'true'
1714
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001715 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001716 if 'ValidationCache' not in name:
Mark Lobodzinski31395512019-06-18 16:25:01 -06001717 self.intercepts += [ ' {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001718 else:
1719 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
Mark Lobodzinski31395512019-06-18 16:25:01 -06001720
1721 self.intercepts += [ ' {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001722 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001723 return
1724 # Record that the function will be intercepted
1725 if (self.featureExtraProtect != None):
1726 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
Mark Lobodzinski31395512019-06-18 16:25:01 -06001727 self.intercepts += [ ' {"%s", {%s, (void*)%s}},' % (name, is_instance, name[2:]) ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001728 if (self.featureExtraProtect != None):
1729 self.intercepts += [ '#endif' ]
1730 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1731 #
1732 decls = self.makeCDecls(cmdinfo.elem)
1733 self.appendSection('command', '')
1734 self.appendSection('command', '%s {' % decls[0][:-1])
1735 # Setup common to call wrappers. First parameter is always dispatchable
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001736 dispatchable_name = cmdinfo.elem.find('param/name').text
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001737 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001738 api_function_name = cmdinfo.elem.attrib.get('name')
1739 params = cmdinfo.elem.findall('param/name')
1740 paramstext = ', '.join([str(param.text) for param in params])
Tony-LunarG152a88b2019-03-20 15:42:24 -06001741 API = api_function_name.replace('vk','Dispatch') + '('
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001742
1743 # Declare result variable, if any.
1744 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001745 'PFN_vkVoidFunction': 'return nullptr;',
1746 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001747 'VkDeviceAddress': 'return 0;',
1748 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1749 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001750 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001751 }
1752 resulttype = cmdinfo.elem.find('proto/type')
1753 assignresult = ''
1754 if (resulttype.text != 'void'):
1755 assignresult = resulttype.text + ' result = '
1756
1757 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001758 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001759
1760 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001761 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001762 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001763 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1764 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1765 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001766
1767 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001768 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001769 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001770 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001771 self.appendSection('command', ' }')
1772
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001773 # Insert pre-dispatch debug utils function call
1774 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001775 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001776
1777 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001778 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001779
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001780 # Insert post-dispatch debug utils function call
1781 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001782 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001783
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001784 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001785 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001786 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001787 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001788 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001789 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001790 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001791 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001792 # Return result variable, if any.
1793 if (resulttype.text != 'void'):
1794 self.appendSection('command', ' return result;')
1795 self.appendSection('command', '}')
1796 #
1797 # Override makeProtoName to drop the "vk" prefix
1798 def makeProtoName(self, name, tail):
1799 return self.genOpts.apientry + name[2:] + tail