blob: 5967cad280891fa96e1edebbcfa6a79c6414dada [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07003# Copyright (c) 2015-2019 Valve Corporation
4# Copyright (c) 2015-2019 LunarG, Inc.
5# Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06006#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
20# Author: Mark Lobodzinski <mark@lunarg.com>
21#
22# This script generates the dispatch portion of a factory layer which intercepts
23# all Vulkan functions. The resultant factory layer allows rapid development of
24# layers and interceptors.
25
26import os,re,sys
27from generator import *
28from common_codegen import *
29
30# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31#
32# Adds options used by LayerFactoryOutputGenerator objects during factory
33# layer generation.
34#
35# Additional members
36# prefixText - list of strings to prefix generated header with
37# (usually a copyright statement + calling convention macros).
38# protectFile - True if multiple inclusion protection should be
39# generated (based on the filename) around the entire header.
40# protectFeature - True if #ifndef..#endif protection should be
41# generated around a feature interface in the header file.
42# genFuncPointers - True if function pointer typedefs should be
43# generated
44# protectProto - If conditional protection should be generated
45# around prototype declarations, set to either '#ifdef'
46# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47# to require opt-out (#ifndef protectProtoStr). Otherwise
48# set to None.
49# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50# declarations, if protectProto is set
51# apicall - string to use for the function declaration prefix,
52# such as APICALL on Windows.
53# apientry - string to use for the calling convention macro,
54# in typedefs, such as APIENTRY.
55# apientryp - string to use for the calling convention macro
56# in function pointer typedefs, such as APIENTRYP.
57# indentFuncProto - True if prototype declarations should put each
58# parameter on a separate line
59# indentFuncPointer - True if typedefed function pointers should put each
60# parameter on a separate line
61# alignFuncParam - if nonzero and parameters are being put on a
62# separate line, align parameter names at the specified column
63class LayerChassisGeneratorOptions(GeneratorOptions):
64 def __init__(self,
65 filename = None,
66 directory = '.',
67 apiname = None,
68 profile = None,
69 versions = '.*',
70 emitversions = '.*',
71 defaultExtensions = None,
72 addExtensions = None,
73 removeExtensions = None,
74 emitExtensions = None,
75 sortProcedure = regSortFeatures,
76 prefixText = "",
77 genFuncPointers = True,
78 protectFile = True,
79 protectFeature = True,
80 apicall = '',
81 apientry = '',
82 apientryp = '',
83 indentFuncProto = True,
84 indentFuncPointer = False,
85 alignFuncParam = 0,
86 helper_file_type = '',
87 expandEnumerants = True):
88 GeneratorOptions.__init__(self, filename, directory, apiname, profile,
89 versions, emitversions, defaultExtensions,
90 addExtensions, removeExtensions, emitExtensions, sortProcedure)
91 self.prefixText = prefixText
92 self.genFuncPointers = genFuncPointers
93 self.protectFile = protectFile
94 self.protectFeature = protectFeature
95 self.apicall = apicall
96 self.apientry = apientry
97 self.apientryp = apientryp
98 self.indentFuncProto = indentFuncProto
99 self.indentFuncPointer = indentFuncPointer
100 self.alignFuncParam = alignFuncParam
101
102# LayerChassisOutputGenerator - subclass of OutputGenerator.
103# Generates a LayerFactory layer that intercepts all API entrypoints
104# This is intended to be used as a starting point for creating custom layers
105#
106# ---- methods ----
107# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
108# OutputGenerator. Defines additional internal state.
109# ---- methods overriding base class ----
110# beginFile(genOpts)
111# endFile()
112# beginFeature(interface, emit)
113# endFeature()
114# genType(typeinfo,name)
115# genStruct(typeinfo,name)
116# genGroup(groupinfo,name)
117# genEnum(enuminfo, name)
118# genCmd(cmdinfo)
119class LayerChassisOutputGenerator(OutputGenerator):
120 """Generate specified API interfaces in a specific style, such as a C header"""
121 # This is an ordered list of sections in the header file.
122 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
123 'group', 'bitmask', 'funcpointer', 'struct']
124 ALL_SECTIONS = TYPE_SECTIONS + ['command']
125
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700126 manual_functions = [
127 # Include functions here to be interecpted w/ manually implemented function bodies
128 'vkGetDeviceProcAddr',
129 'vkGetInstanceProcAddr',
130 'vkGetPhysicalDeviceProcAddr',
131 'vkCreateDevice',
132 'vkDestroyDevice',
133 'vkCreateInstance',
134 'vkDestroyInstance',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700135 'vkEnumerateInstanceLayerProperties',
136 'vkEnumerateInstanceExtensionProperties',
137 'vkEnumerateDeviceLayerProperties',
138 'vkEnumerateDeviceExtensionProperties',
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700139 # Functions that are handled explicitly due to chassis architecture violations
140 'vkCreateGraphicsPipelines',
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700141 'vkCreateComputePipelines',
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700142 'vkCreateRayTracingPipelinesNV',
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -0700143 'vkCreatePipelineLayout',
Mark Lobodzinski1db77e82019-03-01 10:02:54 -0700144 'vkCreateShaderModule',
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -0700145 'vkAllocateDescriptorSets',
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700146 # ValidationCache functions do not get dispatched
147 'vkCreateValidationCacheEXT',
148 'vkDestroyValidationCacheEXT',
149 'vkMergeValidationCachesEXT',
150 'vkGetValidationCacheDataEXT',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700151 ]
152
153 alt_ret_codes = [
154 # Include functions here which must tolerate VK_INCOMPLETE as a return code
155 'vkEnumeratePhysicalDevices',
156 'vkEnumeratePhysicalDeviceGroupsKHR',
157 'vkGetValidationCacheDataEXT',
158 'vkGetPipelineCacheData',
159 'vkGetShaderInfoAMD',
160 'vkGetPhysicalDeviceDisplayPropertiesKHR',
161 'vkGetPhysicalDeviceDisplayProperties2KHR',
162 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
163 'vkGetDisplayPlaneSupportedDisplaysKHR',
164 'vkGetDisplayModePropertiesKHR',
165 'vkGetDisplayModeProperties2KHR',
166 'vkGetPhysicalDeviceSurfaceFormatsKHR',
167 'vkGetPhysicalDeviceSurfacePresentModesKHR',
168 'vkGetPhysicalDevicePresentRectanglesKHR',
169 'vkGetPastPresentationTimingGOOGLE',
170 'vkGetSwapchainImagesKHR',
171 'vkEnumerateInstanceLayerProperties',
172 'vkEnumerateDeviceLayerProperties',
173 'vkEnumerateInstanceExtensionProperties',
174 'vkEnumerateDeviceExtensionProperties',
175 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
176 ]
177
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700178 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700179 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
180 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700181 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
182 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
183 'vkCmdBeginDebugUtilsLabelEXT' : 'BeginCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
184 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);'
185 }
186
187 post_dispatch_debug_utils_functions = {
188 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
189 'vkCmdEndDebugUtilsLabelEXT' : 'EndCmdDebugUtilsLabel(layer_data->report_data, commandBuffer);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700190 'vkCmdInsertDebugUtilsLabelEXT' : 'InsertCmdDebugUtilsLabel(layer_data->report_data, commandBuffer, pLabelInfo);',
191 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
192 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
193 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
194 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700195 }
196
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600197 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
198 precallrecord_loop = precallvalidate_loop
199 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600200
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700201 inline_custom_header_preamble = """
202#define NOMINMAX
203#include <mutex>
204#include <cinttypes>
205#include <stdio.h>
206#include <stdlib.h>
207#include <string.h>
208#include <unordered_map>
209#include <unordered_set>
210#include <algorithm>
211#include <memory>
212
213#include "vk_loader_platform.h"
214#include "vulkan/vulkan.h"
215#include "vk_layer_config.h"
216#include "vk_layer_data.h"
217#include "vk_layer_logging.h"
218#include "vk_object_types.h"
219#include "vulkan/vk_layer.h"
220#include "vk_enum_string_helper.h"
221#include "vk_layer_extension_utils.h"
222#include "vk_layer_utils.h"
223#include "vulkan/vk_layer.h"
224#include "vk_dispatch_table_helper.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700225#include "vk_extension_helper.h"
226#include "vk_safe_struct.h"
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700227#include "vk_typemap_helper.h"
228
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700229
230extern uint64_t global_unique_id;
231extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
232"""
233
234 inline_custom_header_class_definition = """
235
236// Layer object type identifiers
237enum LayerObjectTypeId {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700238 LayerObjectTypeInstance, // Container for an instance dispatch object
239 LayerObjectTypeDevice, // Container for a device dispatch object
240 LayerObjectTypeThreading, // Instance or device threading layer object
241 LayerObjectTypeParameterValidation, // Instance or device parameter validation layer object
242 LayerObjectTypeObjectTracker, // Instance or device object tracker layer object
243 LayerObjectTypeCoreValidation, // Instance or device core validation layer object
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700244};
245
246struct TEMPLATE_STATE {
247 VkDescriptorUpdateTemplateKHR desc_update_template;
248 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
249
250 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
251 : desc_update_template(update_template), create_info(*pCreateInfo) {}
252};
253
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700254class LAYER_PHYS_DEV_PROPERTIES {
255public:
256 VkPhysicalDeviceProperties properties;
257 std::vector<VkQueueFamilyProperties> queue_family_properties;
258};
259
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700260// CHECK_DISABLED struct is a container for bools that can block validation checks from being performed.
261// The end goal is to have all checks guarded by a bool. The bools are all "false" by default meaning that all checks
262// are enabled. At CreateInstance time, the user can use the VK_EXT_validation_flags extension to pass in enum values
263// of VkValidationCheckEXT that will selectively disable checks.
264// The VK_EXT_validation_features extension can also be used with the VkValidationFeaturesEXT structure to set
265// disables in the CHECK_DISABLED struct and/or enables in the CHECK_ENABLED struct.
266struct CHECK_DISABLED {
267 bool command_buffer_state;
268 bool create_descriptor_set_layout;
269 bool destroy_buffer_view; // Skip validation at DestroyBufferView time
270 bool destroy_image_view; // Skip validation at DestroyImageView time
271 bool destroy_pipeline; // Skip validation at DestroyPipeline time
272 bool destroy_descriptor_pool; // Skip validation at DestroyDescriptorPool time
273 bool destroy_framebuffer; // Skip validation at DestroyFramebuffer time
274 bool destroy_renderpass; // Skip validation at DestroyRenderpass time
275 bool destroy_image; // Skip validation at DestroyImage time
276 bool destroy_sampler; // Skip validation at DestroySampler time
277 bool destroy_command_pool; // Skip validation at DestroyCommandPool time
278 bool destroy_event; // Skip validation at DestroyEvent time
279 bool free_memory; // Skip validation at FreeMemory time
280 bool object_in_use; // Skip all object in_use checking
281 bool idle_descriptor_set; // Skip check to verify that descriptor set is no in-use
282 bool push_constant_range; // Skip push constant range checks
283 bool free_descriptor_sets; // Skip validation prior to vkFreeDescriptorSets()
284 bool allocate_descriptor_sets; // Skip validation prior to vkAllocateDescriptorSets()
285 bool update_descriptor_sets; // Skip validation prior to vkUpdateDescriptorSets()
286 bool wait_for_fences;
287 bool get_fence_state;
288 bool queue_wait_idle;
289 bool device_wait_idle;
290 bool destroy_fence;
291 bool destroy_semaphore;
292 bool destroy_query_pool;
293 bool get_query_pool_results;
294 bool destroy_buffer;
295 bool shader_validation; // Skip validation for shaders
296
297 void SetAll(bool value) { std::fill(&command_buffer_state, &shader_validation + 1, value); }
298};
299
300struct CHECK_ENABLED {
301 bool gpu_validation;
302 bool gpu_validation_reserve_binding_slot;
303
304 void SetAll(bool value) { std::fill(&gpu_validation, &gpu_validation_reserve_binding_slot + 1, value); }
305};
306
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700307// Layer chassis validation object base class definition
308class ValidationObject {
309 public:
310 uint32_t api_version;
311 debug_report_data* report_data = nullptr;
312 std::vector<VkDebugReportCallbackEXT> logging_callback;
313 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
314
315 VkLayerInstanceDispatchTable instance_dispatch_table;
316 VkLayerDispatchTable device_dispatch_table;
317
318 InstanceExtensions instance_extensions;
319 DeviceExtensions device_extensions = {};
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700320 CHECK_DISABLED disabled = {};
321 CHECK_ENABLED enabled = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700322
323 VkInstance instance = VK_NULL_HANDLE;
324 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
325 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700326 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700327
328 std::vector<ValidationObject*> object_dispatch;
329 LayerObjectTypeId container_type;
330
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700331 std::string layer_name = "CHASSIS";
332
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700333 // Constructor
334 ValidationObject(){};
335 // Destructor
336 virtual ~ValidationObject() {};
337
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700338 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700339 virtual std::unique_lock<std::mutex> write_lock() {
340 return std::unique_lock<std::mutex>(validation_object_mutex);
341 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700342
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700343 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
344 for (auto validation_object : object_dispatch) {
345 if (validation_object->container_type == object_type) {
346 return validation_object;
347 }
348 }
349 return nullptr;
350 };
351
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700352 // Handle Wrapping Data
353 // Reverse map display handles
354 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
355 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700356 struct SubpassesUsageStates {
357 std::unordered_set<uint32_t> subpasses_using_color_attachment;
358 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
359 };
360 // Uses unwrapped handles
361 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
362 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
363 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
364 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700365 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
366 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700367
368
369 // Unwrap a handle. Must hold lock.
370 template <typename HandleType>
371 HandleType Unwrap(HandleType wrappedHandle) {
372 // TODO: don't use operator[] here.
373 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
374 }
375
376 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
377 template <typename HandleType>
378 HandleType WrapNew(HandleType newlyCreatedHandle) {
379 auto unique_id = global_unique_id++;
380 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
381 return (HandleType)unique_id;
382 }
383
384 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
385 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
386 auto unique_id = global_unique_id++;
387 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
388 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
389 return (VkDisplayKHR)unique_id;
390 }
391
392 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
393 // creating another. Must hold lock.
394 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
395 // See if this display is already known
396 auto it = map_data->display_id_reverse_mapping.find(handle);
397 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
398 // Unknown, so wrap
399 return WrapDisplay(handle, map_data);
400 }
401
402 // Pre/post hook point declarations
403"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600404
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700405 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600406// This file is ***GENERATED***. Do Not Edit.
407// See layer_chassis_generator.py for modifications.
408
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700409/* Copyright (c) 2015-2019 The Khronos Group Inc.
410 * Copyright (c) 2015-2019 Valve Corporation
411 * Copyright (c) 2015-2019 LunarG, Inc.
412 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600413 *
414 * Licensed under the Apache License, Version 2.0 (the "License");
415 * you may not use this file except in compliance with the License.
416 * You may obtain a copy of the License at
417 *
418 * http://www.apache.org/licenses/LICENSE-2.0
419 *
420 * Unless required by applicable law or agreed to in writing, software
421 * distributed under the License is distributed on an "AS IS" BASIS,
422 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
423 * See the License for the specific language governing permissions and
424 * limitations under the License.
425 *
426 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700427 */"""
428
429 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600430
431#include <string.h>
432#include <mutex>
433
434#define VALIDATION_ERROR_MAP_IMPL
435
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600436#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700437#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600438
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600439std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600440
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700441// Global unique object identifier. All increments must be guarded by a lock.
442uint64_t global_unique_id = 1;
443// Map uniqueID to actual object handle
444std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
445
446// TODO: This variable controls handle wrapping -- in the future it should be hooked
447// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
448#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
449bool wrap_handles = true;
450#else
451const bool wrap_handles = false;
452#endif
453
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600454// Set layer name -- Khronos layer name overrides any other defined names
455#if BUILD_KNRONOS_VALIDATION
456#define OBJECT_LAYER_NAME "VK_LAYER_KHRONOS_validation"
457#define OBJECT_LAYER_DESCRIPTION "khronos_validation"
458#elif BUILD_OBJECT_TRACKER
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700459#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600460#define OBJECT_LAYER_DESCRIPTION "lunarg_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700461#elif BUILD_THREAD_SAFETY
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700462#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600463#define OBJECT_LAYER_DESCRIPTION "google_thread_checker"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700464#elif BUILD_PARAMETER_VALIDATION
465#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600466#define OBJECT_LAYER_DESCRIPTION "lunarg_parameter_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700467#elif BUILD_CORE_VALIDATION
468#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600469#define OBJECT_LAYER_DESCRIPTION "lunarg_core_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700470#else
471#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600472#define OBJECT_LAYER_DESCRIPTION "lunarg_unique_objects"
473#endif
474
475// Include layer validation object definitions
476#if BUILD_OBJECT_TRACKER
477#include "object_lifetime_validation.h"
478#endif
479#if BUILD_THREAD_SAFETY
480#include "thread_safety.h"
481#endif
482#if BUILD_PARAMETER_VALIDATION
483#include "stateless_validation.h"
484#endif
485#if BUILD_CORE_VALIDATION
486#include "core_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700487#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600488
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600489namespace vulkan_layer_chassis {
490
491using std::unordered_map;
492
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600493static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700494 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600495};
496
497static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
498
499extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
500
501
502// Manually written functions
503
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700504// Check enabled instance extensions against supported instance extension whitelist
505static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
506 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
507 // Check for recognized instance extensions
508 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
509 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
510 kVUIDUndefined,
511 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
512 "results and/or produce undefined behavior.",
513 pCreateInfo->ppEnabledExtensionNames[i]);
514 }
515 }
516}
517
518// Check enabled device extensions against supported device extension whitelist
519static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
520 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
521 // Check for recognized device extensions
522 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
523 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
524 kVUIDUndefined,
525 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
526 "results and/or produce undefined behavior.",
527 pCreateInfo->ppEnabledExtensionNames[i]);
528 }
529 }
530}
531
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700532// For the given ValidationCheck enum, set all relevant instance disabled flags to true
533void SetDisabledFlags(ValidationObject *instance_data, const VkValidationFlagsEXT *val_flags_struct) {
534 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
535 switch (val_flags_struct->pDisabledValidationChecks[i]) {
536 case VK_VALIDATION_CHECK_SHADERS_EXT:
537 instance_data->disabled.shader_validation = true;
538 break;
539 case VK_VALIDATION_CHECK_ALL_EXT:
540 // Set all disabled flags to true
541 instance_data->disabled.SetAll(true);
542 break;
543 default:
544 break;
545 }
546 }
547}
548
549void SetValidationFeatures(ValidationObject *instance_data, const VkValidationFeaturesEXT *val_features_struct) {
550 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
551 switch (val_features_struct->pDisabledValidationFeatures[i]) {
552 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
553 instance_data->disabled.shader_validation = true;
554 break;
555 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
556 // Set all disabled flags to true
557 instance_data->disabled.SetAll(true);
558 break;
559 default:
560 break;
561 }
562 }
563 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
564 switch (val_features_struct->pEnabledValidationFeatures[i]) {
565 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
566 instance_data->enabled.gpu_validation = true;
567 break;
568 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
569 instance_data->enabled.gpu_validation_reserve_binding_slot = true;
570 break;
571 default:
572 break;
573 }
574 }
575}
576
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600577VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600578 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700579 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700580 return nullptr;
581 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600582 const auto &item = name_to_funcptr_map.find(funcName);
583 if (item != name_to_funcptr_map.end()) {
584 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
585 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600586 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600587 if (!table.GetDeviceProcAddr) return nullptr;
588 return table.GetDeviceProcAddr(device, funcName);
589}
590
591VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600592 const auto &item = name_to_funcptr_map.find(funcName);
593 if (item != name_to_funcptr_map.end()) {
594 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
595 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600596 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
597 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600598 if (!table.GetInstanceProcAddr) return nullptr;
599 return table.GetInstanceProcAddr(instance, funcName);
600}
601
602VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600603 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
604 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600605 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
606 return table.GetPhysicalDeviceProcAddr(instance, funcName);
607}
608
609VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
610 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
611}
612
613VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
614 VkLayerProperties *pProperties) {
615 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
616}
617
618VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
619 VkExtensionProperties *pProperties) {
620 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
621 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
622
623 return VK_ERROR_LAYER_NOT_PRESENT;
624}
625
626VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
627 uint32_t *pCount, VkExtensionProperties *pProperties) {
628 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600629 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600630 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
631 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600632}
633
634VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
635 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600636 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600637
638 assert(chain_info->u.pLayerInfo);
639 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
640 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
641 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
642 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700643 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
644 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
645
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600646
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600647 // Create temporary dispatch vector for pre-calls until instance is created
648 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600649 // Add VOs to dispatch vector. Order here will be the validation dispatch order!
650#if BUILD_THREAD_SAFETY
651 auto thread_checker = new ThreadSafety;
652 local_object_dispatch.emplace_back(thread_checker);
653 thread_checker->container_type = LayerObjectTypeThreading;
654 thread_checker->api_version = api_version;
655#endif
656#if BUILD_PARAMETER_VALIDATION
657 auto parameter_validation = new StatelessValidation;
658 local_object_dispatch.emplace_back(parameter_validation);
659 parameter_validation->container_type = LayerObjectTypeParameterValidation;
660 parameter_validation->api_version = api_version;
661#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700662#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600663 auto object_tracker = new ObjectLifetimes;
664 local_object_dispatch.emplace_back(object_tracker);
665 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700666 object_tracker->api_version = api_version;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600667#endif
668#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700669 auto core_checks = new CoreChecks;
670 local_object_dispatch.emplace_back(core_checks);
671 core_checks->container_type = LayerObjectTypeCoreValidation;
672 core_checks->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700673#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600674
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600675 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600676 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600677 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
678 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600679 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600680 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
681 }
682
683 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600684 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600685
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600686 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600687
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600688 framework->object_dispatch = local_object_dispatch;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700689 framework->container_type = LayerObjectTypeInstance;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600690
691 framework->instance = *pInstance;
692 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
693 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
694 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700695 framework->api_version = api_version;
696 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
697
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700698 // Parse any pNext chains for validation features and flags
699 const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
700 if (validation_flags_ext) {
701 SetDisabledFlags(framework, validation_flags_ext);
702 }
703 const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(pCreateInfo->pNext);
704 if (validation_features_ext) {
705 SetValidationFeatures(framework, validation_features_ext);
706 }
707
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600708 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, OBJECT_LAYER_DESCRIPTION);
709
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700710#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700711 object_tracker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600712 object_tracker->instance_dispatch_table = framework->instance_dispatch_table;
713 object_tracker->enabled = framework->enabled;
714 object_tracker->disabled = framework->disabled;
715#endif
716#if BUILD_THREAD_SAFETY
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700717 thread_checker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600718 thread_checker->instance_dispatch_table = framework->instance_dispatch_table;
719 thread_checker->enabled = framework->enabled;
720 thread_checker->disabled = framework->disabled;
721#endif
722#if BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700723 parameter_validation->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600724 parameter_validation->instance_dispatch_table = framework->instance_dispatch_table;
725 parameter_validation->enabled = framework->enabled;
726 parameter_validation->disabled = framework->disabled;
727#endif
728#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700729 core_checks->report_data = framework->report_data;
730 core_checks->instance_dispatch_table = framework->instance_dispatch_table;
731 core_checks->instance = *pInstance;
732 core_checks->enabled = framework->enabled;
733 core_checks->disabled = framework->disabled;
734 core_checks->instance_state = core_checks;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700735#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600736
737 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700738 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600739 }
740
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700741 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
742
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600743 return result;
744}
745
746VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
747 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600748 auto layer_data = GetLayerDataPtr(key, layer_data_map);
749 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700750 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600751 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
752 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600753 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700754 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600755 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
756 }
757
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600758 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600759
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600760 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700761 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600762 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
763 }
764 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600765 while (layer_data->logging_messenger.size() > 0) {
766 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
767 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
768 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600769 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600770 while (layer_data->logging_callback.size() > 0) {
771 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
772 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
773 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600774 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600775
776 layer_debug_utils_destroy_instance(layer_data->report_data);
777
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700778 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
779 delete *item;
780 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600781 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600782}
783
784VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
785 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600786 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600787
788 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
789
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600790 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
791 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600792 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
793 if (fpCreateDevice == NULL) {
794 return VK_ERROR_INITIALIZATION_FAILED;
795 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600796 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
797
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700798 // Get physical device limits for device
799 VkPhysicalDeviceProperties device_properties = {};
800 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
801
802 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
803 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
804
805 DeviceExtensions device_extensions = {};
806 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
807 for (auto item : instance_interceptor->object_dispatch) {
808 item->device_extensions = device_extensions;
809 }
810
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700811 std::unique_ptr<safe_VkDeviceCreateInfo> modified_create_info(new safe_VkDeviceCreateInfo(pCreateInfo));
812
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700813 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600814 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700815 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700816 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700817 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600818 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600819 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700820 auto lock = intercept->write_lock();
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700821 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, modified_create_info);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600822 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600823
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700824 VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(modified_create_info.get()), pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600825 if (result != VK_SUCCESS) {
826 return result;
827 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600828
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600829 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700830 device_interceptor->container_type = LayerObjectTypeDevice;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700831
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700832 // Save local info in device object
833 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700834 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
835 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700836 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700837
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600838 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700839
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600840 device_interceptor->device = *pDevice;
841 device_interceptor->physical_device = gpu;
842 device_interceptor->instance = instance_interceptor->instance;
843 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600844
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600845 // Note that this defines the order in which the layer validation objects are called
846#if BUILD_THREAD_SAFETY
847 auto thread_safety = new ThreadSafety;
848 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
849 thread_safety->container_type = LayerObjectTypeThreading;
850 thread_safety->physical_device = gpu;
851 thread_safety->instance = instance_interceptor->instance;
852 thread_safety->report_data = device_interceptor->report_data;
853 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
854 thread_safety->api_version = device_interceptor->api_version;
855 device_interceptor->object_dispatch.emplace_back(thread_safety);
856#endif
857#if BUILD_PARAMETER_VALIDATION
858 auto stateless_validation = new StatelessValidation;
859 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
860 stateless_validation->container_type = LayerObjectTypeParameterValidation;
861 stateless_validation->physical_device = gpu;
862 stateless_validation->instance = instance_interceptor->instance;
863 stateless_validation->report_data = device_interceptor->report_data;
864 stateless_validation->device_dispatch_table = device_interceptor->device_dispatch_table;
865 stateless_validation->api_version = device_interceptor->api_version;
866 device_interceptor->object_dispatch.emplace_back(stateless_validation);
867#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700868#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600869 // Create child layer objects for this key and add to dispatch vector
870 auto object_tracker = new ObjectLifetimes;
871 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
872 object_tracker->container_type = LayerObjectTypeObjectTracker;
873 object_tracker->physical_device = gpu;
874 object_tracker->instance = instance_interceptor->instance;
875 object_tracker->report_data = device_interceptor->report_data;
876 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700877 object_tracker->api_version = device_interceptor->api_version;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600878 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600879#endif
880#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700881 auto core_checks = new CoreChecks;
882 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
883 core_checks->container_type = LayerObjectTypeCoreValidation;
884 core_checks->physical_device = gpu;
885 core_checks->instance = instance_interceptor->instance;
886 core_checks->report_data = device_interceptor->report_data;
887 core_checks->device_dispatch_table = device_interceptor->device_dispatch_table;
888 core_checks->instance_dispatch_table = instance_interceptor->instance_dispatch_table;
889 core_checks->api_version = device_interceptor->api_version;
890 core_checks->instance_extensions = instance_interceptor->instance_extensions;
891 core_checks->device_extensions = device_interceptor->device_extensions;
892 core_checks->instance_state = reinterpret_cast<CoreChecks *>(
893 core_checks->GetValidationObject(instance_interceptor->object_dispatch, LayerObjectTypeCoreValidation));
894 core_checks->device = *pDevice;
895 device_interceptor->object_dispatch.emplace_back(core_checks);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700896#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600897
898 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700899 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700900 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600901 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600902
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700903 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
904
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600905 return result;
906}
907
908VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
909 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600910 auto layer_data = GetLayerDataPtr(key, layer_data_map);
911 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700912 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600913 intercept->PreCallValidateDestroyDevice(device, pAllocator);
914 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600915 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700916 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600917 intercept->PreCallRecordDestroyDevice(device, pAllocator);
918 }
919 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600920
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600921 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600922
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600923 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700924 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600925 intercept->PostCallRecordDestroyDevice(device, pAllocator);
926 }
927
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700928 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
929 delete *item;
930 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600931 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700932}
933
934
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700935// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700936
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700937VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
938 VkDevice device,
939 VkPipelineCache pipelineCache,
940 uint32_t createInfoCount,
941 const VkGraphicsPipelineCreateInfo* pCreateInfos,
942 const VkAllocationCallbacks* pAllocator,
943 VkPipeline* pPipelines) {
944 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
945 bool skip = false;
946
947#ifdef BUILD_CORE_VALIDATION
948 create_graphics_pipeline_api_state cgpl_state{};
949#else
950 struct create_graphics_pipeline_api_state {
951 const VkGraphicsPipelineCreateInfo* pCreateInfos;
952 } cgpl_state;
953 cgpl_state.pCreateInfos = pCreateInfos;
954#endif
955
956 for (auto intercept : layer_data->object_dispatch) {
957 auto lock = intercept->write_lock();
958 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
959 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
960 }
961 for (auto intercept : layer_data->object_dispatch) {
962 auto lock = intercept->write_lock();
963 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
964 }
965
966 VkResult result = DispatchCreateGraphicsPipelines(layer_data, device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
967
968 for (auto intercept : layer_data->object_dispatch) {
969 auto lock = intercept->write_lock();
970 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
971 }
972 return result;
973}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700974
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700975// This API saves some core_validation pipeline state state on the stack for performance purposes
976VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
977 VkDevice device,
978 VkPipelineCache pipelineCache,
979 uint32_t createInfoCount,
980 const VkComputePipelineCreateInfo* pCreateInfos,
981 const VkAllocationCallbacks* pAllocator,
982 VkPipeline* pPipelines) {
983 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
984 bool skip = false;
985
986#ifndef BUILD_CORE_VALIDATION
987 struct PIPELINE_STATE {};
988#endif
989
990 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
991
992 for (auto intercept : layer_data->object_dispatch) {
993 auto lock = intercept->write_lock();
994 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
995 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
996 }
997 for (auto intercept : layer_data->object_dispatch) {
998 auto lock = intercept->write_lock();
999 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1000 }
1001 VkResult result = DispatchCreateComputePipelines(layer_data, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1002 for (auto intercept : layer_data->object_dispatch) {
1003 auto lock = intercept->write_lock();
1004 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1005 }
1006 return result;
1007}
1008
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001009VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
1010 VkDevice device,
1011 VkPipelineCache pipelineCache,
1012 uint32_t createInfoCount,
1013 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
1014 const VkAllocationCallbacks* pAllocator,
1015 VkPipeline* pPipelines) {
1016 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1017 bool skip = false;
1018
1019#ifndef BUILD_CORE_VALIDATION
1020 struct PIPELINE_STATE {};
1021#endif
1022
1023 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
1024
1025 for (auto intercept : layer_data->object_dispatch) {
1026 auto lock = intercept->write_lock();
1027 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
1028 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1029 }
1030 for (auto intercept : layer_data->object_dispatch) {
1031 auto lock = intercept->write_lock();
1032 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1033 }
1034 VkResult result = DispatchCreateRayTracingPipelinesNV(layer_data, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1035 for (auto intercept : layer_data->object_dispatch) {
1036 auto lock = intercept->write_lock();
1037 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1038 }
1039 return result;
1040}
1041
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001042// This API needs the ability to modify a down-chain parameter
1043VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
1044 VkDevice device,
1045 const VkPipelineLayoutCreateInfo* pCreateInfo,
1046 const VkAllocationCallbacks* pAllocator,
1047 VkPipelineLayout* pPipelineLayout) {
1048 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1049 bool skip = false;
1050
1051#ifndef BUILD_CORE_VALIDATION
1052 struct create_pipeline_layout_api_state {
1053 VkPipelineLayoutCreateInfo modified_create_info;
1054 };
1055#endif
1056 create_pipeline_layout_api_state cpl_state{};
1057 cpl_state.modified_create_info = *pCreateInfo;
1058
1059 for (auto intercept : layer_data->object_dispatch) {
1060 auto lock = intercept->write_lock();
1061 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1062 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1063 }
1064 for (auto intercept : layer_data->object_dispatch) {
1065 auto lock = intercept->write_lock();
1066 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1067 }
1068 VkResult result = DispatchCreatePipelineLayout(layer_data, device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
1069 for (auto intercept : layer_data->object_dispatch) {
1070 auto lock = intercept->write_lock();
1071 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1072 }
1073 return result;
1074}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001075
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001076// This API needs some local stack data for performance reasons and also may modify a parameter
1077VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1078 VkDevice device,
1079 const VkShaderModuleCreateInfo* pCreateInfo,
1080 const VkAllocationCallbacks* pAllocator,
1081 VkShaderModule* pShaderModule) {
1082 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1083 bool skip = false;
1084
1085#ifndef BUILD_CORE_VALIDATION
1086 struct create_shader_module_api_state {
1087 VkShaderModuleCreateInfo instrumented_create_info;
1088 };
1089#endif
1090 create_shader_module_api_state csm_state{};
1091 csm_state.instrumented_create_info = *pCreateInfo;
1092
1093 for (auto intercept : layer_data->object_dispatch) {
1094 auto lock = intercept->write_lock();
1095 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1096 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1097 }
1098 for (auto intercept : layer_data->object_dispatch) {
1099 auto lock = intercept->write_lock();
1100 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1101 }
1102 VkResult result = DispatchCreateShaderModule(layer_data, device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
1103 for (auto intercept : layer_data->object_dispatch) {
1104 auto lock = intercept->write_lock();
1105 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1106 }
1107 return result;
1108}
1109
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001110VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1111 VkDevice device,
1112 const VkDescriptorSetAllocateInfo* pAllocateInfo,
1113 VkDescriptorSet* pDescriptorSets) {
1114 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1115 bool skip = false;
1116
1117#ifdef BUILD_CORE_VALIDATION
1118 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1119#else
1120 struct ads_state {} ads_state;
1121#endif
1122
1123 for (auto intercept : layer_data->object_dispatch) {
1124 auto lock = intercept->write_lock();
1125 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1126 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1127 }
1128 for (auto intercept : layer_data->object_dispatch) {
1129 auto lock = intercept->write_lock();
1130 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1131 }
1132 VkResult result = DispatchAllocateDescriptorSets(layer_data, device, pAllocateInfo, pDescriptorSets);
1133 for (auto intercept : layer_data->object_dispatch) {
1134 auto lock = intercept->write_lock();
1135 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1136 }
1137 return result;
1138}
1139
1140
1141
1142
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001143
1144// ValidationCache APIs do not dispatch
1145
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001146VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1147 VkDevice device,
1148 const VkValidationCacheCreateInfoEXT* pCreateInfo,
1149 const VkAllocationCallbacks* pAllocator,
1150 VkValidationCacheEXT* pValidationCache) {
1151 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1152 VkResult result = VK_SUCCESS;
1153
1154 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1155 if (validation_data) {
1156 auto lock = validation_data->write_lock();
1157 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1158 }
1159 return result;
1160}
1161
1162VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1163 VkDevice device,
1164 VkValidationCacheEXT validationCache,
1165 const VkAllocationCallbacks* pAllocator) {
1166 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1167
1168 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1169 if (validation_data) {
1170 auto lock = validation_data->write_lock();
1171 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1172 }
1173}
1174
1175VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1176 VkDevice device,
1177 VkValidationCacheEXT dstCache,
1178 uint32_t srcCacheCount,
1179 const VkValidationCacheEXT* pSrcCaches) {
1180 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1181 VkResult result = VK_SUCCESS;
1182
1183 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1184 if (validation_data) {
1185 auto lock = validation_data->write_lock();
1186 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1187 }
1188 return result;
1189}
1190
1191VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1192 VkDevice device,
1193 VkValidationCacheEXT validationCache,
1194 size_t* pDataSize,
1195 void* pData) {
1196 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1197 VkResult result = VK_SUCCESS;
1198
1199 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1200 if (validation_data) {
1201 auto lock = validation_data->write_lock();
1202 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1203 }
1204 return result;
1205
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001206}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001207
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001208 inline_custom_validation_class_definitions = """
1209 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1210 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1211 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1212 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001213
1214 // Allow additional parameter for CreateGraphicsPipelines
1215 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1216 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1217 };
1218 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1219 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1220 };
1221 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1222 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1223 };
1224
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001225 // Allow additional state parameter for CreateComputePipelines
1226 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1227 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1228 };
1229 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1230 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1231 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001232
1233 // Allow additional state parameter for CreateRayTracingPipelinesNV
1234 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1235 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1236 };
1237 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1238 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1239 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001240
1241 // Allow modification of a down-chain parameter for CreatePipelineLayout
1242 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1243 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1244 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001245
1246 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1247 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1248 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1249 };
1250 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1251 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1252 };
1253 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1254 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1255 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001256
1257 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1258 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1259 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1260 };
1261 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1262 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1263 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001264
1265 // Modify a parameter to CreateDevice
1266 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1267 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1268 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001269"""
1270
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001271 inline_custom_source_postamble = """
1272// loader-layer interface v0, just wrappers since there is only a layer
1273
1274VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1275 VkExtensionProperties *pProperties) {
1276 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1277}
1278
1279VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1280 VkLayerProperties *pProperties) {
1281 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1282}
1283
1284VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1285 VkLayerProperties *pProperties) {
1286 // the layer command handles VK_NULL_HANDLE just fine internally
1287 assert(physicalDevice == VK_NULL_HANDLE);
1288 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1289}
1290
1291VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1292 const char *pLayerName, uint32_t *pCount,
1293 VkExtensionProperties *pProperties) {
1294 // the layer command handles VK_NULL_HANDLE just fine internally
1295 assert(physicalDevice == VK_NULL_HANDLE);
1296 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1297}
1298
1299VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1300 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1301}
1302
1303VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1304 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1305}
1306
1307VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
1308 const char *funcName) {
1309 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
1310}
1311
1312VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1313 assert(pVersionStruct != NULL);
1314 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1315
1316 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1317 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1318 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1319 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
1320 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
1321 }
1322
1323 return VK_SUCCESS;
1324}"""
1325
1326
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001327 def __init__(self,
1328 errFile = sys.stderr,
1329 warnFile = sys.stderr,
1330 diagFile = sys.stdout):
1331 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1332 # Internal state - accumulators for different inner block text
1333 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1334 self.intercepts = []
1335 self.layer_factory = '' # String containing base layer factory class definition
1336
1337 # Check if the parameter passed in is a pointer to an array
1338 def paramIsArray(self, param):
1339 return param.attrib.get('len') is not None
1340
1341 # Check if the parameter passed in is a pointer
1342 def paramIsPointer(self, param):
1343 ispointer = False
1344 for elem in param:
1345 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
1346 ispointer = True
1347 return ispointer
1348
1349 # Check if an object is a non-dispatchable handle
1350 def isHandleTypeNonDispatchable(self, handletype):
1351 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1352 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1353 return True
1354 else:
1355 return False
1356
1357 # Check if an object is a dispatchable handle
1358 def isHandleTypeDispatchable(self, handletype):
1359 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1360 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
1361 return True
1362 else:
1363 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001364 #
1365 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001366 def beginFile(self, genOpts):
1367 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001368 # Output Copyright
1369 write(self.inline_copyright_message, file=self.outFile)
1370 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001371 self.header = False
1372 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1373 self.header = True
1374 write('#pragma once', file=self.outFile)
1375 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001376 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001377 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001378 else:
1379 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001380 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001381 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001382 #
1383 def endFile(self):
1384 # Finish C++ namespace and multiple inclusion protection
1385 self.newline()
1386 if not self.header:
1387 # Record intercepted procedures
1388 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
1389 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
1390 write('\n'.join(self.intercepts), file=self.outFile)
1391 write('};\n', file=self.outFile)
1392 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001393 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001394 if self.header:
1395 self.newline()
1396 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001397 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001398 self.layer_factory += '};\n\n'
1399 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001400 write(self.layer_factory, file=self.outFile)
1401 else:
1402 write(self.inline_custom_source_postamble, file=self.outFile)
1403 # Finish processing in superclass
1404 OutputGenerator.endFile(self)
1405
1406 def beginFeature(self, interface, emit):
1407 # Start processing in superclass
1408 OutputGenerator.beginFeature(self, interface, emit)
1409 # Get feature extra protect
1410 self.featureExtraProtect = GetFeatureProtect(interface)
1411 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1412 # feature. They're only printed in endFeature().
1413 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1414
1415 def endFeature(self):
1416 # Actually write the interface to the output file.
1417 if (self.emit):
1418 self.newline()
1419 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1420 # or move it below the 'for section...' loop.
1421 if (self.featureExtraProtect != None):
1422 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1423 for section in self.TYPE_SECTIONS:
1424 contents = self.sections[section]
1425 if contents:
1426 write('\n'.join(contents), file=self.outFile)
1427 self.newline()
1428 if (self.sections['command']):
1429 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1430 self.newline()
1431 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001432 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001433 # Finish processing in superclass
1434 OutputGenerator.endFeature(self)
1435 #
1436 # Append a definition to the specified section
1437 def appendSection(self, section, text):
1438 self.sections[section].append(text)
1439 #
1440 # Type generation
1441 def genType(self, typeinfo, name, alias):
1442 pass
1443 #
1444 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1445 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1446 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1447 # structs etc.)
1448 def genStruct(self, typeinfo, typeName):
1449 OutputGenerator.genStruct(self, typeinfo, typeName)
1450 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1451 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1452 for member in typeinfo.elem.findall('.//member'):
1453 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1454 body += ';\n'
1455 body += '} ' + typeName + ';\n'
1456 self.appendSection('struct', body)
1457 #
1458 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1459 def genGroup(self, groupinfo, groupName, alias):
1460 pass
1461 # Enumerant generation
1462 # <enum> tags may specify their values in several ways, but are usually just integers.
1463 def genEnum(self, enuminfo, name, alias):
1464 pass
1465 #
1466 # Customize Cdecl for layer factory base class
1467 def BaseClassCdecl(self, elem, name):
1468 raw = self.makeCDecls(elem)[1]
1469
1470 # Toss everything before the undecorated name
1471 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1472 prototype = prototype.replace(")", "", 1)
1473 prototype = prototype.replace(";", " {};")
1474
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001475 # Build up pre/post call virtual function declarations
1476 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1477 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1478 pre_call_record = 'virtual void PreCallRecord' + prototype
1479 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001480 resulttype = elem.find('proto/type')
1481 if resulttype.text == 'VkResult':
1482 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001483 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1484 #
1485 # Command generation
1486 def genCmd(self, cmdinfo, name, alias):
1487 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001488 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001489 ]
1490
1491 if name in ignore_functions:
1492 return
1493
1494 if self.header: # In the header declare all intercepts
1495 self.appendSection('command', '')
1496 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1497 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001498 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1499 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001500 if 'ValidationCache' not in name:
1501 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001502 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001503 self.layer_factory += '#endif\n'
1504 return
1505
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001506 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001507 if 'ValidationCache' not in name:
1508 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1509 else:
1510 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1511 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1512 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001513 return
1514 # Record that the function will be intercepted
1515 if (self.featureExtraProtect != None):
1516 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1517 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1518 if (self.featureExtraProtect != None):
1519 self.intercepts += [ '#endif' ]
1520 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1521 #
1522 decls = self.makeCDecls(cmdinfo.elem)
1523 self.appendSection('command', '')
1524 self.appendSection('command', '%s {' % decls[0][:-1])
1525 # Setup common to call wrappers. First parameter is always dispatchable
1526 dispatchable_type = cmdinfo.elem.find('param/type').text
1527 dispatchable_name = cmdinfo.elem.find('param/name').text
1528 # Default to device
1529 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001530 dispatch_table_name = 'VkLayerDispatchTable'
1531 # Set to instance as necessary
1532 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1533 device_or_instance = 'instance'
1534 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001535 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001536 api_function_name = cmdinfo.elem.attrib.get('name')
1537 params = cmdinfo.elem.findall('param/name')
1538 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001539 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001540
1541 # Declare result variable, if any.
1542 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001543 'PFN_vkVoidFunction': 'return nullptr;',
1544 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001545 'VkDeviceAddress': 'return 0;',
1546 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1547 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001548 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001549 }
1550 resulttype = cmdinfo.elem.find('proto/type')
1551 assignresult = ''
1552 if (resulttype.text != 'void'):
1553 assignresult = resulttype.text + ' result = '
1554
1555 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001556 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001557
1558 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001559 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001560 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001561 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1562 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1563 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001564
1565 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001566 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001567 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001568 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001569 self.appendSection('command', ' }')
1570
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001571 # Insert pre-dispatch debug utils function call
1572 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001573 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001574
1575 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001576 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001577
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001578 # Insert post-dispatch debug utils function call
1579 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001580 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001581
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001582 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001583 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001584 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001585 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001586 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001587 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001588 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001589 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001590 # Return result variable, if any.
1591 if (resulttype.text != 'void'):
1592 self.appendSection('command', ' return result;')
1593 self.appendSection('command', '}')
1594 #
1595 # Override makeProtoName to drop the "vk" prefix
1596 def makeProtoName(self, name, tail):
1597 return self.genOpts.apientry + name[2:] + tail