From 0ac38fd1f736f02c456560055428eaabd39ad1c6 Mon Sep 17 00:00:00 2001 From: Mark Lobodzinski Date: Fri, 22 May 2015 14:15:36 -0500 Subject: layers: Add multi-device/instance support to generated layers - Converted Generic and ObjectTracker to C++ - Added multi-device/instance support to objecttracker, generic, and threading layers - Various cleanup and efficiency changes - Paramchecker and apidump layers disabled temporarily Conflicts: vk-layer-generate.py --- layers/CMakeLists.txt | 6 +- vk-layer-generate.py | 271 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 216 insertions(+), 61 deletions(-) diff --git a/layers/CMakeLists.txt b/layers/CMakeLists.txt index 883d880c..4a9efe9e 100644 --- a/layers/CMakeLists.txt +++ b/layers/CMakeLists.txt @@ -84,7 +84,7 @@ add_custom_target(generate_vk_layer_helpers DEPENDS ) run_vk_layer_generate(Generic generic_layer.cpp) -run_vk_layer_generate(APIDump api_dump.cpp) +# LUGMAL run_vk_layer_generate(APIDump api_dump.cpp) run_vk_layer_generate(ObjectTracker object_track.cpp) run_vk_layer_generate(Threading threading.cpp) @@ -102,7 +102,7 @@ add_vk_layer(MemTracker mem_tracker.cpp) add_vk_layer(ShaderChecker shader_checker.cpp) # generated add_vk_layer(Generic generic_layer.cpp) -add_vk_layer(APIDump api_dump.cpp) +# LUGMAL add_vk_layer(APIDump api_dump.cpp) add_vk_layer(ObjectTracker object_track.cpp) -add_vk_layer(ParamChecker param_checker.cpp) +# LUGMAL add_vk_layer(ParamChecker param_checker.cpp) add_vk_layer(Threading threading.cpp) diff --git a/vk-layer-generate.py b/vk-layer-generate.py index b3f8402a..56cb6067 100755 --- a/vk-layer-generate.py +++ b/vk-layer-generate.py @@ -161,7 +161,7 @@ class Subcommand(object): r_body = [] r_body.append('VK_LAYER_EXPORT VkResult VKAPI vkDbgCreateMsgCallback(VkInstance instance, VkFlags msgFlags, const PFN_vkDbgMsgCallback pfnMsgCallback, void* pUserData, VkDbgMsgCallback* pMsgCallback)') r_body.append('{') - r_body.append(' return layer_create_msg_callback(instance, &nextInstanceTable, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);') + r_body.append(' return layer_create_msg_callback(instance, instance_dispatch_table(instance), msgFlags, pfnMsgCallback, pUserData, pMsgCallback);') r_body.append('}') return "\n".join(r_body) @@ -169,7 +169,7 @@ class Subcommand(object): r_body = [] r_body.append('VK_LAYER_EXPORT VkResult VKAPI vkDbgDestroyMsgCallback(VkInstance instance, VkDbgMsgCallback msgCallback)') r_body.append('{') - r_body.append(' return layer_destroy_msg_callback(instance, &nextInstanceTable, msgCallback);') + r_body.append(' return layer_destroy_msg_callback(instance, instance_dispatch_table(instance), msgCallback);') r_body.append('}') return "\n".join(r_body) @@ -354,11 +354,11 @@ class Subcommand(object): "{\n" " VkBaseLayerObject* devw = (VkBaseLayerObject *) device;\n" " void* addr;\n" - " if (device == VK_NULL_HANDLE)\n" + " if (device == VK_NULL_HANDLE) {\n" " return NULL;\n" - " pCurObj = devw;\n" - " loader_platform_thread_once(&initOnce, init%s);\n\n" - " loader_platform_thread_once(&tabDeviceOnce, initDeviceTable);\n\n" + " }\n" + " loader_platform_thread_once(&initOnce, init%s);\n" + " initDeviceTable((const VkBaseLayerObject *) device);\n\n" " addr = layer_intercept_proc(funcName);\n" " if (addr)\n" " return addr;" % self.layer_name) @@ -370,23 +370,23 @@ class Subcommand(object): cpp_prefix = "reinterpret_cast(" cpp_postfix = ")" for ext_name in extensions: - func_body.append(' else if (!strncmp("%s", funcName, sizeof("%s")))\n' - ' return %s%s%s;' % (ext_name, ext_name, cpp_prefix, ext_name, cpp_postfix)) + func_body.append(' else if (!strcmp("%s", funcName))\n' + ' return %s%s%s;' % (ext_name, cpp_prefix, ext_name, cpp_postfix)) func_body.append(" else {\n" " if (devw->pGPA == NULL)\n" " return NULL;\n" " return devw->pGPA((VkObject)devw->nextObject, funcName);\n" " }\n" "}\n") - func_body.append("VK_LAYER_EXPORT void* VKAPI vkGetInstanceProcAddr(VkInstance inst, const char* funcName)\n" + func_body.append("VK_LAYER_EXPORT void* VKAPI vkGetInstanceProcAddr(VkInstance instance, const char* funcName)\n" "{\n" - " VkBaseLayerObject* instw = (VkBaseLayerObject *) inst;\n" + " VkBaseLayerObject* instw = (VkBaseLayerObject *) instance;\n" " void* addr;\n" - " if (inst == VK_NULL_HANDLE)\n" + " if (instance == VK_NULL_HANDLE) {\n" " return NULL;\n" - " pCurObj = instw;\n" - " loader_platform_thread_once(&initOnce, init%s);\n\n" - " loader_platform_thread_once(&tabInstanceOnce, initInstanceTable);\n\n" + " }\n" + " loader_platform_thread_once(&initOnce, init%s);\n" + " initInstanceTable((const VkBaseLayerObject *) instance);\n\n" " addr = layer_intercept_instance_proc(funcName);\n" " if (addr)\n" " return addr;" % self.layer_name) @@ -436,21 +436,49 @@ class Subcommand(object): func_body.append(" }") func_body.append("}\n") func_body.append('') - func_body.append('static void initDeviceTable(void)') - func_body.append('{') - func_body.append(' PFN_vkGetDeviceProcAddr fpNextGPA;') - func_body.append(' fpNextGPA = (PFN_vkGetDeviceProcAddr) pCurObj->pGPA;') - func_body.append(' assert(fpNextGPA);') - func_body.append(' layer_initialize_dispatch_table(&nextTable, fpNextGPA, (VkDevice) pCurObj->nextObject);') + func_body.append('static VkLayerDispatchTable * initDeviceTable(const VkBaseLayerObject *devw)') + func_body.append(' {') + func_body.append(' VkLayerDispatchTable *pTable;') + func_body.append('') + func_body.append(' assert(devw);') + func_body.append(' VkLayerDispatchTable **ppDisp = (VkLayerDispatchTable **) (devw->baseObject);') + func_body.append('') + func_body.append(' std::unordered_map::const_iterator it = tableMap.find((void *) *ppDisp);') + func_body.append(' if (it == tableMap.end())') + func_body.append(' {') + func_body.append(' pTable = new VkLayerDispatchTable;') + func_body.append(' tableMap[(void *) *ppDisp] = pTable;') + func_body.append(' } else') + func_body.append(' {') + func_body.append(' return it->second;') + func_body.append(' }') + func_body.append('') + func_body.append(' layer_initialize_dispatch_table(pTable, (PFN_vkGetDeviceProcAddr) devw->pGPA, (VkDevice) devw->nextObject);') + func_body.append('') + func_body.append(' return pTable;') func_body.append('}') func_body.append('') - func_body.append('static void initInstanceTable(void)') - func_body.append('{') - func_body.append(' PFN_vkGetInstanceProcAddr fpNextGPA;') - func_body.append(' fpNextGPA = (PFN_vkGetInstanceProcAddr) pCurObj->pGPA;') - func_body.append(' assert(fpNextGPA);') - func_body.append(' layer_init_instance_dispatch_table(&nextInstanceTable, fpNextGPA, (VkInstance) pCurObj->nextObject);') + func_body.append('static VkLayerInstanceDispatchTable * initInstanceTable(const VkBaseLayerObject *instw)') + func_body.append(' {') + func_body.append(' VkLayerInstanceDispatchTable *pTable;') + func_body.append(' assert(instw);') + func_body.append(' VkLayerInstanceDispatchTable **ppDisp = (VkLayerInstanceDispatchTable **) instw->baseObject;') + func_body.append('') + func_body.append(' std::unordered_map::const_iterator it = tableInstanceMap.find((void *) *ppDisp);') + func_body.append(' if (it == tableInstanceMap.end())') + func_body.append(' {') + func_body.append(' pTable = new VkLayerInstanceDispatchTable;') + func_body.append(' tableInstanceMap[(void *) *ppDisp] = pTable;') + func_body.append(' } else') + func_body.append(' {') + func_body.append(' return it->second;') + func_body.append(' }') + func_body.append('') + func_body.append(' layer_init_instance_dispatch_table(pTable, (PFN_vkGetInstanceProcAddr) instw->pGPA, (VkInstance) instw->nextObject);') + func_body.append('') + func_body.append(' return pTable;') func_body.append('}') + func_body.append('') return "\n".join(func_body) class LayerFuncsSubcommand(Subcommand): @@ -469,8 +497,36 @@ class LayerDispatchSubcommand(Subcommand): class GenericLayerSubcommand(Subcommand): def generate_header(self): - return '#include \n#include \n#include \n#include "loader_platform.h"\n#include "vkLayer.h"\n//The following is #included again to catch certain OS-specific functions being used:\n#include "loader_platform.h"\n\n#include "layers_config.h"\n#include "layers_msg.h"\n\nstatic VkLayerDispatchTable nextTable;\nstatic VkLayerInstanceDispatchTable nextInstanceTable;\nstatic VkBaseLayerObject *pCurObj;\n\nstatic LOADER_PLATFORM_THREAD_ONCE_DECLARATION(tabDeviceOnce);\nstatic LOADER_PLATFORM_THREAD_ONCE_DECLARATION(tabInstanceOnce);\nstatic LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);' - + gen_header = [] + gen_header.append('#include ') + gen_header.append('#include ') + gen_header.append('#include ') + gen_header.append('#include ') + gen_header.append('#include "loader_platform.h"') + gen_header.append('#include "vkLayer.h"') + gen_header.append('//The following is #included again to catch certain OS-specific functions being used:') + gen_header.append('') + gen_header.append('#include "loader_platform.h"') + gen_header.append('#include "layers_config.h"') + gen_header.append('#include "layers_msg.h"') + gen_header.append('') + gen_header.append('static std::unordered_map tableMap;') + gen_header.append('static std::unordered_map tableInstanceMap;') + gen_header.append('') + gen_header.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);') + gen_header.append('') + gen_header.append(' static inline VkLayerDispatchTable *device_dispatch_table(VkObject object) {') + gen_header.append(' VkLayerDispatchTable *pDisp = *(VkLayerDispatchTable **) object;') + gen_header.append(' VkLayerDispatchTable *pTable = tableMap[pDisp];') + gen_header.append(' return pTable;') + gen_header.append('}') + gen_header.append('') + gen_header.append('static inline VkLayerInstanceDispatchTable *instance_dispatch_table(VkObject object) {') + gen_header.append(' VkLayerInstanceDispatchTable **ppDisp = (VkLayerInstanceDispatchTable **) object;') + gen_header.append(' VkLayerInstanceDispatchTable *pInstanceTable = tableInstanceMap[*ppDisp];') + gen_header.append(' return pInstanceTable;') + gen_header.append('}') + return "\n".join(gen_header) def generate_intercept(self, proto, qual): if proto.name in [ 'GetGlobalExtensionInfo' ]: # use default version @@ -482,25 +538,56 @@ class GenericLayerSubcommand(Subcommand): table = '' if proto_is_global(proto): table = 'Instance' - if proto.ret != "void": ret_val = "%s result = " % proto.ret stmt = " return result;\n" if proto.name == "CreateDevice": funcs.append('%s%s\n' '{\n' - ' %snextInstanceTable.%s;\n' + ' char str[1024];\n' + ' sprintf(str, "At start of layered %s\\n");\n' + ' layerCbMsg(VK_DBG_REPORT_INFO_BIT,VK_OBJECT_TYPE_PHYSICAL_DEVICE, gpu, 0, 0, (char *) "GENERIC", (char *) str);\n' + ' %sinstance_dispatch_table(gpu)->%s;\n' ' if (result == VK_SUCCESS) {\n' ' enable_debug_report(pCreateInfo->extensionCount, pCreateInfo->pEnabledExtensions);\n' ' }\n' - '%s' - '}' % (qual, decl, ret_val, proto.c_call(), stmt)) + ' sprintf(str, "Completed layered %s\\n");\n' + ' layerCbMsg(VK_DBG_REPORT_INFO_BIT, VK_OBJECT_TYPE_PHYSICAL_DEVICE, gpu, 0, 0, (char *) "GENERIC", (char *) str);\n' + ' fflush(stdout);\n' + ' %s' + '}' % (qual, decl, proto.name, ret_val, proto.c_call(), proto.name, stmt)) + elif proto.name == "DestroyDevice": + funcs.append('%s%s\n' + '{\n' + ' VkLayerDispatchTable *pDisp = *(VkLayerDispatchTable **) device;\n' + ' VkResult res = device_dispatch_table(device)->DestroyDevice(device);\n' + ' tableMap.erase(pDisp);\n' + ' return res;\n' + '}\n' % (qual, decl)) + elif proto.name == "DestroyInstance": + funcs.append('%s%s\n' + '{\n' + ' VkLayerInstanceDispatchTable *pDisp = *(VkLayerInstanceDispatchTable **) instance;\n' + ' VkResult res = instance_dispatch_table(instance)->DestroyInstance(instance);\n' + ' tableInstanceMap.erase(pDisp);\n' + ' return res;\n' + '}\n' % (qual, decl)) else: + # CreateInstance needs to use the second parm instead of the first to set the correct dispatch table + dispatch_param = proto.params[0].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 'CreateInstance' in proto.name: + dispatch_param = '*' + proto.params[1].name funcs.append('%s%s\n' '{\n' - ' %snext%sTable.%s;\n' + ' %s%s_dispatch_table(%s)->%s;\n' '%s' - '}' % (qual, decl, ret_val, table, proto.c_call(), stmt)) + '}' % (qual, decl, ret_val, table_type, dispatch_param, proto.c_call(), stmt)) return "\n\n".join(funcs) def generate_body(self): @@ -813,7 +900,8 @@ class APIDumpSubcommand(Subcommand): class ObjectTrackerSubcommand(Subcommand): def generate_header(self): header_txt = [] - header_txt.append('#include \n#include \n#include \n#include \n#include "loader_platform.h"') + header_txt.append('#include \n#include \n#include \n#include \n') + header_txt.append('#include "loader_platform.h"\n') header_txt.append('#include "object_track.h"\n\n') header_txt.append('#include ') header_txt.append('using namespace std;') @@ -822,11 +910,23 @@ class ObjectTrackerSubcommand(Subcommand): header_txt.append('#include "layers_config.h"') header_txt.append('#include "layers_msg.h"') header_txt.append('#include "vk_debug_report_lunarg.h"') - header_txt.append('static VkLayerDispatchTable nextTable;\nstatic VkLayerInstanceDispatchTable nextInstanceTable;\n') - header_txt.append('static VkBaseLayerObject *pCurObj;') + header_txt.append('') + header_txt.append('static std::unordered_map tableMap;') + header_txt.append('static std::unordered_map tableInstanceMap;') header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);') - header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(tabDeviceOnce);') - header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(tabInstanceOnce);') + header_txt.append('') + header_txt.append('static inline VkLayerDispatchTable *device_dispatch_table(VkObject object) {') + header_txt.append(' VkLayerDispatchTable *pDisp = *(VkLayerDispatchTable **) object;') + header_txt.append(' VkLayerDispatchTable *pTable = tableMap[pDisp];') + header_txt.append(' return pTable;') + header_txt.append('}') + header_txt.append('') + header_txt.append('static inline VkLayerInstanceDispatchTable *instance_dispatch_table(VkObject object) {') + header_txt.append(' VkLayerInstanceDispatchTable **ppDisp = (VkLayerInstanceDispatchTable **) object;') + header_txt.append(' VkLayerInstanceDispatchTable *pInstanceTable = tableInstanceMap[*ppDisp];') + header_txt.append(' return pInstanceTable;') + header_txt.append('}') + header_txt.append('') header_txt.append('static long long unsigned int object_track_index = 0;') header_txt.append('static int objLockInitialized = 0;') header_txt.append('static loader_platform_thread_mutex objLock;') @@ -1160,6 +1260,20 @@ class ObjectTrackerSubcommand(Subcommand): destroy_line += ' // Clean up Queue\'s MemRef Linked Lists\n' destroy_line += ' destroyQueueMemRefLists();\n' destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n' + elif 'DestroyInstance' in proto.name: + destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n' + destroy_line += ' destroy_obj(%s);\n' % (param0_name) + destroy_line += ' // Report any remaining objects in LL\n' + destroy_line += ' for (auto it = objMap.begin(); it != objMap.end(); ++it) {\n' + destroy_line += ' OBJTRACK_NODE* pNode = it->second; if ((pNode->objType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) || (pNode->objType == VK_OBJECT_TYPE_QUEUE)) {\n' + destroy_line += ' // Cannot destroy physical device so ignore\n' + destroy_line += ' } else {\n' + destroy_line += ' char str[1024];\n' + destroy_line += ' sprintf(str, "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkObjectType(pNode->objType), reinterpret_cast(pNode->vkObj));\n' + destroy_line += ' layerCbMsg(VK_DBG_REPORT_ERROR_BIT, pNode->objType, pNode->vkObj, 0, OBJTRACK_OBJECT_LEAK, "OBJTRACK", str);\n' + destroy_line += ' }\n' + destroy_line += ' }\n' + destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n' elif 'Free' in proto.name: destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n' destroy_line += ' destroy_obj(%s);\n' % (proto.params[1].name) @@ -1195,19 +1309,30 @@ class ObjectTrackerSubcommand(Subcommand): gpu_state += ' }\n' funcs.append('%s%s\n' '{\n' - ' %snext%sTable.%s;\n' + '%s' + ' %sinstance_dispatch_table(gpu)->%s;\n' '%s%s' '%s' '%s' - '}' % (qual, decl, ret_val, table, proto.c_call(), create_line, destroy_line, gpu_state, stmt)) + '}' % (qual, decl, using_line, ret_val, proto.c_call(), create_line, destroy_line, gpu_state, stmt)) else: + # CreateInstance needs to use the second parm instead of the first to set the correct dispatch table + dispatch_param = param0_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 'CreateInstance' in proto.name: + dispatch_param = '*' + proto.params[1].name funcs.append('%s%s\n' '{\n' '%s' - ' %snext%sTable.%s;\n' + ' %s%s_dispatch_table(%s)->%s;\n' '%s%s' '%s' - '}' % (qual, decl, using_line, ret_val, table, proto.c_call(), create_line, destroy_line, stmt)) + '}' % (qual, decl, using_line, ret_val, table_type, dispatch_param, proto.c_call(), create_line, destroy_line, stmt)) return "\n\n".join(funcs) def generate_body(self): @@ -1234,12 +1359,24 @@ class ThreadingSubcommand(Subcommand): header_txt.append('//The following is #included again to catch certain OS-specific functions being used:') header_txt.append('#include "loader_platform.h"\n') header_txt.append('#include "layers_msg.h"\n') - header_txt.append('static VkLayerDispatchTable nextTable;') - header_txt.append('static VkLayerInstanceDispatchTable nextInstanceTable;') - header_txt.append('static VkBaseLayerObject *pCurObj;') - header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(tabDeviceOnce);') - header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(tabInstanceOnce);') - header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);\n') + header_txt.append('') + header_txt.append('static std::unordered_map tableMap;') + header_txt.append('static std::unordered_map tableInstanceMap;') + header_txt.append('') + header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);') + header_txt.append('') + header_txt.append('static inline VkLayerDispatchTable *device_dispatch_table(VkObject object) {') + header_txt.append(' VkLayerDispatchTable *pDisp = *(VkLayerDispatchTable **) object;') + header_txt.append(' VkLayerDispatchTable *pTable = tableMap[pDisp];') + header_txt.append(' return pTable;') + header_txt.append('}') + header_txt.append('') + header_txt.append('static inline VkLayerInstanceDispatchTable *instance_dispatch_table(VkObject object) {') + header_txt.append(' VkLayerInstanceDispatchTable **ppDisp = (VkLayerInstanceDispatchTable **) object;') + header_txt.append(' VkLayerInstanceDispatchTable *pInstanceTable = tableInstanceMap[*ppDisp];') + header_txt.append(' return pInstanceTable;') + header_txt.append('}') + header_txt.append('') header_txt.append('using namespace std;') header_txt.append('static unordered_map proxy_objectsInUse;\n') header_txt.append('static unordered_map objectsInUse;\n') @@ -1302,12 +1439,12 @@ class ThreadingSubcommand(Subcommand): ret_val = '' stmt = '' funcs = [] - table = '' + table = 'device' if proto.ret != "void": ret_val = "%s result = " % proto.ret stmt = " return result;\n" if proto_is_global(proto): - table = 'Instance' + table = 'instance' # Memory range calls are special in needed thread checking within structs if proto.name in ["FlushMappedMemoryRanges","InvalidateMappedMemoryRanges"]: @@ -1316,12 +1453,12 @@ class ThreadingSubcommand(Subcommand): ' for (int i=0; i%s;\n' ' for (int i=0; i%s;\n' '%s' - '}' % (qual, decl, ret_val, table, proto.c_call(), stmt)) + '}' % (qual, decl, ret_val, table, proto.params[0].name, proto.c_call(), stmt)) return "\n".join(funcs) # Functions changing command buffers need thread safe use of first parameter if proto.params[0].ty == "VkCmdBuffer": funcs.append('%s%s\n' '{\n' ' useObject((VkObject) %s, "%s");\n' - ' %snext%sTable.%s;\n' + ' %s%s_dispatch_table(%s)->%s;\n' ' finishUsingObject((VkObject) %s);\n' '%s' - '}' % (qual, decl, proto.params[0].name, proto.params[0].ty, ret_val, table, proto.c_call(), proto.params[0].name, stmt)) + '}' % (qual, decl, proto.params[0].name, proto.params[0].ty, ret_val, table, proto.params[0].name, proto.c_call(), proto.params[0].name, stmt)) return "\n".join(funcs) # Non-Cmd functions that do a Wait are thread safe if 'Wait' in proto.name: @@ -1355,6 +1492,24 @@ class ThreadingSubcommand(Subcommand): for param in proto.params: if param.ty in thread_check_objects: checked_params.append(param) + if proto.name == "DestroyDevice": + funcs.append('%s%s\n' + '{\n' + ' VkLayerDispatchTable *pDisp = *(VkLayerDispatchTable **) device;\n' + ' %s%s_dispatch_table(%s)->%s;\n' + ' tableMap.erase(pDisp);\n' + ' return result;\n' + '}\n' % (qual, decl, ret_val, table, proto.params[0].name, proto.c_call())) + return "\n".join(funcs); + elif proto.name == "DestroyInstance": + funcs.append('%s%s\n' + '{\n' + ' VkLayerInstanceDispatchTable *pDisp = *(VkLayerInstanceDispatchTable **) instance;\n' + ' %s%s_dispatch_table(%s)->%s;\n' + ' tableInstanceMap.erase(pDisp);\n' + ' return result;\n' + '}\n' % (qual, decl, ret_val, table, proto.params[0].name, proto.c_call())) + return "\n".join(funcs); if len(checked_params) == 0: return None # Surround call with useObject and finishUsingObject for each checked_param @@ -1362,7 +1517,7 @@ class ThreadingSubcommand(Subcommand): funcs.append('{') for param in checked_params: funcs.append(' useObject((VkObject) %s, "%s");' % (param.name, param.ty)) - funcs.append(' %snext%sTable.%s;' % (ret_val, table, proto.c_call())) + funcs.append(' %s%s_dispatch_table(%s)->%s;' % (ret_val, table, proto.params[0].name, proto.c_call())) for param in checked_params: funcs.append(' finishUsingObject((VkObject) %s);' % param.name) funcs.append('%s' -- cgit v1.2.3