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 dispatch_key key = get_dispatch_key(object); 100 instance_table_map::const_iterator it = map.find((void *)key); 101 #if DISPATCH_MAP_DEBUG 102 if (it != map.end()) { 103 fprintf(stderr, "instance_dispatch_table: map: 0x%p, object: 0x%p, key: 0x%p, table: 0x%p\n", &tableInstanceMap, object, key, 104 it->second); 105 } else { 106 fprintf(stderr, "instance_dispatch_table: map: 0x%p, object: 0x%p, key: 0x%p, table: UNKNOWN\n", &tableInstanceMap, object, key); 107 } 108 #endif 109 assert(it != map.end() && "Not able to find instance dispatch entry"); 110 return it->second; 111 } 112 113 VkLayerInstanceCreateInfo *get_chain_info(const VkInstanceCreateInfo *pCreateInfo, VkLayerFunction func) { 114 VkLayerInstanceCreateInfo *chain_info = (VkLayerInstanceCreateInfo *)pCreateInfo->pNext; 115 while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && chain_info->function == func)) { 116 chain_info = (VkLayerInstanceCreateInfo *)chain_info->pNext; 117 } 118 assert(chain_info != NULL); 119 return chain_info; 120 } 121 122 VkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo, VkLayerFunction func) { 123 VkLayerDeviceCreateInfo *chain_info = (VkLayerDeviceCreateInfo *)pCreateInfo->pNext; 124 while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && chain_info->function == func)) { 125 chain_info = (VkLayerDeviceCreateInfo *)chain_info->pNext; 126 } 127 assert(chain_info != NULL); 128 return chain_info; 129 } 130 131 /* Various dispatchable objects will use the same underlying dispatch table if they 132 * are created from that "parent" object. Thus use pointer to dispatch table 133 * as the key to these table maps. 134 * Instance -> PhysicalDevice 135 * Device -> CommandBuffer or Queue 136 * If use the object themselves as key to map then implies Create entrypoints have to be intercepted 137 * and a new key inserted into map */ 138 VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa, instance_table_map &map) { 139 VkLayerInstanceDispatchTable *pTable; 140 dispatch_key key = get_dispatch_key(instance); 141 instance_table_map::const_iterator it = map.find((void *)key); 142 143 if (it == map.end()) { 144 pTable = new VkLayerInstanceDispatchTable; 145 map[(void *)key] = pTable; 146 #if DISPATCH_MAP_DEBUG 147 fprintf(stderr, "New, Instance: map: 0x%p, key: 0x%p, table: 0x%p\n", &map, key, pTable); 148 #endif 149 } else { 150 #if DISPATCH_MAP_DEBUG 151 fprintf(stderr, "Instance: map: 0x%p, key: 0x%p, table: 0x%p\n", &map, key, it->second); 152 #endif 153 return it->second; 154 } 155 156 layer_init_instance_dispatch_table(instance, pTable, gpa); 157 158 return pTable; 159 } 160 161 VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa) { 162 return initInstanceTable(instance, gpa, tableInstanceMap); 163 } 164 165 VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa, device_table_map &map) { 166 VkLayerDispatchTable *pTable; 167 dispatch_key key = get_dispatch_key(device); 168 device_table_map::const_iterator it = map.find((void *)key); 169 170 if (it == map.end()) { 171 pTable = new VkLayerDispatchTable; 172 map[(void *)key] = pTable; 173 #if DISPATCH_MAP_DEBUG 174 fprintf(stderr, "New, Device: map: 0x%p, key: 0x%p, table: 0x%p\n", &map, key, pTable); 175 #endif 176 } else { 177 #if DISPATCH_MAP_DEBUG 178 fprintf(stderr, "Device: map: 0x%p, key: 0x%p, table: 0x%p\n", &map, key, it->second); 179 #endif 180 return it->second; 181 } 182 183 layer_init_device_dispatch_table(device, pTable, gpa); 184 185 return pTable; 186 } 187 188 VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa) { 189 return initDeviceTable(device, gpa, tableMap); 190 } 191