blob: 912604160c6d509dbf55c17dbf332814572e6c0f [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;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600295
296 bool object_tracking; // Disable object lifetime validation
297 bool core_checks; // Disable core validation checks
298 bool thread_safety; // Disable thread safety validation
299 bool stateless_checks; // Disable stateless validation checks
300 bool handle_wrapping; // Disable unique handles/handle wrapping
301 bool shader_validation; // Skip validation for shaders
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700302
303 void SetAll(bool value) { std::fill(&command_buffer_state, &shader_validation + 1, value); }
304};
305
306struct CHECK_ENABLED {
307 bool gpu_validation;
308 bool gpu_validation_reserve_binding_slot;
309
310 void SetAll(bool value) { std::fill(&gpu_validation, &gpu_validation_reserve_binding_slot + 1, value); }
311};
312
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700313// Layer chassis validation object base class definition
314class ValidationObject {
315 public:
316 uint32_t api_version;
317 debug_report_data* report_data = nullptr;
318 std::vector<VkDebugReportCallbackEXT> logging_callback;
319 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
320
321 VkLayerInstanceDispatchTable instance_dispatch_table;
322 VkLayerDispatchTable device_dispatch_table;
323
324 InstanceExtensions instance_extensions;
325 DeviceExtensions device_extensions = {};
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700326 CHECK_DISABLED disabled = {};
327 CHECK_ENABLED enabled = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700328
329 VkInstance instance = VK_NULL_HANDLE;
330 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
331 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700332 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700333
334 std::vector<ValidationObject*> object_dispatch;
335 LayerObjectTypeId container_type;
336
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700337 std::string layer_name = "CHASSIS";
338
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700339 // Constructor
340 ValidationObject(){};
341 // Destructor
342 virtual ~ValidationObject() {};
343
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700344 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700345 virtual std::unique_lock<std::mutex> write_lock() {
346 return std::unique_lock<std::mutex>(validation_object_mutex);
347 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700348
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700349 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
350 for (auto validation_object : object_dispatch) {
351 if (validation_object->container_type == object_type) {
352 return validation_object;
353 }
354 }
355 return nullptr;
356 };
357
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700358 // Handle Wrapping Data
359 // Reverse map display handles
360 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
361 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700362 struct SubpassesUsageStates {
363 std::unordered_set<uint32_t> subpasses_using_color_attachment;
364 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
365 };
366 // Uses unwrapped handles
367 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
368 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
369 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
370 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700371 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
372 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700373
374
375 // Unwrap a handle. Must hold lock.
376 template <typename HandleType>
377 HandleType Unwrap(HandleType wrappedHandle) {
378 // TODO: don't use operator[] here.
379 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
380 }
381
382 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
383 template <typename HandleType>
384 HandleType WrapNew(HandleType newlyCreatedHandle) {
385 auto unique_id = global_unique_id++;
386 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
387 return (HandleType)unique_id;
388 }
389
390 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
391 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
392 auto unique_id = global_unique_id++;
393 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
394 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
395 return (VkDisplayKHR)unique_id;
396 }
397
398 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
399 // creating another. Must hold lock.
400 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
401 // See if this display is already known
402 auto it = map_data->display_id_reverse_mapping.find(handle);
403 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
404 // Unknown, so wrap
405 return WrapDisplay(handle, map_data);
406 }
407
408 // Pre/post hook point declarations
409"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600410
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700411 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600412// This file is ***GENERATED***. Do Not Edit.
413// See layer_chassis_generator.py for modifications.
414
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700415/* Copyright (c) 2015-2019 The Khronos Group Inc.
416 * Copyright (c) 2015-2019 Valve Corporation
417 * Copyright (c) 2015-2019 LunarG, Inc.
418 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600419 *
420 * Licensed under the Apache License, Version 2.0 (the "License");
421 * you may not use this file except in compliance with the License.
422 * You may obtain a copy of the License at
423 *
424 * http://www.apache.org/licenses/LICENSE-2.0
425 *
426 * Unless required by applicable law or agreed to in writing, software
427 * distributed under the License is distributed on an "AS IS" BASIS,
428 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
429 * See the License for the specific language governing permissions and
430 * limitations under the License.
431 *
432 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700433 */"""
434
435 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600436
437#include <string.h>
438#include <mutex>
439
440#define VALIDATION_ERROR_MAP_IMPL
441
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600442#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700443#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600444
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600445std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600446
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700447// Global unique object identifier. All increments must be guarded by a lock.
448uint64_t global_unique_id = 1;
449// Map uniqueID to actual object handle
450std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
451
452// TODO: This variable controls handle wrapping -- in the future it should be hooked
453// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
454#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
455bool wrap_handles = true;
456#else
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600457bool wrap_handles = false;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700458#endif
459
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600460// Set layer name -- Khronos layer name overrides any other defined names
Mark Lobodzinskiaa6fd7b2019-03-19 09:26:48 -0600461#if BUILD_KHRONOS_VALIDATION
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600462#define OBJECT_LAYER_NAME "VK_LAYER_KHRONOS_validation"
463#define OBJECT_LAYER_DESCRIPTION "khronos_validation"
464#elif BUILD_OBJECT_TRACKER
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700465#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600466#define OBJECT_LAYER_DESCRIPTION "lunarg_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700467#elif BUILD_THREAD_SAFETY
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700468#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600469#define OBJECT_LAYER_DESCRIPTION "google_thread_checker"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700470#elif BUILD_PARAMETER_VALIDATION
471#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600472#define OBJECT_LAYER_DESCRIPTION "lunarg_parameter_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700473#elif BUILD_CORE_VALIDATION
474#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600475#define OBJECT_LAYER_DESCRIPTION "lunarg_core_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700476#else
477#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600478#define OBJECT_LAYER_DESCRIPTION "lunarg_unique_objects"
479#endif
480
481// Include layer validation object definitions
482#if BUILD_OBJECT_TRACKER
483#include "object_lifetime_validation.h"
484#endif
485#if BUILD_THREAD_SAFETY
486#include "thread_safety.h"
487#endif
488#if BUILD_PARAMETER_VALIDATION
489#include "stateless_validation.h"
490#endif
491#if BUILD_CORE_VALIDATION
492#include "core_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700493#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600494
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600495namespace vulkan_layer_chassis {
496
497using std::unordered_map;
498
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600499static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700500 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600501};
502
503static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
504
505extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
506
507
508// Manually written functions
509
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700510// Check enabled instance extensions against supported instance extension whitelist
511static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
512 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
513 // Check for recognized instance extensions
514 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
515 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
516 kVUIDUndefined,
517 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
518 "results and/or produce undefined behavior.",
519 pCreateInfo->ppEnabledExtensionNames[i]);
520 }
521 }
522}
523
524// Check enabled device extensions against supported device extension whitelist
525static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
526 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
527 // Check for recognized device extensions
528 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
529 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
530 kVUIDUndefined,
531 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
532 "results and/or produce undefined behavior.",
533 pCreateInfo->ppEnabledExtensionNames[i]);
534 }
535 }
536}
537
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700538// For the given ValidationCheck enum, set all relevant instance disabled flags to true
539void SetDisabledFlags(ValidationObject *instance_data, const VkValidationFlagsEXT *val_flags_struct) {
540 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
541 switch (val_flags_struct->pDisabledValidationChecks[i]) {
542 case VK_VALIDATION_CHECK_SHADERS_EXT:
543 instance_data->disabled.shader_validation = true;
544 break;
545 case VK_VALIDATION_CHECK_ALL_EXT:
546 // Set all disabled flags to true
547 instance_data->disabled.SetAll(true);
548 break;
549 default:
550 break;
551 }
552 }
553}
554
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600555void SetValidationFeatures(CHECK_DISABLED *disable_data, CHECK_ENABLED *enable_data,
556 const VkValidationFeaturesEXT *val_features_struct) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700557 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
558 switch (val_features_struct->pDisabledValidationFeatures[i]) {
559 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600560 disable_data->shader_validation = true;
561 break;
562 case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
563 disable_data->thread_safety = true;
564 break;
565 case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
566 disable_data->stateless_checks = true;
567 break;
568 case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
569 disable_data->object_tracking = true;
570 break;
571 case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
572 disable_data->core_checks = true;
573 break;
574 case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
575 disable_data->handle_wrapping = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700576 break;
577 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
578 // Set all disabled flags to true
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600579 disable_data->SetAll(true);
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700580 break;
581 default:
582 break;
583 }
584 }
585 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
586 switch (val_features_struct->pEnabledValidationFeatures[i]) {
587 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600588 enable_data->gpu_validation = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700589 break;
590 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600591 enable_data->gpu_validation_reserve_binding_slot = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700592 break;
593 default:
594 break;
595 }
596 }
597}
598
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600599VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600600 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700601 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700602 return nullptr;
603 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600604 const auto &item = name_to_funcptr_map.find(funcName);
605 if (item != name_to_funcptr_map.end()) {
606 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
607 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600608 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600609 if (!table.GetDeviceProcAddr) return nullptr;
610 return table.GetDeviceProcAddr(device, funcName);
611}
612
613VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600614 const auto &item = name_to_funcptr_map.find(funcName);
615 if (item != name_to_funcptr_map.end()) {
616 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
617 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600618 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
619 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600620 if (!table.GetInstanceProcAddr) return nullptr;
621 return table.GetInstanceProcAddr(instance, funcName);
622}
623
624VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600625 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
626 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600627 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
628 return table.GetPhysicalDeviceProcAddr(instance, funcName);
629}
630
631VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
632 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
633}
634
635VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
636 VkLayerProperties *pProperties) {
637 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
638}
639
640VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
641 VkExtensionProperties *pProperties) {
642 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
643 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
644
645 return VK_ERROR_LAYER_NOT_PRESENT;
646}
647
648VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
649 uint32_t *pCount, VkExtensionProperties *pProperties) {
650 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600651 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600652 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
653 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600654}
655
656VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
657 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600658 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600659
660 assert(chain_info->u.pLayerInfo);
661 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
662 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
663 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
664 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700665 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
666 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
667
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600668 CHECK_ENABLED local_enables {};
669 CHECK_DISABLED local_disables {};
670 const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(pCreateInfo->pNext);
671 if (validation_features_ext) {
672 SetValidationFeatures(&local_disables, &local_enables, validation_features_ext);
673 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600674
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600675 // Create temporary dispatch vector for pre-calls until instance is created
676 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600677 // Add VOs to dispatch vector. Order here will be the validation dispatch order!
678#if BUILD_THREAD_SAFETY
679 auto thread_checker = new ThreadSafety;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600680 if (!local_disables.thread_safety) {
681 local_object_dispatch.emplace_back(thread_checker);
682 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600683 thread_checker->container_type = LayerObjectTypeThreading;
684 thread_checker->api_version = api_version;
685#endif
686#if BUILD_PARAMETER_VALIDATION
687 auto parameter_validation = new StatelessValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600688 if (!local_disables.stateless_checks) {
689 local_object_dispatch.emplace_back(parameter_validation);
690 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600691 parameter_validation->container_type = LayerObjectTypeParameterValidation;
692 parameter_validation->api_version = api_version;
693#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700694#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600695 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600696 if (!local_disables.object_tracking) {
697 local_object_dispatch.emplace_back(object_tracker);
698 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600699 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700700 object_tracker->api_version = api_version;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600701#endif
702#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700703 auto core_checks = new CoreChecks;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600704 if (!local_disables.core_checks) {
705 local_object_dispatch.emplace_back(core_checks);
706 }
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700707 core_checks->container_type = LayerObjectTypeCoreValidation;
708 core_checks->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700709#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600710
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600711 // If handle wrapping is disabled via the ValidationFeatures extension, override build flag
712 if (local_disables.handle_wrapping) {
713 wrap_handles = false;
714 }
715
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600716 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600717 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600718 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
719 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600720 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600721 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
722 }
723
724 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600725 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600726
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600727 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600728
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600729 framework->object_dispatch = local_object_dispatch;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700730 framework->container_type = LayerObjectTypeInstance;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600731 framework->disabled = local_disables;
732 framework->enabled = local_enables;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600733
734 framework->instance = *pInstance;
735 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
736 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
737 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700738 framework->api_version = api_version;
739 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
740
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700741 // Parse any pNext chains for validation features and flags
742 const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
743 if (validation_flags_ext) {
744 SetDisabledFlags(framework, validation_flags_ext);
745 }
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700746
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600747 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, OBJECT_LAYER_DESCRIPTION);
748
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700749#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700750 object_tracker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600751 object_tracker->instance_dispatch_table = framework->instance_dispatch_table;
752 object_tracker->enabled = framework->enabled;
753 object_tracker->disabled = framework->disabled;
754#endif
755#if BUILD_THREAD_SAFETY
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700756 thread_checker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600757 thread_checker->instance_dispatch_table = framework->instance_dispatch_table;
758 thread_checker->enabled = framework->enabled;
759 thread_checker->disabled = framework->disabled;
760#endif
761#if BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700762 parameter_validation->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600763 parameter_validation->instance_dispatch_table = framework->instance_dispatch_table;
764 parameter_validation->enabled = framework->enabled;
765 parameter_validation->disabled = framework->disabled;
766#endif
767#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700768 core_checks->report_data = framework->report_data;
769 core_checks->instance_dispatch_table = framework->instance_dispatch_table;
770 core_checks->instance = *pInstance;
771 core_checks->enabled = framework->enabled;
772 core_checks->disabled = framework->disabled;
773 core_checks->instance_state = core_checks;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700774#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600775
776 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700777 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600778 }
779
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700780 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
781
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600782 return result;
783}
784
785VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
786 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600787 auto layer_data = GetLayerDataPtr(key, layer_data_map);
788 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700789 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600790 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
791 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600792 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700793 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600794 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
795 }
796
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600797 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600798
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600799 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700800 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600801 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
802 }
803 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600804 while (layer_data->logging_messenger.size() > 0) {
805 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
806 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
807 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600808 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600809 while (layer_data->logging_callback.size() > 0) {
810 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
811 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
812 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600813 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600814
815 layer_debug_utils_destroy_instance(layer_data->report_data);
816
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700817 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
818 delete *item;
819 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600820 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600821}
822
823VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
824 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600825 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600826
827 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
828
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600829 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
830 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600831 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
832 if (fpCreateDevice == NULL) {
833 return VK_ERROR_INITIALIZATION_FAILED;
834 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600835 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
836
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700837 // Get physical device limits for device
838 VkPhysicalDeviceProperties device_properties = {};
839 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
840
841 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
842 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
843
844 DeviceExtensions device_extensions = {};
845 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
846 for (auto item : instance_interceptor->object_dispatch) {
847 item->device_extensions = device_extensions;
848 }
849
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700850 std::unique_ptr<safe_VkDeviceCreateInfo> modified_create_info(new safe_VkDeviceCreateInfo(pCreateInfo));
851
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700852 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600853 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700854 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700855 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700856 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600857 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600858 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700859 auto lock = intercept->write_lock();
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700860 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, modified_create_info);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600861 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600862
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700863 VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(modified_create_info.get()), pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600864 if (result != VK_SUCCESS) {
865 return result;
866 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600867
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600868 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700869 device_interceptor->container_type = LayerObjectTypeDevice;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700870
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700871 // Save local info in device object
872 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700873 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
874 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700875 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700876
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600877 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700878
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600879 device_interceptor->device = *pDevice;
880 device_interceptor->physical_device = gpu;
881 device_interceptor->instance = instance_interceptor->instance;
882 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600883
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600884 // Note that this defines the order in which the layer validation objects are called
885#if BUILD_THREAD_SAFETY
886 auto thread_safety = new ThreadSafety;
887 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
888 thread_safety->container_type = LayerObjectTypeThreading;
889 thread_safety->physical_device = gpu;
890 thread_safety->instance = instance_interceptor->instance;
891 thread_safety->report_data = device_interceptor->report_data;
892 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
893 thread_safety->api_version = device_interceptor->api_version;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600894 if (!instance_interceptor->disabled.thread_safety) {
895 device_interceptor->object_dispatch.emplace_back(thread_safety);
896 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600897#endif
898#if BUILD_PARAMETER_VALIDATION
899 auto stateless_validation = new StatelessValidation;
900 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
901 stateless_validation->container_type = LayerObjectTypeParameterValidation;
902 stateless_validation->physical_device = gpu;
903 stateless_validation->instance = instance_interceptor->instance;
904 stateless_validation->report_data = device_interceptor->report_data;
905 stateless_validation->device_dispatch_table = device_interceptor->device_dispatch_table;
906 stateless_validation->api_version = device_interceptor->api_version;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600907 if (!instance_interceptor->disabled.stateless_checks) {
908 device_interceptor->object_dispatch.emplace_back(stateless_validation);
909 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600910#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700911#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600912 // Create child layer objects for this key and add to dispatch vector
913 auto object_tracker = new ObjectLifetimes;
914 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
915 object_tracker->container_type = LayerObjectTypeObjectTracker;
916 object_tracker->physical_device = gpu;
917 object_tracker->instance = instance_interceptor->instance;
918 object_tracker->report_data = device_interceptor->report_data;
919 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700920 object_tracker->api_version = device_interceptor->api_version;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600921 if (!instance_interceptor->disabled.object_tracking) {
922 device_interceptor->object_dispatch.emplace_back(object_tracker);
923 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600924#endif
925#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700926 auto core_checks = new CoreChecks;
927 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
928 core_checks->container_type = LayerObjectTypeCoreValidation;
929 core_checks->physical_device = gpu;
930 core_checks->instance = instance_interceptor->instance;
931 core_checks->report_data = device_interceptor->report_data;
932 core_checks->device_dispatch_table = device_interceptor->device_dispatch_table;
933 core_checks->instance_dispatch_table = instance_interceptor->instance_dispatch_table;
934 core_checks->api_version = device_interceptor->api_version;
935 core_checks->instance_extensions = instance_interceptor->instance_extensions;
936 core_checks->device_extensions = device_interceptor->device_extensions;
937 core_checks->instance_state = reinterpret_cast<CoreChecks *>(
938 core_checks->GetValidationObject(instance_interceptor->object_dispatch, LayerObjectTypeCoreValidation));
939 core_checks->device = *pDevice;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600940 if (!instance_interceptor->disabled.core_checks) {
941 device_interceptor->object_dispatch.emplace_back(core_checks);
942 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700943#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600944
945 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700946 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700947 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600948 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600949
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700950 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
951
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600952 return result;
953}
954
955VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
956 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600957 auto layer_data = GetLayerDataPtr(key, layer_data_map);
958 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700959 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600960 intercept->PreCallValidateDestroyDevice(device, pAllocator);
961 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600962 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700963 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600964 intercept->PreCallRecordDestroyDevice(device, pAllocator);
965 }
966 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600967
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600968 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600969
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600970 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700971 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600972 intercept->PostCallRecordDestroyDevice(device, pAllocator);
973 }
974
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700975 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
976 delete *item;
977 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600978 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700979}
980
981
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700982// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700983
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700984VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
985 VkDevice device,
986 VkPipelineCache pipelineCache,
987 uint32_t createInfoCount,
988 const VkGraphicsPipelineCreateInfo* pCreateInfos,
989 const VkAllocationCallbacks* pAllocator,
990 VkPipeline* pPipelines) {
991 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
992 bool skip = false;
993
994#ifdef BUILD_CORE_VALIDATION
995 create_graphics_pipeline_api_state cgpl_state{};
996#else
997 struct create_graphics_pipeline_api_state {
998 const VkGraphicsPipelineCreateInfo* pCreateInfos;
999 } cgpl_state;
1000 cgpl_state.pCreateInfos = pCreateInfos;
1001#endif
1002
1003 for (auto intercept : layer_data->object_dispatch) {
1004 auto lock = intercept->write_lock();
1005 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1006 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1007 }
1008 for (auto intercept : layer_data->object_dispatch) {
1009 auto lock = intercept->write_lock();
1010 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1011 }
1012
1013 VkResult result = DispatchCreateGraphicsPipelines(layer_data, device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
1014
1015 for (auto intercept : layer_data->object_dispatch) {
1016 auto lock = intercept->write_lock();
1017 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
1018 }
1019 return result;
1020}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001021
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001022// This API saves some core_validation pipeline state state on the stack for performance purposes
1023VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
1024 VkDevice device,
1025 VkPipelineCache pipelineCache,
1026 uint32_t createInfoCount,
1027 const VkComputePipelineCreateInfo* pCreateInfos,
1028 const VkAllocationCallbacks* pAllocator,
1029 VkPipeline* pPipelines) {
1030 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1031 bool skip = false;
1032
1033#ifndef BUILD_CORE_VALIDATION
1034 struct PIPELINE_STATE {};
1035#endif
1036
1037 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
1038
1039 for (auto intercept : layer_data->object_dispatch) {
1040 auto lock = intercept->write_lock();
1041 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
1042 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1043 }
1044 for (auto intercept : layer_data->object_dispatch) {
1045 auto lock = intercept->write_lock();
1046 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1047 }
1048 VkResult result = DispatchCreateComputePipelines(layer_data, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1049 for (auto intercept : layer_data->object_dispatch) {
1050 auto lock = intercept->write_lock();
1051 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1052 }
1053 return result;
1054}
1055
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001056VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
1057 VkDevice device,
1058 VkPipelineCache pipelineCache,
1059 uint32_t createInfoCount,
1060 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
1061 const VkAllocationCallbacks* pAllocator,
1062 VkPipeline* pPipelines) {
1063 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1064 bool skip = false;
1065
1066#ifndef BUILD_CORE_VALIDATION
1067 struct PIPELINE_STATE {};
1068#endif
1069
1070 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
1071
1072 for (auto intercept : layer_data->object_dispatch) {
1073 auto lock = intercept->write_lock();
1074 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
1075 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1076 }
1077 for (auto intercept : layer_data->object_dispatch) {
1078 auto lock = intercept->write_lock();
1079 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1080 }
1081 VkResult result = DispatchCreateRayTracingPipelinesNV(layer_data, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1082 for (auto intercept : layer_data->object_dispatch) {
1083 auto lock = intercept->write_lock();
1084 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1085 }
1086 return result;
1087}
1088
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001089// This API needs the ability to modify a down-chain parameter
1090VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
1091 VkDevice device,
1092 const VkPipelineLayoutCreateInfo* pCreateInfo,
1093 const VkAllocationCallbacks* pAllocator,
1094 VkPipelineLayout* pPipelineLayout) {
1095 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1096 bool skip = false;
1097
1098#ifndef BUILD_CORE_VALIDATION
1099 struct create_pipeline_layout_api_state {
1100 VkPipelineLayoutCreateInfo modified_create_info;
1101 };
1102#endif
1103 create_pipeline_layout_api_state cpl_state{};
1104 cpl_state.modified_create_info = *pCreateInfo;
1105
1106 for (auto intercept : layer_data->object_dispatch) {
1107 auto lock = intercept->write_lock();
1108 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1109 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1110 }
1111 for (auto intercept : layer_data->object_dispatch) {
1112 auto lock = intercept->write_lock();
1113 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1114 }
1115 VkResult result = DispatchCreatePipelineLayout(layer_data, device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
1116 for (auto intercept : layer_data->object_dispatch) {
1117 auto lock = intercept->write_lock();
1118 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1119 }
1120 return result;
1121}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001122
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001123// This API needs some local stack data for performance reasons and also may modify a parameter
1124VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1125 VkDevice device,
1126 const VkShaderModuleCreateInfo* pCreateInfo,
1127 const VkAllocationCallbacks* pAllocator,
1128 VkShaderModule* pShaderModule) {
1129 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1130 bool skip = false;
1131
1132#ifndef BUILD_CORE_VALIDATION
1133 struct create_shader_module_api_state {
1134 VkShaderModuleCreateInfo instrumented_create_info;
1135 };
1136#endif
1137 create_shader_module_api_state csm_state{};
1138 csm_state.instrumented_create_info = *pCreateInfo;
1139
1140 for (auto intercept : layer_data->object_dispatch) {
1141 auto lock = intercept->write_lock();
1142 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1143 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1144 }
1145 for (auto intercept : layer_data->object_dispatch) {
1146 auto lock = intercept->write_lock();
1147 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1148 }
1149 VkResult result = DispatchCreateShaderModule(layer_data, device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
1150 for (auto intercept : layer_data->object_dispatch) {
1151 auto lock = intercept->write_lock();
1152 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1153 }
1154 return result;
1155}
1156
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001157VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1158 VkDevice device,
1159 const VkDescriptorSetAllocateInfo* pAllocateInfo,
1160 VkDescriptorSet* pDescriptorSets) {
1161 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1162 bool skip = false;
1163
1164#ifdef BUILD_CORE_VALIDATION
1165 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1166#else
1167 struct ads_state {} ads_state;
1168#endif
1169
1170 for (auto intercept : layer_data->object_dispatch) {
1171 auto lock = intercept->write_lock();
1172 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1173 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1174 }
1175 for (auto intercept : layer_data->object_dispatch) {
1176 auto lock = intercept->write_lock();
1177 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1178 }
1179 VkResult result = DispatchAllocateDescriptorSets(layer_data, device, pAllocateInfo, pDescriptorSets);
1180 for (auto intercept : layer_data->object_dispatch) {
1181 auto lock = intercept->write_lock();
1182 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1183 }
1184 return result;
1185}
1186
1187
1188
1189
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001190
1191// ValidationCache APIs do not dispatch
1192
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001193VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1194 VkDevice device,
1195 const VkValidationCacheCreateInfoEXT* pCreateInfo,
1196 const VkAllocationCallbacks* pAllocator,
1197 VkValidationCacheEXT* pValidationCache) {
1198 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1199 VkResult result = VK_SUCCESS;
1200
1201 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1202 if (validation_data) {
1203 auto lock = validation_data->write_lock();
1204 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1205 }
1206 return result;
1207}
1208
1209VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1210 VkDevice device,
1211 VkValidationCacheEXT validationCache,
1212 const VkAllocationCallbacks* pAllocator) {
1213 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1214
1215 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1216 if (validation_data) {
1217 auto lock = validation_data->write_lock();
1218 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1219 }
1220}
1221
1222VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1223 VkDevice device,
1224 VkValidationCacheEXT dstCache,
1225 uint32_t srcCacheCount,
1226 const VkValidationCacheEXT* pSrcCaches) {
1227 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1228 VkResult result = VK_SUCCESS;
1229
1230 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1231 if (validation_data) {
1232 auto lock = validation_data->write_lock();
1233 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1234 }
1235 return result;
1236}
1237
1238VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1239 VkDevice device,
1240 VkValidationCacheEXT validationCache,
1241 size_t* pDataSize,
1242 void* pData) {
1243 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1244 VkResult result = VK_SUCCESS;
1245
1246 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1247 if (validation_data) {
1248 auto lock = validation_data->write_lock();
1249 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1250 }
1251 return result;
1252
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001253}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001254
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001255 inline_custom_validation_class_definitions = """
1256 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1257 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1258 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1259 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001260
1261 // Allow additional parameter for CreateGraphicsPipelines
1262 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1263 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1264 };
1265 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1266 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1267 };
1268 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1269 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1270 };
1271
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001272 // Allow additional state parameter for CreateComputePipelines
1273 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1274 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1275 };
1276 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1277 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1278 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001279
1280 // Allow additional state parameter for CreateRayTracingPipelinesNV
1281 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1282 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1283 };
1284 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1285 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1286 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001287
1288 // Allow modification of a down-chain parameter for CreatePipelineLayout
1289 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1290 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1291 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001292
1293 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1294 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1295 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1296 };
1297 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1298 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1299 };
1300 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1301 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1302 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001303
1304 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1305 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1306 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1307 };
1308 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1309 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1310 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001311
1312 // Modify a parameter to CreateDevice
1313 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1314 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1315 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001316"""
1317
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001318 inline_custom_source_postamble = """
1319// loader-layer interface v0, just wrappers since there is only a layer
1320
1321VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1322 VkExtensionProperties *pProperties) {
1323 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1324}
1325
1326VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1327 VkLayerProperties *pProperties) {
1328 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1329}
1330
1331VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1332 VkLayerProperties *pProperties) {
1333 // the layer command handles VK_NULL_HANDLE just fine internally
1334 assert(physicalDevice == VK_NULL_HANDLE);
1335 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1336}
1337
1338VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1339 const char *pLayerName, uint32_t *pCount,
1340 VkExtensionProperties *pProperties) {
1341 // the layer command handles VK_NULL_HANDLE just fine internally
1342 assert(physicalDevice == VK_NULL_HANDLE);
1343 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1344}
1345
1346VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1347 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1348}
1349
1350VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1351 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1352}
1353
1354VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
1355 const char *funcName) {
1356 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
1357}
1358
1359VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1360 assert(pVersionStruct != NULL);
1361 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1362
1363 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1364 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1365 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1366 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
1367 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
1368 }
1369
1370 return VK_SUCCESS;
1371}"""
1372
1373
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001374 def __init__(self,
1375 errFile = sys.stderr,
1376 warnFile = sys.stderr,
1377 diagFile = sys.stdout):
1378 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1379 # Internal state - accumulators for different inner block text
1380 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1381 self.intercepts = []
1382 self.layer_factory = '' # String containing base layer factory class definition
1383
1384 # Check if the parameter passed in is a pointer to an array
1385 def paramIsArray(self, param):
1386 return param.attrib.get('len') is not None
1387
1388 # Check if the parameter passed in is a pointer
1389 def paramIsPointer(self, param):
1390 ispointer = False
1391 for elem in param:
1392 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
1393 ispointer = True
1394 return ispointer
1395
1396 # Check if an object is a non-dispatchable handle
1397 def isHandleTypeNonDispatchable(self, handletype):
1398 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1399 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1400 return True
1401 else:
1402 return False
1403
1404 # Check if an object is a dispatchable handle
1405 def isHandleTypeDispatchable(self, handletype):
1406 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1407 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
1408 return True
1409 else:
1410 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001411 #
1412 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001413 def beginFile(self, genOpts):
1414 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001415 # Output Copyright
1416 write(self.inline_copyright_message, file=self.outFile)
1417 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001418 self.header = False
1419 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1420 self.header = True
1421 write('#pragma once', file=self.outFile)
1422 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001423 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001424 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001425 else:
1426 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001427 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001428 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001429 #
1430 def endFile(self):
1431 # Finish C++ namespace and multiple inclusion protection
1432 self.newline()
1433 if not self.header:
1434 # Record intercepted procedures
1435 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
1436 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
1437 write('\n'.join(self.intercepts), file=self.outFile)
1438 write('};\n', file=self.outFile)
1439 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001440 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001441 if self.header:
1442 self.newline()
1443 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001444 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001445 self.layer_factory += '};\n\n'
1446 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001447 write(self.layer_factory, file=self.outFile)
1448 else:
1449 write(self.inline_custom_source_postamble, file=self.outFile)
1450 # Finish processing in superclass
1451 OutputGenerator.endFile(self)
1452
1453 def beginFeature(self, interface, emit):
1454 # Start processing in superclass
1455 OutputGenerator.beginFeature(self, interface, emit)
1456 # Get feature extra protect
1457 self.featureExtraProtect = GetFeatureProtect(interface)
1458 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1459 # feature. They're only printed in endFeature().
1460 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1461
1462 def endFeature(self):
1463 # Actually write the interface to the output file.
1464 if (self.emit):
1465 self.newline()
1466 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1467 # or move it below the 'for section...' loop.
1468 if (self.featureExtraProtect != None):
1469 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1470 for section in self.TYPE_SECTIONS:
1471 contents = self.sections[section]
1472 if contents:
1473 write('\n'.join(contents), file=self.outFile)
1474 self.newline()
1475 if (self.sections['command']):
1476 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1477 self.newline()
1478 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001479 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001480 # Finish processing in superclass
1481 OutputGenerator.endFeature(self)
1482 #
1483 # Append a definition to the specified section
1484 def appendSection(self, section, text):
1485 self.sections[section].append(text)
1486 #
1487 # Type generation
1488 def genType(self, typeinfo, name, alias):
1489 pass
1490 #
1491 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1492 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1493 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1494 # structs etc.)
1495 def genStruct(self, typeinfo, typeName):
1496 OutputGenerator.genStruct(self, typeinfo, typeName)
1497 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1498 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1499 for member in typeinfo.elem.findall('.//member'):
1500 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1501 body += ';\n'
1502 body += '} ' + typeName + ';\n'
1503 self.appendSection('struct', body)
1504 #
1505 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1506 def genGroup(self, groupinfo, groupName, alias):
1507 pass
1508 # Enumerant generation
1509 # <enum> tags may specify their values in several ways, but are usually just integers.
1510 def genEnum(self, enuminfo, name, alias):
1511 pass
1512 #
1513 # Customize Cdecl for layer factory base class
1514 def BaseClassCdecl(self, elem, name):
1515 raw = self.makeCDecls(elem)[1]
1516
1517 # Toss everything before the undecorated name
1518 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1519 prototype = prototype.replace(")", "", 1)
1520 prototype = prototype.replace(";", " {};")
1521
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001522 # Build up pre/post call virtual function declarations
1523 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1524 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1525 pre_call_record = 'virtual void PreCallRecord' + prototype
1526 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001527 resulttype = elem.find('proto/type')
1528 if resulttype.text == 'VkResult':
1529 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001530 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1531 #
1532 # Command generation
1533 def genCmd(self, cmdinfo, name, alias):
1534 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001535 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001536 ]
1537
1538 if name in ignore_functions:
1539 return
1540
1541 if self.header: # In the header declare all intercepts
1542 self.appendSection('command', '')
1543 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1544 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001545 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1546 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001547 if 'ValidationCache' not in name:
1548 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001549 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001550 self.layer_factory += '#endif\n'
1551 return
1552
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001553 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001554 if 'ValidationCache' not in name:
1555 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1556 else:
1557 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1558 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1559 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001560 return
1561 # Record that the function will be intercepted
1562 if (self.featureExtraProtect != None):
1563 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1564 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1565 if (self.featureExtraProtect != None):
1566 self.intercepts += [ '#endif' ]
1567 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1568 #
1569 decls = self.makeCDecls(cmdinfo.elem)
1570 self.appendSection('command', '')
1571 self.appendSection('command', '%s {' % decls[0][:-1])
1572 # Setup common to call wrappers. First parameter is always dispatchable
1573 dispatchable_type = cmdinfo.elem.find('param/type').text
1574 dispatchable_name = cmdinfo.elem.find('param/name').text
1575 # Default to device
1576 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001577 dispatch_table_name = 'VkLayerDispatchTable'
1578 # Set to instance as necessary
1579 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1580 device_or_instance = 'instance'
1581 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001582 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001583 api_function_name = cmdinfo.elem.attrib.get('name')
1584 params = cmdinfo.elem.findall('param/name')
1585 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001586 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001587
1588 # Declare result variable, if any.
1589 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001590 'PFN_vkVoidFunction': 'return nullptr;',
1591 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001592 'VkDeviceAddress': 'return 0;',
1593 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1594 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001595 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001596 }
1597 resulttype = cmdinfo.elem.find('proto/type')
1598 assignresult = ''
1599 if (resulttype.text != 'void'):
1600 assignresult = resulttype.text + ' result = '
1601
1602 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001603 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001604
1605 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001606 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001607 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001608 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1609 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1610 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001611
1612 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001613 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001614 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001615 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001616 self.appendSection('command', ' }')
1617
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001618 # Insert pre-dispatch debug utils function call
1619 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001620 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001621
1622 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001623 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001624
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001625 # Insert post-dispatch debug utils function call
1626 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001627 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001628
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001629 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001630 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001631 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001632 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001633 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001634 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001635 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001636 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001637 # Return result variable, if any.
1638 if (resulttype.text != 'void'):
1639 self.appendSection('command', ' return result;')
1640 self.appendSection('command', '}')
1641 #
1642 # Override makeProtoName to drop the "vk" prefix
1643 def makeProtoName(self, name, tail):
1644 return self.genOpts.apientry + name[2:] + tail