blob: e901a3f2fd7c3cbcb836fba04c7a030c691c0f2e [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07003# Copyright (c) 2015-2019 Valve Corporation
4# Copyright (c) 2015-2019 LunarG, Inc.
5# Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06006#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
20# Author: Mark Lobodzinski <mark@lunarg.com>
21#
22# This script generates the dispatch portion of a factory layer which intercepts
23# all Vulkan functions. The resultant factory layer allows rapid development of
24# layers and interceptors.
25
26import os,re,sys
27from generator import *
28from common_codegen import *
29
30# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31#
32# Adds options used by LayerFactoryOutputGenerator objects during factory
33# layer generation.
34#
35# Additional members
36# prefixText - list of strings to prefix generated header with
37# (usually a copyright statement + calling convention macros).
38# protectFile - True if multiple inclusion protection should be
39# generated (based on the filename) around the entire header.
40# protectFeature - True if #ifndef..#endif protection should be
41# generated around a feature interface in the header file.
42# genFuncPointers - True if function pointer typedefs should be
43# generated
44# protectProto - If conditional protection should be generated
45# around prototype declarations, set to either '#ifdef'
46# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47# to require opt-out (#ifndef protectProtoStr). Otherwise
48# set to None.
49# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50# declarations, if protectProto is set
51# apicall - string to use for the function declaration prefix,
52# such as APICALL on Windows.
53# apientry - string to use for the calling convention macro,
54# in typedefs, such as APIENTRY.
55# apientryp - string to use for the calling convention macro
56# in function pointer typedefs, such as APIENTRYP.
57# indentFuncProto - True if prototype declarations should put each
58# parameter on a separate line
59# indentFuncPointer - True if typedefed function pointers should put each
60# parameter on a separate line
61# alignFuncParam - if nonzero and parameters are being put on a
62# separate line, align parameter names at the specified column
63class LayerChassisGeneratorOptions(GeneratorOptions):
64 def __init__(self,
Mike Schuchardt21638df2019-03-16 10:52:02 -070065 conventions = None,
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -060066 filename = None,
67 directory = '.',
68 apiname = None,
69 profile = None,
70 versions = '.*',
71 emitversions = '.*',
72 defaultExtensions = None,
73 addExtensions = None,
74 removeExtensions = None,
75 emitExtensions = None,
76 sortProcedure = regSortFeatures,
77 prefixText = "",
78 genFuncPointers = True,
79 protectFile = True,
80 protectFeature = True,
81 apicall = '',
82 apientry = '',
83 apientryp = '',
84 indentFuncProto = True,
85 indentFuncPointer = False,
86 alignFuncParam = 0,
87 helper_file_type = '',
88 expandEnumerants = True):
Mike Schuchardt21638df2019-03-16 10:52:02 -070089 GeneratorOptions.__init__(self, conventions, filename, directory, apiname, profile,
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -060090 versions, emitversions, defaultExtensions,
91 addExtensions, removeExtensions, emitExtensions, sortProcedure)
92 self.prefixText = prefixText
93 self.genFuncPointers = genFuncPointers
94 self.protectFile = protectFile
95 self.protectFeature = protectFeature
96 self.apicall = apicall
97 self.apientry = apientry
98 self.apientryp = apientryp
99 self.indentFuncProto = indentFuncProto
100 self.indentFuncPointer = indentFuncPointer
101 self.alignFuncParam = alignFuncParam
102
103# LayerChassisOutputGenerator - subclass of OutputGenerator.
104# Generates a LayerFactory layer that intercepts all API entrypoints
105# This is intended to be used as a starting point for creating custom layers
106#
107# ---- methods ----
108# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
109# OutputGenerator. Defines additional internal state.
110# ---- methods overriding base class ----
111# beginFile(genOpts)
112# endFile()
113# beginFeature(interface, emit)
114# endFeature()
115# genType(typeinfo,name)
116# genStruct(typeinfo,name)
117# genGroup(groupinfo,name)
118# genEnum(enuminfo, name)
119# genCmd(cmdinfo)
120class LayerChassisOutputGenerator(OutputGenerator):
121 """Generate specified API interfaces in a specific style, such as a C header"""
122 # This is an ordered list of sections in the header file.
123 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
124 'group', 'bitmask', 'funcpointer', 'struct']
125 ALL_SECTIONS = TYPE_SECTIONS + ['command']
126
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700127 manual_functions = [
128 # Include functions here to be interecpted w/ manually implemented function bodies
129 'vkGetDeviceProcAddr',
130 'vkGetInstanceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700131 'vkCreateDevice',
132 'vkDestroyDevice',
133 'vkCreateInstance',
134 'vkDestroyInstance',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700135 'vkEnumerateInstanceLayerProperties',
136 'vkEnumerateInstanceExtensionProperties',
137 'vkEnumerateDeviceLayerProperties',
138 'vkEnumerateDeviceExtensionProperties',
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -0700139 # Functions that are handled explicitly due to chassis architecture violations
140 'vkCreateGraphicsPipelines',
Mark Lobodzinski768a84e2019-03-01 08:46:03 -0700141 'vkCreateComputePipelines',
Mark Lobodzinski082cafd2019-03-01 08:56:52 -0700142 'vkCreateRayTracingPipelinesNV',
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -0700143 'vkCreatePipelineLayout',
Mark Lobodzinski1db77e82019-03-01 10:02:54 -0700144 'vkCreateShaderModule',
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -0700145 'vkAllocateDescriptorSets',
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -0700146 # ValidationCache functions do not get dispatched
147 'vkCreateValidationCacheEXT',
148 'vkDestroyValidationCacheEXT',
149 'vkMergeValidationCachesEXT',
150 'vkGetValidationCacheDataEXT',
Mark Lobodzinski56e88122019-03-26 10:21:48 -0600151 # We don't wanna hook this function
152 'vkGetPhysicalDeviceProcAddr',
Mark Lobodzinski09f86362018-12-13 14:07:20 -0700153 ]
154
155 alt_ret_codes = [
156 # Include functions here which must tolerate VK_INCOMPLETE as a return code
157 'vkEnumeratePhysicalDevices',
158 'vkEnumeratePhysicalDeviceGroupsKHR',
159 'vkGetValidationCacheDataEXT',
160 'vkGetPipelineCacheData',
161 'vkGetShaderInfoAMD',
162 'vkGetPhysicalDeviceDisplayPropertiesKHR',
163 'vkGetPhysicalDeviceDisplayProperties2KHR',
164 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
165 'vkGetDisplayPlaneSupportedDisplaysKHR',
166 'vkGetDisplayModePropertiesKHR',
167 'vkGetDisplayModeProperties2KHR',
168 'vkGetPhysicalDeviceSurfaceFormatsKHR',
169 'vkGetPhysicalDeviceSurfacePresentModesKHR',
170 'vkGetPhysicalDevicePresentRectanglesKHR',
171 'vkGetPastPresentationTimingGOOGLE',
172 'vkGetSwapchainImagesKHR',
173 'vkEnumerateInstanceLayerProperties',
174 'vkEnumerateDeviceLayerProperties',
175 'vkEnumerateInstanceExtensionProperties',
176 'vkEnumerateDeviceExtensionProperties',
177 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT',
178 ]
179
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700180 pre_dispatch_debug_utils_functions = {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700181 'vkDebugMarkerSetObjectNameEXT' : 'layer_data->report_data->DebugReportSetMarkerObjectName(pNameInfo);',
182 'vkSetDebugUtilsObjectNameEXT' : 'layer_data->report_data->DebugReportSetUtilsObjectName(pNameInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700183 'vkQueueBeginDebugUtilsLabelEXT' : 'BeginQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
184 'vkQueueInsertDebugUtilsLabelEXT' : 'InsertQueueDebugUtilsLabel(layer_data->report_data, queue, pLabelInfo);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700185 }
186
187 post_dispatch_debug_utils_functions = {
188 'vkQueueEndDebugUtilsLabelEXT' : 'EndQueueDebugUtilsLabel(layer_data->report_data, queue);',
Mark Lobodzinski201e12c2019-02-19 14:55:30 -0700189 'vkCreateDebugReportCallbackEXT' : 'layer_create_report_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pCallback);',
190 'vkDestroyDebugReportCallbackEXT' : 'layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);',
191 'vkCreateDebugUtilsMessengerEXT' : 'layer_create_messenger_callback(layer_data->report_data, false, pCreateInfo, pAllocator, pMessenger);',
192 'vkDestroyDebugUtilsMessengerEXT' : 'layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);',
Mark Lobodzinskif57e8282018-12-13 11:34:33 -0700193 }
194
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600195 precallvalidate_loop = "for (auto intercept : layer_data->object_dispatch) {"
196 precallrecord_loop = precallvalidate_loop
197 postcallrecord_loop = "for (auto intercept : layer_data->object_dispatch) {"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600198
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700199 inline_custom_header_preamble = """
200#define NOMINMAX
201#include <mutex>
202#include <cinttypes>
203#include <stdio.h>
204#include <stdlib.h>
205#include <string.h>
206#include <unordered_map>
207#include <unordered_set>
208#include <algorithm>
209#include <memory>
210
211#include "vk_loader_platform.h"
212#include "vulkan/vulkan.h"
213#include "vk_layer_config.h"
214#include "vk_layer_data.h"
215#include "vk_layer_logging.h"
216#include "vk_object_types.h"
217#include "vulkan/vk_layer.h"
218#include "vk_enum_string_helper.h"
219#include "vk_layer_extension_utils.h"
220#include "vk_layer_utils.h"
221#include "vulkan/vk_layer.h"
222#include "vk_dispatch_table_helper.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700223#include "vk_extension_helper.h"
224#include "vk_safe_struct.h"
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700225#include "vk_typemap_helper.h"
226
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700227
228extern uint64_t global_unique_id;
229extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
230"""
231
232 inline_custom_header_class_definition = """
233
234// Layer object type identifiers
235enum LayerObjectTypeId {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700236 LayerObjectTypeInstance, // Container for an instance dispatch object
237 LayerObjectTypeDevice, // Container for a device dispatch object
238 LayerObjectTypeThreading, // Instance or device threading layer object
239 LayerObjectTypeParameterValidation, // Instance or device parameter validation layer object
240 LayerObjectTypeObjectTracker, // Instance or device object tracker layer object
241 LayerObjectTypeCoreValidation, // Instance or device core validation layer object
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700242};
243
244struct TEMPLATE_STATE {
245 VkDescriptorUpdateTemplateKHR desc_update_template;
246 safe_VkDescriptorUpdateTemplateCreateInfo create_info;
247
248 TEMPLATE_STATE(VkDescriptorUpdateTemplateKHR update_template, safe_VkDescriptorUpdateTemplateCreateInfo *pCreateInfo)
249 : desc_update_template(update_template), create_info(*pCreateInfo) {}
250};
251
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700252class LAYER_PHYS_DEV_PROPERTIES {
253public:
254 VkPhysicalDeviceProperties properties;
255 std::vector<VkQueueFamilyProperties> queue_family_properties;
256};
257
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600258typedef enum ValidationCheckDisables {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600259 VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600260 VALIDATION_CHECK_DISABLE_OBJECT_IN_USE,
261 VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET,
262 VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE,
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600263 VALIDATION_CHECK_DISABLE_QUERY_VALIDATION,
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600264} ValidationCheckDisables;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600265
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600266
267// CHECK_DISABLED struct is a container for bools that can block validation checks from being performed.
268// These bools are all "false" by default meaning that all checks are enabled. Enum values can be specified
269// via the vk_layer_setting.txt config file or at CreateInstance time via the VK_EXT_validation_features extension
270// that can selectively disable checks.
271struct CHECK_DISABLED {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600272 bool command_buffer_state; // Skip command buffer state validation
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600273 bool object_in_use; // Skip all object in_use checking
274 bool idle_descriptor_set; // Skip check to verify that descriptor set is not in-use
275 bool push_constant_range; // Skip push constant range checks
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600276 bool query_validation; // Disable all core validation query-related checks
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600277 bool object_tracking; // Disable object lifetime validation
278 bool core_checks; // Disable core validation checks
279 bool thread_safety; // Disable thread safety validation
280 bool stateless_checks; // Disable stateless validation checks
281 bool handle_wrapping; // Disable unique handles/handle wrapping
282 bool shader_validation; // Skip validation for shaders
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700283
284 void SetAll(bool value) { std::fill(&command_buffer_state, &shader_validation + 1, value); }
285};
286
287struct CHECK_ENABLED {
288 bool gpu_validation;
289 bool gpu_validation_reserve_binding_slot;
290
291 void SetAll(bool value) { std::fill(&gpu_validation, &gpu_validation_reserve_binding_slot + 1, value); }
292};
293
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700294// Layer chassis validation object base class definition
295class ValidationObject {
296 public:
297 uint32_t api_version;
298 debug_report_data* report_data = nullptr;
299 std::vector<VkDebugReportCallbackEXT> logging_callback;
300 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
301
302 VkLayerInstanceDispatchTable instance_dispatch_table;
303 VkLayerDispatchTable device_dispatch_table;
304
305 InstanceExtensions instance_extensions;
306 DeviceExtensions device_extensions = {};
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700307 CHECK_DISABLED disabled = {};
308 CHECK_ENABLED enabled = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700309
310 VkInstance instance = VK_NULL_HANDLE;
311 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
312 VkDevice device = VK_NULL_HANDLE;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700313 LAYER_PHYS_DEV_PROPERTIES phys_dev_properties = {};
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700314
315 std::vector<ValidationObject*> object_dispatch;
316 LayerObjectTypeId container_type;
317
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700318 std::string layer_name = "CHASSIS";
319
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700320 // Constructor
321 ValidationObject(){};
322 // Destructor
323 virtual ~ValidationObject() {};
324
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700325 std::mutex validation_object_mutex;
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700326 virtual std::unique_lock<std::mutex> write_lock() {
327 return std::unique_lock<std::mutex>(validation_object_mutex);
328 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700329
Mark Lobodzinski64b39c12018-12-25 10:01:48 -0700330 ValidationObject* GetValidationObject(std::vector<ValidationObject*>& object_dispatch, LayerObjectTypeId object_type) {
331 for (auto validation_object : object_dispatch) {
332 if (validation_object->container_type == object_type) {
333 return validation_object;
334 }
335 }
336 return nullptr;
337 };
338
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700339 // Handle Wrapping Data
340 // Reverse map display handles
341 std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping;
Mark Lobodzinskidd28ee22019-06-04 14:20:56 -0600342 // Wrapping Descriptor Template Update structures requires access to the template createinfo structs
343 std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_createinfo_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700344 struct SubpassesUsageStates {
345 std::unordered_set<uint32_t> subpasses_using_color_attachment;
346 std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
347 };
348 // Uses unwrapped handles
349 std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
350 // Map of wrapped swapchain handles to arrays of wrapped swapchain image IDs
351 // Each swapchain has an immutable list of wrapped swapchain image IDs -- always return these IDs if they exist
352 std::unordered_map<VkSwapchainKHR, std::vector<VkImage>> swapchain_wrapped_image_handle_map;
Mike Schuchardt1df790d2018-12-11 16:24:47 -0700353 // Map of wrapped descriptor pools to set of wrapped descriptor sets allocated from each pool
354 std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700355
356
357 // Unwrap a handle. Must hold lock.
358 template <typename HandleType>
359 HandleType Unwrap(HandleType wrappedHandle) {
360 // TODO: don't use operator[] here.
361 return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)];
362 }
363
364 // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock.
365 template <typename HandleType>
366 HandleType WrapNew(HandleType newlyCreatedHandle) {
367 auto unique_id = global_unique_id++;
368 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
369 return (HandleType)unique_id;
370 }
371
372 // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock.
373 VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) {
374 auto unique_id = global_unique_id++;
375 unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle);
376 map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id;
377 return (VkDisplayKHR)unique_id;
378 }
379
380 // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before
381 // creating another. Must hold lock.
382 VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) {
383 // See if this display is already known
384 auto it = map_data->display_id_reverse_mapping.find(handle);
385 if (it != map_data->display_id_reverse_mapping.end()) return (VkDisplayKHR)it->second;
386 // Unknown, so wrap
387 return WrapDisplay(handle, map_data);
388 }
389
390 // Pre/post hook point declarations
391"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600392
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700393 inline_copyright_message = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600394// This file is ***GENERATED***. Do Not Edit.
395// See layer_chassis_generator.py for modifications.
396
Shannon McPherson9a4ae982019-01-07 16:05:25 -0700397/* Copyright (c) 2015-2019 The Khronos Group Inc.
398 * Copyright (c) 2015-2019 Valve Corporation
399 * Copyright (c) 2015-2019 LunarG, Inc.
400 * Copyright (c) 2015-2019 Google Inc.
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600401 *
402 * Licensed under the Apache License, Version 2.0 (the "License");
403 * you may not use this file except in compliance with the License.
404 * You may obtain a copy of the License at
405 *
406 * http://www.apache.org/licenses/LICENSE-2.0
407 *
408 * Unless required by applicable law or agreed to in writing, software
409 * distributed under the License is distributed on an "AS IS" BASIS,
410 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
411 * See the License for the specific language governing permissions and
412 * limitations under the License.
413 *
414 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinskid03ed352018-11-09 09:34:24 -0700415 */"""
416
417 inline_custom_source_preamble = """
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600418
419#include <string.h>
420#include <mutex>
421
422#define VALIDATION_ERROR_MAP_IMPL
423
Mark Lobodzinski0c668462018-09-27 10:13:19 -0600424#include "chassis.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700425#include "layer_chassis_dispatch.h"
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600426
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600427std::unordered_map<void*, ValidationObject*> layer_data_map;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600428
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700429// Global unique object identifier. All increments must be guarded by a lock.
430uint64_t global_unique_id = 1;
431// Map uniqueID to actual object handle
432std::unordered_map<uint64_t, uint64_t> unique_id_mapping;
433
434// TODO: This variable controls handle wrapping -- in the future it should be hooked
435// up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag.
436#if defined(LAYER_CHASSIS_CAN_WRAP_HANDLES)
437bool wrap_handles = true;
438#else
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600439bool wrap_handles = false;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700440#endif
441
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600442// Set layer name -- Khronos layer name overrides any other defined names
Mark Lobodzinskiaa6fd7b2019-03-19 09:26:48 -0600443#if BUILD_KHRONOS_VALIDATION
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600444#define OBJECT_LAYER_NAME "VK_LAYER_KHRONOS_validation"
445#define OBJECT_LAYER_DESCRIPTION "khronos_validation"
446#elif BUILD_OBJECT_TRACKER
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700447#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_object_tracker"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600448#define OBJECT_LAYER_DESCRIPTION "lunarg_object_tracker"
Mark Lobodzinski1f2ba262018-12-04 14:15:47 -0700449#elif BUILD_THREAD_SAFETY
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700450#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_threading"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600451#define OBJECT_LAYER_DESCRIPTION "google_thread_checker"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700452#elif BUILD_PARAMETER_VALIDATION
453#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_parameter_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600454#define OBJECT_LAYER_DESCRIPTION "lunarg_parameter_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700455#elif BUILD_CORE_VALIDATION
456#define OBJECT_LAYER_NAME "VK_LAYER_LUNARG_core_validation"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600457#define OBJECT_LAYER_DESCRIPTION "lunarg_core_validation"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700458#else
459#define OBJECT_LAYER_NAME "VK_LAYER_GOOGLE_unique_objects"
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600460#define OBJECT_LAYER_DESCRIPTION "lunarg_unique_objects"
461#endif
462
463// Include layer validation object definitions
464#if BUILD_OBJECT_TRACKER
465#include "object_lifetime_validation.h"
466#endif
467#if BUILD_THREAD_SAFETY
468#include "thread_safety.h"
469#endif
470#if BUILD_PARAMETER_VALIDATION
471#include "stateless_validation.h"
472#endif
473#if BUILD_CORE_VALIDATION
474#include "core_validation.h"
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700475#endif
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600476
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600477namespace vulkan_layer_chassis {
478
479using std::unordered_map;
480
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600481static const VkLayerProperties global_layer = {
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700482 OBJECT_LAYER_NAME, VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600483};
484
John Zulauf358462e2019-04-10 11:10:32 -0600485static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION},
486 {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION}};
Lenny Komow3627f6e2019-06-19 13:54:59 -0600487static const VkExtensionProperties device_extensions[] = {
488 {VK_EXT_VALIDATION_CACHE_EXTENSION_NAME, VK_EXT_VALIDATION_CACHE_SPEC_VERSION},
489 {VK_EXT_DEBUG_MARKER_EXTENSION_NAME, VK_EXT_DEBUG_MARKER_SPEC_VERSION},
490};
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600491
492extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
493
494
495// Manually written functions
496
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700497// Check enabled instance extensions against supported instance extension whitelist
498static void InstanceExtensionWhitelist(ValidationObject *layer_data, const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
499 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
500 // Check for recognized instance extensions
501 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kInstanceExtensionNames)) {
502 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
503 kVUIDUndefined,
504 "Instance Extension %s is not supported by this layer. Using this extension may adversely affect validation "
505 "results and/or produce undefined behavior.",
506 pCreateInfo->ppEnabledExtensionNames[i]);
507 }
508 }
509}
510
511// Check enabled device extensions against supported device extension whitelist
512static void DeviceExtensionWhitelist(ValidationObject *layer_data, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
513 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
514 // Check for recognized device extensions
515 if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kDeviceExtensionNames)) {
516 log_msg(layer_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
517 kVUIDUndefined,
518 "Device Extension %s is not supported by this layer. Using this extension may adversely affect validation "
519 "results and/or produce undefined behavior.",
520 pCreateInfo->ppEnabledExtensionNames[i]);
521 }
522 }
523}
524
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600525
526// Process validation features, flags and settings specified through extensions, a layer settings file, or environment variables
527
528static const std::unordered_map<std::string, VkValidationFeatureDisableEXT> VkValFeatureDisableLookup = {
529 {"VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT", VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT},
530 {"VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT", VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT},
531 {"VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT", VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT},
532 {"VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT", VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT},
533 {"VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT", VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT},
534 {"VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT", VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT},
535 {"VK_VALIDATION_FEATURE_DISABLE_ALL_EXT", VK_VALIDATION_FEATURE_DISABLE_ALL_EXT},
536};
537
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600538static const std::unordered_map<std::string, VkValidationFeatureEnableEXT> VkValFeatureEnableLookup = {
539 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT},
540 {"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT},
541};
542
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600543static const std::unordered_map<std::string, ValidationCheckDisables> ValidationDisableLookup = {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600544 {"VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE", VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600545 {"VALIDATION_CHECK_DISABLE_OBJECT_IN_USE", VALIDATION_CHECK_DISABLE_OBJECT_IN_USE},
546 {"VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET", VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET},
547 {"VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE", VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE},
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600548 {"VALIDATION_CHECK_DISABLE_QUERY_VALIDATION", VALIDATION_CHECK_DISABLE_QUERY_VALIDATION},
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600549};
550
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600551// Set the local disable flag for the appropriate VALIDATION_CHECK_DISABLE enum
552void SetValidationDisable(CHECK_DISABLED* disable_data, const ValidationCheckDisables disable_id) {
553 switch (disable_id) {
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600554 case VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE:
555 disable_data->command_buffer_state = true;
556 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600557 case VALIDATION_CHECK_DISABLE_OBJECT_IN_USE:
558 disable_data->object_in_use = true;
559 break;
560 case VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET:
561 disable_data->idle_descriptor_set = true;
562 break;
563 case VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE:
564 disable_data->push_constant_range = true;
565 break;
Mark Lobodzinski31f6f7d2019-03-27 16:11:46 -0600566 case VALIDATION_CHECK_DISABLE_QUERY_VALIDATION:
567 disable_data->query_validation = true;
568 break;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600569 default:
570 assert(true);
571 }
572}
573
574// Set the local disable flag for a single VK_VALIDATION_FEATURE_DISABLE_* flag
575void SetValidationFeatureDisable(CHECK_DISABLED* disable_data, const VkValidationFeatureDisableEXT feature_disable) {
576 switch (feature_disable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700577 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600578 disable_data->shader_validation = true;
579 break;
580 case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
581 disable_data->thread_safety = true;
582 break;
583 case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
584 disable_data->stateless_checks = true;
585 break;
586 case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
587 disable_data->object_tracking = true;
588 break;
589 case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
590 disable_data->core_checks = true;
591 break;
592 case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
593 disable_data->handle_wrapping = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700594 break;
595 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
596 // Set all disabled flags to true
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600597 disable_data->SetAll(true);
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700598 break;
599 default:
600 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700601 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600602}
603
604// Set the local enable flag for a single VK_VALIDATION_FEATURE_ENABLE_* flag
605void SetValidationFeatureEnable(CHECK_ENABLED *enable_data, const VkValidationFeatureEnableEXT feature_enable) {
606 switch (feature_enable) {
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700607 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600608 enable_data->gpu_validation = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700609 break;
610 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600611 enable_data->gpu_validation_reserve_binding_slot = true;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700612 break;
613 default:
614 break;
Mark Lobodzinskif1af2a22019-03-04 11:11:16 -0700615 }
616}
617
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600618// Set the local disable flag for settings specified through the VK_EXT_validation_flags extension
619void SetValidationFlags(CHECK_DISABLED* disables, const VkValidationFlagsEXT* val_flags_struct) {
620 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
621 switch (val_flags_struct->pDisabledValidationChecks[i]) {
622 case VK_VALIDATION_CHECK_SHADERS_EXT:
623 disables->shader_validation = true;
624 break;
625 case VK_VALIDATION_CHECK_ALL_EXT:
626 // Set all disabled flags to true
627 disables->SetAll(true);
628 break;
629 default:
630 break;
631 }
632 }
633}
634
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600635// Process Validation Features flags specified through the ValidationFeature extension
636void SetValidationFeatures(CHECK_DISABLED *disable_data, CHECK_ENABLED *enable_data,
637 const VkValidationFeaturesEXT *val_features_struct) {
638 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
639 SetValidationFeatureDisable(disable_data, val_features_struct->pDisabledValidationFeatures[i]);
640 }
641 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
642 SetValidationFeatureEnable(enable_data, val_features_struct->pEnabledValidationFeatures[i]);
643 }
644}
645
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600646// Given a string representation of a list of enable enum values, call the appropriate setter function
647void SetLocalEnableSetting(std::string list_of_enables, std::string delimiter, CHECK_ENABLED* enables) {
648 size_t pos = 0;
649 std::string token;
650 while (list_of_enables.length() != 0) {
651 pos = list_of_enables.find(delimiter);
652 if (pos != std::string::npos) {
653 token = list_of_enables.substr(0, pos);
654 } else {
655 pos = list_of_enables.length() - delimiter.length();
656 token = list_of_enables;
657 }
658 if (token.find("VK_VALIDATION_FEATURE_ENABLE_") != std::string::npos) {
659 auto result = VkValFeatureEnableLookup.find(token);
660 if (result != VkValFeatureEnableLookup.end()) {
661 SetValidationFeatureEnable(enables, result->second);
662 }
663 }
664 list_of_enables.erase(0, pos + delimiter.length());
665 }
666}
667
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600668// Given a string representation of a list of disable enum values, call the appropriate setter function
669void SetLocalDisableSetting(std::string list_of_disables, std::string delimiter, CHECK_DISABLED* disables) {
670 size_t pos = 0;
671 std::string token;
672 while (list_of_disables.length() != 0) {
673 pos = list_of_disables.find(delimiter);
674 if (pos != std::string::npos) {
675 token = list_of_disables.substr(0, pos);
676 } else {
677 pos = list_of_disables.length() - delimiter.length();
678 token = list_of_disables;
679 }
680 if (token.find("VK_VALIDATION_FEATURE_DISABLE_") != std::string::npos) {
681 auto result = VkValFeatureDisableLookup.find(token);
682 if (result != VkValFeatureDisableLookup.end()) {
683 SetValidationFeatureDisable(disables, result->second);
684 }
685 }
686 if (token.find("VALIDATION_CHECK_DISABLE_") != std::string::npos) {
687 auto result = ValidationDisableLookup.find(token);
688 if (result != ValidationDisableLookup.end()) {
689 SetValidationDisable(disables, result->second);
690 }
691 }
692 list_of_disables.erase(0, pos + delimiter.length());
693 }
694}
695
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600696// Process enables and disables set though the vk_layer_settings.txt config file or through an environment variable
697void ProcessConfigAndEnvSettings(const char* layer_description, CHECK_ENABLED* enables, CHECK_DISABLED* disables) {
698 std::string enable_key = layer_description;
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600699 std::string disable_key = layer_description;
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600700 enable_key.append(".enables");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600701 disable_key.append(".disables");
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600702 std::string list_of_config_enables = getLayerOption(enable_key.c_str());
703 std::string list_of_env_enables = GetLayerEnvVar("VK_LAYER_ENABLES");
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600704 std::string list_of_config_disables = getLayerOption(disable_key.c_str());
705 std::string list_of_env_disables = GetLayerEnvVar("VK_LAYER_DISABLES");
706#if defined(_WIN32)
707 std::string env_delimiter = ";";
708#else
709 std::string env_delimiter = ":";
710#endif
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600711 SetLocalEnableSetting(list_of_config_enables, ",", enables);
712 SetLocalEnableSetting(list_of_env_enables, env_delimiter, enables);
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600713 SetLocalDisableSetting(list_of_config_disables, ",", disables);
714 SetLocalDisableSetting(list_of_env_disables, env_delimiter, disables);
715}
716
717
718// Non-code-generated chassis API functions
719
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600720VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600721 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700722 if (!ApiParentExtensionEnabled(funcName, layer_data->device_extensions.device_extension_set)) {
Mark Lobodzinski2fc88fe2018-12-11 12:28:57 -0700723 return nullptr;
724 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600725 const auto &item = name_to_funcptr_map.find(funcName);
726 if (item != name_to_funcptr_map.end()) {
727 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
728 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600729 auto &table = layer_data->device_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600730 if (!table.GetDeviceProcAddr) return nullptr;
731 return table.GetDeviceProcAddr(device, funcName);
732}
733
734VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600735 const auto &item = name_to_funcptr_map.find(funcName);
736 if (item != name_to_funcptr_map.end()) {
737 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
738 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600739 auto layer_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
740 auto &table = layer_data->instance_dispatch_table;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600741 if (!table.GetInstanceProcAddr) return nullptr;
742 return table.GetInstanceProcAddr(instance, funcName);
743}
744
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600745VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
746 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
747}
748
749VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
750 VkLayerProperties *pProperties) {
751 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
752}
753
754VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
755 VkExtensionProperties *pProperties) {
756 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
John Zulauf358462e2019-04-10 11:10:32 -0600757 return util_GetExtensionProperties(ARRAY_SIZE(instance_extensions), instance_extensions, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600758
759 return VK_ERROR_LAYER_NOT_PRESENT;
760}
761
762VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
763 uint32_t *pCount, VkExtensionProperties *pProperties) {
Lenny Komow3627f6e2019-06-19 13:54:59 -0600764 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(ARRAY_SIZE(device_extensions), device_extensions, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600765 assert(physicalDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600766 auto layer_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), layer_data_map);
Lenny Komow7b567f72019-06-10 16:49:43 -0600767 return layer_data->instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pCount, pProperties);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600768}
769
770VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
771 VkInstance *pInstance) {
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600772 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600773
774 assert(chain_info->u.pLayerInfo);
775 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
776 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
777 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
778 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700779 uint32_t specified_version = (pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0);
780 uint32_t api_version = (specified_version < VK_API_VERSION_1_1) ? VK_API_VERSION_1_0 : VK_API_VERSION_1_1;
781
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600782 CHECK_ENABLED local_enables {};
783 CHECK_DISABLED local_disables {};
784 const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(pCreateInfo->pNext);
785 if (validation_features_ext) {
786 SetValidationFeatures(&local_disables, &local_enables, validation_features_ext);
787 }
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600788 const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
789 if (validation_flags_ext) {
790 SetValidationFlags(&local_disables, validation_flags_ext);
791 }
Mark Lobodzinskie7dc9252019-03-22 11:36:32 -0600792 ProcessConfigAndEnvSettings(OBJECT_LAYER_DESCRIPTION, &local_enables, &local_disables);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600793
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600794 // Create temporary dispatch vector for pre-calls until instance is created
795 std::vector<ValidationObject*> local_object_dispatch;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600796 // Add VOs to dispatch vector. Order here will be the validation dispatch order!
797#if BUILD_THREAD_SAFETY
798 auto thread_checker = new ThreadSafety;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600799 if (!local_disables.thread_safety) {
800 local_object_dispatch.emplace_back(thread_checker);
801 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600802 thread_checker->container_type = LayerObjectTypeThreading;
803 thread_checker->api_version = api_version;
804#endif
805#if BUILD_PARAMETER_VALIDATION
806 auto parameter_validation = new StatelessValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600807 if (!local_disables.stateless_checks) {
808 local_object_dispatch.emplace_back(parameter_validation);
809 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600810 parameter_validation->container_type = LayerObjectTypeParameterValidation;
811 parameter_validation->api_version = api_version;
812#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700813#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600814 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600815 if (!local_disables.object_tracking) {
816 local_object_dispatch.emplace_back(object_tracker);
817 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600818 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700819 object_tracker->api_version = api_version;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600820#endif
821#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700822 auto core_checks = new CoreChecks;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600823 if (!local_disables.core_checks) {
824 local_object_dispatch.emplace_back(core_checks);
825 }
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700826 core_checks->container_type = LayerObjectTypeCoreValidation;
827 core_checks->api_version = api_version;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700828#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600829
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600830 // If handle wrapping is disabled via the ValidationFeatures extension, override build flag
831 if (local_disables.handle_wrapping) {
832 wrap_handles = false;
833 }
834
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600835 // Init dispatch array and call registration functions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600836 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600837 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
838 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600839 for (auto intercept : local_object_dispatch) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600840 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
841 }
842
843 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600844 if (result != VK_SUCCESS) return result;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600845
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600846 auto framework = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600847
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600848 framework->object_dispatch = local_object_dispatch;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700849 framework->container_type = LayerObjectTypeInstance;
Mark Lobodzinskic3909802019-03-12 16:27:20 -0600850 framework->disabled = local_disables;
851 framework->enabled = local_enables;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600852
853 framework->instance = *pInstance;
854 layer_init_instance_dispatch_table(*pInstance, &framework->instance_dispatch_table, fpGetInstanceProcAddr);
855 framework->report_data = debug_utils_create_instance(&framework->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
856 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskic1608f22019-01-11 14:47:55 -0700857 framework->api_version = api_version;
858 framework->instance_extensions.InitFromInstanceCreateInfo(specified_version, pCreateInfo);
859
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600860 layer_debug_messenger_actions(framework->report_data, framework->logging_messenger, pAllocator, OBJECT_LAYER_DESCRIPTION);
861
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700862#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700863 object_tracker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600864 object_tracker->instance_dispatch_table = framework->instance_dispatch_table;
865 object_tracker->enabled = framework->enabled;
866 object_tracker->disabled = framework->disabled;
867#endif
868#if BUILD_THREAD_SAFETY
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700869 thread_checker->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600870 thread_checker->instance_dispatch_table = framework->instance_dispatch_table;
871 thread_checker->enabled = framework->enabled;
872 thread_checker->disabled = framework->disabled;
873#endif
874#if BUILD_PARAMETER_VALIDATION
Mark Lobodzinskiaf7c0382018-12-18 11:55:55 -0700875 parameter_validation->report_data = framework->report_data;
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600876 parameter_validation->instance_dispatch_table = framework->instance_dispatch_table;
877 parameter_validation->enabled = framework->enabled;
878 parameter_validation->disabled = framework->disabled;
879#endif
880#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700881 core_checks->report_data = framework->report_data;
882 core_checks->instance_dispatch_table = framework->instance_dispatch_table;
883 core_checks->instance = *pInstance;
884 core_checks->enabled = framework->enabled;
885 core_checks->disabled = framework->disabled;
886 core_checks->instance_state = core_checks;
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700887#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600888
889 for (auto intercept : framework->object_dispatch) {
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -0700890 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600891 }
892
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -0700893 InstanceExtensionWhitelist(framework, pCreateInfo, *pInstance);
894
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600895 return result;
896}
897
898VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
899 dispatch_key key = get_dispatch_key(instance);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600900 auto layer_data = GetLayerDataPtr(key, layer_data_map);
901 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700902 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600903 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
904 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600905 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700906 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600907 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
908 }
909
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600910 layer_data->instance_dispatch_table.DestroyInstance(instance, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600911
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600912 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700913 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600914 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
915 }
916 // Clean up logging callback, if any
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600917 while (layer_data->logging_messenger.size() > 0) {
918 VkDebugUtilsMessengerEXT messenger = layer_data->logging_messenger.back();
919 layer_destroy_messenger_callback(layer_data->report_data, messenger, pAllocator);
920 layer_data->logging_messenger.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600921 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600922 while (layer_data->logging_callback.size() > 0) {
923 VkDebugReportCallbackEXT callback = layer_data->logging_callback.back();
924 layer_destroy_report_callback(layer_data->report_data, callback, pAllocator);
925 layer_data->logging_callback.pop_back();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600926 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600927
928 layer_debug_utils_destroy_instance(layer_data->report_data);
929
Mark Lobodzinskic5003372018-12-17 16:36:01 -0700930 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
931 delete *item;
932 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600933 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600934}
935
936VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
937 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600938 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600939
940 auto instance_interceptor = GetLayerDataPtr(get_dispatch_key(gpu), layer_data_map);
941
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600942 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
943 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600944 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_interceptor->instance, "vkCreateDevice");
945 if (fpCreateDevice == NULL) {
946 return VK_ERROR_INITIALIZATION_FAILED;
947 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600948 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
949
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700950 // Get physical device limits for device
951 VkPhysicalDeviceProperties device_properties = {};
952 instance_interceptor->instance_dispatch_table.GetPhysicalDeviceProperties(gpu, &device_properties);
953
954 // Setup the validation tables based on the application API version from the instance and the capabilities of the device driver
955 uint32_t effective_api_version = std::min(device_properties.apiVersion, instance_interceptor->api_version);
956
957 DeviceExtensions device_extensions = {};
958 device_extensions.InitFromDeviceCreateInfo(&instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
959 for (auto item : instance_interceptor->object_dispatch) {
960 item->device_extensions = device_extensions;
961 }
962
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700963 std::unique_ptr<safe_VkDeviceCreateInfo> modified_create_info(new safe_VkDeviceCreateInfo(pCreateInfo));
964
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700965 bool skip = false;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600966 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700967 auto lock = intercept->write_lock();
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700968 skip |= intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700969 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600970 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600971 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -0700972 auto lock = intercept->write_lock();
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700973 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, modified_create_info);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600974 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600975
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -0700976 VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo *>(modified_create_info.get()), pAllocator, pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600977 if (result != VK_SUCCESS) {
978 return result;
979 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -0600980
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600981 auto device_interceptor = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700982 device_interceptor->container_type = LayerObjectTypeDevice;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700983
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700984 // Save local info in device object
985 device_interceptor->phys_dev_properties.properties = device_properties;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700986 device_interceptor->api_version = device_interceptor->device_extensions.InitFromDeviceCreateInfo(
987 &instance_interceptor->instance_extensions, effective_api_version, pCreateInfo);
Mark Lobodzinski0068bd82018-12-28 12:08:44 -0700988 device_interceptor->device_extensions = device_extensions;
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700989
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600990 layer_init_device_dispatch_table(*pDevice, &device_interceptor->device_dispatch_table, fpGetDeviceProcAddr);
Mark Lobodzinskicc4e4a22018-12-18 16:16:21 -0700991
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600992 device_interceptor->device = *pDevice;
993 device_interceptor->physical_device = gpu;
994 device_interceptor->instance = instance_interceptor->instance;
995 device_interceptor->report_data = layer_debug_utils_create_device(instance_interceptor->report_data, *pDevice);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -0600996
Mark Lobodzinski9951e922019-03-11 12:37:46 -0600997 // Note that this defines the order in which the layer validation objects are called
998#if BUILD_THREAD_SAFETY
999 auto thread_safety = new ThreadSafety;
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001000 thread_safety->container_type = LayerObjectTypeThreading;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001001 if (!instance_interceptor->disabled.thread_safety) {
1002 device_interceptor->object_dispatch.emplace_back(thread_safety);
1003 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001004#endif
1005#if BUILD_PARAMETER_VALIDATION
1006 auto stateless_validation = new StatelessValidation;
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001007 stateless_validation->container_type = LayerObjectTypeParameterValidation;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001008 if (!instance_interceptor->disabled.stateless_checks) {
1009 device_interceptor->object_dispatch.emplace_back(stateless_validation);
1010 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001011#endif
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001012#if BUILD_OBJECT_TRACKER
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001013 auto object_tracker = new ObjectLifetimes;
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001014 object_tracker->container_type = LayerObjectTypeObjectTracker;
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001015 if (!instance_interceptor->disabled.object_tracking) {
1016 device_interceptor->object_dispatch.emplace_back(object_tracker);
1017 }
Mark Lobodzinski9951e922019-03-11 12:37:46 -06001018#endif
1019#if BUILD_CORE_VALIDATION
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001020 auto core_checks = new CoreChecks;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001021 core_checks->container_type = LayerObjectTypeCoreValidation;
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001022 core_checks->instance_state = reinterpret_cast<CoreChecks *>(
1023 core_checks->GetValidationObject(instance_interceptor->object_dispatch, LayerObjectTypeCoreValidation));
Mark Lobodzinskic3909802019-03-12 16:27:20 -06001024 if (!instance_interceptor->disabled.core_checks) {
1025 device_interceptor->object_dispatch.emplace_back(core_checks);
1026 }
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001027#endif
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001028
Mark Lobodzinski7314bf42019-03-28 08:54:53 -06001029 // Set per-intercept common data items
1030 for (auto dev_intercept : device_interceptor->object_dispatch) {
1031 dev_intercept->device = *pDevice;
1032 dev_intercept->physical_device = gpu;
1033 dev_intercept->instance = instance_interceptor->instance;
1034 dev_intercept->report_data = device_interceptor->report_data;
1035 dev_intercept->device_dispatch_table = device_interceptor->device_dispatch_table;
1036 dev_intercept->api_version = device_interceptor->api_version;
1037 dev_intercept->disabled = instance_interceptor->disabled;
1038 dev_intercept->enabled = instance_interceptor->enabled;
1039 dev_intercept->instance_dispatch_table = instance_interceptor->instance_dispatch_table;
1040 dev_intercept->instance_extensions = instance_interceptor->instance_extensions;
1041 dev_intercept->device_extensions = device_interceptor->device_extensions;
1042 }
1043
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001044 for (auto intercept : instance_interceptor->object_dispatch) {
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001045 auto lock = intercept->write_lock();
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001046 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001047 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001048
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001049 DeviceExtensionWhitelist(device_interceptor, pCreateInfo, *pDevice);
1050
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001051 return result;
1052}
1053
1054VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
1055 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001056 auto layer_data = GetLayerDataPtr(key, layer_data_map);
1057 """ + precallvalidate_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001058 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001059 intercept->PreCallValidateDestroyDevice(device, pAllocator);
1060 }
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001061 """ + precallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001062 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001063 intercept->PreCallRecordDestroyDevice(device, pAllocator);
1064 }
1065 layer_debug_utils_destroy_device(device);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001066
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001067 layer_data->device_dispatch_table.DestroyDevice(device, pAllocator);
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001068
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001069 """ + postcallrecord_loop + """
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001070 auto lock = intercept->write_lock();
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001071 intercept->PostCallRecordDestroyDevice(device, pAllocator);
1072 }
1073
Mark Lobodzinskic5003372018-12-17 16:36:01 -07001074 for (auto item = layer_data->object_dispatch.begin(); item != layer_data->object_dispatch.end(); item++) {
1075 delete *item;
1076 }
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001077 FreeLayerDataPtr(key, layer_data_map);
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001078}
1079
1080
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001081// Special-case APIs for which core_validation needs custom parameter lists and/or modifies parameters
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001082
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001083VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(
1084 VkDevice device,
1085 VkPipelineCache pipelineCache,
1086 uint32_t createInfoCount,
1087 const VkGraphicsPipelineCreateInfo* pCreateInfos,
1088 const VkAllocationCallbacks* pAllocator,
1089 VkPipeline* pPipelines) {
1090 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1091 bool skip = false;
1092
1093#ifdef BUILD_CORE_VALIDATION
1094 create_graphics_pipeline_api_state cgpl_state{};
1095#else
1096 struct create_graphics_pipeline_api_state {
1097 const VkGraphicsPipelineCreateInfo* pCreateInfos;
1098 } cgpl_state;
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001099#endif
Mark Lobodzinskid08e16c2019-06-11 10:22:10 -06001100 cgpl_state.pCreateInfos = pCreateInfos;
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001101
1102 for (auto intercept : layer_data->object_dispatch) {
1103 auto lock = intercept->write_lock();
1104 skip |= intercept->PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1105 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1106 }
1107 for (auto intercept : layer_data->object_dispatch) {
1108 auto lock = intercept->write_lock();
1109 intercept->PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &cgpl_state);
1110 }
1111
Tony-LunarG152a88b2019-03-20 15:42:24 -06001112 VkResult result = DispatchCreateGraphicsPipelines(device, pipelineCache, createInfoCount, cgpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001113
1114 for (auto intercept : layer_data->object_dispatch) {
1115 auto lock = intercept->write_lock();
1116 intercept->PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &cgpl_state);
1117 }
1118 return result;
1119}
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001120
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001121// This API saves some core_validation pipeline state state on the stack for performance purposes
1122VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(
1123 VkDevice device,
1124 VkPipelineCache pipelineCache,
1125 uint32_t createInfoCount,
1126 const VkComputePipelineCreateInfo* pCreateInfos,
1127 const VkAllocationCallbacks* pAllocator,
1128 VkPipeline* pPipelines) {
1129 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1130 bool skip = false;
1131
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001132#ifdef BUILD_CORE_VALIDATION
1133 create_compute_pipeline_api_state ccpl_state{};
1134#else
1135 struct create_compute_pipeline_api_state {
1136 const VkComputePipelineCreateInfo* pCreateInfos;
1137 } ccpl_state;
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001138#endif
Mark Lobodzinskid08e16c2019-06-11 10:22:10 -06001139 ccpl_state.pCreateInfos = pCreateInfos;
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001140
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001141 for (auto intercept : layer_data->object_dispatch) {
1142 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001143 skip |= intercept->PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001144 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1145 }
1146 for (auto intercept : layer_data->object_dispatch) {
1147 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001148 intercept->PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001149 }
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001150 VkResult result = DispatchCreateComputePipelines(device, pipelineCache, createInfoCount, ccpl_state.pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001151 for (auto intercept : layer_data->object_dispatch) {
1152 auto lock = intercept->write_lock();
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001153 intercept->PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &ccpl_state);
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001154 }
1155 return result;
1156}
1157
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001158VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
1159 VkDevice device,
1160 VkPipelineCache pipelineCache,
1161 uint32_t createInfoCount,
1162 const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
1163 const VkAllocationCallbacks* pAllocator,
1164 VkPipeline* pPipelines) {
1165 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1166 bool skip = false;
1167
1168#ifndef BUILD_CORE_VALIDATION
1169 struct PIPELINE_STATE {};
1170#endif
1171
1172 std::vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
1173
1174 for (auto intercept : layer_data->object_dispatch) {
1175 auto lock = intercept->write_lock();
1176 skip |= intercept->PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, &pipe_state);
1177 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1178 }
1179 for (auto intercept : layer_data->object_dispatch) {
1180 auto lock = intercept->write_lock();
1181 intercept->PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1182 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001183 VkResult result = DispatchCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001184 for (auto intercept : layer_data->object_dispatch) {
1185 auto lock = intercept->write_lock();
1186 intercept->PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result, &pipe_state);
1187 }
1188 return result;
1189}
1190
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001191// This API needs the ability to modify a down-chain parameter
1192VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(
1193 VkDevice device,
1194 const VkPipelineLayoutCreateInfo* pCreateInfo,
1195 const VkAllocationCallbacks* pAllocator,
1196 VkPipelineLayout* pPipelineLayout) {
1197 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1198 bool skip = false;
1199
1200#ifndef BUILD_CORE_VALIDATION
1201 struct create_pipeline_layout_api_state {
1202 VkPipelineLayoutCreateInfo modified_create_info;
1203 };
1204#endif
1205 create_pipeline_layout_api_state cpl_state{};
1206 cpl_state.modified_create_info = *pCreateInfo;
1207
1208 for (auto intercept : layer_data->object_dispatch) {
1209 auto lock = intercept->write_lock();
1210 skip |= intercept->PreCallValidateCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1211 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1212 }
1213 for (auto intercept : layer_data->object_dispatch) {
1214 auto lock = intercept->write_lock();
1215 intercept->PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, &cpl_state);
1216 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001217 VkResult result = DispatchCreatePipelineLayout(device, &cpl_state.modified_create_info, pAllocator, pPipelineLayout);
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001218 for (auto intercept : layer_data->object_dispatch) {
1219 auto lock = intercept->write_lock();
1220 intercept->PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1221 }
1222 return result;
1223}
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001224
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001225// This API needs some local stack data for performance reasons and also may modify a parameter
1226VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(
1227 VkDevice device,
1228 const VkShaderModuleCreateInfo* pCreateInfo,
1229 const VkAllocationCallbacks* pAllocator,
1230 VkShaderModule* pShaderModule) {
1231 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1232 bool skip = false;
1233
1234#ifndef BUILD_CORE_VALIDATION
1235 struct create_shader_module_api_state {
1236 VkShaderModuleCreateInfo instrumented_create_info;
1237 };
1238#endif
1239 create_shader_module_api_state csm_state{};
1240 csm_state.instrumented_create_info = *pCreateInfo;
1241
1242 for (auto intercept : layer_data->object_dispatch) {
1243 auto lock = intercept->write_lock();
1244 skip |= intercept->PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1245 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1246 }
1247 for (auto intercept : layer_data->object_dispatch) {
1248 auto lock = intercept->write_lock();
1249 intercept->PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, &csm_state);
1250 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001251 VkResult result = DispatchCreateShaderModule(device, &csm_state.instrumented_create_info, pAllocator, pShaderModule);
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001252 for (auto intercept : layer_data->object_dispatch) {
1253 auto lock = intercept->write_lock();
1254 intercept->PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result, &csm_state);
1255 }
1256 return result;
1257}
1258
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001259VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(
1260 VkDevice device,
1261 const VkDescriptorSetAllocateInfo* pAllocateInfo,
1262 VkDescriptorSet* pDescriptorSets) {
1263 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1264 bool skip = false;
1265
1266#ifdef BUILD_CORE_VALIDATION
1267 cvdescriptorset::AllocateDescriptorSetsData ads_state(pAllocateInfo->descriptorSetCount);
1268#else
1269 struct ads_state {} ads_state;
1270#endif
1271
1272 for (auto intercept : layer_data->object_dispatch) {
1273 auto lock = intercept->write_lock();
1274 skip |= intercept->PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, &ads_state);
1275 if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
1276 }
1277 for (auto intercept : layer_data->object_dispatch) {
1278 auto lock = intercept->write_lock();
1279 intercept->PreCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1280 }
Tony-LunarG152a88b2019-03-20 15:42:24 -06001281 VkResult result = DispatchAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001282 for (auto intercept : layer_data->object_dispatch) {
1283 auto lock = intercept->write_lock();
1284 intercept->PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result, &ads_state);
1285 }
1286 return result;
1287}
1288
1289
1290
1291
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001292
1293// ValidationCache APIs do not dispatch
1294
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001295VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
1296 VkDevice device,
1297 const VkValidationCacheCreateInfoEXT* pCreateInfo,
1298 const VkAllocationCallbacks* pAllocator,
1299 VkValidationCacheEXT* pValidationCache) {
1300 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1301 VkResult result = VK_SUCCESS;
1302
1303 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1304 if (validation_data) {
1305 auto lock = validation_data->write_lock();
1306 result = validation_data->CoreLayerCreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
1307 }
1308 return result;
1309}
1310
1311VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
1312 VkDevice device,
1313 VkValidationCacheEXT validationCache,
1314 const VkAllocationCallbacks* pAllocator) {
1315 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1316
1317 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1318 if (validation_data) {
1319 auto lock = validation_data->write_lock();
1320 validation_data->CoreLayerDestroyValidationCacheEXT(device, validationCache, pAllocator);
1321 }
1322}
1323
1324VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
1325 VkDevice device,
1326 VkValidationCacheEXT dstCache,
1327 uint32_t srcCacheCount,
1328 const VkValidationCacheEXT* pSrcCaches) {
1329 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1330 VkResult result = VK_SUCCESS;
1331
1332 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1333 if (validation_data) {
1334 auto lock = validation_data->write_lock();
1335 result = validation_data->CoreLayerMergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
1336 }
1337 return result;
1338}
1339
1340VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
1341 VkDevice device,
1342 VkValidationCacheEXT validationCache,
1343 size_t* pDataSize,
1344 void* pData) {
1345 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1346 VkResult result = VK_SUCCESS;
1347
1348 ValidationObject *validation_data = layer_data->GetValidationObject(layer_data->object_dispatch, LayerObjectTypeCoreValidation);
1349 if (validation_data) {
1350 auto lock = validation_data->write_lock();
1351 result = validation_data->CoreLayerGetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
1352 }
1353 return result;
1354
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001355}"""
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001356
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001357 inline_custom_validation_class_definitions = """
1358 virtual VkResult CoreLayerCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
1359 virtual void CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) {};
1360 virtual VkResult CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
1361 virtual VkResult CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
Mark Lobodzinski5f194cc2019-02-28 16:34:49 -07001362
1363 // Allow additional parameter for CreateGraphicsPipelines
1364 virtual bool PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1365 return PreCallValidateCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1366 };
1367 virtual void PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* cgpl_state) {
1368 PreCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1369 };
1370 virtual void PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* cgpl_state) {
1371 PostCallRecordCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1372 };
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001373 virtual void PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* ccpl_state) {
1374 PreCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1375 };
Mark Lobodzinski768a84e2019-03-01 08:46:03 -07001376 // Allow additional state parameter for CreateComputePipelines
1377 virtual bool PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1378 return PreCallValidateCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1379 };
1380 virtual void PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1381 PostCallRecordCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1382 };
Mark Lobodzinski082cafd2019-03-01 08:56:52 -07001383
1384 // Allow additional state parameter for CreateRayTracingPipelinesNV
1385 virtual bool PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, void* pipe_state) {
1386 return PreCallValidateCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1387 };
1388 virtual void PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines, VkResult result, void* pipe_state) {
1389 PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines, result);
1390 };
Mark Lobodzinski76a3a0f2019-03-01 09:50:29 -07001391
1392 // Allow modification of a down-chain parameter for CreatePipelineLayout
1393 virtual void PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout, void *cpl_state) {
1394 PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
1395 };
Mark Lobodzinski1db77e82019-03-01 10:02:54 -07001396
1397 // Enable the CreateShaderModule API to take an extra argument for state preservation and paramter modification
1398 virtual bool PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1399 return PreCallValidateCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1400 };
1401 virtual void PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, void* csm_state) {
1402 PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
1403 };
1404 virtual void PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, VkResult result, void* csm_state) {
1405 PostCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, result);
1406 };
Mark Lobodzinski3fb1dab2019-03-01 10:20:27 -07001407
1408 // Allow AllocateDescriptorSets to use some local stack storage for performance purposes
1409 virtual bool PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, void* ads_state) {
1410 return PreCallValidateAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1411 };
1412 virtual void PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets, VkResult result, void* ads_state) {
1413 PostCallRecordAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets, result);
1414 };
Mark Lobodzinski5eb3c262019-03-01 16:08:30 -07001415
1416 // Modify a parameter to CreateDevice
1417 virtual void PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice, std::unique_ptr<safe_VkDeviceCreateInfo> &modified_create_info) {
1418 PreCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1419 };
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001420"""
1421
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001422 inline_custom_source_postamble = """
1423// loader-layer interface v0, just wrappers since there is only a layer
1424
1425VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
1426 VkExtensionProperties *pProperties) {
1427 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1428}
1429
1430VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
1431 VkLayerProperties *pProperties) {
1432 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
1433}
1434
1435VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
1436 VkLayerProperties *pProperties) {
1437 // the layer command handles VK_NULL_HANDLE just fine internally
1438 assert(physicalDevice == VK_NULL_HANDLE);
1439 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
1440}
1441
1442VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1443 const char *pLayerName, uint32_t *pCount,
1444 VkExtensionProperties *pProperties) {
1445 // the layer command handles VK_NULL_HANDLE just fine internally
1446 assert(physicalDevice == VK_NULL_HANDLE);
1447 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
1448}
1449
1450VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1451 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
1452}
1453
1454VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1455 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
1456}
1457
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001458VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
1459 assert(pVersionStruct != NULL);
1460 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
1461
1462 // Fill in the function pointers if our version is at least capable of having the structure contain them.
1463 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
1464 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
1465 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
Mark Lobodzinski56e88122019-03-26 10:21:48 -06001466 pVersionStruct->pfnGetPhysicalDeviceProcAddr = nullptr;
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001467 }
1468
1469 return VK_SUCCESS;
1470}"""
1471
1472
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001473 def __init__(self,
1474 errFile = sys.stderr,
1475 warnFile = sys.stderr,
1476 diagFile = sys.stdout):
1477 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
1478 # Internal state - accumulators for different inner block text
1479 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1480 self.intercepts = []
1481 self.layer_factory = '' # String containing base layer factory class definition
1482
1483 # Check if the parameter passed in is a pointer to an array
1484 def paramIsArray(self, param):
1485 return param.attrib.get('len') is not None
1486
1487 # Check if the parameter passed in is a pointer
1488 def paramIsPointer(self, param):
1489 ispointer = False
1490 for elem in param:
Raul Tambre7b300182019-05-04 11:25:14 +03001491 if elem.tag == 'type' and elem.tail is not None and '*' in elem.tail:
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001492 ispointer = True
1493 return ispointer
1494
1495 # Check if an object is a non-dispatchable handle
1496 def isHandleTypeNonDispatchable(self, handletype):
1497 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1498 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1499 return True
1500 else:
1501 return False
1502
1503 # Check if an object is a dispatchable handle
1504 def isHandleTypeDispatchable(self, handletype):
1505 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
1506 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
1507 return True
1508 else:
1509 return False
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001510 #
1511 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001512 def beginFile(self, genOpts):
1513 OutputGenerator.beginFile(self, genOpts)
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001514 # Output Copyright
1515 write(self.inline_copyright_message, file=self.outFile)
1516 # Multiple inclusion protection
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001517 self.header = False
1518 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
1519 self.header = True
1520 write('#pragma once', file=self.outFile)
1521 self.newline()
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001522 if self.header:
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001523 write(self.inline_custom_header_preamble, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001524 else:
1525 write(self.inline_custom_source_preamble, file=self.outFile)
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001526 self.layer_factory += self.inline_custom_header_class_definition
Mark Lobodzinskid03ed352018-11-09 09:34:24 -07001527 #
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001528 #
1529 def endFile(self):
1530 # Finish C++ namespace and multiple inclusion protection
1531 self.newline()
1532 if not self.header:
1533 # Record intercepted procedures
1534 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
1535 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
1536 write('\n'.join(self.intercepts), file=self.outFile)
1537 write('};\n', file=self.outFile)
1538 self.newline()
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001539 write('} // namespace vulkan_layer_chassis', file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001540 if self.header:
1541 self.newline()
1542 # Output Layer Factory Class Definitions
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001543 self.layer_factory += self.inline_custom_validation_class_definitions
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001544 self.layer_factory += '};\n\n'
1545 self.layer_factory += 'extern std::unordered_map<void*, ValidationObject*> layer_data_map;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001546 write(self.layer_factory, file=self.outFile)
1547 else:
1548 write(self.inline_custom_source_postamble, file=self.outFile)
1549 # Finish processing in superclass
1550 OutputGenerator.endFile(self)
1551
1552 def beginFeature(self, interface, emit):
1553 # Start processing in superclass
1554 OutputGenerator.beginFeature(self, interface, emit)
1555 # Get feature extra protect
1556 self.featureExtraProtect = GetFeatureProtect(interface)
1557 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
1558 # feature. They're only printed in endFeature().
1559 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
1560
1561 def endFeature(self):
1562 # Actually write the interface to the output file.
1563 if (self.emit):
1564 self.newline()
1565 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
1566 # or move it below the 'for section...' loop.
1567 if (self.featureExtraProtect != None):
1568 write('#ifdef', self.featureExtraProtect, file=self.outFile)
1569 for section in self.TYPE_SECTIONS:
1570 contents = self.sections[section]
1571 if contents:
1572 write('\n'.join(contents), file=self.outFile)
1573 self.newline()
1574 if (self.sections['command']):
1575 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
1576 self.newline()
1577 if (self.featureExtraProtect != None):
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001578 write('#endif //', self.featureExtraProtect, file=self.outFile)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001579 # Finish processing in superclass
1580 OutputGenerator.endFeature(self)
1581 #
1582 # Append a definition to the specified section
1583 def appendSection(self, section, text):
1584 self.sections[section].append(text)
1585 #
1586 # Type generation
1587 def genType(self, typeinfo, name, alias):
1588 pass
1589 #
1590 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
1591 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
1592 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
1593 # structs etc.)
1594 def genStruct(self, typeinfo, typeName):
1595 OutputGenerator.genStruct(self, typeinfo, typeName)
1596 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
1597 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
1598 for member in typeinfo.elem.findall('.//member'):
1599 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
1600 body += ';\n'
1601 body += '} ' + typeName + ';\n'
1602 self.appendSection('struct', body)
1603 #
1604 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
1605 def genGroup(self, groupinfo, groupName, alias):
1606 pass
1607 # Enumerant generation
1608 # <enum> tags may specify their values in several ways, but are usually just integers.
1609 def genEnum(self, enuminfo, name, alias):
1610 pass
1611 #
1612 # Customize Cdecl for layer factory base class
1613 def BaseClassCdecl(self, elem, name):
1614 raw = self.makeCDecls(elem)[1]
1615
1616 # Toss everything before the undecorated name
1617 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
1618 prototype = prototype.replace(")", "", 1)
1619 prototype = prototype.replace(";", " {};")
1620
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001621 # Build up pre/post call virtual function declarations
1622 pre_call_validate = 'virtual bool PreCallValidate' + prototype
1623 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
1624 pre_call_record = 'virtual void PreCallRecord' + prototype
1625 post_call_record = 'virtual void PostCallRecord' + prototype
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001626 resulttype = elem.find('proto/type')
1627 if resulttype.text == 'VkResult':
1628 post_call_record = post_call_record.replace(')', ', VkResult result)')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001629 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
1630 #
1631 # Command generation
1632 def genCmd(self, cmdinfo, name, alias):
1633 ignore_functions = [
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001634 'vkEnumerateInstanceVersion',
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001635 ]
1636
1637 if name in ignore_functions:
1638 return
1639
1640 if self.header: # In the header declare all intercepts
1641 self.appendSection('command', '')
1642 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
1643 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001644 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
1645 # Update base class with virtual function declarations
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001646 if 'ValidationCache' not in name:
1647 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001648 if (self.featureExtraProtect != None):
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001649 self.layer_factory += '#endif\n'
1650 return
1651
Mark Lobodzinski09f86362018-12-13 14:07:20 -07001652 if name in self.manual_functions:
Mark Lobodzinskic37c82a2019-02-28 13:13:02 -07001653 if 'ValidationCache' not in name:
1654 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1655 else:
1656 self.intercepts += [ '#ifdef BUILD_CORE_VALIDATION' ]
1657 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1658 self.intercepts += [ '#endif' ]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001659 return
1660 # Record that the function will be intercepted
1661 if (self.featureExtraProtect != None):
1662 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1663 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1664 if (self.featureExtraProtect != None):
1665 self.intercepts += [ '#endif' ]
1666 OutputGenerator.genCmd(self, cmdinfo, name, alias)
1667 #
1668 decls = self.makeCDecls(cmdinfo.elem)
1669 self.appendSection('command', '')
1670 self.appendSection('command', '%s {' % decls[0][:-1])
1671 # Setup common to call wrappers. First parameter is always dispatchable
1672 dispatchable_type = cmdinfo.elem.find('param/type').text
1673 dispatchable_name = cmdinfo.elem.find('param/name').text
1674 # Default to device
1675 device_or_instance = 'device'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001676 dispatch_table_name = 'VkLayerDispatchTable'
1677 # Set to instance as necessary
1678 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
1679 device_or_instance = 'instance'
1680 dispatch_table_name = 'VkLayerInstanceDispatchTable'
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001681 self.appendSection('command', ' auto layer_data = GetLayerDataPtr(get_dispatch_key(%s), layer_data_map);' % (dispatchable_name))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001682 api_function_name = cmdinfo.elem.attrib.get('name')
1683 params = cmdinfo.elem.findall('param/name')
1684 paramstext = ', '.join([str(param.text) for param in params])
Tony-LunarG152a88b2019-03-20 15:42:24 -06001685 API = api_function_name.replace('vk','Dispatch') + '('
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001686
1687 # Declare result variable, if any.
1688 return_map = {
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001689 'PFN_vkVoidFunction': 'return nullptr;',
1690 'VkBool32': 'return VK_FALSE;',
Shannon McPherson9a4ae982019-01-07 16:05:25 -07001691 'VkDeviceAddress': 'return 0;',
1692 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
1693 'void': 'return;',
Eric Wernessf46b8a02019-01-30 12:24:39 -08001694 'uint32_t': 'return 0;'
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001695 }
1696 resulttype = cmdinfo.elem.find('proto/type')
1697 assignresult = ''
1698 if (resulttype.text != 'void'):
1699 assignresult = resulttype.text + ' result = '
1700
1701 # Set up skip and locking
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001702 self.appendSection('command', ' bool skip = false;')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001703
1704 # Generate pre-call validation source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001705 self.appendSection('command', ' %s' % self.precallvalidate_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001706 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001707 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
1708 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
1709 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001710
1711 # Generate pre-call state recording source code
Mark Lobodzinskiadd93232018-10-09 11:49:42 -06001712 self.appendSection('command', ' %s' % self.precallrecord_loop)
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001713 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskie37e2fc2018-11-26 16:31:17 -07001714 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001715 self.appendSection('command', ' }')
1716
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001717 # Insert pre-dispatch debug utils function call
1718 if name in self.pre_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001719 self.appendSection('command', ' %s' % self.pre_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001720
1721 # Output dispatch (down-chain) function call
Mark Lobodzinskia5b163f2018-11-08 12:31:46 -07001722 self.appendSection('command', ' ' + assignresult + API + paramstext + ');')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001723
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001724 # Insert post-dispatch debug utils function call
1725 if name in self.post_dispatch_debug_utils_functions:
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -07001726 self.appendSection('command', ' %s' % self.post_dispatch_debug_utils_functions[name])
Mark Lobodzinskif57e8282018-12-13 11:34:33 -07001727
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001728 # Generate post-call object processing source code
Mark Lobodzinskid939fcb2019-01-10 15:49:12 -07001729 self.appendSection('command', ' %s' % self.postcallrecord_loop)
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001730 returnparam = ''
Mark Lobodzinski0c668462018-09-27 10:13:19 -06001731 if (resulttype.text == 'VkResult'):
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001732 returnparam = ', result'
Jeremy Hayesd4a3ec32019-01-29 14:42:08 -07001733 self.appendSection('command', ' auto lock = intercept->write_lock();')
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001734 self.appendSection('command', ' intercept->PostCallRecord%s(%s%s);' % (api_function_name[2:], paramstext, returnparam))
Mark Lobodzinskicd05c1e2019-01-17 15:33:46 -07001735 self.appendSection('command', ' }')
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001736 # Return result variable, if any.
1737 if (resulttype.text != 'void'):
1738 self.appendSection('command', ' return result;')
1739 self.appendSection('command', '}')
1740 #
1741 # Override makeProtoName to drop the "vk" prefix
1742 def makeProtoName(self, name, tail):
1743 return self.genOpts.apientry + name[2:] + tail