1 /* Copyright (c) 2015-2016 The Khronos Group Inc. 2 * Copyright (c) 2015-2016 Valve Corporation 3 * Copyright (c) 2015-2016 LunarG, Inc. 4 * Copyright (c) 2015-2016 Google, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and/or associated documentation files (the "Materials"), to 8 * deal in the Materials without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Materials, and to permit persons to whom the Materials 11 * are furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice(s) and this permission notice shall be included 14 * in all copies or substantial portions of the Materials. 15 * 16 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 * 20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE 23 * USE OR OTHER DEALINGS IN THE MATERIALS 24 * 25 * Author: Tobin Ehlis <tobin (at) lunarg.com> 26 */ 27 #include <assert.h> 28 #include <unordered_map> 29 #include "vk_dispatch_table_helper.h" 30 #include "vulkan/vk_layer.h" 31 #include "vk_layer_table.h" 32 static device_table_map tableMap; 33 static instance_table_map tableInstanceMap; 34 35 #define DISPATCH_MAP_DEBUG 0 36 37 // Map lookup must be thread safe 38 VkLayerDispatchTable *device_dispatch_table(void *object) { 39 dispatch_key key = get_dispatch_key(object); 40 device_table_map::const_iterator it = tableMap.find((void *)key); 41 assert(it != tableMap.end() && "Not able to find device dispatch entry"); 42 return it->second; 43 } 44 45 VkLayerInstanceDispatchTable *instance_dispatch_table(void *object) { 46 dispatch_key key = get_dispatch_key(object); 47 instance_table_map::const_iterator it = tableInstanceMap.find((void *)key); 48 #if DISPATCH_MAP_DEBUG 49 if (it != tableInstanceMap.end()) { 50 fprintf(stderr, "instance_dispatch_table: map: %p, object: %p, key: %p, table: %p\n", &tableInstanceMap, object, key, 51 it->second); 52 } else { 53 fprintf(stderr, "instance_dispatch_table: map: %p, object: %p, key: %p, table: UNKNOWN\n", &tableInstanceMap, object, key); 54 } 55 #endif 56 assert(it != tableInstanceMap.end() && "Not able to find instance dispatch entry"); 57 return it->second; 58 } 59 60 void destroy_dispatch_table(device_table_map &map, dispatch_key key) { 61 #if DISPATCH_MAP_DEBUG 62 device_table_map::const_iterator it = map.find((void *)key); 63 if (it != map.end()) { 64 fprintf(stderr, "destroy device dispatch_table: map: %p, key: %p, table: %p\n", &map, key, it->second); 65 } else { 66 fprintf(stderr, "destroy device dispatch table: map: %p, key: %p, table: UNKNOWN\n", &map, key); 67 assert(it != map.end()); 68 } 69 #endif 70 map.erase(key); 71 } 72 73 void destroy_dispatch_table(instance_table_map &map, dispatch_key key) { 74 #if DISPATCH_MAP_DEBUG 75 instance_table_map::const_iterator it = map.find((void *)key); 76 if (it != map.end()) { 77 fprintf(stderr, "destroy instance dispatch_table: map: %p, key: %p, table: %p\n", &map, key, it->second); 78 } else { 79 fprintf(stderr, "destroy instance dispatch table: map: %p, key: %p, table: UNKNOWN\n", &map, key); 80 assert(it != map.end()); 81 } 82 #endif 83 map.erase(key); 84 } 85 86 void destroy_device_dispatch_table(dispatch_key key) { destroy_dispatch_table(tableMap, key); } 87 88 void destroy_instance_dispatch_table(dispatch_key key) { destroy_dispatch_table(tableInstanceMap, key); } 89 90 VkLayerDispatchTable *get_dispatch_table(device_table_map &map, void *object) { 91 dispatch_key key = get_dispatch_key(object); 92 device_table_map::const_iterator it = map.find((void *)key); 93 #if DISPATCH_MAP_DEBUG 94 if (it != map.end()) { 95 fprintf(stderr, "device_dispatch_table: map: %p, object: %p, key: %p, table: %p\n", &tableInstanceMap, object, key, 96 it->second); 97 } else { 98 fprintf(stderr, "device_dispatch_table: map: %p, object: %p, key: %p, table: UNKNOWN\n", &tableInstanceMap, object, key); 99 } 100 #endif 101 assert(it != map.end() && "Not able to find device dispatch entry"); 102 return it->second; 103 } 104 105 VkLayerInstanceDispatchTable *get_dispatch_table(instance_table_map &map, void *object) { 106 // VkLayerInstanceDispatchTable *pDisp = *(VkLayerInstanceDispatchTable **) object; 107 dispatch_key key = get_dispatch_key(object); 108 instance_table_map::const_iterator it = map.find((void *)key); 109 #if DISPATCH_MAP_DEBUG 110 if (it != map.end()) { 111 fprintf(stderr, "instance_dispatch_table: map: %p, object: %p, key: %p, table: %p\n", &tableInstanceMap, object, key, 112 it->second); 113 } else { 114 fprintf(stderr, "instance_dispatch_table: map: %p, object: %p, key: %p, table: UNKNOWN\n", &tableInstanceMap, object, key); 115 } 116 #endif 117 assert(it != map.end() && "Not able to find instance dispatch entry"); 118 return it->second; 119 } 120 121 VkLayerInstanceCreateInfo *get_chain_info(const VkInstanceCreateInfo *pCreateInfo, VkLayerFunction func) { 122 VkLayerInstanceCreateInfo *chain_info = (VkLayerInstanceCreateInfo *)pCreateInfo->pNext; 123 while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && chain_info->function == func)) { 124 chain_info = (VkLayerInstanceCreateInfo *)chain_info->pNext; 125 } 126 assert(chain_info != NULL); 127 return chain_info; 128 } 129 130 VkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo, VkLayerFunction func) { 131 VkLayerDeviceCreateInfo *chain_info = (VkLayerDeviceCreateInfo *)pCreateInfo->pNext; 132 while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && chain_info->function == func)) { 133 chain_info = (VkLayerDeviceCreateInfo *)chain_info->pNext; 134 } 135 assert(chain_info != NULL); 136 return chain_info; 137 } 138 139 /* Various dispatchable objects will use the same underlying dispatch table if they 140 * are created from that "parent" object. Thus use pointer to dispatch table 141 * as the key to these table maps. 142 * Instance -> PhysicalDevice 143 * Device -> CommandBuffer or Queue 144 * If use the object themselves as key to map then implies Create entrypoints have to be intercepted 145 * and a new key inserted into map */ 146 VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa, instance_table_map &map) { 147 VkLayerInstanceDispatchTable *pTable; 148 dispatch_key key = get_dispatch_key(instance); 149 instance_table_map::const_iterator it = map.find((void *)key); 150 151 if (it == map.end()) { 152 pTable = new VkLayerInstanceDispatchTable; 153 map[(void *)key] = pTable; 154 #if DISPATCH_MAP_DEBUG 155 fprintf(stderr, "New, Instance: map: %p, key: %p, table: %p\n", &map, key, pTable); 156 #endif 157 } else { 158 #if DISPATCH_MAP_DEBUG 159 fprintf(stderr, "Instance: map: %p, key: %p, table: %p\n", &map, key, it->second); 160 #endif 161 return it->second; 162 } 163 164 layer_init_instance_dispatch_table(instance, pTable, gpa); 165 166 return pTable; 167 } 168 169 VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa) { 170 return initInstanceTable(instance, gpa, tableInstanceMap); 171 } 172 173 VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa, device_table_map &map) { 174 VkLayerDispatchTable *pTable; 175 dispatch_key key = get_dispatch_key(device); 176 device_table_map::const_iterator it = map.find((void *)key); 177 178 if (it == map.end()) { 179 pTable = new VkLayerDispatchTable; 180 map[(void *)key] = pTable; 181 #if DISPATCH_MAP_DEBUG 182 fprintf(stderr, "New, Device: map: %p, key: %p, table: %p\n", &map, key, pTable); 183 #endif 184 } else { 185 #if DISPATCH_MAP_DEBUG 186 fprintf(stderr, "Device: map: %p, key: %p, table: %p\n", &map, key, it->second); 187 #endif 188 return it->second; 189 } 190 191 layer_init_device_dispatch_table(device, pTable, gpa); 192 193 return pTable; 194 } 195 196 VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa) { 197 return initDeviceTable(device, gpa, tableMap); 198 } 199