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 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * Author: Tobin Ehlis <tobin (at) lunarg.com> 19 */ 20 #include <assert.h> 21 #include <unordered_map> 22 #include "vk_dispatch_table_helper.h" 23 #include "vulkan/vk_layer.h" 24 #include "vk_layer_table.h" 25 static device_table_map tableMap; 26 static instance_table_map tableInstanceMap; 27 28 #define DISPATCH_MAP_DEBUG 0 29 30 // Map lookup must be thread safe 31 VkLayerDispatchTable *device_dispatch_table(void *object) { 32 dispatch_key key = get_dispatch_key(object); 33 device_table_map::const_iterator it = tableMap.find((void *)key); 34 assert(it != tableMap.end() && "Not able to find device dispatch entry"); 35 return it->second; 36 } 37 38 VkLayerInstanceDispatchTable *instance_dispatch_table(void *object) { 39 dispatch_key key = get_dispatch_key(object); 40 instance_table_map::const_iterator it = tableInstanceMap.find((void *)key); 41 #if DISPATCH_MAP_DEBUG 42 if (it != tableInstanceMap.end()) { 43 fprintf(stderr, "instance_dispatch_table: map: 0x%p, object: 0x%p, key: 0x%p, table: 0x%p\n", &tableInstanceMap, object, key, 44 it->second); 45 } else { 46 fprintf(stderr, "instance_dispatch_table: map: 0x%p, object: 0x%p, key: 0x%p, table: UNKNOWN\n", &tableInstanceMap, object, key); 47 } 48 #endif 49 assert(it != tableInstanceMap.end() && "Not able to find instance dispatch entry"); 50 return it->second; 51 } 52 53 void destroy_dispatch_table(device_table_map &map, dispatch_key key) { 54 #if DISPATCH_MAP_DEBUG 55 device_table_map::const_iterator it = map.find((void *)key); 56 if (it != map.end()) { 57 fprintf(stderr, "destroy device dispatch_table: map: 0x%p, key: 0x%p, table: 0x%p\n", &map, key, it->second); 58 } else { 59 fprintf(stderr, "destroy device dispatch table: map: 0x%p, key: 0x%p, table: UNKNOWN\n", &map, key); 60 assert(it != map.end()); 61 } 62 #endif 63 map.erase(key); 64 } 65 66 void destroy_dispatch_table(instance_table_map &map, dispatch_key key) { 67 #if DISPATCH_MAP_DEBUG 68 instance_table_map::const_iterator it = map.find((void *)key); 69 if (it != map.end()) { 70 fprintf(stderr, "destroy instance dispatch_table: map: 0x%p, key: 0x%p, table: 0x%p\n", &map, key, it->second); 71 } else { 72 fprintf(stderr, "destroy instance dispatch table: map: 0x%p, key: 0x%p, table: UNKNOWN\n", &map, key); 73 assert(it != map.end()); 74 } 75 #endif 76 map.erase(key); 77 } 78 79 void destroy_device_dispatch_table(dispatch_key key) { destroy_dispatch_table(tableMap, key); } 80 81 void destroy_instance_dispatch_table(dispatch_key key) { destroy_dispatch_table(tableInstanceMap, key); } 82 83 VkLayerDispatchTable *get_dispatch_table(device_table_map &map, void *object) { 84 dispatch_key key = get_dispatch_key(object); 85 device_table_map::const_iterator it = map.find((void *)key); 86 #if DISPATCH_MAP_DEBUG 87 if (it != map.end()) { 88 fprintf(stderr, "device_dispatch_table: map: 0x%p, object: 0x%p, key: 0x%p, table: 0x%p\n", &tableInstanceMap, object, key, 89 it->second); 90 } else { 91 fprintf(stderr, "device_dispatch_table: map: 0x%p, object: 0x%p, key: 0x%p, table: UNKNOWN\n", &tableInstanceMap, object, key); 92 } 93 #endif 94 assert(it != map.end() && "Not able to find device dispatch entry"); 95 return it->second; 96 } 97 98 VkLayerInstanceDispatchTable *get_dispatch_table(instance_table_map &map, void *object) { 99 // VkLayerInstanceDispatchTable *pDisp = *(VkLayerInstanceDispatchTable **) object; 100 dispatch_key key = get_dispatch_key(object); 101 instance_table_map::const_iterator it = map.find((void *)key); 102 #if DISPATCH_MAP_DEBUG 103 if (it != map.end()) { 104 fprintf(stderr, "instance_dispatch_table: map: 0x%p, object: 0x%p, key: 0x%p, table: 0x%p\n", &tableInstanceMap, object, key, 105 it->second); 106 } else { 107 fprintf(stderr, "instance_dispatch_table: map: 0x%p, object: 0x%p, key: 0x%p, table: UNKNOWN\n", &tableInstanceMap, object, key); 108 } 109 #endif 110 assert(it != map.end() && "Not able to find instance dispatch entry"); 111 return it->second; 112 } 113 114 VkLayerInstanceCreateInfo *get_chain_info(const VkInstanceCreateInfo *pCreateInfo, VkLayerFunction func) { 115 VkLayerInstanceCreateInfo *chain_info = (VkLayerInstanceCreateInfo *)pCreateInfo->pNext; 116 while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && chain_info->function == func)) { 117 chain_info = (VkLayerInstanceCreateInfo *)chain_info->pNext; 118 } 119 assert(chain_info != NULL); 120 return chain_info; 121 } 122 123 VkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo, VkLayerFunction func) { 124 VkLayerDeviceCreateInfo *chain_info = (VkLayerDeviceCreateInfo *)pCreateInfo->pNext; 125 while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && chain_info->function == func)) { 126 chain_info = (VkLayerDeviceCreateInfo *)chain_info->pNext; 127 } 128 assert(chain_info != NULL); 129 return chain_info; 130 } 131 132 /* Various dispatchable objects will use the same underlying dispatch table if they 133 * are created from that "parent" object. Thus use pointer to dispatch table 134 * as the key to these table maps. 135 * Instance -> PhysicalDevice 136 * Device -> CommandBuffer or Queue 137 * If use the object themselves as key to map then implies Create entrypoints have to be intercepted 138 * and a new key inserted into map */ 139 VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa, instance_table_map &map) { 140 VkLayerInstanceDispatchTable *pTable; 141 dispatch_key key = get_dispatch_key(instance); 142 instance_table_map::const_iterator it = map.find((void *)key); 143 144 if (it == map.end()) { 145 pTable = new VkLayerInstanceDispatchTable; 146 map[(void *)key] = pTable; 147 #if DISPATCH_MAP_DEBUG 148 fprintf(stderr, "New, Instance: map: 0x%p, key: 0x%p, table: 0x%p\n", &map, key, pTable); 149 #endif 150 } else { 151 #if DISPATCH_MAP_DEBUG 152 fprintf(stderr, "Instance: map: 0x%p, key: 0x%p, table: 0x%p\n", &map, key, it->second); 153 #endif 154 return it->second; 155 } 156 157 layer_init_instance_dispatch_table(instance, pTable, gpa); 158 159 return pTable; 160 } 161 162 VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa) { 163 return initInstanceTable(instance, gpa, tableInstanceMap); 164 } 165 166 VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa, device_table_map &map) { 167 VkLayerDispatchTable *pTable; 168 dispatch_key key = get_dispatch_key(device); 169 device_table_map::const_iterator it = map.find((void *)key); 170 171 if (it == map.end()) { 172 pTable = new VkLayerDispatchTable; 173 map[(void *)key] = pTable; 174 #if DISPATCH_MAP_DEBUG 175 fprintf(stderr, "New, Device: map: 0x%p, key: 0x%p, table: 0x%p\n", &map, key, pTable); 176 #endif 177 } else { 178 #if DISPATCH_MAP_DEBUG 179 fprintf(stderr, "Device: map: 0x%p, key: 0x%p, table: 0x%p\n", &map, key, it->second); 180 #endif 181 return it->second; 182 } 183 184 layer_init_device_dispatch_table(device, pTable, gpa); 185 186 return pTable; 187 } 188 189 VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa) { 190 return initDeviceTable(device, gpa, tableMap); 191 } 192