layers: Update codegen for OT removal
Removed object_tracker code from vk_layer_generate.py.
Change-Id: I0ebd1c379deabfb0712d6692751145f34b430459
diff --git a/vk-layer-generate.py b/vk-layer-generate.py
index bde7e34..5301e26 100755
--- a/vk-layer-generate.py
+++ b/vk-layer-generate.py
@@ -303,7 +303,7 @@
r_body.append(' VkDebugReportCallbackEXT* pCallback)')
r_body.append('{')
# Switch to this code section for the new per-instance storage and debug callbacks
- if self.layer_name in ['object_tracker', 'unique_objects']:
+ if self.layer_name in ['unique_objects']:
r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
r_body.append(' VkResult result = pInstanceTable->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);')
r_body.append(' if (VK_SUCCESS == result) {')
@@ -331,7 +331,7 @@
r_body.append('VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, const VkAllocationCallbacks *pAllocator)')
r_body.append('{')
# Switch to this code section for the new per-instance storage and debug callbacks
- if self.layer_name in ['object_tracker', 'unique_objects']:
+ if self.layer_name in ['unique_objects']:
r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
else:
r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = instance_dispatch_table(instance);')
@@ -347,10 +347,7 @@
r_body.append('VKAPI_ATTR void VKAPI_CALL DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg)')
r_body.append('{')
# Switch to this code section for the new per-instance storage and debug callbacks
- if self.layer_name == 'object_tracker':
- r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
- else:
- r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = instance_dispatch_table(instance);')
+ r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = instance_dispatch_table(instance);')
r_body.append(' pInstanceTable->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);')
r_body.append('}')
return "\n".join(r_body)
@@ -503,30 +500,13 @@
def _generate_layer_introspection_function(self):
body = []
body.append('%s' % self.lineinfo.get())
- if self.layer_name == 'object_tracker':
- body.append('static const VkExtensionProperties instance_extensions[] = {')
- body.append(' {')
- body.append(' VK_EXT_DEBUG_REPORT_EXTENSION_NAME,')
- body.append(' VK_EXT_DEBUG_REPORT_SPEC_VERSION')
- body.append(' }')
- body.append('};')
- body.append('')
-
- body.append('static const VkLayerProperties globalLayerProps = {')
- body.append(' "VK_LAYER_LUNARG_%s",' % self.layer_name)
- body.append(' VK_LAYER_API_VERSION, // specVersion')
- body.append(' 1, // implementationVersion')
- body.append(' "LunarG Validation Layer"')
- body.append('};')
- body.append('')
- else:
- body.append('static const VkLayerProperties globalLayerProps = {')
- body.append(' "VK_LAYER_GOOGLE_%s",' % self.layer_name)
- body.append(' VK_LAYER_API_VERSION, // specVersion')
- body.append(' 1, // implementationVersion')
- body.append(' "Google Validation Layer"')
- body.append('};')
- body.append('')
+ body.append('static const VkLayerProperties globalLayerProps = {')
+ body.append(' "VK_LAYER_GOOGLE_%s",' % self.layer_name)
+ body.append(' VK_LAYER_API_VERSION, // specVersion')
+ body.append(' 1, // implementationVersion')
+ body.append(' "Google Validation Layer"')
+ body.append('};')
+ body.append('')
body.append('VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties* pProperties)')
body.append('{')
@@ -541,10 +521,7 @@
body.append('VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties* pProperties)')
body.append('{')
body.append(' if (pLayerName && !strcmp(pLayerName, globalLayerProps.layerName))')
- if self.layer_name == 'object_tracker':
- body.append(' return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);')
- else:
- body.append(' return util_GetExtensionProperties(0, NULL, pCount, pProperties);')
+ body.append(' return util_GetExtensionProperties(0, NULL, pCount, pProperties);')
body.append('')
body.append(' return VK_ERROR_LAYER_NOT_PRESENT;')
body.append('}')
@@ -568,7 +545,7 @@
#
# New style of GPA Functions for the new layer_data/layer_logging changes
#
- if self.layer_name in ['object_tracker', 'unique_objects']:
+ if self.layer_name in ['unique_objects']:
for ext_enable, ext_list in extensions:
func_body.append('%s' % self.lineinfo.get())
func_body.append('static inline PFN_vkVoidFunction intercept_%s_command(const char *name, VkDevice dev)' % ext_enable)
@@ -766,677 +743,6 @@
func_body.append('')
return "\n".join(func_body)
-class ObjectTrackerSubcommand(Subcommand):
- def generate_header(self):
- header_txt = []
- header_txt.append('%s' % self.lineinfo.get())
- header_txt.append('#include "vk_loader_platform.h"')
- header_txt.append('#include "vulkan/vulkan.h"')
- header_txt.append('')
- header_txt.append('#include <stdio.h>')
- header_txt.append('#include <stdlib.h>')
- header_txt.append('#include <string.h>')
- header_txt.append('#include <cinttypes>')
- header_txt.append('')
- header_txt.append('#include <unordered_map>')
- header_txt.append('')
- header_txt.append('#include "vulkan/vk_layer.h"')
- header_txt.append('#include "vk_layer_config.h"')
- header_txt.append('#include "vk_layer_table.h"')
- header_txt.append('#include "vk_layer_data.h"')
- header_txt.append('#include "vk_layer_logging.h"')
- header_txt.append('')
-# NOTE: The non-autoGenerated code is in the object_tracker.h header file
- header_txt.append('#include "object_tracker.h"')
- header_txt.append('')
- return "\n".join(header_txt)
-
- def generate_maps(self):
- maps_txt = []
- for o in vulkan.object_type_list:
- maps_txt.append('std::unordered_map<uint64_t, OBJTRACK_NODE*> %sMap;' % (o))
- return "\n".join(maps_txt)
-
- def _gather_object_uses(self, obj_list, struct_type, obj_set):
- # for each member of struct_type
- # add objs in obj_list to obj_set
- # call self for structs
- for m in sorted(vk_helper.struct_dict[struct_type]):
- if vk_helper.struct_dict[struct_type][m]['type'] in obj_list:
- obj_set.add(vk_helper.struct_dict[struct_type][m]['type'])
- elif vk_helper.is_type(vk_helper.struct_dict[struct_type][m]['type'], 'struct'):
- obj_set = obj_set.union(self._gather_object_uses(obj_list, vk_helper.struct_dict[struct_type][m]['type'], obj_set))
- return obj_set
-
- def generate_procs(self):
- procs_txt = []
- # First parse through funcs and gather dict of all objects seen by each call
- obj_use_dict = {}
- proto_list = []
- for grp in vulkan.extensions:
- proto_list += grp.protos
- #vulkan.core.protos + vulkan.ext_khr_surface.protos + vulkan.ext_khr_surface.protos + vulkan.ext_khr_win32_surface.protos + vulkan.ext_khr_device_swapchain.protos
- for proto in proto_list:
- disp_obj = proto.params[0].ty.strip('*').replace('const ', '')
- if disp_obj in vulkan.object_dispatch_list:
- if disp_obj not in obj_use_dict:
- obj_use_dict[disp_obj] = set()
- for p in proto.params[1:]:
- base_type = p.ty.strip('*').replace('const ', '')
- if base_type in vulkan.object_type_list:
- obj_use_dict[disp_obj].add(base_type)
- if vk_helper.is_type(base_type, 'struct'):
- obj_use_dict[disp_obj] = self._gather_object_uses(vulkan.object_type_list, base_type, obj_use_dict[disp_obj])
- #for do in obj_use_dict:
- # print("Disp obj %s has uses for objs: %s" % (do, ', '.join(obj_use_dict[do])))
-
- for o in vulkan.object_type_list:# vulkan.core.objects:
- procs_txt.append('%s' % self.lineinfo.get())
- name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o)
- name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
- if o in vulkan.object_dispatch_list:
- procs_txt.append('static void create_%s(%s dispatchable_object, %s vkObj, VkDebugReportObjectTypeEXT objType)' % (name, o, o))
- elif o in ['VkSurfaceKHR', 'VkDisplayKHR', 'VkDisplayModeKHR']:
- procs_txt.append('static void create_%s(VkPhysicalDevice dispatchable_object, %s vkObj, VkDebugReportObjectTypeEXT objType)' % (name, o))
- else:
- procs_txt.append('static void create_%s(VkDevice dispatchable_object, %s vkObj, VkDebugReportObjectTypeEXT objType)' % (name, o))
- procs_txt.append('{')
- procs_txt.append(' log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFORMATION_BIT_EXT, objType,(uint64_t)(vkObj), __LINE__, OBJTRACK_NONE, "OBJTRACK",')
- procs_txt.append(' "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64 , object_track_index++, string_VkDebugReportObjectTypeEXT(objType),')
- procs_txt.append(' (uint64_t)(vkObj));')
- procs_txt.append('')
- procs_txt.append(' OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE;')
- procs_txt.append(' pNewObjNode->belongsTo = (uint64_t)dispatchable_object;')
- procs_txt.append(' pNewObjNode->objType = objType;')
- procs_txt.append(' pNewObjNode->status = OBJSTATUS_NONE;')
- procs_txt.append(' pNewObjNode->vkObj = (uint64_t)(vkObj);')
- procs_txt.append(' %sMap[(uint64_t)vkObj] = pNewObjNode;' % (o))
- procs_txt.append(' uint32_t objIndex = objTypeToIndex(objType);')
- procs_txt.append(' numObjs[objIndex]++;')
- procs_txt.append(' numTotalObjs++;')
- procs_txt.append('}')
- procs_txt.append('')
- procs_txt.append('%s' % self.lineinfo.get())
- if o in vulkan.object_dispatch_list:
- procs_txt.append('static void destroy_%s(%s dispatchable_object, %s object)' % (name, o, o))
- elif o in ['VkSurfaceKHR', 'VkDisplayKHR', 'VkDisplayModeKHR']:
- procs_txt.append('static void destroy_%s(VkPhysicalDevice dispatchable_object, %s object)' % (name, o))
- else:
- procs_txt.append('static void destroy_%s(VkDevice dispatchable_object, %s object)' % (name, o))
- procs_txt.append('{')
- procs_txt.append(' uint64_t object_handle = (uint64_t)(object);')
- procs_txt.append(' auto it = %sMap.find(object_handle);' % o)
- procs_txt.append(' if (it != %sMap.end()) {' % o)
- procs_txt.append(' OBJTRACK_NODE* pNode = it->second;')
- procs_txt.append(' uint32_t objIndex = objTypeToIndex(pNode->objType);')
- procs_txt.append(' assert(numTotalObjs > 0);')
- procs_txt.append(' numTotalObjs--;')
- procs_txt.append(' assert(numObjs[objIndex] > 0);')
- procs_txt.append(' numObjs[objIndex]--;')
- procs_txt.append(' log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFORMATION_BIT_EXT, pNode->objType, object_handle, __LINE__, OBJTRACK_NONE, "OBJTRACK",')
- procs_txt.append(' "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%" PRIu64 " total objs remain & %" PRIu64 " %s objs).",')
- procs_txt.append(' string_VkDebugReportObjectTypeEXT(pNode->objType), (uint64_t)(object), numTotalObjs, numObjs[objIndex],')
- procs_txt.append(' string_VkDebugReportObjectTypeEXT(pNode->objType));')
- procs_txt.append(' delete pNode;')
- procs_txt.append(' %sMap.erase(it);' % (o))
- procs_txt.append(' } else {')
- procs_txt.append(' log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT ) 0,')
- procs_txt.append(' object_handle, __LINE__, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",')
- procs_txt.append(' "Unable to remove obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?",')
- procs_txt.append(' object_handle);')
- procs_txt.append(' }')
- procs_txt.append('}')
- procs_txt.append('')
- # Generate the permutations of validate_* functions where for each
- # dispatchable object type, we have a corresponding validate_* function
- # for that object and all non-dispatchable objects that are used in API
- # calls with that dispatchable object.
- procs_txt.append('//%s' % str(sorted(obj_use_dict)))
- for do in sorted(obj_use_dict):
- name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', do)
- name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
- # First create validate_* func for disp obj
- procs_txt.append('%s' % self.lineinfo.get())
- procs_txt.append('static bool validate_%s(%s dispatchable_object, %s object, VkDebugReportObjectTypeEXT objType, bool null_allowed)' % (name, do, do))
- procs_txt.append('{')
- procs_txt.append(' if (null_allowed && (object == VK_NULL_HANDLE))')
- procs_txt.append(' return false;')
- procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (do, do))
- procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, objType, (uint64_t)(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
- procs_txt.append(' "Invalid %s Object 0x%%" PRIx64 ,(uint64_t)(object));' % do)
- procs_txt.append(' }')
- procs_txt.append(' return false;')
- procs_txt.append('}')
- procs_txt.append('')
- for o in sorted(obj_use_dict[do]):
- if o == do: # We already generated this case above so skip here
- continue
- name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o)
- name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
- procs_txt.append('%s' % self.lineinfo.get())
- procs_txt.append('static bool validate_%s(%s dispatchable_object, %s object, VkDebugReportObjectTypeEXT objType, bool null_allowed)' % (name, do, o))
- procs_txt.append('{')
- procs_txt.append(' if (null_allowed && (object == VK_NULL_HANDLE))')
- procs_txt.append(' return false;')
- if o == "VkImage":
- procs_txt.append(' // We need to validate normal image objects and those from the swapchain')
- procs_txt.append(' if ((%sMap.find((uint64_t)object) == %sMap.end()) &&' % (o, o))
- procs_txt.append(' (swapchainImageMap.find((uint64_t)object) == swapchainImageMap.end())) {')
- else:
- procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (o, o))
- procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, objType, (uint64_t)(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
- procs_txt.append(' "Invalid %s Object 0x%%" PRIx64, (uint64_t)(object));' % o)
- procs_txt.append(' }')
- procs_txt.append(' return false;')
- procs_txt.append('}')
- procs_txt.append('')
- procs_txt.append('')
- return "\n".join(procs_txt)
-
- def generate_destroy_instance(self):
- gedi_txt = []
- gedi_txt.append('%s' % self.lineinfo.get())
- gedi_txt.append('VKAPI_ATTR void VKAPI_CALL DestroyInstance(')
- gedi_txt.append('VkInstance instance,')
- gedi_txt.append('const VkAllocationCallbacks* pAllocator)')
- gedi_txt.append('{')
- gedi_txt.append(' std::unique_lock<std::mutex> lock(global_lock);')
- gedi_txt.append('')
- gedi_txt.append(' dispatch_key key = get_dispatch_key(instance);')
- gedi_txt.append(' layer_data *my_data = get_my_data_ptr(key, layer_data_map);')
- gedi_txt.append('')
- gedi_txt.append(' // Enable the temporary callback(s) here to catch cleanup issues:')
- gedi_txt.append(' bool callback_setup = false;')
- gedi_txt.append(' if (my_data->num_tmp_callbacks > 0) {')
- gedi_txt.append(' if (!layer_enable_tmp_callbacks(my_data->report_data,')
- gedi_txt.append(' my_data->num_tmp_callbacks,')
- gedi_txt.append(' my_data->tmp_dbg_create_infos,')
- gedi_txt.append(' my_data->tmp_callbacks)) {')
- gedi_txt.append(' callback_setup = true;')
- gedi_txt.append(' }')
- gedi_txt.append(' }')
- gedi_txt.append('')
- gedi_txt.append(' validate_instance(instance, instance, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, false);')
- gedi_txt.append('')
- gedi_txt.append(' destroy_instance(instance, instance);')
- gedi_txt.append(' // Report any remaining objects in LL')
- gedi_txt.append('')
- gedi_txt.append(' for (auto iit = VkDeviceMap.begin(); iit != VkDeviceMap.end();) {')
- gedi_txt.append(' OBJTRACK_NODE* pNode = iit->second;')
- gedi_txt.append(' if (pNode->belongsTo == (uint64_t)instance) {')
- gedi_txt.append(' log_msg(mid(instance), VK_DEBUG_REPORT_ERROR_BIT_EXT, pNode->objType, pNode->vkObj, __LINE__, OBJTRACK_OBJECT_LEAK, "OBJTRACK",')
- gedi_txt.append(' "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),')
- gedi_txt.append(' pNode->vkObj);')
- for o in vulkan.core.objects:
- if o in ['VkInstance', 'VkPhysicalDevice', 'VkQueue', 'VkDevice']:
- continue
- gedi_txt.append(' for (auto idt = %sMap.begin(); idt != %sMap.end();) {' % (o, o))
- gedi_txt.append(' OBJTRACK_NODE* pNode = idt->second;')
- gedi_txt.append(' if (pNode->belongsTo == iit->first) {')
- gedi_txt.append(' log_msg(mid(instance), VK_DEBUG_REPORT_ERROR_BIT_EXT, pNode->objType, pNode->vkObj, __LINE__, OBJTRACK_OBJECT_LEAK, "OBJTRACK",')
- gedi_txt.append(' "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),')
- gedi_txt.append(' pNode->vkObj);')
- gedi_txt.append(' %sMap.erase(idt++);' % o )
- gedi_txt.append(' } else {')
- gedi_txt.append(' ++idt;')
- gedi_txt.append(' }')
- gedi_txt.append(' }')
- gedi_txt.append(' VkDeviceMap.erase(iit++);')
- gedi_txt.append(' } else {')
- gedi_txt.append(' ++iit;')
- gedi_txt.append(' }')
- gedi_txt.append(' }')
- gedi_txt.append('')
- gedi_txt.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(object_tracker_instance_table_map, instance);')
- gedi_txt.append(' pInstanceTable->DestroyInstance(instance, pAllocator);')
- gedi_txt.append('')
- gedi_txt.append(' // Disable and cleanup the temporary callback(s):')
- gedi_txt.append(' if (callback_setup) {')
- gedi_txt.append(' layer_disable_tmp_callbacks(my_data->report_data,')
- gedi_txt.append(' my_data->num_tmp_callbacks,')
- gedi_txt.append(' my_data->tmp_callbacks);')
- gedi_txt.append(' }')
- gedi_txt.append(' if (my_data->num_tmp_callbacks > 0) {')
- gedi_txt.append(' layer_free_tmp_callbacks(my_data->tmp_dbg_create_infos,')
- gedi_txt.append(' my_data->tmp_callbacks);')
- gedi_txt.append(' my_data->num_tmp_callbacks = 0;')
- gedi_txt.append(' }')
- gedi_txt.append('')
- gedi_txt.append(' // Clean up logging callback, if any')
- gedi_txt.append(' while (my_data->logging_callback.size() > 0) {')
- gedi_txt.append(' VkDebugReportCallbackEXT callback = my_data->logging_callback.back();')
- gedi_txt.append(' layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);')
- gedi_txt.append(' my_data->logging_callback.pop_back();')
- gedi_txt.append(' }')
- gedi_txt.append('')
- gedi_txt.append(' layer_debug_report_destroy_instance(mid(instance));')
- gedi_txt.append(' layer_data_map.erase(key);')
- gedi_txt.append('')
- gedi_txt.append(' instanceExtMap.erase(pInstanceTable);')
- gedi_txt.append(' lock.unlock();')
- # The loader holds a mutex that protects this from other threads
- gedi_txt.append(' object_tracker_instance_table_map.erase(key);')
- gedi_txt.append('}')
- gedi_txt.append('')
- return "\n".join(gedi_txt)
-
- def generate_destroy_device(self):
- gedd_txt = []
- gedd_txt.append('%s' % self.lineinfo.get())
- gedd_txt.append('VKAPI_ATTR void VKAPI_CALL DestroyDevice(')
- gedd_txt.append('VkDevice device,')
- gedd_txt.append('const VkAllocationCallbacks* pAllocator)')
- gedd_txt.append('{')
- gedd_txt.append(' std::unique_lock<std::mutex> lock(global_lock);')
- gedd_txt.append(' validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);')
- gedd_txt.append('')
- gedd_txt.append(' destroy_device(device, device);')
- gedd_txt.append(' // Report any remaining objects associated with this VkDevice object in LL')
- for o in vulkan.core.objects:
- # DescriptorSets and Command Buffers are destroyed through their pools, not explicitly
- if o in ['VkInstance', 'VkPhysicalDevice', 'VkQueue', 'VkDevice', 'VkDescriptorSet', 'VkCommandBuffer']:
- continue
- gedd_txt.append(' for (auto it = %sMap.begin(); it != %sMap.end();) {' % (o, o))
- gedd_txt.append(' OBJTRACK_NODE* pNode = it->second;')
- gedd_txt.append(' if (pNode->belongsTo == (uint64_t)device) {')
- gedd_txt.append(' log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, pNode->objType, pNode->vkObj, __LINE__, OBJTRACK_OBJECT_LEAK, "OBJTRACK",')
- gedd_txt.append(' "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),')
- gedd_txt.append(' pNode->vkObj);')
- gedd_txt.append(' %sMap.erase(it++);' % o )
- gedd_txt.append(' } else {')
- gedd_txt.append(' ++it;')
- gedd_txt.append(' }')
- gedd_txt.append(' }')
- gedd_txt.append('')
- gedd_txt.append(" // Clean up Queue's MemRef Linked Lists")
- gedd_txt.append(' destroyQueueMemRefLists();')
- gedd_txt.append('')
- gedd_txt.append(' lock.unlock();')
- gedd_txt.append('')
- gedd_txt.append(' dispatch_key key = get_dispatch_key(device);')
- gedd_txt.append(' VkLayerDispatchTable *pDisp = get_dispatch_table(object_tracker_device_table_map, device);')
- gedd_txt.append(' pDisp->DestroyDevice(device, pAllocator);')
- gedd_txt.append(' object_tracker_device_table_map.erase(key);')
- gedd_txt.append('')
- gedd_txt.append('}')
- gedd_txt.append('')
- return "\n".join(gedd_txt)
-
- # Special-case validating some objects -- they may be non-NULL but should
- # only be validated upon meeting some condition specified below.
- def _dereference_conditionally(self, indent, prefix, type_name, name):
- s_code = ''
- if type_name == 'pBufferInfo':
- s_code += '%sif ((%sdescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||\n' % (indent, prefix)
- s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||\n' % (indent, prefix)
- s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||\n' % (indent, prefix)
- s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) ) {\n' % (indent, prefix)
- elif type_name == 'pImageInfo':
- s_code += '%sif ((%sdescriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) ||\n' % (indent, prefix)
- s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||\n' % (indent, prefix)
- s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) ||\n' % (indent, prefix)
- s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||\n' % (indent, prefix)
- s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ) {\n' % (indent, prefix)
- elif type_name == 'pTexelBufferView':
- s_code += '%sif ((%sdescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) ||\n' % (indent, prefix)
- s_code += '%s (%sdescriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) ) {\n' % (indent, prefix)
- elif name == 'pBeginInfo->pInheritanceInfo':
- s_code += '%sOBJTRACK_NODE* pNode = VkCommandBufferMap[(uint64_t)commandBuffer];\n' % (indent)
- s_code += '%sif ((%s) && (pNode->status & OBJSTATUS_COMMAND_BUFFER_SECONDARY)) {\n' % (indent, name)
- else:
- s_code += '%sif (%s) {\n' % (indent, name)
- return s_code
-
- def _gen_obj_validate_code(self, struct_uses, obj_type_mapping, func_name, valid_null_dict, param0_name, indent, prefix, array_index):
- pre_code = ''
- for obj in sorted(struct_uses):
- name = obj
- array = ''
- type_name = ''
- if '[' in obj:
- (name, array) = obj.split('[')
- type_name = name
- array = array.strip(']')
- if isinstance(struct_uses[obj], dict):
- local_prefix = ''
- name = '%s%s' % (prefix, name)
- ptr_type = False
- if 'p' == obj[0]:
- ptr_type = True
- tmp_pre = self._dereference_conditionally(indent, prefix, type_name, name)
- pre_code += tmp_pre
- indent += ' '
- if array != '':
- idx = 'idx%s' % str(array_index)
- array_index += 1
- deref = ''
- if 'p' == array[0]:
- deref = '*'
- pre_code += '%s\n' % self.lineinfo.get()
- pre_code += '%sfor (uint32_t %s=0; %s<%s%s%s; ++%s) {\n' % (indent, idx, idx, deref, prefix, array, idx)
- indent += ' '
- local_prefix = '%s[%s].' % (name, idx)
- elif ptr_type:
- local_prefix = '%s->' % (name)
- else:
- local_prefix = '%s.' % (name)
- tmp_pre = self._gen_obj_validate_code(struct_uses[obj], obj_type_mapping, func_name, valid_null_dict, param0_name, indent, local_prefix, array_index)
- pre_code += tmp_pre
- if array != '':
- indent = indent[4:]
- pre_code += '%s}\n' % (indent)
- if ptr_type:
- indent = indent[4:]
- pre_code += '%s}\n' % (indent)
- else:
- ptype = struct_uses[obj]
- dbg_obj_type = obj_type_mapping[ptype]
- fname = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', ptype)
- fname = re.sub('([a-z0-9])([A-Z])', r'\1_\2', fname).lower()[3:]
- full_name = '%s%s' % (prefix, name)
- null_obj_ok = 'false'
- # If a valid null param is defined for this func and we have a match, allow NULL
- if func_name in valid_null_dict and True in [name in pn for pn in sorted(valid_null_dict[func_name])]:
- null_obj_ok = 'true'
- if (array_index > 0) or '' != array:
- tmp_pre = self._dereference_conditionally(indent, prefix, type_name, full_name)
- pre_code += tmp_pre
- indent += ' '
- if array != '':
- idx = 'idx%s' % str(array_index)
- array_index += 1
- pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
- indent += ' '
- full_name = '%s[%s]' % (full_name, idx)
- pre_code += '%s\n' % self.lineinfo.get()
- pre_code += '%sskipCall |= validate_%s(%s, %s, %s, %s);\n' %(indent, fname, param0_name, full_name, dbg_obj_type, null_obj_ok)
- if array != '':
- indent = indent[4:]
- pre_code += '%s}\n' % (indent)
- indent = indent[4:]
- pre_code += '%s}\n' % (indent)
- else:
- pre_code += '%s\n' % self.lineinfo.get()
- pre_code += '%sskipCall |= validate_%s(%s, %s, %s, %s);\n' %(indent, fname, param0_name, full_name, dbg_obj_type, null_obj_ok)
- return pre_code
-
- def generate_intercept(self, proto, qual):
- if proto.name in [ 'CreateDebugReportCallbackEXT', 'EnumerateInstanceLayerProperties', 'EnumerateInstanceExtensionProperties','EnumerateDeviceLayerProperties', 'EnumerateDeviceExtensionProperties' ]:
- # use default version
- return None
-
- # Create map of object names to object type enums of the form VkName : VkObjectTypeName
- obj_type_mapping = {base_t : base_t.replace("Vk", "VkDebugReportObjectType") for base_t in vulkan.object_type_list}
- # Convert object type enum names from UpperCamelCase to UPPER_CASE_WITH_UNDERSCORES
- for objectName, objectTypeEnum in obj_type_mapping.items():
- obj_type_mapping[objectName] = ucc_to_U_C_C(objectTypeEnum) + '_EXT';
- # Command Buffer Object doesn't follow the rule.
- obj_type_mapping['VkCommandBuffer'] = "VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT"
- obj_type_mapping['VkShaderModule'] = "VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT"
- obj_type_mapping['VkDisplayKHR'] = "VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT"
- obj_type_mapping['VkDisplayModeKHR'] = "VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT"
-
- explicit_object_tracker_functions = [
- "CreateInstance",
- "EnumeratePhysicalDevices",
- "GetPhysicalDeviceQueueFamilyProperties",
- "CreateDevice",
- "GetDeviceQueue",
- "QueueBindSparse",
- "AllocateDescriptorSets",
- "FreeDescriptorSets",
- "CreateGraphicsPipelines",
- "CreateComputePipelines",
- "AllocateCommandBuffers",
- "FreeCommandBuffers",
- "DestroyDescriptorPool",
- "DestroyCommandPool",
- "MapMemory",
- "UnmapMemory",
- "FreeMemory",
- "DestroySwapchainKHR",
- "GetSwapchainImagesKHR",
- "GetPhysicalDeviceDisplayPropertiesKHR",
- "GetDisplayModePropertiesKHR"
- ]
- decl = proto.c_func(attr="VKAPI")
- param0_name = proto.params[0].name
- using_line = ''
- create_line = ''
- destroy_line = ''
- # Dict below tracks params that are vk objects. Dict is "loop count"->["params w/ that loop count"] where '0' is params that aren't in an array
- # TODO : Should integrate slightly better code for this purpose from unique_objects layer
- loop_params = defaultdict(list) # Dict uses loop count as key to make final code generation cleaner so params shared in single loop where needed
- loop_types = defaultdict(list)
- # TODO : For now skipping objs that can be NULL. Really should check these and have special case that allows them to be NULL
- # or better yet, these should be encoded into an API json definition and we generate checks from there
- # Until then, this is a dict where each func name is a list of object params that can be null (so don't need to be validated)
- # param names may be directly passed to the function, or may be a field in a struct param
- valid_null_object_names = {'CreateGraphicsPipelines' : ['basePipelineHandle'],
- 'CreateComputePipelines' : ['basePipelineHandle'],
- 'BeginCommandBuffer' : ['renderPass', 'framebuffer'],
- 'QueueSubmit' : ['fence'],
- 'AcquireNextImageKHR' : ['fence', 'semaphore' ],
- 'UpdateDescriptorSets' : ['pTexelBufferView'],
- 'CreateSwapchainKHR' : ['oldSwapchain'],
- }
- param_count = 'NONE' # keep track of arrays passed directly into API functions
- for p in proto.params:
- base_type = p.ty.replace('const ', '').strip('*')
- if 'count' in p.name.lower():
- param_count = p.name
- if base_type in vulkan.core.objects:
- # This is an object to potentially check for validity. First see if it's an array
- if '*' in p.ty and 'const' in p.ty and param_count != 'NONE':
- loop_params[param_count].append(p.name)
- loop_types[param_count].append(str(p.ty[6:-1]))
- # Not an array, check for just a base Object that's not in exceptions
- elif '*' not in p.ty and (proto.name not in valid_null_object_names or p.name not in valid_null_object_names[proto.name]):
- loop_params[0].append(p.name)
- loop_types[0].append(str(p.ty))
- elif vk_helper.is_type(base_type, 'struct'):
- struct_type = base_type
- if vk_helper.typedef_rev_dict[struct_type] in vk_helper.struct_dict:
- struct_type = vk_helper.typedef_rev_dict[struct_type]
- # Parse elements of this struct param to identify objects and/or arrays of objects
- for m in sorted(vk_helper.struct_dict[struct_type]):
- if vk_helper.struct_dict[struct_type][m]['type'] in vulkan.core.objects and vk_helper.struct_dict[struct_type][m]['type'] not in ['VkPhysicalDevice', 'VkQueue', 'VkFence', 'VkImage', 'VkDeviceMemory']:
- if proto.name not in valid_null_object_names or vk_helper.struct_dict[struct_type][m]['name'] not in valid_null_object_names[proto.name]:
- # This is not great, but gets the job done for now, but If we have a count and this param is a ptr w/
- # last letter 's' OR non-'count' string of count is in the param name, then this is a dynamically sized array param
- param_array = False
- if param_count != 'NONE':
- if '*' in p.ty:
- if 's' == p.name[-1] or param_count.lower().replace('count', '') in p.name.lower():
- param_array = True
- if param_array:
- param_name = '%s[i].%s' % (p.name, vk_helper.struct_dict[struct_type][m]['name'])
- else:
- param_name = '%s->%s' % (p.name, vk_helper.struct_dict[struct_type][m]['name'])
- if vk_helper.struct_dict[struct_type][m]['dyn_array']:
- if param_count != 'NONE': # this will be a double-embedded loop, use comma delineated 'count,name' for param_name
- loop_count = '%s[i].%s' % (p.name, vk_helper.struct_dict[struct_type][m]['array_size'])
- loop_params[param_count].append('%s,%s' % (loop_count, param_name))
- loop_types[param_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
- else:
- loop_count = '%s->%s' % (p.name, vk_helper.struct_dict[struct_type][m]['array_size'])
- loop_params[loop_count].append(param_name)
- loop_types[loop_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
- else:
- if '[' in param_name: # dynamic array param, set size
- loop_params[param_count].append(param_name)
- loop_types[param_count].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
- else:
- loop_params[0].append(param_name)
- loop_types[0].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
- last_param_index = None
- create_func = False
- if True in [create_txt in proto.name for create_txt in ['Create', 'Allocate']]:
- create_func = True
- last_param_index = -1 # For create funcs don't validate last object
- if proto.name == 'GetDisplayPlaneSupportedDisplaysKHR':
- last_param_index = -1 # don't validate the DisplayKHR objects which are non-created output parameters
- (struct_uses, local_decls) = get_object_uses(vulkan.object_type_list, proto.params[:last_param_index])
- funcs = []
- mutex_unlock = False
- funcs.append('%s\n' % self.lineinfo.get())
- if proto.name in explicit_object_tracker_functions:
- funcs.append('%s%s\n'
- '{\n'
- ' return explicit_%s;\n'
- '}' % (qual, decl, proto.c_call()))
- return "".join(funcs)
- elif 'DestroyInstance' in proto.name or 'DestroyDevice' in proto.name:
- return ""
- else:
- if create_func:
- typ = proto.params[-1].ty.strip('*').replace('const ', '');
- name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
- name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
- create_line = ' {\n'
- create_line += ' std::lock_guard<std::mutex> lock(global_lock);\n'
- create_line += ' if (result == VK_SUCCESS) {\n'
- create_line += ' create_%s(%s, *%s, %s);\n' % (name, param0_name, proto.params[-1].name, obj_type_mapping[typ])
- create_line += ' }\n'
- create_line += ' }\n'
- if 'FreeCommandBuffers' in proto.name:
- typ = proto.params[-1].ty.strip('*').replace('const ', '');
- name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
- name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
- funcs.append('%s\n' % self.lineinfo.get())
- destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
- destroy_line += ' for (uint32_t i = 0; i < commandBufferCount; i++) {\n'
- destroy_line += ' destroy_%s(%s[i], %s[i]);\n' % (name, proto.params[-1].name, proto.params[-1].name)
- destroy_line += ' }\n'
- destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
- if 'Destroy' in proto.name:
- typ = proto.params[-2].ty.strip('*').replace('const ', '');
- name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
- name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
- funcs.append('%s\n' % self.lineinfo.get())
- destroy_line = ' {\n'
- destroy_line += ' std::lock_guard<std::mutex> lock(global_lock);\n'
- destroy_line += ' destroy_%s(%s, %s);\n' % (name, param0_name, proto.params[-2].name)
- destroy_line += ' }\n'
- indent = ' '
- if len(struct_uses) > 0:
- using_line += '%sbool skipCall = false;\n' % (indent)
- if not mutex_unlock:
- using_line += '%s{\n' % (indent)
- indent += ' '
- using_line += '%sstd::lock_guard<std::mutex> lock(global_lock);\n' % (indent)
- mutex_unlock = True
- using_line += '// objects to validate: %s\n' % str(sorted(struct_uses))
- using_line += self._gen_obj_validate_code(struct_uses, obj_type_mapping, proto.name, valid_null_object_names, param0_name, indent, '', 0)
- if mutex_unlock:
- indent = indent[4:]
- using_line += '%s}\n' % (indent)
- if len(struct_uses) > 0:
- using_line += ' if (skipCall)\n'
- if proto.ret == "bool":
- using_line += ' return false;\n'
- elif proto.ret == "VkBool32":
- using_line += ' return VK_FALSE;\n'
- elif proto.ret != "void":
- using_line += ' return VK_ERROR_VALIDATION_FAILED_EXT;\n'
- else:
- using_line += ' return;\n'
- ret_val = ''
- stmt = ''
- if proto.ret != "void":
- ret_val = "%s result = " % proto.ret
- stmt = " return result;\n"
-
- dispatch_param = proto.params[0].name
- if 'CreateInstance' in proto.name:
- dispatch_param = '*' + proto.params[1].name
-
- # Must use 'instance' table for these APIs, 'device' table otherwise
- table_type = ""
- if proto_is_global(proto):
- table_type = "instance"
- else:
- table_type = "device"
- if wsi_name(proto.name):
- funcs.append('%s' % wsi_ifdef(proto.name))
- funcs.append('%s%s\n'
- '{\n'
- '%s'
- '%s'
- ' %sget_dispatch_table(object_tracker_%s_table_map, %s)->%s;\n'
- '%s'
- '%s'
- '}' % (qual, decl, using_line, destroy_line, ret_val, table_type, dispatch_param, proto.c_call(), create_line, stmt))
- if wsi_name(proto.name):
- funcs.append('%s' % wsi_endif(proto.name))
- return "\n\n".join(funcs)
-
- def generate_body(self):
- self.layer_name = "object_tracker"
- extensions=[('wsi_enabled',
- ['vkCreateSwapchainKHR',
- 'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
- 'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
- additional_instance_extensions = [
- 'vkDestroySurfaceKHR',
- 'vkGetPhysicalDeviceSurfaceSupportKHR',
- 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
- 'vkGetPhysicalDeviceSurfaceFormatsKHR',
- 'vkGetPhysicalDeviceSurfacePresentModesKHR',
- 'vkGetPhysicalDeviceDisplayPropertiesKHR',
- 'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
- 'vkGetDisplayPlaneSupportedDisplaysKHR',
- 'vkGetDisplayModePropertiesKHR',
- 'vkCreateDisplayModeKHR',
- 'vkGetDisplayPlaneCapabilitiesKHR',
- 'vkCreateDisplayPlaneSurfaceKHR',
- ]
- additional_android_instance_extensions = [
- 'vkDestroySurfaceKHR',
- 'vkGetPhysicalDeviceSurfaceSupportKHR',
- 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
- 'vkGetPhysicalDeviceSurfaceFormatsKHR',
- 'vkGetPhysicalDeviceSurfacePresentModesKHR',
- ]
- if self.wsi == 'Win32':
- instance_extensions=[('msg_callback_get_proc_addr', []),
- ('wsi_enabled',
- ['vkCreateWin32SurfaceKHR',
- 'vkGetPhysicalDeviceWin32PresentationSupportKHR'] + additional_instance_extensions)]
- elif self.wsi == 'Android':
- instance_extensions=[('msg_callback_get_proc_addr', []),
- ('wsi_enabled',
- ['vkCreateAndroidSurfaceKHR'] + additional_android_instance_extensions)]
- elif self.wsi == 'Xcb' or self.wsi == 'Xlib' or self.wsi == 'Wayland' or self.wsi == 'Mir':
- instance_extensions=[('msg_callback_get_proc_addr', []),
- ('wsi_enabled',
- additional_instance_extensions + ['vkCreateXcbSurfaceKHR',
- 'vkGetPhysicalDeviceXcbPresentationSupportKHR',
- 'vkCreateXlibSurfaceKHR',
- 'vkGetPhysicalDeviceXlibPresentationSupportKHR',
- 'vkCreateWaylandSurfaceKHR',
- 'vkGetPhysicalDeviceWaylandPresentationSupportKHR',
- 'vkCreateMirSurfaceKHR',
- 'vkGetPhysicalDeviceMirPresentationSupportKHR'])]
- else:
- print('Error: Undefined DisplayServer')
- instance_extensions=[]
-
- body = ["namespace %s {" % self.layer_name,
- self.generate_maps(),
- self.generate_procs(),
- self.generate_destroy_instance(),
- self.generate_destroy_device(),
- self._generate_dispatch_entrypoints(),
- self._generate_extensions(),
- self._generate_layer_introspection_function(),
- self._generate_layer_gpa_function(extensions,
- instance_extensions),
- "} // namespace %s" % self.layer_name,
- self._gen_layer_logging_workaround(),
- self._gen_layer_interface_v0_functions()]
- return "\n\n".join(body)
-
class UniqueObjectsSubcommand(Subcommand):
def generate_header(self):
header_txt = []
@@ -1746,7 +1052,6 @@
}
subcommands = {
- "object_tracker" : ObjectTrackerSubcommand,
"unique_objects" : UniqueObjectsSubcommand,
}