blob: 2ca3891aecb76340dde346703526fd70ed87c78a [file] [log] [blame]
Mark Lobodzinski9b6522d2018-09-26 11:07:45 -06001#!/usr/bin/python3 -i
2#
3# Copyright (c) 2015-2016 Valve Corporation
4# Copyright (c) 2015-2016 LunarG, Inc.
5# Copyright (c) 2015-2016 Google Inc.
6#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
20# Author: Mark Lobodzinski <mark@lunarg.com>
21#
22# This script generates the dispatch portion of a factory layer which intercepts
23# all Vulkan functions. The resultant factory layer allows rapid development of
24# layers and interceptors.
25
26import os,re,sys
27from generator import *
28from common_codegen import *
29
30# LayerFactoryGeneratorOptions - subclass of GeneratorOptions.
31#
32# Adds options used by LayerFactoryOutputGenerator objects during factory
33# layer generation.
34#
35# Additional members
36# prefixText - list of strings to prefix generated header with
37# (usually a copyright statement + calling convention macros).
38# protectFile - True if multiple inclusion protection should be
39# generated (based on the filename) around the entire header.
40# protectFeature - True if #ifndef..#endif protection should be
41# generated around a feature interface in the header file.
42# genFuncPointers - True if function pointer typedefs should be
43# generated
44# protectProto - If conditional protection should be generated
45# around prototype declarations, set to either '#ifdef'
46# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
47# to require opt-out (#ifndef protectProtoStr). Otherwise
48# set to None.
49# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
50# declarations, if protectProto is set
51# apicall - string to use for the function declaration prefix,
52# such as APICALL on Windows.
53# apientry - string to use for the calling convention macro,
54# in typedefs, such as APIENTRY.
55# apientryp - string to use for the calling convention macro
56# in function pointer typedefs, such as APIENTRYP.
57# indentFuncProto - True if prototype declarations should put each
58# parameter on a separate line
59# indentFuncPointer - True if typedefed function pointers should put each
60# parameter on a separate line
61# alignFuncParam - if nonzero and parameters are being put on a
62# separate line, align parameter names at the specified column
63class LayerChassisGeneratorOptions(GeneratorOptions):
64 def __init__(self,
65 filename = None,
66 directory = '.',
67 apiname = None,
68 profile = None,
69 versions = '.*',
70 emitversions = '.*',
71 defaultExtensions = None,
72 addExtensions = None,
73 removeExtensions = None,
74 emitExtensions = None,
75 sortProcedure = regSortFeatures,
76 prefixText = "",
77 genFuncPointers = True,
78 protectFile = True,
79 protectFeature = True,
80 apicall = '',
81 apientry = '',
82 apientryp = '',
83 indentFuncProto = True,
84 indentFuncPointer = False,
85 alignFuncParam = 0,
86 helper_file_type = '',
87 expandEnumerants = True):
88 GeneratorOptions.__init__(self, filename, directory, apiname, profile,
89 versions, emitversions, defaultExtensions,
90 addExtensions, removeExtensions, emitExtensions, sortProcedure)
91 self.prefixText = prefixText
92 self.genFuncPointers = genFuncPointers
93 self.protectFile = protectFile
94 self.protectFeature = protectFeature
95 self.apicall = apicall
96 self.apientry = apientry
97 self.apientryp = apientryp
98 self.indentFuncProto = indentFuncProto
99 self.indentFuncPointer = indentFuncPointer
100 self.alignFuncParam = alignFuncParam
101
102# LayerChassisOutputGenerator - subclass of OutputGenerator.
103# Generates a LayerFactory layer that intercepts all API entrypoints
104# This is intended to be used as a starting point for creating custom layers
105#
106# ---- methods ----
107# LayerChassisOutputGenerator(errFile, warnFile, diagFile) - args as for
108# OutputGenerator. Defines additional internal state.
109# ---- methods overriding base class ----
110# beginFile(genOpts)
111# endFile()
112# beginFeature(interface, emit)
113# endFeature()
114# genType(typeinfo,name)
115# genStruct(typeinfo,name)
116# genGroup(groupinfo,name)
117# genEnum(enuminfo, name)
118# genCmd(cmdinfo)
119class LayerChassisOutputGenerator(OutputGenerator):
120 """Generate specified API interfaces in a specific style, such as a C header"""
121 # This is an ordered list of sections in the header file.
122 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
123 'group', 'bitmask', 'funcpointer', 'struct']
124 ALL_SECTIONS = TYPE_SECTIONS + ['command']
125
126
127
128
129 inline_custom_source_preamble = """
130// This file is ***GENERATED***. Do Not Edit.
131// See layer_chassis_generator.py for modifications.
132
133/* Copyright (c) 2015-2018 The Khronos Group Inc.
134 * Copyright (c) 2015-2018 Valve Corporation
135 * Copyright (c) 2015-2018 LunarG, Inc.
136 * Copyright (c) 2015-2018 Google Inc.
137 *
138 * Licensed under the Apache License, Version 2.0 (the "License");
139 * you may not use this file except in compliance with the License.
140 * You may obtain a copy of the License at
141 *
142 * http://www.apache.org/licenses/LICENSE-2.0
143 *
144 * Unless required by applicable law or agreed to in writing, software
145 * distributed under the License is distributed on an "AS IS" BASIS,
146 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
147 * See the License for the specific language governing permissions and
148 * limitations under the License.
149 *
150 * Author: Mark Lobodzinski <mark@lunarg.com>
151 */
152
153#include <string.h>
154#include <mutex>
155
156#define VALIDATION_ERROR_MAP_IMPL
157
158#include "vk_loader_platform.h"
159#include "vk_dispatch_table_helper.h"
160#include "vk_layer_data.h"
161#include "vk_layer_extension_utils.h"
162#include "vk_layer_logging.h"
163#include "vk_extension_helper.h"
164#include "vk_layer_utils.h"
165
166class layer_chassis;
167
168std::vector<layer_chassis *> global_interceptor_list;
169debug_report_data *report_data = VK_NULL_HANDLE;
170
171#include "chassis.h"
172
173struct instance_layer_data {
174 VkLayerInstanceDispatchTable dispatch_table;
175 VkInstance instance = VK_NULL_HANDLE;
176 debug_report_data *report_data = nullptr;
177 std::vector<VkDebugReportCallbackEXT> logging_callback;
178 std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
179 InstanceExtensions extensions;
180};
181
182struct layer_data {
183 debug_report_data *report_data = nullptr;
184 VkLayerDispatchTable dispatch_table;
185 DeviceExtensions extensions = {};
186 VkDevice device = VK_NULL_HANDLE;
187 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
188 instance_layer_data *instance_data = nullptr;
189};
190
191static std::unordered_map<void *, layer_data *> layer_data_map;
192static std::unordered_map<void *, instance_layer_data *> instance_layer_data_map;
193
194#include "interceptor_objects.h"
195
196using mutex_t = std::mutex;
197using lock_guard_t = std::lock_guard<mutex_t>;
198using unique_lock_t = std::unique_lock<mutex_t>;
199
200namespace vulkan_layer_chassis {
201
202using std::unordered_map;
203
204static mutex_t global_lock;
205
206static const VkLayerProperties global_layer = {
207 "VK_LAYER_KHRONOS_validation", VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
208};
209
210static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
211
212extern const std::unordered_map<std::string, void*> name_to_funcptr_map;
213
214
215// Manually written functions
216
217VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
218 assert(device);
219 layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
220 const auto &item = name_to_funcptr_map.find(funcName);
221 if (item != name_to_funcptr_map.end()) {
222 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
223 }
224 auto &table = device_data->dispatch_table;
225 if (!table.GetDeviceProcAddr) return nullptr;
226 return table.GetDeviceProcAddr(device, funcName);
227}
228
229VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
230 instance_layer_data *instance_data;
231 const auto &item = name_to_funcptr_map.find(funcName);
232 if (item != name_to_funcptr_map.end()) {
233 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
234 }
235 instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
236 auto &table = instance_data->dispatch_table;
237 if (!table.GetInstanceProcAddr) return nullptr;
238 return table.GetInstanceProcAddr(instance, funcName);
239}
240
241VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
242 instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
243 auto &table = instance_data->dispatch_table;
244 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
245 return table.GetPhysicalDeviceProcAddr(instance, funcName);
246}
247
248VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
249 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
250}
251
252VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
253 VkLayerProperties *pProperties) {
254 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
255}
256
257VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
258 VkExtensionProperties *pProperties) {
259 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
260 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
261
262 return VK_ERROR_LAYER_NOT_PRESENT;
263}
264
265VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
266 uint32_t *pCount, VkExtensionProperties *pProperties) {
267 if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
268
269 assert(physicalDevice);
270
271 instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
272 return instance_data->dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
273}
274
275VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
276 VkInstance *pInstance) {
277 VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
278
279 assert(chain_info->u.pLayerInfo);
280 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
281 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
282 if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
283 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
284
285 // Init dispatch array and call registration functions
286 for (auto intercept : global_interceptor_list) {
287 intercept->PreCallValidateCreateInstance(pCreateInfo, pAllocator, pInstance);
288 }
289 for (auto intercept : global_interceptor_list) {
290 intercept->PreCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
291 }
292
293 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
294
295 instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(*pInstance), instance_layer_data_map);
296 instance_data->instance = *pInstance;
297 layer_init_instance_dispatch_table(*pInstance, &instance_data->dispatch_table, fpGetInstanceProcAddr);
298 instance_data->report_data = debug_utils_create_instance(
299 &instance_data->dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
300 instance_data->extensions.InitFromInstanceCreateInfo((pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0), pCreateInfo);
301 layer_debug_messenger_actions(instance_data->report_data, instance_data->logging_messenger, pAllocator, "lunarg_validation_layer");
302 report_data = instance_data->report_data;
303
304 for (auto intercept : global_interceptor_list) {
305 intercept->PostCallRecordCreateInstance(pCreateInfo, pAllocator, pInstance);
306 }
307
308 return result;
309}
310
311VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
312 dispatch_key key = get_dispatch_key(instance);
313 instance_layer_data *instance_data = GetLayerDataPtr(key, instance_layer_data_map);
314 for (auto intercept : global_interceptor_list) {
315 intercept->PreCallValidateDestroyInstance(instance, pAllocator);
316 }
317 for (auto intercept : global_interceptor_list) {
318 intercept->PreCallRecordDestroyInstance(instance, pAllocator);
319 }
320
321 instance_data->dispatch_table.DestroyInstance(instance, pAllocator);
322
323 lock_guard_t lock(global_lock);
324 for (auto intercept : global_interceptor_list) {
325 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
326 }
327 // Clean up logging callback, if any
328 while (instance_data->logging_messenger.size() > 0) {
329 VkDebugUtilsMessengerEXT messenger = instance_data->logging_messenger.back();
330 layer_destroy_messenger_callback(instance_data->report_data, messenger, pAllocator);
331 instance_data->logging_messenger.pop_back();
332 }
333 while (instance_data->logging_callback.size() > 0) {
334 VkDebugReportCallbackEXT callback = instance_data->logging_callback.back();
335 layer_destroy_report_callback(instance_data->report_data, callback, pAllocator);
336 instance_data->logging_callback.pop_back();
337 }
338 for (auto intercept : global_interceptor_list) {
339 intercept->PostCallRecordDestroyInstance(instance, pAllocator);
340 }
341 layer_debug_utils_destroy_instance(instance_data->report_data);
342 FreeLayerDataPtr(key, instance_layer_data_map);
343}
344
345VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
346 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
347 instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(gpu), instance_layer_data_map);
348
349 unique_lock_t lock(global_lock);
350 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
351 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
352 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
353 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_data->instance, "vkCreateDevice");
354 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
355
356 for (auto intercept : global_interceptor_list) {
357 intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
358 }
359 for (auto intercept : global_interceptor_list) {
360 intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
361 }
362 lock.unlock();
363
364 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
365
366 lock.lock();
367 for (auto intercept : global_interceptor_list) {
368 intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
369 }
370 layer_data *device_data = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
371 device_data->instance_data = instance_data;
372 layer_init_device_dispatch_table(*pDevice, &device_data->dispatch_table, fpGetDeviceProcAddr);
373 device_data->device = *pDevice;
374 device_data->physical_device = gpu;
375 device_data->report_data = layer_debug_utils_create_device(instance_data->report_data, *pDevice);
376 VkPhysicalDeviceProperties physical_device_properties{};
377 instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &physical_device_properties);
378 device_data->extensions.InitFromDeviceCreateInfo(&instance_data->extensions, physical_device_properties.apiVersion, pCreateInfo);
379 lock.unlock();
380
381 return result;
382}
383
384VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
385 dispatch_key key = get_dispatch_key(device);
386 layer_data *device_data = GetLayerDataPtr(key, layer_data_map);
387
388 unique_lock_t lock(global_lock);
389 for (auto intercept : global_interceptor_list) {
390 intercept->PreCallValidateDestroyDevice(device, pAllocator);
391 }
392 for (auto intercept : global_interceptor_list) {
393 intercept->PreCallRecordDestroyDevice(device, pAllocator);
394 }
395 layer_debug_utils_destroy_device(device);
396 lock.unlock();
397
398 device_data->dispatch_table.DestroyDevice(device, pAllocator);
399
400 lock.lock();
401 for (auto intercept : global_interceptor_list) {
402 intercept->PostCallRecordDestroyDevice(device, pAllocator);
403 }
404
405 FreeLayerDataPtr(key, layer_data_map);
406}
407
408VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
409 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
410 const VkAllocationCallbacks *pAllocator,
411 VkDebugReportCallbackEXT *pCallback) {
412 instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
413 for (auto intercept : global_interceptor_list) {
414 intercept->PreCallValidateCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
415 }
416 for (auto intercept : global_interceptor_list) {
417 intercept->PreCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
418 }
419 VkResult result = instance_data->dispatch_table.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
420 result = layer_create_report_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pCallback);
421 for (auto intercept : global_interceptor_list) {
422 intercept->PostCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
423 }
424 return result;
425}
426
427VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
428 const VkAllocationCallbacks *pAllocator) {
429 instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
430 for (auto intercept : global_interceptor_list) {
431 intercept->PreCallValidateDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
432 }
433 for (auto intercept : global_interceptor_list) {
434 intercept->PreCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
435 }
436 instance_data->dispatch_table.DestroyDebugReportCallbackEXT(instance, callback, pAllocator);
437 layer_destroy_report_callback(instance_data->report_data, callback, pAllocator);
438 for (auto intercept : global_interceptor_list) {
439 intercept->PostCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
440 }
441}
442"""
443
444 inline_custom_source_postamble = """
445// loader-layer interface v0, just wrappers since there is only a layer
446
447VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
448 VkExtensionProperties *pProperties) {
449 return vulkan_layer_chassis::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
450}
451
452VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
453 VkLayerProperties *pProperties) {
454 return vulkan_layer_chassis::EnumerateInstanceLayerProperties(pCount, pProperties);
455}
456
457VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
458 VkLayerProperties *pProperties) {
459 // the layer command handles VK_NULL_HANDLE just fine internally
460 assert(physicalDevice == VK_NULL_HANDLE);
461 return vulkan_layer_chassis::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
462}
463
464VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
465 const char *pLayerName, uint32_t *pCount,
466 VkExtensionProperties *pProperties) {
467 // the layer command handles VK_NULL_HANDLE just fine internally
468 assert(physicalDevice == VK_NULL_HANDLE);
469 return vulkan_layer_chassis::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
470}
471
472VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
473 return vulkan_layer_chassis::GetDeviceProcAddr(dev, funcName);
474}
475
476VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
477 return vulkan_layer_chassis::GetInstanceProcAddr(instance, funcName);
478}
479
480VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
481 const char *funcName) {
482 return vulkan_layer_chassis::GetPhysicalDeviceProcAddr(instance, funcName);
483}
484
485VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
486 assert(pVersionStruct != NULL);
487 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
488
489 // Fill in the function pointers if our version is at least capable of having the structure contain them.
490 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
491 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
492 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
493 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
494 }
495
496 return VK_SUCCESS;
497}"""
498
499
500
501
502
503 def __init__(self,
504 errFile = sys.stderr,
505 warnFile = sys.stderr,
506 diagFile = sys.stdout):
507 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
508 # Internal state - accumulators for different inner block text
509 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
510 self.intercepts = []
511 self.layer_factory = '' # String containing base layer factory class definition
512
513 # Check if the parameter passed in is a pointer to an array
514 def paramIsArray(self, param):
515 return param.attrib.get('len') is not None
516
517 # Check if the parameter passed in is a pointer
518 def paramIsPointer(self, param):
519 ispointer = False
520 for elem in param:
521 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
522 ispointer = True
523 return ispointer
524
525 # Check if an object is a non-dispatchable handle
526 def isHandleTypeNonDispatchable(self, handletype):
527 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
528 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
529 return True
530 else:
531 return False
532
533 # Check if an object is a dispatchable handle
534 def isHandleTypeDispatchable(self, handletype):
535 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
536 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
537 return True
538 else:
539 return False
540
541 def beginFile(self, genOpts):
542 OutputGenerator.beginFile(self, genOpts)
543 # Multiple inclusion protection & C++ namespace.
544 self.header = False
545 if (self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
546 self.header = True
547 write('#pragma once', file=self.outFile)
548 self.newline()
549 # User-supplied prefix text, if any (list of strings)
550 if self.header:
551 if (genOpts.prefixText):
552 for s in genOpts.prefixText:
553 write(s, file=self.outFile)
554 write('#include "vulkan/vk_layer.h"', file=self.outFile)
555 write('#include <unordered_map>\n', file=self.outFile)
556 write('class layer_chassis;', file=self.outFile)
557 write('extern std::vector<layer_chassis *> global_interceptor_list;', file=self.outFile)
558 write('extern debug_report_data *report_data;\n', file=self.outFile)
559 write('namespace vulkan_layer_chassis {\n', file=self.outFile)
560 else:
561 write(self.inline_custom_source_preamble, file=self.outFile)
562
563 # Initialize Enum Section
564 self.layer_factory += '// Layer Factory base class definition\n'
565 self.layer_factory += 'class layer_chassis {\n'
566 self.layer_factory += ' public:\n'
567 self.layer_factory += ' layer_chassis() {\n'
568 self.layer_factory += ' global_interceptor_list.emplace_back(this);\n'
569 self.layer_factory += ' };\n'
570 self.layer_factory += '\n'
571 self.layer_factory += ' std::string layer_name = "CHASSIS";\n'
572 self.layer_factory += '\n'
573 self.layer_factory += ' // Pre/post hook point declarations\n'
574 #
575 def endFile(self):
576 # Finish C++ namespace and multiple inclusion protection
577 self.newline()
578 if not self.header:
579 # Record intercepted procedures
580 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
581 write('const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
582 write('\n'.join(self.intercepts), file=self.outFile)
583 write('};\n', file=self.outFile)
584 self.newline()
585 write('} // namespace vulkan_layer_chassis', file=self.outFile)
586 if self.header:
587 self.newline()
588 # Output Layer Factory Class Definitions
589 self.layer_factory += '};\n'
590 write(self.layer_factory, file=self.outFile)
591 else:
592 write(self.inline_custom_source_postamble, file=self.outFile)
593 # Finish processing in superclass
594 OutputGenerator.endFile(self)
595
596 def beginFeature(self, interface, emit):
597 # Start processing in superclass
598 OutputGenerator.beginFeature(self, interface, emit)
599 # Get feature extra protect
600 self.featureExtraProtect = GetFeatureProtect(interface)
601 # Accumulate includes, defines, types, enums, function pointer typedefs, end function prototypes separately for this
602 # feature. They're only printed in endFeature().
603 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
604
605 def endFeature(self):
606 # Actually write the interface to the output file.
607 if (self.emit):
608 self.newline()
609 # If type declarations are needed by other features based on this one, it may be necessary to suppress the ExtraProtect,
610 # or move it below the 'for section...' loop.
611 if (self.featureExtraProtect != None):
612 write('#ifdef', self.featureExtraProtect, file=self.outFile)
613 for section in self.TYPE_SECTIONS:
614 contents = self.sections[section]
615 if contents:
616 write('\n'.join(contents), file=self.outFile)
617 self.newline()
618 if (self.sections['command']):
619 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
620 self.newline()
621 if (self.featureExtraProtect != None):
622 write('#endif /*', self.featureExtraProtect, '*/', file=self.outFile)
623 # Finish processing in superclass
624 OutputGenerator.endFeature(self)
625 #
626 # Append a definition to the specified section
627 def appendSection(self, section, text):
628 self.sections[section].append(text)
629 #
630 # Type generation
631 def genType(self, typeinfo, name, alias):
632 pass
633 #
634 # Struct (e.g. C "struct" type) generation. This is a special case of the <type> tag where the contents are
635 # interpreted as a set of <member> tags instead of freeform C type declarations. The <member> tags are just like <param>
636 # tags - they are a declaration of a struct or union member. Only simple member declarations are supported (no nested
637 # structs etc.)
638 def genStruct(self, typeinfo, typeName):
639 OutputGenerator.genStruct(self, typeinfo, typeName)
640 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
641 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
642 for member in typeinfo.elem.findall('.//member'):
643 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
644 body += ';\n'
645 body += '} ' + typeName + ';\n'
646 self.appendSection('struct', body)
647 #
648 # Group (e.g. C "enum" type) generation. These are concatenated together with other types.
649 def genGroup(self, groupinfo, groupName, alias):
650 pass
651 # Enumerant generation
652 # <enum> tags may specify their values in several ways, but are usually just integers.
653 def genEnum(self, enuminfo, name, alias):
654 pass
655 #
656 # Customize Cdecl for layer factory base class
657 def BaseClassCdecl(self, elem, name):
658 raw = self.makeCDecls(elem)[1]
659
660 # Toss everything before the undecorated name
661 prototype = raw.split("VKAPI_PTR *PFN_vk")[1]
662 prototype = prototype.replace(")", "", 1)
663 prototype = prototype.replace(";", " {};")
664
665 if 'GetPhysicalDeviceMemoryProperties' in prototype:
666 stop = 'here'
667
668 # Build up pre/post call virtual function declarations
669 pre_call_validate = 'virtual bool PreCallValidate' + prototype
670 pre_call_validate = pre_call_validate.replace("{}", " { return false; }")
671 pre_call_record = 'virtual void PreCallRecord' + prototype
672 post_call_record = 'virtual void PostCallRecord' + prototype
673 return ' %s\n %s\n %s\n' % (pre_call_validate, pre_call_record, post_call_record)
674 #
675 # Command generation
676 def genCmd(self, cmdinfo, name, alias):
677 ignore_functions = [
678 'vkEnumerateInstanceVersion'
679 ]
680
681 if name in ignore_functions:
682 return
683
684 if self.header: # In the header declare all intercepts
685 self.appendSection('command', '')
686 self.appendSection('command', self.makeCDecls(cmdinfo.elem)[0])
687 if (self.featureExtraProtect != None):
688 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
689 self.layer_factory += '#ifdef %s\n' % self.featureExtraProtect
690 # Update base class with virtual function declarations
691 self.layer_factory += self.BaseClassCdecl(cmdinfo.elem, name)
692 # Update function intercepts
693 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
694 if (self.featureExtraProtect != None):
695 self.intercepts += [ '#endif' ]
696 self.layer_factory += '#endif\n'
697 return
698
699 manual_functions = [
700 # Include functions here to be interecpted w/ manually implemented function bodies
701 'vkGetDeviceProcAddr',
702 'vkGetInstanceProcAddr',
703 'vkGetPhysicalDeviceProcAddr',
704 'vkCreateDevice',
705 'vkDestroyDevice',
706 'vkCreateInstance',
707 'vkDestroyInstance',
708 'vkCreateDebugReportCallbackEXT',
709 'vkDestroyDebugReportCallbackEXT',
710 'vkEnumerateInstanceLayerProperties',
711 'vkEnumerateInstanceExtensionProperties',
712 'vkEnumerateDeviceLayerProperties',
713 'vkEnumerateDeviceExtensionProperties',
714 ]
715 if name in manual_functions:
716 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
717 return
718 # Record that the function will be intercepted
719 if (self.featureExtraProtect != None):
720 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
721 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
722 if (self.featureExtraProtect != None):
723 self.intercepts += [ '#endif' ]
724 OutputGenerator.genCmd(self, cmdinfo, name, alias)
725 #
726 decls = self.makeCDecls(cmdinfo.elem)
727 self.appendSection('command', '')
728 self.appendSection('command', '%s {' % decls[0][:-1])
729 # Setup common to call wrappers. First parameter is always dispatchable
730 dispatchable_type = cmdinfo.elem.find('param/type').text
731 dispatchable_name = cmdinfo.elem.find('param/name').text
732 # Default to device
733 device_or_instance = 'device'
734 map_name = 'layer_data'
735 dispatch_table_name = 'VkLayerDispatchTable'
736 # Set to instance as necessary
737 if dispatchable_type in ["VkPhysicalDevice", "VkInstance"] or name == 'vkCreateInstance':
738 device_or_instance = 'instance'
739 dispatch_table_name = 'VkLayerInstanceDispatchTable'
740 map_name = 'instance_layer_data'
741 self.appendSection('command', ' %s *%s_data = GetLayerDataPtr(get_dispatch_key(%s), %s_map);' % (map_name, device_or_instance, dispatchable_name, map_name))
742 api_function_name = cmdinfo.elem.attrib.get('name')
743 params = cmdinfo.elem.findall('param/name')
744 paramstext = ', '.join([str(param.text) for param in params])
745 API = api_function_name.replace('vk','%s_data->dispatch_table.' % (device_or_instance),1)
746
747 # Declare result variable, if any.
748 return_map = {
749 'void': 'return;',
750 'VkResult': 'return VK_ERROR_VALIDATION_FAILED_EXT;',
751 'PFN_vkVoidFunction': 'return nullptr;',
752 'VkBool32': 'return VK_FALSE;',
753 }
754 resulttype = cmdinfo.elem.find('proto/type')
755 assignresult = ''
756 if (resulttype.text != 'void'):
757 assignresult = resulttype.text + ' result = '
758
759 # Set up skip and locking
760 self.appendSection('command', ' {')
761 self.appendSection('command', ' bool skip = false;')
762 self.appendSection('command', ' std::lock_guard<std::mutex> lock(global_lock);')
763
764 # Generate pre-call validation source code
765 self.appendSection('command', ' for (auto intercept : global_interceptor_list) {')
766 self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
767 self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
768 self.appendSection('command', ' }')
769
770 # Generate pre-call state recording source code
771 self.appendSection('command', ' for (auto intercept : global_interceptor_list) {')
772 self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
773 self.appendSection('command', ' }')
774 self.appendSection('command', ' }')
775
776 self.appendSection('command', ' ' + assignresult + API + '(' + paramstext + ');')
777
778 # Generate post-call object processing source code
779 self.appendSection('command', ' {')
780 self.appendSection('command', ' std::lock_guard<std::mutex> lock(global_lock);')
781 self.appendSection('command', ' for (auto intercept : global_interceptor_list) {')
782 self.appendSection('command', ' intercept->PostCallRecord%s(%s);' % (api_function_name[2:], paramstext))
783 self.appendSection('command', ' }')
784 self.appendSection('command', ' }')
785
786 # Return result variable, if any.
787 if (resulttype.text != 'void'):
788 self.appendSection('command', ' return result;')
789 self.appendSection('command', '}')
790 #
791 # Override makeProtoName to drop the "vk" prefix
792 def makeProtoName(self, name, tail):
793 return self.genOpts.apientry + name[2:] + tail