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@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
device_dispatch_table(void * object)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
instance_dispatch_table(void * object)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
destroy_dispatch_table(device_table_map & map,dispatch_key key)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
destroy_dispatch_table(instance_table_map & map,dispatch_key key)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
destroy_device_dispatch_table(dispatch_key key)79 void destroy_device_dispatch_table(dispatch_key key) { destroy_dispatch_table(tableMap, key); }
80
destroy_instance_dispatch_table(dispatch_key key)81 void destroy_instance_dispatch_table(dispatch_key key) { destroy_dispatch_table(tableInstanceMap, key); }
82
get_dispatch_table(device_table_map & map,void * object)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
get_dispatch_table(instance_table_map & map,void * object)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
get_chain_info(const VkInstanceCreateInfo * pCreateInfo,VkLayerFunction func)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
get_chain_info(const VkDeviceCreateInfo * pCreateInfo,VkLayerFunction func)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 */
initInstanceTable(VkInstance instance,const PFN_vkGetInstanceProcAddr gpa,instance_table_map & 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
initInstanceTable(VkInstance instance,const PFN_vkGetInstanceProcAddr gpa)161 VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa) {
162 return initInstanceTable(instance, gpa, tableInstanceMap);
163 }
164
initDeviceTable(VkDevice device,const PFN_vkGetDeviceProcAddr gpa,device_table_map & map)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
initDeviceTable(VkDevice device,const PFN_vkGetDeviceProcAddr gpa)188 VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa) {
189 return initDeviceTable(device, gpa, tableMap);
190 }
191