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 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and/or associated documentation files (the "Materials"), to
8 * deal in the Materials without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Materials, and to permit persons to whom the Materials
11 * are furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice(s) and this permission notice shall be included
14 * in all copies or substantial portions of the Materials.
15 *
16 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 *
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
23 * USE OR OTHER DEALINGS IN THE MATERIALS
24 *
25 * Author: Tobin Ehlis <tobin@lunarg.com>
26 */
27 #include <assert.h>
28 #include <unordered_map>
29 #include "vk_dispatch_table_helper.h"
30 #include "vulkan/vk_layer.h"
31 #include "vk_layer_table.h"
32 static device_table_map tableMap;
33 static instance_table_map tableInstanceMap;
34
35 #define DISPATCH_MAP_DEBUG 0
36
37 // Map lookup must be thread safe
device_dispatch_table(void * object)38 VkLayerDispatchTable *device_dispatch_table(void *object) {
39 dispatch_key key = get_dispatch_key(object);
40 device_table_map::const_iterator it = tableMap.find((void *)key);
41 assert(it != tableMap.end() && "Not able to find device dispatch entry");
42 return it->second;
43 }
44
instance_dispatch_table(void * object)45 VkLayerInstanceDispatchTable *instance_dispatch_table(void *object) {
46 dispatch_key key = get_dispatch_key(object);
47 instance_table_map::const_iterator it = tableInstanceMap.find((void *)key);
48 #if DISPATCH_MAP_DEBUG
49 if (it != tableInstanceMap.end()) {
50 fprintf(stderr, "instance_dispatch_table: map: %p, object: %p, key: %p, table: %p\n", &tableInstanceMap, object, key,
51 it->second);
52 } else {
53 fprintf(stderr, "instance_dispatch_table: map: %p, object: %p, key: %p, table: UNKNOWN\n", &tableInstanceMap, object, key);
54 }
55 #endif
56 assert(it != tableInstanceMap.end() && "Not able to find instance dispatch entry");
57 return it->second;
58 }
59
destroy_dispatch_table(device_table_map & map,dispatch_key key)60 void destroy_dispatch_table(device_table_map &map, dispatch_key key) {
61 #if DISPATCH_MAP_DEBUG
62 device_table_map::const_iterator it = map.find((void *)key);
63 if (it != map.end()) {
64 fprintf(stderr, "destroy device dispatch_table: map: %p, key: %p, table: %p\n", &map, key, it->second);
65 } else {
66 fprintf(stderr, "destroy device dispatch table: map: %p, key: %p, table: UNKNOWN\n", &map, key);
67 assert(it != map.end());
68 }
69 #endif
70 map.erase(key);
71 }
72
destroy_dispatch_table(instance_table_map & map,dispatch_key key)73 void destroy_dispatch_table(instance_table_map &map, dispatch_key key) {
74 #if DISPATCH_MAP_DEBUG
75 instance_table_map::const_iterator it = map.find((void *)key);
76 if (it != map.end()) {
77 fprintf(stderr, "destroy instance dispatch_table: map: %p, key: %p, table: %p\n", &map, key, it->second);
78 } else {
79 fprintf(stderr, "destroy instance dispatch table: map: %p, key: %p, table: UNKNOWN\n", &map, key);
80 assert(it != map.end());
81 }
82 #endif
83 map.erase(key);
84 }
85
destroy_device_dispatch_table(dispatch_key key)86 void destroy_device_dispatch_table(dispatch_key key) { destroy_dispatch_table(tableMap, key); }
87
destroy_instance_dispatch_table(dispatch_key key)88 void destroy_instance_dispatch_table(dispatch_key key) { destroy_dispatch_table(tableInstanceMap, key); }
89
get_dispatch_table(device_table_map & map,void * object)90 VkLayerDispatchTable *get_dispatch_table(device_table_map &map, void *object) {
91 dispatch_key key = get_dispatch_key(object);
92 device_table_map::const_iterator it = map.find((void *)key);
93 #if DISPATCH_MAP_DEBUG
94 if (it != map.end()) {
95 fprintf(stderr, "device_dispatch_table: map: %p, object: %p, key: %p, table: %p\n", &tableInstanceMap, object, key,
96 it->second);
97 } else {
98 fprintf(stderr, "device_dispatch_table: map: %p, object: %p, key: %p, table: UNKNOWN\n", &tableInstanceMap, object, key);
99 }
100 #endif
101 assert(it != map.end() && "Not able to find device dispatch entry");
102 return it->second;
103 }
104
get_dispatch_table(instance_table_map & map,void * object)105 VkLayerInstanceDispatchTable *get_dispatch_table(instance_table_map &map, void *object) {
106 // VkLayerInstanceDispatchTable *pDisp = *(VkLayerInstanceDispatchTable **) object;
107 dispatch_key key = get_dispatch_key(object);
108 instance_table_map::const_iterator it = map.find((void *)key);
109 #if DISPATCH_MAP_DEBUG
110 if (it != map.end()) {
111 fprintf(stderr, "instance_dispatch_table: map: %p, object: %p, key: %p, table: %p\n", &tableInstanceMap, object, key,
112 it->second);
113 } else {
114 fprintf(stderr, "instance_dispatch_table: map: %p, object: %p, key: %p, table: UNKNOWN\n", &tableInstanceMap, object, key);
115 }
116 #endif
117 assert(it != map.end() && "Not able to find instance dispatch entry");
118 return it->second;
119 }
120
get_chain_info(const VkInstanceCreateInfo * pCreateInfo,VkLayerFunction func)121 VkLayerInstanceCreateInfo *get_chain_info(const VkInstanceCreateInfo *pCreateInfo, VkLayerFunction func) {
122 VkLayerInstanceCreateInfo *chain_info = (VkLayerInstanceCreateInfo *)pCreateInfo->pNext;
123 while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && chain_info->function == func)) {
124 chain_info = (VkLayerInstanceCreateInfo *)chain_info->pNext;
125 }
126 assert(chain_info != NULL);
127 return chain_info;
128 }
129
get_chain_info(const VkDeviceCreateInfo * pCreateInfo,VkLayerFunction func)130 VkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo, VkLayerFunction func) {
131 VkLayerDeviceCreateInfo *chain_info = (VkLayerDeviceCreateInfo *)pCreateInfo->pNext;
132 while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && chain_info->function == func)) {
133 chain_info = (VkLayerDeviceCreateInfo *)chain_info->pNext;
134 }
135 assert(chain_info != NULL);
136 return chain_info;
137 }
138
139 /* Various dispatchable objects will use the same underlying dispatch table if they
140 * are created from that "parent" object. Thus use pointer to dispatch table
141 * as the key to these table maps.
142 * Instance -> PhysicalDevice
143 * Device -> CommandBuffer or Queue
144 * If use the object themselves as key to map then implies Create entrypoints have to be intercepted
145 * and a new key inserted into map */
initInstanceTable(VkInstance instance,const PFN_vkGetInstanceProcAddr gpa,instance_table_map & map)146 VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa, instance_table_map &map) {
147 VkLayerInstanceDispatchTable *pTable;
148 dispatch_key key = get_dispatch_key(instance);
149 instance_table_map::const_iterator it = map.find((void *)key);
150
151 if (it == map.end()) {
152 pTable = new VkLayerInstanceDispatchTable;
153 map[(void *)key] = pTable;
154 #if DISPATCH_MAP_DEBUG
155 fprintf(stderr, "New, Instance: map: %p, key: %p, table: %p\n", &map, key, pTable);
156 #endif
157 } else {
158 #if DISPATCH_MAP_DEBUG
159 fprintf(stderr, "Instance: map: %p, key: %p, table: %p\n", &map, key, it->second);
160 #endif
161 return it->second;
162 }
163
164 layer_init_instance_dispatch_table(instance, pTable, gpa);
165
166 return pTable;
167 }
168
initInstanceTable(VkInstance instance,const PFN_vkGetInstanceProcAddr gpa)169 VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa) {
170 return initInstanceTable(instance, gpa, tableInstanceMap);
171 }
172
initDeviceTable(VkDevice device,const PFN_vkGetDeviceProcAddr gpa,device_table_map & map)173 VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa, device_table_map &map) {
174 VkLayerDispatchTable *pTable;
175 dispatch_key key = get_dispatch_key(device);
176 device_table_map::const_iterator it = map.find((void *)key);
177
178 if (it == map.end()) {
179 pTable = new VkLayerDispatchTable;
180 map[(void *)key] = pTable;
181 #if DISPATCH_MAP_DEBUG
182 fprintf(stderr, "New, Device: map: %p, key: %p, table: %p\n", &map, key, pTable);
183 #endif
184 } else {
185 #if DISPATCH_MAP_DEBUG
186 fprintf(stderr, "Device: map: %p, key: %p, table: %p\n", &map, key, it->second);
187 #endif
188 return it->second;
189 }
190
191 layer_init_device_dispatch_table(device, pTable, gpa);
192
193 return pTable;
194 }
195
initDeviceTable(VkDevice device,const PFN_vkGetDeviceProcAddr gpa)196 VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa) {
197 return initDeviceTable(device, gpa, tableMap);
198 }
199