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