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 // Map lookup must be thread safe 29 VkLayerDispatchTable *device_dispatch_table(void *object) { 30 dispatch_key key = get_dispatch_key(object); 31 device_table_map::const_iterator it = tableMap.find((void *)key); 32 assert(it != tableMap.end() && "Not able to find device dispatch entry"); 33 return it->second; 34 } 35 36 VkLayerInstanceDispatchTable *instance_dispatch_table(void *object) { 37 dispatch_key key = get_dispatch_key(object); 38 instance_table_map::const_iterator it = tableInstanceMap.find((void *)key); 39 assert(it != tableInstanceMap.end() && "Not able to find instance dispatch entry"); 40 return it->second; 41 } 42 43 void destroy_dispatch_table(device_table_map &map, dispatch_key key) { 44 device_table_map::const_iterator it = map.find((void *)key); 45 if (it != map.end()) { 46 delete it->second; 47 map.erase(it); 48 } 49 } 50 51 void destroy_dispatch_table(instance_table_map &map, dispatch_key key) { 52 instance_table_map::const_iterator it = map.find((void *)key); 53 if (it != map.end()) { 54 delete it->second; 55 map.erase(it); 56 } 57 } 58 59 void destroy_device_dispatch_table(dispatch_key key) { destroy_dispatch_table(tableMap, key); } 60 61 void destroy_instance_dispatch_table(dispatch_key key) { destroy_dispatch_table(tableInstanceMap, key); } 62 63 VkLayerDispatchTable *get_dispatch_table(device_table_map &map, void *object) { 64 dispatch_key key = get_dispatch_key(object); 65 device_table_map::const_iterator it = map.find((void *)key); 66 assert(it != map.end() && "Not able to find device dispatch entry"); 67 return it->second; 68 } 69 70 VkLayerInstanceDispatchTable *get_dispatch_table(instance_table_map &map, void *object) { 71 dispatch_key key = get_dispatch_key(object); 72 instance_table_map::const_iterator it = map.find((void *)key); 73 assert(it != map.end() && "Not able to find instance dispatch entry"); 74 return it->second; 75 } 76 77 VkLayerInstanceCreateInfo *get_chain_info(const VkInstanceCreateInfo *pCreateInfo, VkLayerFunction func) { 78 VkLayerInstanceCreateInfo *chain_info = (VkLayerInstanceCreateInfo *)pCreateInfo->pNext; 79 while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && chain_info->function == func)) { 80 chain_info = (VkLayerInstanceCreateInfo *)chain_info->pNext; 81 } 82 assert(chain_info != NULL); 83 return chain_info; 84 } 85 86 VkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo, VkLayerFunction func) { 87 VkLayerDeviceCreateInfo *chain_info = (VkLayerDeviceCreateInfo *)pCreateInfo->pNext; 88 while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && chain_info->function == func)) { 89 chain_info = (VkLayerDeviceCreateInfo *)chain_info->pNext; 90 } 91 assert(chain_info != NULL); 92 return chain_info; 93 } 94 95 /* Various dispatchable objects will use the same underlying dispatch table if they 96 * are created from that "parent" object. Thus use pointer to dispatch table 97 * as the key to these table maps. 98 * Instance -> PhysicalDevice 99 * Device -> CommandBuffer or Queue 100 * If use the object themselves as key to map then implies Create entrypoints have to be intercepted 101 * and a new key inserted into map */ 102 VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa, instance_table_map &map) { 103 VkLayerInstanceDispatchTable *pTable; 104 dispatch_key key = get_dispatch_key(instance); 105 instance_table_map::const_iterator it = map.find((void *)key); 106 107 if (it == map.end()) { 108 pTable = new VkLayerInstanceDispatchTable; 109 map[(void *)key] = pTable; 110 } else { 111 return it->second; 112 } 113 114 layer_init_instance_dispatch_table(instance, pTable, gpa); 115 116 // Setup func pointers that are required but not externally exposed. These won't be added to the instance dispatch table by 117 // default. 118 pTable->GetPhysicalDeviceProcAddr = (PFN_GetPhysicalDeviceProcAddr)gpa(instance, "vk_layerGetPhysicalDeviceProcAddr"); 119 120 return pTable; 121 } 122 123 VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa) { 124 return initInstanceTable(instance, gpa, tableInstanceMap); 125 } 126 127 VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa, device_table_map &map) { 128 VkLayerDispatchTable *pTable; 129 dispatch_key key = get_dispatch_key(device); 130 device_table_map::const_iterator it = map.find((void *)key); 131 132 if (it == map.end()) { 133 pTable = new VkLayerDispatchTable; 134 map[(void *)key] = pTable; 135 } else { 136 return it->second; 137 } 138 139 layer_init_device_dispatch_table(device, pTable, gpa); 140 141 return pTable; 142 } 143 144 VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa) { 145 return initDeviceTable(device, gpa, tableMap); 146 } 147