blob: 5b406ae4adb155714a42c88c6877abbd18e57d92 [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 Lobodzinskiadd93232018-10-09 11:49:42 -0600454// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700455#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600456#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700457#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700458#elif BUILD_THREAD_SAFETY
Mark Lobodzinski706e52b2018-12-11 13:21:52 -0700459#include "thread_safety.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700460#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
461#elif BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700462#include "stateless_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700463#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
464#elif BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700465#include "core_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700466#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
467#else
468#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
469#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600470
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600471namespace vulkan_layer_chassis {
472
473using std::unordered_map;
474
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600475static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700476 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600477};
478
479static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
480
481extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
482
483
484// Manually written functions
485
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700486// Check enabled instance extensions against supported instance extension whitelist
487static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
488 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
489 // Check for recognized instance extensions
490 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
491 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
492 kVUIDUndefined,
493 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
494 "results and/or produce undefined behavior.",
495 pCreateInfo->ppEnabledExtensionNames[i]);
496 }
497 }
498}
499
500// Check enabled device extensions against supported device extension whitelist
501static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
502 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
503 // Check for recognized device extensions
504 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
505 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
506 kVUIDUndefined,
507 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
508 "results and/or produce undefined behavior.",
509 pCreateInfo->ppEnabledExtensionNames[i]);
510 }
511 }
512}
513
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700514// For the given ValidationCheck enum, set all relevant instance disabled flags to true
515void SetDisabledFlags(ValidationObject *instance_data, const VkValidationFlagsEXT *val_flags_struct) {
516 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
517 switch (val_flags_struct->pDisabledValidationChecks[i]) {
518 case VK_VALIDATION_CHECK_SHADERS_EXT:
519 instance_data->disabled.shader_validation = true;
520 break;
521 case VK_VALIDATION_CHECK_ALL_EXT:
522 // Set all disabled flags to true
523 instance_data->disabled.SetAll(true);
524 break;
525 default:
526 break;
527 }
528 }
529}
530
531void SetValidationFeatures(ValidationObject *instance_data, const VkValidationFeaturesEXT *val_features_struct) {
532 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
533 switch (val_features_struct->pDisabledValidationFeatures[i]) {
534 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
535 instance_data->disabled.shader_validation = true;
536 break;
537 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
538 // Set all disabled flags to true
539 instance_data->disabled.SetAll(true);
540 break;
541 default:
542 break;
543 }
544 }
545 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
546 switch (val_features_struct->pEnabledValidationFeatures[i]) {
547 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
548 instance_data->enabled.gpu_validation = true;
549 break;
550 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
551 instance_data->enabled.gpu_validation_reserve_binding_slot = true;
552 break;
553 default:
554 break;
555 }
556 }
557}
558
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600559VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600560 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700561 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700562 return nullptr;
563 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600564 const auto &item = name_to_funcptr_map.find(funcName);
565 if (item != name_to_funcptr_map.end()) {
566 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
567 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600568 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600569 if (!table.GetDeviceProcAddr) return nullptr;
570 return table.GetDeviceProcAddr(device, funcName);
571}
572
573VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600574 const auto &item = name_to_funcptr_map.find(funcName);
575 if (item != name_to_funcptr_map.end()) {
576 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
577 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600578 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
579 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600580 if (!table.GetInstanceProcAddr) return nullptr;
581 return table.GetInstanceProcAddr(instance, funcName);
582}
583
584VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600585 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
586 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600587 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
588 return table.GetPhysicalDeviceProcAddr(instance, funcName);
589}
590
591VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
592 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
593}
594
595VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
596 VkLayerProperties *pProperties) {
597 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
598}
599
600VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
601 VkExtensionProperties *pProperties) {
602 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
603 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
604
605 return VK_ERROR_LAYER_NOT_PRESENT;
606}
607
608VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
609 uint32_t *pCount, VkExtensionProperties *pProperties) {
610 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600611 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600612 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
613 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600614}
615
616VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
617 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600618 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600619
620 assert(chain_info->u.pLayerInfo);
621 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
622 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
623 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
624 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700625 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
626 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
627
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600628
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600629 // Create temporary dispatch vector for pre-calls until instance is created
630 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700631#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600632 auto object_tracker = new ObjectLifetimes;
633 local_object_dispatch.emplace_back(object_tracker);
634 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700635 object_tracker->api_version = api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700636#elif BUILD_THREAD_SAFETY
637 auto thread_checker = new ThreadSafety;
638 local_object_dispatch.emplace_back(thread_checker);
639 thread_checker->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700640 thread_checker->api_version = api_version;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700641#elif BUILD_PARAMETER_VALIDATION
642 auto parameter_validation = new StatelessValidation;
643 local_object_dispatch.emplace_back(parameter_validation);
644 parameter_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700645 parameter_validation->api_version = api_version;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700646#elif BUILD_CORE_VALIDATION
647 auto core_checks = new CoreChecks;
648 local_object_dispatch.emplace_back(core_checks);
649 core_checks->container_type = LayerObjectTypeCoreValidation;
650 core_checks->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700651#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600652
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600653 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600654 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600655 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
656 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600657 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600658 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
659 }
660
661 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600662 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600663
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600664 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600665
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600666 framework->object_dispatch = local_object_dispatch;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700667 framework->container_type = LayerObjectTypeInstance;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600668
669 framework->instance = *pInstance;
670 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
671 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
672 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700673 framework->api_version = api_version;
674 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
675
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700676 // Parse any pNext chains for validation features and flags
677 const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
678 if (validation_flags_ext) {
679 SetDisabledFlags(framework, validation_flags_ext);
680 }
681 const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(pCreateInfo->pNext);
682 if (validation_features_ext) {
683 SetValidationFeatures(framework, validation_features_ext);
684 }
685
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700686#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600687 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700688 object_tracker->report_data = framework->report_data;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700689#elif BUILD_THREAD_SAFETY
690 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "google_thread_checker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700691 thread_checker->report_data = framework->report_data;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700692#elif BUILD_PARAMETER_VALIDATION
693 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_parameter_validation");
694 parameter_validation->report_data = framework->report_data;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700695#elif BUILD_CORE_VALIDATION
696 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_core_validation");
697 core_checks->report_data = framework->report_data;
698 core_checks->instance_dispatch_table = framework->instance_dispatch_table;
699 core_checks->instance = *pInstance;
700 core_checks->enabled = framework->enabled;
701 core_checks->disabled = framework->disabled;
702 core_checks->instance_state = core_checks;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700703#else
704 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
705#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600706
707 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700708 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600709 }
710
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700711 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
712
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600713 return result;
714}
715
716VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
717 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600718 auto layer_data = GetLayerDataPtr(key, layer_data_map);
719 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700720 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600721 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
722 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600723 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700724 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600725 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
726 }
727
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600728 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600729
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600730 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700731 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600732 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
733 }
734 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600735 while (layer_data->logging_messenger.size() > 0) {
736 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
737 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
738 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600739 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600740 while (layer_data->logging_callback.size() > 0) {
741 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
742 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
743 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600744 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600745
746 layer_debug_utils_destroy_instance(layer_data->report_data);
747
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700748 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
749 delete *item;
750 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600751 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600752}
753
754VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
755 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600756 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600757
758 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
759
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600760 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
761 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600762 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
763 if (fpCreateDevice == NULL) {
764 return VK_ERROR_INITIALIZATION_FAILED;
765 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600766 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
767
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700768 // Get physical device limits for device
769 VkPhysicalDeviceProperties device_properties = {};
770 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
771
772 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
773 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
774
775 DeviceExtensions device_extensions = {};
776 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
777 for (auto item : instance_interceptor->object_dispatch) {
778 item->device_extensions = device_extensions;
779 }
780
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700781 std::unique_ptr<safe_VkDeviceCreateInfo> modified_create_info(new safe_VkDeviceCreateInfo(pCreateInfo));
782
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700783 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600784 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700785 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700786 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700787 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600788 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600789 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700790 auto lock = intercept->write_lock();
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700791 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, modified_create_info);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600792 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600793
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700794 VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(modified_create_info.get()), pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600795 if (result != VK_SUCCESS) {
796 return result;
797 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600798
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600799 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700800 device_interceptor->container_type = LayerObjectTypeDevice;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700801
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700802 // Save local info in device object
803 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700804 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
805 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700806 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700807
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600808 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700809
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600810 device_interceptor->device = *pDevice;
811 device_interceptor->physical_device = gpu;
812 device_interceptor->instance = instance_interceptor->instance;
813 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600814
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700815#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600816 // Create child layer objects for this key and add to dispatch vector
817 auto object_tracker = new ObjectLifetimes;
818 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
819 object_tracker->container_type = LayerObjectTypeObjectTracker;
820 object_tracker->physical_device = gpu;
821 object_tracker->instance = instance_interceptor->instance;
822 object_tracker->report_data = device_interceptor->report_data;
823 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700824 object_tracker->api_version = device_interceptor->api_version;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600825 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700826#elif BUILD_THREAD_SAFETY
827 auto thread_safety = new ThreadSafety;
828 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
829 thread_safety->container_type = LayerObjectTypeThreading;
830 thread_safety->physical_device = gpu;
831 thread_safety->instance = instance_interceptor->instance;
832 thread_safety->report_data = device_interceptor->report_data;
833 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700834 thread_safety->api_version = device_interceptor->api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700835 device_interceptor->object_dispatch.emplace_back(thread_safety);
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700836#elif BUILD_PARAMETER_VALIDATION
837 auto stateless_validation = new StatelessValidation;
838 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
839 stateless_validation->container_type = LayerObjectTypeParameterValidation;
840 stateless_validation->physical_device = gpu;
841 stateless_validation->instance = instance_interceptor->instance;
842 stateless_validation->report_data = device_interceptor->report_data;
843 stateless_validation->device_dispatch_table = device_interceptor->device_dispatch_table;
844 stateless_validation->api_version = device_interceptor->api_version;
845 device_interceptor->object_dispatch.emplace_back(stateless_validation);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700846#elif BUILD_CORE_VALIDATION
847 auto core_checks = new CoreChecks;
848 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
849 core_checks->container_type = LayerObjectTypeCoreValidation;
850 core_checks->physical_device = gpu;
851 core_checks->instance = instance_interceptor->instance;
852 core_checks->report_data = device_interceptor->report_data;
853 core_checks->device_dispatch_table = device_interceptor->device_dispatch_table;
854 core_checks->instance_dispatch_table = instance_interceptor->instance_dispatch_table;
855 core_checks->api_version = device_interceptor->api_version;
856 core_checks->instance_extensions = instance_interceptor->instance_extensions;
857 core_checks->device_extensions = device_interceptor->device_extensions;
858 core_checks->instance_state = reinterpret_cast<CoreChecks *>(
859 core_checks->GetValidationObject(instance_interceptor->object_dispatch, LayerObjectTypeCoreValidation));
860 core_checks->device = *pDevice;
861 device_interceptor->object_dispatch.emplace_back(core_checks);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700862#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600863
864 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700865 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700866 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600867 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600868
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700869 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
870
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600871 return result;
872}
873
874VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
875 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600876 auto layer_data = GetLayerDataPtr(key, layer_data_map);
877 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700878 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600879 intercept->PreCallValidateDestroyDevice(device, pAllocator);
880 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600881 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700882 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600883 intercept->PreCallRecordDestroyDevice(device, pAllocator);
884 }
885 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600886
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600887 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600888
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600889 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700890 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600891 intercept->PostCallRecordDestroyDevice(device, pAllocator);
892 }
893
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700894 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
895 delete *item;
896 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600897 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700898}
899
900
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700901// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700902
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700903VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
904 VkDevice device,
905 VkPipelineCache pipelineCache,
906 uint32_t createInfoCount,
907 const VkGraphicsPipelineCreateInfo* pCreateInfos,
908 const VkAllocationCallbacks* pAllocator,
909 VkPipeline* pPipelines) {
910 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
911 bool skip = false;
912
913#ifdef BUILD_CORE_VALIDATION
914 create_graphics_pipeline_api_state cgpl_state{};
915#else
916 struct create_graphics_pipeline_api_state {
917 const VkGraphicsPipelineCreateInfo* pCreateInfos;
918 } cgpl_state;
919 cgpl_state.pCreateInfos = pCreateInfos;
920#endif
921
922 for (auto intercept : layer_data->object_dispatch) {
923 auto lock = intercept->write_lock();
924 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
925 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
926 }
927 for (auto intercept : layer_data->object_dispatch) {
928 auto lock = intercept->write_lock();
929 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
930 }
931
932 VkResult result = DispatchCreateGraphicsPipelines(layer_data, device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
933
934 for (auto intercept : layer_data->object_dispatch) {
935 auto lock = intercept->write_lock();
936 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
937 }
938 return result;
939}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700940
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700941// This API saves some core_validation pipeline state state on the stack for performance purposes
942VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
943 VkDevice device,
944 VkPipelineCache pipelineCache,
945 uint32_t createInfoCount,
946 const VkComputePipelineCreateInfo* pCreateInfos,
947 const VkAllocationCallbacks* pAllocator,
948 VkPipeline* pPipelines) {
949 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
950 bool skip = false;
951
952#ifndef BUILD_CORE_VALIDATION
953 struct PIPELINE_STATE {};
954#endif
955
956 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
957
958 for (auto intercept : layer_data->object_dispatch) {
959 auto lock = intercept->write_lock();
960 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
961 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
962 }
963 for (auto intercept : layer_data->object_dispatch) {
964 auto lock = intercept->write_lock();
965 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
966 }
967 VkResult result = DispatchCreateComputePipelines(layer_data, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
968 for (auto intercept : layer_data->object_dispatch) {
969 auto lock = intercept->write_lock();
970 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
971 }
972 return result;
973}
974
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700975VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
976 VkDevice device,
977 VkPipelineCache pipelineCache,
978 uint32_t createInfoCount,
979 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
980 const VkAllocationCallbacks* pAllocator,
981 VkPipeline* pPipelines) {
982 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
983 bool skip = false;
984
985#ifndef BUILD_CORE_VALIDATION
986 struct PIPELINE_STATE {};
987#endif
988
989 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
990
991 for (auto intercept : layer_data->object_dispatch) {
992 auto lock = intercept->write_lock();
993 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
994 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
995 }
996 for (auto intercept : layer_data->object_dispatch) {
997 auto lock = intercept->write_lock();
998 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
999 }
1000 VkResult result = DispatchCreateRayTracingPipelinesNV(layer_data, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1001 for (auto intercept : layer_data->object_dispatch) {
1002 auto lock = intercept->write_lock();
1003 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1004 }
1005 return result;
1006}
1007
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001008// This API needs the ability to modify a down-chain parameter
1009VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
1010 VkDevice device,
1011 const VkPipelineLayoutCreateInfo* pCreateInfo,
1012 const VkAllocationCallbacks* pAllocator,
1013 VkPipelineLayout* pPipelineLayout) {
1014 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1015 bool skip = false;
1016
1017#ifndef BUILD_CORE_VALIDATION
1018 struct create_pipeline_layout_api_state {
1019 VkPipelineLayoutCreateInfo modified_create_info;
1020 };
1021#endif
1022 create_pipeline_layout_api_state cpl_state{};
1023 cpl_state.modified_create_info = *pCreateInfo;
1024
1025 for (auto intercept : layer_data->object_dispatch) {
1026 auto lock = intercept->write_lock();
1027 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
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->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1033 }
1034 VkResult result = DispatchCreatePipelineLayout(layer_data, device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
1035 for (auto intercept : layer_data->object_dispatch) {
1036 auto lock = intercept->write_lock();
1037 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1038 }
1039 return result;
1040}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001041
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001042// This API needs some local stack data for performance reasons and also may modify a parameter
1043VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1044 VkDevice device,
1045 const VkShaderModuleCreateInfo* pCreateInfo,
1046 const VkAllocationCallbacks* pAllocator,
1047 VkShaderModule* pShaderModule) {
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_shader_module_api_state {
1053 VkShaderModuleCreateInfo instrumented_create_info;
1054 };
1055#endif
1056 create_shader_module_api_state csm_state{};
1057 csm_state.instrumented_create_info = *pCreateInfo;
1058
1059 for (auto intercept : layer_data->object_dispatch) {
1060 auto lock = intercept->write_lock();
1061 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
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->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1067 }
1068 VkResult result = DispatchCreateShaderModule(layer_data, device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
1069 for (auto intercept : layer_data->object_dispatch) {
1070 auto lock = intercept->write_lock();
1071 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1072 }
1073 return result;
1074}
1075
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001076VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1077 VkDevice device,
1078 const VkDescriptorSetAllocateInfo* pAllocateInfo,
1079 VkDescriptorSet* pDescriptorSets) {
1080 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1081 bool skip = false;
1082
1083#ifdef BUILD_CORE_VALIDATION
1084 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1085#else
1086 struct ads_state {} ads_state;
1087#endif
1088
1089 for (auto intercept : layer_data->object_dispatch) {
1090 auto lock = intercept->write_lock();
1091 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1092 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1093 }
1094 for (auto intercept : layer_data->object_dispatch) {
1095 auto lock = intercept->write_lock();
1096 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1097 }
1098 VkResult result = DispatchAllocateDescriptorSets(layer_data, device, pAllocateInfo, pDescriptorSets);
1099 for (auto intercept : layer_data->object_dispatch) {
1100 auto lock = intercept->write_lock();
1101 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1102 }
1103 return result;
1104}
1105
1106
1107
1108
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001109
1110// ValidationCache APIs do not dispatch
1111
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001112VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1113 VkDevice device,
1114 const VkValidationCacheCreateInfoEXT* pCreateInfo,
1115 const VkAllocationCallbacks* pAllocator,
1116 VkValidationCacheEXT* pValidationCache) {
1117 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1118 VkResult result = VK_SUCCESS;
1119
1120 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1121 if (validation_data) {
1122 auto lock = validation_data->write_lock();
1123 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1124 }
1125 return result;
1126}
1127
1128VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1129 VkDevice device,
1130 VkValidationCacheEXT validationCache,
1131 const VkAllocationCallbacks* pAllocator) {
1132 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1133
1134 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1135 if (validation_data) {
1136 auto lock = validation_data->write_lock();
1137 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1138 }
1139}
1140
1141VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1142 VkDevice device,
1143 VkValidationCacheEXT dstCache,
1144 uint32_t srcCacheCount,
1145 const VkValidationCacheEXT* pSrcCaches) {
1146 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1147 VkResult result = VK_SUCCESS;
1148
1149 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1150 if (validation_data) {
1151 auto lock = validation_data->write_lock();
1152 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1153 }
1154 return result;
1155}
1156
1157VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1158 VkDevice device,
1159 VkValidationCacheEXT validationCache,
1160 size_t* pDataSize,
1161 void* pData) {
1162 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1163 VkResult result = VK_SUCCESS;
1164
1165 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1166 if (validation_data) {
1167 auto lock = validation_data->write_lock();
1168 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1169 }
1170 return result;
1171
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001172}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001173
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001174 inline_custom_validation_class_definitions = """
1175 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1176 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1177 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1178 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001179
1180 // Allow additional parameter for CreateGraphicsPipelines
1181 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1182 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1183 };
1184 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1185 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1186 };
1187 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1188 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1189 };
1190
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001191 // Allow additional state parameter for CreateComputePipelines
1192 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1193 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1194 };
1195 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1196 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1197 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001198
1199 // Allow additional state parameter for CreateRayTracingPipelinesNV
1200 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1201 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1202 };
1203 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1204 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1205 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001206
1207 // Allow modification of a down-chain parameter for CreatePipelineLayout
1208 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1209 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1210 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001211
1212 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1213 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1214 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1215 };
1216 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1217 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1218 };
1219 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1220 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1221 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001222
1223 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1224 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1225 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1226 };
1227 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1228 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1229 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001230
1231 // Modify a parameter to CreateDevice
1232 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1233 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1234 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001235"""
1236
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001237 inline_custom_source_postamble = """
1238// loader-layer interface v0, just wrappers since there is only a layer
1239
1240VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1241 VkExtensionProperties *pProperties) {
1242 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1243}
1244
1245VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1246 VkLayerProperties *pProperties) {
1247 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1248}
1249
1250VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1251 VkLayerProperties *pProperties) {
1252 // the layer command handles VK_NULL_HANDLE just fine internally
1253 assert(physicalDevice == VK_NULL_HANDLE);
1254 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1255}
1256
1257VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1258 const char *pLayerName, uint32_t *pCount,
1259 VkExtensionProperties *pProperties) {
1260 // the layer command handles VK_NULL_HANDLE just fine internally
1261 assert(physicalDevice == VK_NULL_HANDLE);
1262 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1263}
1264
1265VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1266 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1267}
1268
1269VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1270 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1271}
1272
1273VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
1274 const char *funcName) {
1275 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
1276}
1277
1278VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1279 assert(pVersionStruct != NULL);
1280 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1281
1282 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1283 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1284 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1285 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
1286 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
1287 }
1288
1289 return VK_SUCCESS;
1290}"""
1291
1292
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001293 def __init__(self,
1294 errFile = sys.stderr,
1295 warnFile = sys.stderr,
1296 diagFile = sys.stdout):
1297 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1298 # Internal state - accumulators for different inner block text
1299 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1300 self.intercepts = []
1301 self.layer_factory = '' # String containing base layer factory class definition
1302
1303 # Check if the parameter passed in is a pointer to an array
1304 def paramIsArray(self, param):
1305 return param.attrib.get('len') is not None
1306
1307 # Check if the parameter passed in is a pointer
1308 def paramIsPointer(self, param):
1309 ispointer = False
1310 for elem in param:
1311 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
1312 ispointer = True
1313 return ispointer
1314
1315 # Check if an object is a non-dispatchable handle
1316 def isHandleTypeNonDispatchable(self, handletype):
1317 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1318 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1319 return True
1320 else:
1321 return False
1322
1323 # Check if an object is a dispatchable handle
1324 def isHandleTypeDispatchable(self, handletype):
1325 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1326 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
1327 return True
1328 else:
1329 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001330 #
1331 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001332 def beginFile(self, genOpts):
1333 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001334 # Output Copyright
1335 write(self.inline_copyright_message, file=self.outFile)
1336 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001337 self.header = False
1338 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1339 self.header = True
1340 write('#pragma once', file=self.outFile)
1341 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001342 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001343 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001344 else:
1345 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001346 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001347 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001348 #
1349 def endFile(self):
1350 # Finish C++ namespace and multiple inclusion protection
1351 self.newline()
1352 if not self.header:
1353 # Record intercepted procedures
1354 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
1355 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
1356 write('\n'.join(self.intercepts), file=self.outFile)
1357 write('};\n', file=self.outFile)
1358 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001359 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001360 if self.header:
1361 self.newline()
1362 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001363 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001364 self.layer_factory += '};\n\n'
1365 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001366 write(self.layer_factory, file=self.outFile)
1367 else:
1368 write(self.inline_custom_source_postamble, file=self.outFile)
1369 # Finish processing in superclass
1370 OutputGenerator.endFile(self)
1371
1372 def beginFeature(self, interface, emit):
1373 # Start processing in superclass
1374 OutputGenerator.beginFeature(self, interface, emit)
1375 # Get feature extra protect
1376 self.featureExtraProtect = GetFeatureProtect(interface)
1377 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1378 # feature. They're only printed in endFeature().
1379 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1380
1381 def endFeature(self):
1382 # Actually write the interface to the output file.
1383 if (self.emit):
1384 self.newline()
1385 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1386 # or move it below the 'for section...' loop.
1387 if (self.featureExtraProtect != None):
1388 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1389 for section in self.TYPE_SECTIONS:
1390 contents = self.sections[section]
1391 if contents:
1392 write('\n'.join(contents), file=self.outFile)
1393 self.newline()
1394 if (self.sections['command']):
1395 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1396 self.newline()
1397 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001398 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001399 # Finish processing in superclass
1400 OutputGenerator.endFeature(self)
1401 #
1402 # Append a definition to the specified section
1403 def appendSection(self, section, text):
1404 self.sections[section].append(text)
1405 #
1406 # Type generation
1407 def genType(self, typeinfo, name, alias):
1408 pass
1409 #
1410 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1411 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1412 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1413 # structs etc.)
1414 def genStruct(self, typeinfo, typeName):
1415 OutputGenerator.genStruct(self, typeinfo, typeName)
1416 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1417 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1418 for member in typeinfo.elem.findall('.//member'):
1419 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1420 body += ';\n'
1421 body += '} ' + typeName + ';\n'
1422 self.appendSection('struct', body)
1423 #
1424 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1425 def genGroup(self, groupinfo, groupName, alias):
1426 pass
1427 # Enumerant generation
1428 # <enum> tags may specify their values in several ways, but are usually just integers.
1429 def genEnum(self, enuminfo, name, alias):
1430 pass
1431 #
1432 # Customize Cdecl for layer factory base class
1433 def BaseClassCdecl(self, elem, name):
1434 raw = self.makeCDecls(elem)[1]
1435
1436 # Toss everything before the undecorated name
1437 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1438 prototype = prototype.replace(")", "", 1)
1439 prototype = prototype.replace(";", " {};")
1440
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001441 # Build up pre/post call virtual function declarations
1442 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1443 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1444 pre_call_record = 'virtual void PreCallRecord' + prototype
1445 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001446 resulttype = elem.find('proto/type')
1447 if resulttype.text == 'VkResult':
1448 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001449 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1450 #
1451 # Command generation
1452 def genCmd(self, cmdinfo, name, alias):
1453 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001454 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001455 ]
1456
1457 if name in ignore_functions:
1458 return
1459
1460 if self.header: # In the header declare all intercepts
1461 self.appendSection('command', '')
1462 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1463 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001464 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1465 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001466 if 'ValidationCache' not in name:
1467 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001468 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001469 self.layer_factory += '#endif\n'
1470 return
1471
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001472 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001473 if 'ValidationCache' not in name:
1474 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1475 else:
1476 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1477 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1478 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001479 return
1480 # Record that the function will be intercepted
1481 if (self.featureExtraProtect != None):
1482 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1483 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1484 if (self.featureExtraProtect != None):
1485 self.intercepts += [ '#endif' ]
1486 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1487 #
1488 decls = self.makeCDecls(cmdinfo.elem)
1489 self.appendSection('command', '')
1490 self.appendSection('command', '%s {' % decls[0][:-1])
1491 # Setup common to call wrappers. First parameter is always dispatchable
1492 dispatchable_type = cmdinfo.elem.find('param/type').text
1493 dispatchable_name = cmdinfo.elem.find('param/name').text
1494 # Default to device
1495 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001496 dispatch_table_name = 'VkLayerDispatchTable'
1497 # Set to instance as necessary
1498 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1499 device_or_instance = 'instance'
1500 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001501 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001502 api_function_name = cmdinfo.elem.attrib.get('name')
1503 params = cmdinfo.elem.findall('param/name')
1504 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001505 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001506
1507 # Declare result variable, if any.
1508 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001509 'PFN_vkVoidFunction': 'return nullptr;',
1510 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001511 'VkDeviceAddress': 'return 0;',
1512 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1513 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001514 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001515 }
1516 resulttype = cmdinfo.elem.find('proto/type')
1517 assignresult = ''
1518 if (resulttype.text != 'void'):
1519 assignresult = resulttype.text + ' result = '
1520
1521 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001522 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001523
1524 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001525 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001526 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001527 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1528 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1529 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001530
1531 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001532 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001533 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001534 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001535 self.appendSection('command', ' }')
1536
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001537 # Insert pre-dispatch debug utils function call
1538 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001539 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001540
1541 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001542 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001543
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001544 # Insert post-dispatch debug utils function call
1545 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001546 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001547
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001548 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001549 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001550 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001551 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001552 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001553 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001554 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001555 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001556 # Return result variable, if any.
1557 if (resulttype.text != 'void'):
1558 self.appendSection('command', ' return result;')
1559 self.appendSection('command', '}')
1560 #
1561 # Override makeProtoName to drop the "vk" prefix
1562 def makeProtoName(self, name, tail):
1563 return self.genOpts.apientry + name[2:] + tail