blob: 89c84de747137993735f07f520024710d4e1cdb1 [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"
225#include "vk_validation_error_messages.h"
226#include "vk_extension_helper.h"
227#include "vk_safe_struct.h"
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700228#include "vk_typemap_helper.h"
229
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700230
231extern uint64_t global_unique_id;
232extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
233"""
234
235 inline_custom_header_class_definition = """
236
237// Layer object type identifiers
238enum LayerObjectTypeId {
239 LayerObjectTypeThreading,
240 LayerObjectTypeParameterValidation,
241 LayerObjectTypeObjectTracker,
242 LayerObjectTypeCoreValidation,
243};
244
245struct TEMPLATE_STATE {
246 VkDescriptorUpdateTemplateKHR desc_update_template;
247 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
248
249 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
250 : desc_update_template(update_template), create_info(*pCreateInfo) {}
251};
252
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700253class LAYER_PHYS_DEV_PROPERTIES {
254public:
255 VkPhysicalDeviceProperties properties;
256 std::vector<VkQueueFamilyProperties> queue_family_properties;
257};
258
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700259// CHECK_DISABLED struct is a container for bools that can block validation checks from being performed.
260// The end goal is to have all checks guarded by a bool. The bools are all "false" by default meaning that all checks
261// are enabled. At CreateInstance time, the user can use the VK_EXT_validation_flags extension to pass in enum values
262// of VkValidationCheckEXT that will selectively disable checks.
263// The VK_EXT_validation_features extension can also be used with the VkValidationFeaturesEXT structure to set
264// disables in the CHECK_DISABLED struct and/or enables in the CHECK_ENABLED struct.
265struct CHECK_DISABLED {
266 bool command_buffer_state;
267 bool create_descriptor_set_layout;
268 bool destroy_buffer_view; // Skip validation at DestroyBufferView time
269 bool destroy_image_view; // Skip validation at DestroyImageView time
270 bool destroy_pipeline; // Skip validation at DestroyPipeline time
271 bool destroy_descriptor_pool; // Skip validation at DestroyDescriptorPool time
272 bool destroy_framebuffer; // Skip validation at DestroyFramebuffer time
273 bool destroy_renderpass; // Skip validation at DestroyRenderpass time
274 bool destroy_image; // Skip validation at DestroyImage time
275 bool destroy_sampler; // Skip validation at DestroySampler time
276 bool destroy_command_pool; // Skip validation at DestroyCommandPool time
277 bool destroy_event; // Skip validation at DestroyEvent time
278 bool free_memory; // Skip validation at FreeMemory time
279 bool object_in_use; // Skip all object in_use checking
280 bool idle_descriptor_set; // Skip check to verify that descriptor set is no in-use
281 bool push_constant_range; // Skip push constant range checks
282 bool free_descriptor_sets; // Skip validation prior to vkFreeDescriptorSets()
283 bool allocate_descriptor_sets; // Skip validation prior to vkAllocateDescriptorSets()
284 bool update_descriptor_sets; // Skip validation prior to vkUpdateDescriptorSets()
285 bool wait_for_fences;
286 bool get_fence_state;
287 bool queue_wait_idle;
288 bool device_wait_idle;
289 bool destroy_fence;
290 bool destroy_semaphore;
291 bool destroy_query_pool;
292 bool get_query_pool_results;
293 bool destroy_buffer;
294 bool shader_validation; // Skip validation for shaders
295
296 void SetAll(bool value) { std::fill(&command_buffer_state, &shader_validation + 1, value); }
297};
298
299struct CHECK_ENABLED {
300 bool gpu_validation;
301 bool gpu_validation_reserve_binding_slot;
302
303 void SetAll(bool value) { std::fill(&gpu_validation, &gpu_validation_reserve_binding_slot + 1, value); }
304};
305
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700306// Layer chassis validation object base class definition
307class ValidationObject {
308 public:
309 uint32_t api_version;
310 debug_report_data* report_data = nullptr;
311 std::vector<VkDebugReportCallbackEXT> logging_callback;
312 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
313
314 VkLayerInstanceDispatchTable instance_dispatch_table;
315 VkLayerDispatchTable device_dispatch_table;
316
317 InstanceExtensions instance_extensions;
318 DeviceExtensions device_extensions = {};
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700319 CHECK_DISABLED disabled = {};
320 CHECK_ENABLED enabled = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700321
322 VkInstance instance = VK_NULL_HANDLE;
323 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
324 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700325 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700326
327 std::vector<ValidationObject*> object_dispatch;
328 LayerObjectTypeId container_type;
329
330 // Constructor
331 ValidationObject(){};
332 // Destructor
333 virtual ~ValidationObject() {};
334
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700335 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700336 virtual std::unique_lock<std::mutex> write_lock() {
337 return std::unique_lock<std::mutex>(validation_object_mutex);
338 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700339
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700340 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
341 for (auto validation_object : object_dispatch) {
342 if (validation_object->container_type == object_type) {
343 return validation_object;
344 }
345 }
346 return nullptr;
347 };
348
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700349 std::string layer_name = "CHASSIS";
350
351 // Handle Wrapping Data
352 // Reverse map display handles
353 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
354 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700355 struct SubpassesUsageStates {
356 std::unordered_set<uint32_t> subpasses_using_color_attachment;
357 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
358 };
359 // Uses unwrapped handles
360 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
361 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
362 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
363 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700364 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
365 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700366
367
368 // Unwrap a handle. Must hold lock.
369 template <typename HandleType>
370 HandleType Unwrap(HandleType wrappedHandle) {
371 // TODO: don't use operator[] here.
372 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
373 }
374
375 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
376 template <typename HandleType>
377 HandleType WrapNew(HandleType newlyCreatedHandle) {
378 auto unique_id = global_unique_id++;
379 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
380 return (HandleType)unique_id;
381 }
382
383 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
384 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
385 auto unique_id = global_unique_id++;
386 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
387 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
388 return (VkDisplayKHR)unique_id;
389 }
390
391 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
392 // creating another. Must hold lock.
393 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
394 // See if this display is already known
395 auto it = map_data->display_id_reverse_mapping.find(handle);
396 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
397 // Unknown, so wrap
398 return WrapDisplay(handle, map_data);
399 }
400
401 // Pre/post hook point declarations
402"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600403
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700404 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600405// This file is ***GENERATED***. Do Not Edit.
406// See layer_chassis_generator.py for modifications.
407
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700408/* Copyright (c) 2015-2019 The Khronos Group Inc.
409 * Copyright (c) 2015-2019 Valve Corporation
410 * Copyright (c) 2015-2019 LunarG, Inc.
411 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600412 *
413 * Licensed under the Apache License, Version 2.0 (the "License");
414 * you may not use this file except in compliance with the License.
415 * You may obtain a copy of the License at
416 *
417 * http://www.apache.org/licenses/LICENSE-2.0
418 *
419 * Unless required by applicable law or agreed to in writing, software
420 * distributed under the License is distributed on an "AS IS" BASIS,
421 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
422 * See the License for the specific language governing permissions and
423 * limitations under the License.
424 *
425 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700426 */"""
427
428 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600429
430#include <string.h>
431#include <mutex>
432
433#define VALIDATION_ERROR_MAP_IMPL
434
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600435#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700436#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600437
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600438std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600439
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700440// Global unique object identifier. All increments must be guarded by a lock.
441uint64_t global_unique_id = 1;
442// Map uniqueID to actual object handle
443std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
444
445// TODO: This variable controls handle wrapping -- in the future it should be hooked
446// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
447#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
448bool wrap_handles = true;
449#else
450const bool wrap_handles = false;
451#endif
452
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600453// Include child object (layer) definitions
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700454#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600455#include "object_lifetime_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700456#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700457#elif BUILD_THREAD_SAFETY
Mark Lobodzinski706e52b2018-12-11 13:21:52 -0700458#include "thread_safety.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700459#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
460#elif BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700461#include "stateless_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700462#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
463#elif BUILD_CORE_VALIDATION
464#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
465#else
466#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
467#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600468
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600469namespace vulkan_layer_chassis {
470
471using std::unordered_map;
472
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600473static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700474 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600475};
476
477static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
478
479extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
480
481
482// Manually written functions
483
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700484// Check enabled instance extensions against supported instance extension whitelist
485static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
486 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
487 // Check for recognized instance extensions
488 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
489 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
490 kVUIDUndefined,
491 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
492 "results and/or produce undefined behavior.",
493 pCreateInfo->ppEnabledExtensionNames[i]);
494 }
495 }
496}
497
498// Check enabled device extensions against supported device extension whitelist
499static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
500 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
501 // Check for recognized device extensions
502 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
503 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
504 kVUIDUndefined,
505 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
506 "results and/or produce undefined behavior.",
507 pCreateInfo->ppEnabledExtensionNames[i]);
508 }
509 }
510}
511
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700512// For the given ValidationCheck enum, set all relevant instance disabled flags to true
513void SetDisabledFlags(ValidationObject *instance_data, const VkValidationFlagsEXT *val_flags_struct) {
514 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
515 switch (val_flags_struct->pDisabledValidationChecks[i]) {
516 case VK_VALIDATION_CHECK_SHADERS_EXT:
517 instance_data->disabled.shader_validation = true;
518 break;
519 case VK_VALIDATION_CHECK_ALL_EXT:
520 // Set all disabled flags to true
521 instance_data->disabled.SetAll(true);
522 break;
523 default:
524 break;
525 }
526 }
527}
528
529void SetValidationFeatures(ValidationObject *instance_data, const VkValidationFeaturesEXT *val_features_struct) {
530 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
531 switch (val_features_struct->pDisabledValidationFeatures[i]) {
532 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
533 instance_data->disabled.shader_validation = true;
534 break;
535 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
536 // Set all disabled flags to true
537 instance_data->disabled.SetAll(true);
538 break;
539 default:
540 break;
541 }
542 }
543 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
544 switch (val_features_struct->pEnabledValidationFeatures[i]) {
545 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
546 instance_data->enabled.gpu_validation = true;
547 break;
548 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
549 instance_data->enabled.gpu_validation_reserve_binding_slot = true;
550 break;
551 default:
552 break;
553 }
554 }
555}
556
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600557VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600558 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700559 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700560 return nullptr;
561 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600562 const auto &item = name_to_funcptr_map.find(funcName);
563 if (item != name_to_funcptr_map.end()) {
564 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
565 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600566 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600567 if (!table.GetDeviceProcAddr) return nullptr;
568 return table.GetDeviceProcAddr(device, funcName);
569}
570
571VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600572 const auto &item = name_to_funcptr_map.find(funcName);
573 if (item != name_to_funcptr_map.end()) {
574 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
575 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600576 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
577 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600578 if (!table.GetInstanceProcAddr) return nullptr;
579 return table.GetInstanceProcAddr(instance, funcName);
580}
581
582VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600583 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
584 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600585 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
586 return table.GetPhysicalDeviceProcAddr(instance, funcName);
587}
588
589VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
590 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
591}
592
593VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
594 VkLayerProperties *pProperties) {
595 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
596}
597
598VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
599 VkExtensionProperties *pProperties) {
600 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
601 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
602
603 return VK_ERROR_LAYER_NOT_PRESENT;
604}
605
606VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
607 uint32_t *pCount, VkExtensionProperties *pProperties) {
608 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600609 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600610 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
611 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600612}
613
614VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
615 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600616 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600617
618 assert(chain_info->u.pLayerInfo);
619 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
620 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
621 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
622 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700623 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
624 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
625
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600626
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600627 // Create temporary dispatch vector for pre-calls until instance is created
628 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700629#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600630 auto object_tracker = new ObjectLifetimes;
631 local_object_dispatch.emplace_back(object_tracker);
632 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700633 object_tracker->api_version = api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700634#elif BUILD_THREAD_SAFETY
635 auto thread_checker = new ThreadSafety;
636 local_object_dispatch.emplace_back(thread_checker);
637 thread_checker->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700638 thread_checker->api_version = api_version;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700639#elif BUILD_PARAMETER_VALIDATION
640 auto parameter_validation = new StatelessValidation;
641 local_object_dispatch.emplace_back(parameter_validation);
642 parameter_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700643 parameter_validation->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700644#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600645
646
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600647 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600648 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600649 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
650 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600651 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600652 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
653 }
654
655 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600656 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600657
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600658 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600659
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600660 framework->object_dispatch = local_object_dispatch;
661
662 framework->instance = *pInstance;
663 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
664 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
665 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700666 framework->api_version = api_version;
667 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
668
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700669 // Parse any pNext chains for validation features and flags
670 const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
671 if (validation_flags_ext) {
672 SetDisabledFlags(framework, validation_flags_ext);
673 }
674 const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(pCreateInfo->pNext);
675 if (validation_features_ext) {
676 SetValidationFeatures(framework, validation_features_ext);
677 }
678
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700679#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600680 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_object_tracker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700681 object_tracker->report_data = framework->report_data;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700682#elif BUILD_THREAD_SAFETY
683 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "google_thread_checker");
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700684 thread_checker->report_data = framework->report_data;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700685#elif BUILD_PARAMETER_VALIDATION
686 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_parameter_validation");
687 parameter_validation->report_data = framework->report_data;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700688#else
689 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, "lunarg_unique_objects");
690#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600691
692 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700693 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600694 }
695
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700696 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
697
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600698 return result;
699}
700
701VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
702 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600703 auto layer_data = GetLayerDataPtr(key, layer_data_map);
704 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700705 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600706 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
707 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600708 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700709 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600710 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
711 }
712
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600713 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600714
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600715 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700716 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600717 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
718 }
719 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600720 while (layer_data->logging_messenger.size() > 0) {
721 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
722 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
723 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600724 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600725 while (layer_data->logging_callback.size() > 0) {
726 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
727 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
728 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600729 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600730
731 layer_debug_utils_destroy_instance(layer_data->report_data);
732
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700733 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
734 delete *item;
735 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600736 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600737}
738
739VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
740 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600741 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600742
743 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
744
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600745 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
746 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600747 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
748 if (fpCreateDevice == NULL) {
749 return VK_ERROR_INITIALIZATION_FAILED;
750 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600751 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
752
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700753 // Get physical device limits for device
754 VkPhysicalDeviceProperties device_properties = {};
755 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
756
757 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
758 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
759
760 DeviceExtensions device_extensions = {};
761 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
762 for (auto item : instance_interceptor->object_dispatch) {
763 item->device_extensions = device_extensions;
764 }
765
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700766 std::unique_ptr<safe_VkDeviceCreateInfo> modified_create_info(new safe_VkDeviceCreateInfo(pCreateInfo));
767
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700768 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600769 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700770 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700771 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700772 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600773 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600774 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700775 auto lock = intercept->write_lock();
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700776 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, modified_create_info);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600777 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600778
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700779 VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(modified_create_info.get()), pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600780 if (result != VK_SUCCESS) {
781 return result;
782 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600783
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600784 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700785
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700786 // Save local info in device object
787 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700788 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
789 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700790 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700791
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600792 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700793
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600794 device_interceptor->device = *pDevice;
795 device_interceptor->physical_device = gpu;
796 device_interceptor->instance = instance_interceptor->instance;
797 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600798
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700799#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600800 // Create child layer objects for this key and add to dispatch vector
801 auto object_tracker = new ObjectLifetimes;
802 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
803 object_tracker->container_type = LayerObjectTypeObjectTracker;
804 object_tracker->physical_device = gpu;
805 object_tracker->instance = instance_interceptor->instance;
806 object_tracker->report_data = device_interceptor->report_data;
807 object_tracker->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700808 object_tracker->api_version = device_interceptor->api_version;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600809 device_interceptor->object_dispatch.emplace_back(object_tracker);
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700810#elif BUILD_THREAD_SAFETY
811 auto thread_safety = new ThreadSafety;
812 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
813 thread_safety->container_type = LayerObjectTypeThreading;
814 thread_safety->physical_device = gpu;
815 thread_safety->instance = instance_interceptor->instance;
816 thread_safety->report_data = device_interceptor->report_data;
817 thread_safety->device_dispatch_table = device_interceptor->device_dispatch_table;
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700818 thread_safety->api_version = device_interceptor->api_version;
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700819 device_interceptor->object_dispatch.emplace_back(thread_safety);
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700820#elif BUILD_PARAMETER_VALIDATION
821 auto stateless_validation = new StatelessValidation;
822 // TODO: Initialize child objects with parent info thru constuctor taking a parent object
823 stateless_validation->container_type = LayerObjectTypeParameterValidation;
824 stateless_validation->physical_device = gpu;
825 stateless_validation->instance = instance_interceptor->instance;
826 stateless_validation->report_data = device_interceptor->report_data;
827 stateless_validation->device_dispatch_table = device_interceptor->device_dispatch_table;
828 stateless_validation->api_version = device_interceptor->api_version;
829 device_interceptor->object_dispatch.emplace_back(stateless_validation);
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700830#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600831
832 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700833 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700834 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600835 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600836
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700837 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
838
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600839 return result;
840}
841
842VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
843 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600844 auto layer_data = GetLayerDataPtr(key, layer_data_map);
845 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700846 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600847 intercept->PreCallValidateDestroyDevice(device, pAllocator);
848 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600849 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700850 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600851 intercept->PreCallRecordDestroyDevice(device, pAllocator);
852 }
853 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600854
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600855 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600856
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600857 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700858 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600859 intercept->PostCallRecordDestroyDevice(device, pAllocator);
860 }
861
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700862 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
863 delete *item;
864 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600865 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700866}
867
868
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700869// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700870
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700871VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
872 VkDevice device,
873 VkPipelineCache pipelineCache,
874 uint32_t createInfoCount,
875 const VkGraphicsPipelineCreateInfo* pCreateInfos,
876 const VkAllocationCallbacks* pAllocator,
877 VkPipeline* pPipelines) {
878 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
879 bool skip = false;
880
881#ifdef BUILD_CORE_VALIDATION
882 create_graphics_pipeline_api_state cgpl_state{};
883#else
884 struct create_graphics_pipeline_api_state {
885 const VkGraphicsPipelineCreateInfo* pCreateInfos;
886 } cgpl_state;
887 cgpl_state.pCreateInfos = pCreateInfos;
888#endif
889
890 for (auto intercept : layer_data->object_dispatch) {
891 auto lock = intercept->write_lock();
892 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
893 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
894 }
895 for (auto intercept : layer_data->object_dispatch) {
896 auto lock = intercept->write_lock();
897 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
898 }
899
900 VkResult result = DispatchCreateGraphicsPipelines(layer_data, device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
901
902 for (auto intercept : layer_data->object_dispatch) {
903 auto lock = intercept->write_lock();
904 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
905 }
906 return result;
907}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700908
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700909// This API saves some core_validation pipeline state state on the stack for performance purposes
910VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
911 VkDevice device,
912 VkPipelineCache pipelineCache,
913 uint32_t createInfoCount,
914 const VkComputePipelineCreateInfo* pCreateInfos,
915 const VkAllocationCallbacks* pAllocator,
916 VkPipeline* pPipelines) {
917 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
918 bool skip = false;
919
920#ifndef BUILD_CORE_VALIDATION
921 struct PIPELINE_STATE {};
922#endif
923
924 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
925
926 for (auto intercept : layer_data->object_dispatch) {
927 auto lock = intercept->write_lock();
928 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
929 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
930 }
931 for (auto intercept : layer_data->object_dispatch) {
932 auto lock = intercept->write_lock();
933 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
934 }
935 VkResult result = DispatchCreateComputePipelines(layer_data, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
936 for (auto intercept : layer_data->object_dispatch) {
937 auto lock = intercept->write_lock();
938 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
939 }
940 return result;
941}
942
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700943VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
944 VkDevice device,
945 VkPipelineCache pipelineCache,
946 uint32_t createInfoCount,
947 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
948 const VkAllocationCallbacks* pAllocator,
949 VkPipeline* pPipelines) {
950 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
951 bool skip = false;
952
953#ifndef BUILD_CORE_VALIDATION
954 struct PIPELINE_STATE {};
955#endif
956
957 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
958
959 for (auto intercept : layer_data->object_dispatch) {
960 auto lock = intercept->write_lock();
961 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
962 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
963 }
964 for (auto intercept : layer_data->object_dispatch) {
965 auto lock = intercept->write_lock();
966 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
967 }
968 VkResult result = DispatchCreateRayTracingPipelinesNV(layer_data, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
969 for (auto intercept : layer_data->object_dispatch) {
970 auto lock = intercept->write_lock();
971 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
972 }
973 return result;
974}
975
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -0700976// This API needs the ability to modify a down-chain parameter
977VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
978 VkDevice device,
979 const VkPipelineLayoutCreateInfo* pCreateInfo,
980 const VkAllocationCallbacks* pAllocator,
981 VkPipelineLayout* pPipelineLayout) {
982 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
983 bool skip = false;
984
985#ifndef BUILD_CORE_VALIDATION
986 struct create_pipeline_layout_api_state {
987 VkPipelineLayoutCreateInfo modified_create_info;
988 };
989#endif
990 create_pipeline_layout_api_state cpl_state{};
991 cpl_state.modified_create_info = *pCreateInfo;
992
993 for (auto intercept : layer_data->object_dispatch) {
994 auto lock = intercept->write_lock();
995 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
996 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
997 }
998 for (auto intercept : layer_data->object_dispatch) {
999 auto lock = intercept->write_lock();
1000 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1001 }
1002 VkResult result = DispatchCreatePipelineLayout(layer_data, device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
1003 for (auto intercept : layer_data->object_dispatch) {
1004 auto lock = intercept->write_lock();
1005 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1006 }
1007 return result;
1008}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001009
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001010// This API needs some local stack data for performance reasons and also may modify a parameter
1011VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1012 VkDevice device,
1013 const VkShaderModuleCreateInfo* pCreateInfo,
1014 const VkAllocationCallbacks* pAllocator,
1015 VkShaderModule* pShaderModule) {
1016 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1017 bool skip = false;
1018
1019#ifndef BUILD_CORE_VALIDATION
1020 struct create_shader_module_api_state {
1021 VkShaderModuleCreateInfo instrumented_create_info;
1022 };
1023#endif
1024 create_shader_module_api_state csm_state{};
1025 csm_state.instrumented_create_info = *pCreateInfo;
1026
1027 for (auto intercept : layer_data->object_dispatch) {
1028 auto lock = intercept->write_lock();
1029 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1030 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1031 }
1032 for (auto intercept : layer_data->object_dispatch) {
1033 auto lock = intercept->write_lock();
1034 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1035 }
1036 VkResult result = DispatchCreateShaderModule(layer_data, device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
1037 for (auto intercept : layer_data->object_dispatch) {
1038 auto lock = intercept->write_lock();
1039 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1040 }
1041 return result;
1042}
1043
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001044VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1045 VkDevice device,
1046 const VkDescriptorSetAllocateInfo* pAllocateInfo,
1047 VkDescriptorSet* pDescriptorSets) {
1048 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1049 bool skip = false;
1050
1051#ifdef BUILD_CORE_VALIDATION
1052 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1053#else
1054 struct ads_state {} ads_state;
1055#endif
1056
1057 for (auto intercept : layer_data->object_dispatch) {
1058 auto lock = intercept->write_lock();
1059 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1060 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1061 }
1062 for (auto intercept : layer_data->object_dispatch) {
1063 auto lock = intercept->write_lock();
1064 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1065 }
1066 VkResult result = DispatchAllocateDescriptorSets(layer_data, device, pAllocateInfo, pDescriptorSets);
1067 for (auto intercept : layer_data->object_dispatch) {
1068 auto lock = intercept->write_lock();
1069 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1070 }
1071 return result;
1072}
1073
1074
1075
1076
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001077
1078// ValidationCache APIs do not dispatch
1079
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001080VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1081 VkDevice device,
1082 const VkValidationCacheCreateInfoEXT* pCreateInfo,
1083 const VkAllocationCallbacks* pAllocator,
1084 VkValidationCacheEXT* pValidationCache) {
1085 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1086 VkResult result = VK_SUCCESS;
1087
1088 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1089 if (validation_data) {
1090 auto lock = validation_data->write_lock();
1091 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1092 }
1093 return result;
1094}
1095
1096VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1097 VkDevice device,
1098 VkValidationCacheEXT validationCache,
1099 const VkAllocationCallbacks* pAllocator) {
1100 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1101
1102 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1103 if (validation_data) {
1104 auto lock = validation_data->write_lock();
1105 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1106 }
1107}
1108
1109VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1110 VkDevice device,
1111 VkValidationCacheEXT dstCache,
1112 uint32_t srcCacheCount,
1113 const VkValidationCacheEXT* pSrcCaches) {
1114 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1115 VkResult result = VK_SUCCESS;
1116
1117 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1118 if (validation_data) {
1119 auto lock = validation_data->write_lock();
1120 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1121 }
1122 return result;
1123}
1124
1125VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1126 VkDevice device,
1127 VkValidationCacheEXT validationCache,
1128 size_t* pDataSize,
1129 void* pData) {
1130 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1131 VkResult result = VK_SUCCESS;
1132
1133 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1134 if (validation_data) {
1135 auto lock = validation_data->write_lock();
1136 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1137 }
1138 return result;
1139
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001140}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001141
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001142 inline_custom_validation_class_definitions = """
1143 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1144 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1145 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1146 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001147
1148 // Allow additional parameter for CreateGraphicsPipelines
1149 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1150 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1151 };
1152 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1153 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1154 };
1155 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1156 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1157 };
1158
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001159 // Allow additional state parameter for CreateComputePipelines
1160 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1161 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1162 };
1163 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1164 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1165 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001166
1167 // Allow additional state parameter for CreateRayTracingPipelinesNV
1168 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1169 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1170 };
1171 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1172 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1173 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001174
1175 // Allow modification of a down-chain parameter for CreatePipelineLayout
1176 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1177 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1178 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001179
1180 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1181 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1182 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1183 };
1184 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1185 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1186 };
1187 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1188 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1189 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001190
1191 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1192 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1193 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1194 };
1195 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1196 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1197 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001198
1199 // Modify a parameter to CreateDevice
1200 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1201 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1202 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001203"""
1204
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001205 inline_custom_source_postamble = """
1206// loader-layer interface v0, just wrappers since there is only a layer
1207
1208VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1209 VkExtensionProperties *pProperties) {
1210 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1211}
1212
1213VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1214 VkLayerProperties *pProperties) {
1215 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1216}
1217
1218VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1219 VkLayerProperties *pProperties) {
1220 // the layer command handles VK_NULL_HANDLE just fine internally
1221 assert(physicalDevice == VK_NULL_HANDLE);
1222 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1223}
1224
1225VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1226 const char *pLayerName, uint32_t *pCount,
1227 VkExtensionProperties *pProperties) {
1228 // the layer command handles VK_NULL_HANDLE just fine internally
1229 assert(physicalDevice == VK_NULL_HANDLE);
1230 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1231}
1232
1233VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1234 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1235}
1236
1237VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1238 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1239}
1240
1241VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
1242 const char *funcName) {
1243 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
1244}
1245
1246VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1247 assert(pVersionStruct != NULL);
1248 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1249
1250 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1251 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1252 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1253 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
1254 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
1255 }
1256
1257 return VK_SUCCESS;
1258}"""
1259
1260
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001261 def __init__(self,
1262 errFile = sys.stderr,
1263 warnFile = sys.stderr,
1264 diagFile = sys.stdout):
1265 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1266 # Internal state - accumulators for different inner block text
1267 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1268 self.intercepts = []
1269 self.layer_factory = '' # String containing base layer factory class definition
1270
1271 # Check if the parameter passed in is a pointer to an array
1272 def paramIsArray(self, param):
1273 return param.attrib.get('len') is not None
1274
1275 # Check if the parameter passed in is a pointer
1276 def paramIsPointer(self, param):
1277 ispointer = False
1278 for elem in param:
1279 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
1280 ispointer = True
1281 return ispointer
1282
1283 # Check if an object is a non-dispatchable handle
1284 def isHandleTypeNonDispatchable(self, handletype):
1285 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1286 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1287 return True
1288 else:
1289 return False
1290
1291 # Check if an object is a dispatchable handle
1292 def isHandleTypeDispatchable(self, handletype):
1293 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1294 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
1295 return True
1296 else:
1297 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001298 #
1299 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001300 def beginFile(self, genOpts):
1301 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001302 # Output Copyright
1303 write(self.inline_copyright_message, file=self.outFile)
1304 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001305 self.header = False
1306 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1307 self.header = True
1308 write('#pragma once', file=self.outFile)
1309 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001310 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001311 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001312 else:
1313 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001314 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001315 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001316 #
1317 def endFile(self):
1318 # Finish C++ namespace and multiple inclusion protection
1319 self.newline()
1320 if not self.header:
1321 # Record intercepted procedures
1322 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
1323 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
1324 write('\n'.join(self.intercepts), file=self.outFile)
1325 write('};\n', file=self.outFile)
1326 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001327 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001328 if self.header:
1329 self.newline()
1330 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001331 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001332 self.layer_factory += '};\n\n'
1333 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001334 write(self.layer_factory, file=self.outFile)
1335 else:
1336 write(self.inline_custom_source_postamble, file=self.outFile)
1337 # Finish processing in superclass
1338 OutputGenerator.endFile(self)
1339
1340 def beginFeature(self, interface, emit):
1341 # Start processing in superclass
1342 OutputGenerator.beginFeature(self, interface, emit)
1343 # Get feature extra protect
1344 self.featureExtraProtect = GetFeatureProtect(interface)
1345 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1346 # feature. They're only printed in endFeature().
1347 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1348
1349 def endFeature(self):
1350 # Actually write the interface to the output file.
1351 if (self.emit):
1352 self.newline()
1353 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1354 # or move it below the 'for section...' loop.
1355 if (self.featureExtraProtect != None):
1356 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1357 for section in self.TYPE_SECTIONS:
1358 contents = self.sections[section]
1359 if contents:
1360 write('\n'.join(contents), file=self.outFile)
1361 self.newline()
1362 if (self.sections['command']):
1363 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1364 self.newline()
1365 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001366 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001367 # Finish processing in superclass
1368 OutputGenerator.endFeature(self)
1369 #
1370 # Append a definition to the specified section
1371 def appendSection(self, section, text):
1372 self.sections[section].append(text)
1373 #
1374 # Type generation
1375 def genType(self, typeinfo, name, alias):
1376 pass
1377 #
1378 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1379 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1380 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1381 # structs etc.)
1382 def genStruct(self, typeinfo, typeName):
1383 OutputGenerator.genStruct(self, typeinfo, typeName)
1384 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1385 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1386 for member in typeinfo.elem.findall('.//member'):
1387 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1388 body += ';\n'
1389 body += '} ' + typeName + ';\n'
1390 self.appendSection('struct', body)
1391 #
1392 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1393 def genGroup(self, groupinfo, groupName, alias):
1394 pass
1395 # Enumerant generation
1396 # <enum> tags may specify their values in several ways, but are usually just integers.
1397 def genEnum(self, enuminfo, name, alias):
1398 pass
1399 #
1400 # Customize Cdecl for layer factory base class
1401 def BaseClassCdecl(self, elem, name):
1402 raw = self.makeCDecls(elem)[1]
1403
1404 # Toss everything before the undecorated name
1405 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1406 prototype = prototype.replace(")", "", 1)
1407 prototype = prototype.replace(";", " {};")
1408
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001409 # Build up pre/post call virtual function declarations
1410 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1411 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1412 pre_call_record = 'virtual void PreCallRecord' + prototype
1413 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001414 resulttype = elem.find('proto/type')
1415 if resulttype.text == 'VkResult':
1416 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001417 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1418 #
1419 # Command generation
1420 def genCmd(self, cmdinfo, name, alias):
1421 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001422 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001423 ]
1424
1425 if name in ignore_functions:
1426 return
1427
1428 if self.header: # In the header declare all intercepts
1429 self.appendSection('command', '')
1430 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1431 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001432 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1433 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001434 if 'ValidationCache' not in name:
1435 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001436 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001437 self.layer_factory += '#endif\n'
1438 return
1439
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001440 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001441 if 'ValidationCache' not in name:
1442 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1443 else:
1444 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1445 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1446 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001447 return
1448 # Record that the function will be intercepted
1449 if (self.featureExtraProtect != None):
1450 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1451 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1452 if (self.featureExtraProtect != None):
1453 self.intercepts += [ '#endif' ]
1454 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1455 #
1456 decls = self.makeCDecls(cmdinfo.elem)
1457 self.appendSection('command', '')
1458 self.appendSection('command', '%s {' % decls[0][:-1])
1459 # Setup common to call wrappers. First parameter is always dispatchable
1460 dispatchable_type = cmdinfo.elem.find('param/type').text
1461 dispatchable_name = cmdinfo.elem.find('param/name').text
1462 # Default to device
1463 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001464 dispatch_table_name = 'VkLayerDispatchTable'
1465 # Set to instance as necessary
1466 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1467 device_or_instance = 'instance'
1468 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001469 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001470 api_function_name = cmdinfo.elem.attrib.get('name')
1471 params = cmdinfo.elem.findall('param/name')
1472 paramstext = ', '.join([str(param.text) for param in params])
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001473 API = api_function_name.replace('vk','Dispatch') + '(layer_data, '
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001474
1475 # Declare result variable, if any.
1476 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001477 'PFN_vkVoidFunction': 'return nullptr;',
1478 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001479 'VkDeviceAddress': 'return 0;',
1480 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1481 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001482 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001483 }
1484 resulttype = cmdinfo.elem.find('proto/type')
1485 assignresult = ''
1486 if (resulttype.text != 'void'):
1487 assignresult = resulttype.text + ' result = '
1488
1489 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001490 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001491
1492 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001493 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001494 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001495 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1496 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1497 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001498
1499 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001500 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001501 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001502 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001503 self.appendSection('command', ' }')
1504
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001505 # Insert pre-dispatch debug utils function call
1506 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001507 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001508
1509 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001510 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001511
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001512 # Insert post-dispatch debug utils function call
1513 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001514 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001515
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001516 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001517 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001518 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001519 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001520 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001521 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001522 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001523 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001524 # Return result variable, if any.
1525 if (resulttype.text != 'void'):
1526 self.appendSection('command', ' return result;')
1527 self.appendSection('command', '}')
1528 #
1529 # Override makeProtoName to drop the "vk" prefix
1530 def makeProtoName(self, name, tail):
1531 return self.genOpts.apientry + name[2:] + tail