blob: f5edf7c06733f80342f926126c16bbeb83374f81 [file] [log] [blame]
Jon Ashburn79113cc2014-12-01 14:22:40 -07001/*
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06002 * Vulkan
Jon Ashburn79113cc2014-12-01 14:22:40 -07003 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS 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. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
Jon Ashburn1fec4242014-11-26 11:10:26 -070024#include <string.h>
25#include <stdlib.h>
26#include <assert.h>
27#include <unordered_map>
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070028#include "loader_platform.h"
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060029#include "vk_dispatch_table_helper.h"
30#include "vkLayer.h"
Ian Elliott655cad72015-02-12 17:08:34 -070031// The following is #included again to catch certain OS-specific functions
32// being used:
33#include "loader_platform.h"
Jon Ashburn1fec4242014-11-26 11:10:26 -070034
Jon Ashburnbacb0f52015-04-06 10:58:22 -060035static std::unordered_map<void *, VkLayerDispatchTable *> tableMap;
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -060036static std::unordered_map<void *, VkLayerInstanceDispatchTable *> tableInstanceMap;
37
Jon Ashburnfe7ff9c2015-05-15 16:40:25 -060038/* Various dispatchable objects will use the same underlying dispatch table if they
39 * are created from that "parent" object. Thus use pointer to dispatch table
40 * as the key to these table maps.
41 * Instance -> PhysicalDevice
42 * Device -> CmdBuffer or Queue
43 * If use the object themselves as key to map then implies Create entrypoints have to be intercepted
44 * and a new key inserted into map */
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -060045static VkLayerInstanceDispatchTable * initLayerInstanceTable(const VkBaseLayerObject *instancew)
46{
47 VkLayerInstanceDispatchTable *pTable;
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -060048 assert(instancew);
Jon Ashburnfe7ff9c2015-05-15 16:40:25 -060049 VkLayerInstanceDispatchTable **ppDisp = (VkLayerInstanceDispatchTable **) instancew->baseObject;
50
51 std::unordered_map<void *, VkLayerInstanceDispatchTable *>::const_iterator it = tableInstanceMap.find((void *) *ppDisp);
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -060052 if (it == tableInstanceMap.end())
53 {
54 pTable = new VkLayerInstanceDispatchTable;
Jon Ashburnfe7ff9c2015-05-15 16:40:25 -060055 tableInstanceMap[(void *) *ppDisp] = pTable;
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -060056 } else
57 {
58 return it->second;
59 }
60
61 layer_init_instance_dispatch_table(pTable, (PFN_vkGetInstanceProcAddr) instancew->pGPA, (VkInstance) instancew->nextObject);
62
63 return pTable;
64}
Jon Ashburn1fec4242014-11-26 11:10:26 -070065
Jon Ashburnfe7ff9c2015-05-15 16:40:25 -060066static VkLayerDispatchTable * initLayerTable(const VkBaseLayerObject *devw)
Jon Ashburn1fec4242014-11-26 11:10:26 -070067{
Jon Ashburnbacb0f52015-04-06 10:58:22 -060068 VkLayerDispatchTable *pTable;
Jon Ashburnfe7ff9c2015-05-15 16:40:25 -060069 assert(devw);
70 VkLayerDispatchTable **ppDisp = (VkLayerDispatchTable **) (devw->baseObject);
Jon Ashburn1fec4242014-11-26 11:10:26 -070071
Jon Ashburnfe7ff9c2015-05-15 16:40:25 -060072 std::unordered_map<void *, VkLayerDispatchTable *>::const_iterator it = tableMap.find((void *) *ppDisp);
Jon Ashburn1fec4242014-11-26 11:10:26 -070073 if (it == tableMap.end())
74 {
Jon Ashburnbacb0f52015-04-06 10:58:22 -060075 pTable = new VkLayerDispatchTable;
Jon Ashburnfe7ff9c2015-05-15 16:40:25 -060076 tableMap[(void *) *ppDisp] = pTable;
Jon Ashburn1fec4242014-11-26 11:10:26 -070077 } else
78 {
79 return it->second;
80 }
Chia-I Wuaa4121f2015-01-04 23:11:43 +080081
Jon Ashburn8d1b0b52015-05-18 13:20:15 -060082 layer_initialize_dispatch_table(pTable, (PFN_vkGetDeviceProcAddr) devw->pGPA, (VkDevice) devw->nextObject);
Chia-I Wuaa4121f2015-01-04 23:11:43 +080083
Jon Ashburn1fec4242014-11-26 11:10:26 -070084 return pTable;
85}
86
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -060087VK_LAYER_EXPORT VkResult VKAPI vkLayerExtension1(VkDevice device)
Jon Ashburn1fec4242014-11-26 11:10:26 -070088{
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060089 printf("In vkLayerExtension1() call w/ device: %p\n", (void*)device);
90 printf("vkLayerExtension1 returning SUCCESS\n");
91 return VK_SUCCESS;
Jon Ashburn1fec4242014-11-26 11:10:26 -070092}
93
Jon Ashburn9fd4cc42015-04-10 14:33:07 -060094struct extProps {
95 uint32_t version;
96 const char * const name;
97};
98#define BASIC_LAYER_EXT_ARRAY_SIZE 2
99static const struct extProps basicExts[BASIC_LAYER_EXT_ARRAY_SIZE] = {
100 // TODO what is the version?
101 0x10, "Basic",
102 0x10, "vkLayerExtension1"
103};
104
105VK_LAYER_EXPORT VkResult VKAPI vkGetGlobalExtensionInfo(
106 VkExtensionInfoType infoType,
107 uint32_t extensionIndex,
108 size_t* pDataSize,
109 void* pData)
110{
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600111 /* This entrypoint is NOT going to init it's own dispatch table since loader calls here early */
112 VkExtensionProperties *ext_props;
113 uint32_t *count;
114
115 if (pDataSize == NULL)
116 return VK_ERROR_INVALID_POINTER;
117
118 switch (infoType) {
119 case VK_EXTENSION_INFO_TYPE_COUNT:
120 *pDataSize = sizeof(uint32_t);
121 if (pData == NULL)
122 return VK_SUCCESS;
123 count = (uint32_t *) pData;
124 *count = BASIC_LAYER_EXT_ARRAY_SIZE;
125 break;
126 case VK_EXTENSION_INFO_TYPE_PROPERTIES:
127 *pDataSize = sizeof(VkExtensionProperties);
128 if (pData == NULL)
129 return VK_SUCCESS;
130 if (extensionIndex >= BASIC_LAYER_EXT_ARRAY_SIZE)
131 return VK_ERROR_INVALID_VALUE;
132 ext_props = (VkExtensionProperties *) pData;
133 ext_props->version = basicExts[extensionIndex].version;
134 strncpy(ext_props->extName, basicExts[extensionIndex].name,
135 VK_MAX_EXTENSION_NAME);
136 ext_props->extName[VK_MAX_EXTENSION_NAME - 1] = '\0';
137 break;
138 default:
139 return VK_ERROR_INVALID_VALUE;
140 };
141
142 return VK_SUCCESS;
143}
144
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600145VK_LAYER_EXPORT VkResult VKAPI vkEnumeratePhysicalDevices(
146 VkInstance instance,
147 uint32_t* pPhysicalDeviceCount,
148 VkPhysicalDevice* pPhysicalDevices)
149{
Jon Ashburnfe7ff9c2015-05-15 16:40:25 -0600150 VkLayerInstanceDispatchTable **ppDisp = (VkLayerInstanceDispatchTable **) instance;
151 VkLayerInstanceDispatchTable *pInstTable = tableInstanceMap[*ppDisp];
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600152 printf("At start of wrapped vkEnumeratePhysicalDevices() call w/ inst: %p\n", (void*)instance);
153 VkResult result = pInstTable->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600154 printf("Completed wrapped vkEnumeratePhysicalDevices() call w/ count %u\n", *pPhysicalDeviceCount);
155 return result;
156}
157
Tony Barbourd1c35722015-04-16 15:59:00 -0600158VK_LAYER_EXPORT VkResult VKAPI vkCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo* pCreateInfo, VkDevice* pDevice)
Jon Ashburn1fec4242014-11-26 11:10:26 -0700159{
Jon Ashburnfe7ff9c2015-05-15 16:40:25 -0600160 VkLayerInstanceDispatchTable **ppDisp = (VkLayerInstanceDispatchTable **) gpu;
161 VkLayerInstanceDispatchTable* pInstTable = tableInstanceMap[*ppDisp];
Jon Ashburn1fec4242014-11-26 11:10:26 -0700162
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600163 printf("At start of wrapped vkCreateDevice() call w/ gpu: %p\n", (void*)gpu);
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600164 VkResult result = pInstTable->CreateDevice(gpu, pCreateInfo, pDevice);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600165 printf("Completed wrapped vkCreateDevice() call w/ pDevice, Device %p: %p\n", (void*)pDevice, (void *) *pDevice);
Jon Ashburn1fec4242014-11-26 11:10:26 -0700166 return result;
167}
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600168
Jon Ashburn9a8a2e22015-05-19 16:34:53 -0600169/* hook DestroyDevice to remove tableMap entry */
170VK_LAYER_EXPORT VkResult VKAPI vkDestroyDevice(VkDevice device)
171{
172 VkLayerDispatchTable *pDisp = *(VkLayerDispatchTable **) device;
173 VkLayerDispatchTable *pTable = tableMap[pDisp];
174 VkResult res = pTable->DestroyDevice(device);
175 tableMap.erase(pDisp);
176 return res;
177}
178
179/* hook DestroyInstance to remove tableInstanceMap entry */
180VK_LAYER_EXPORT VkResult VKAPI vkDestroyInstance(VkInstance instance)
181{
182 VkLayerInstanceDispatchTable *pDisp = *(VkLayerInstanceDispatchTable **) instance;
183 VkLayerInstanceDispatchTable *pTable = tableInstanceMap[pDisp];
184 VkResult res = pTable->DestroyInstance(instance);
185 tableInstanceMap.erase(pDisp);
186 return res;
187}
188
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600189VK_LAYER_EXPORT VkResult VKAPI vkGetFormatInfo(VkDevice device, VkFormat format, VkFormatInfoType infoType, size_t* pDataSize, void* pData)
Jon Ashburn1fec4242014-11-26 11:10:26 -0700190{
Jon Ashburnfe7ff9c2015-05-15 16:40:25 -0600191 VkLayerDispatchTable **ppDisp = (VkLayerDispatchTable **) device;
192 VkLayerDispatchTable* pTable = tableMap[*ppDisp];
Jon Ashburn1fec4242014-11-26 11:10:26 -0700193
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600194 printf("At start of wrapped vkGetFormatInfo() call w/ device: %p\n", (void*)device);
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600195 VkResult result = pTable->GetFormatInfo(device, format, infoType, pDataSize, pData);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600196 printf("Completed wrapped vkGetFormatInfo() call w/ device: %p\n", (void*)device);
Jon Ashburn1fec4242014-11-26 11:10:26 -0700197 return result;
198}
199
Courtney Goeltzenleuchterd9dc0c72015-04-20 11:04:54 -0600200VK_LAYER_EXPORT VkResult VKAPI vkEnumerateLayers(VkPhysicalDevice gpu, size_t maxStringSize, size_t* pLayerCount, char* const* pOutLayers, void* pReserved)
Jon Ashburn1fec4242014-11-26 11:10:26 -0700201{
202 if (gpu != NULL)
203 {
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600204 VkLayerInstanceDispatchTable* pTable = initLayerInstanceTable((const VkBaseLayerObject *) gpu);
Jon Ashburn1fec4242014-11-26 11:10:26 -0700205
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600206 printf("At start of wrapped vkEnumerateLayers() call w/ gpu: %p\n", gpu);
Courtney Goeltzenleuchterd9dc0c72015-04-20 11:04:54 -0600207 VkResult result = pTable->EnumerateLayers(gpu, maxStringSize, pLayerCount, pOutLayers, pReserved);
Jon Ashburn1fec4242014-11-26 11:10:26 -0700208 return result;
209 } else
210 {
Courtney Goeltzenleuchterd9dc0c72015-04-20 11:04:54 -0600211 if (pLayerCount == NULL || pOutLayers == NULL || pOutLayers[0] == NULL || pReserved == NULL)
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600212 return VK_ERROR_INVALID_POINTER;
Jon Ashburn1fec4242014-11-26 11:10:26 -0700213
214 // Example of a layer that is only compatible with Intel's GPUs
Jon Ashburnbacb0f52015-04-06 10:58:22 -0600215 VkBaseLayerObject* gpuw = (VkBaseLayerObject*) pReserved;
Tony Barbourd1c35722015-04-16 15:59:00 -0600216 PFN_vkGetPhysicalDeviceInfo fpGetGpuInfo;
217 VkPhysicalDeviceProperties gpuProps;
218 size_t dataSize = sizeof(VkPhysicalDeviceProperties);
219 fpGetGpuInfo = (PFN_vkGetPhysicalDeviceInfo) gpuw->pGPA((VkPhysicalDevice) gpuw->nextObject, "vkGetPhysicalDeviceInfo");
220 fpGetGpuInfo((VkPhysicalDevice) gpuw->nextObject, VK_PHYSICAL_DEVICE_INFO_TYPE_PROPERTIES, &dataSize, &gpuProps);
Jon Ashburn1fec4242014-11-26 11:10:26 -0700221 if (gpuProps.vendorId == 0x8086)
222 {
Courtney Goeltzenleuchterd9dc0c72015-04-20 11:04:54 -0600223 *pLayerCount = 1;
Jon Ashburn1fec4242014-11-26 11:10:26 -0700224 strncpy((char *) pOutLayers[0], "Basic", maxStringSize);
225 } else
226 {
Courtney Goeltzenleuchterd9dc0c72015-04-20 11:04:54 -0600227 *pLayerCount = 0;
Jon Ashburn1fec4242014-11-26 11:10:26 -0700228 }
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600229 return VK_SUCCESS;
Jon Ashburn1fec4242014-11-26 11:10:26 -0700230 }
231}
232
Jon Ashburn8d1b0b52015-05-18 13:20:15 -0600233VK_LAYER_EXPORT void * VKAPI vkGetDeviceProcAddr(VkDevice device, const char* pName)
Jon Ashburn79113cc2014-12-01 14:22:40 -0700234{
Jon Ashburn8d1b0b52015-05-18 13:20:15 -0600235 if (device == NULL)
Jon Ashburn1fec4242014-11-26 11:10:26 -0700236 return NULL;
Chia-I Wub665d942015-01-05 09:41:27 +0800237
Jon Ashburn8d1b0b52015-05-18 13:20:15 -0600238 initLayerTable((const VkBaseLayerObject *) device);
Chia-I Wub665d942015-01-05 09:41:27 +0800239
Jon Ashburn8d1b0b52015-05-18 13:20:15 -0600240 if (!strcmp("vkGetDeviceProcAddr", pName))
241 return (void *) vkGetDeviceProcAddr;
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600242 if (!strcmp("vkGetFormatInfo", pName))
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600243 return (void *) vkGetFormatInfo;
Jon Ashburn9a8a2e22015-05-19 16:34:53 -0600244 if (!strcmp("vkDestroyDevice", pName))
245 return (void *) vkDestroyDevice;
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600246 if (!strcmp("vkLayerExtension1", pName))
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600247 return (void *) vkLayerExtension1;
Jon Ashburn1fec4242014-11-26 11:10:26 -0700248 else {
Jon Ashburn8d1b0b52015-05-18 13:20:15 -0600249 VkBaseLayerObject* devw = (VkBaseLayerObject *) device;
250 if (devw->pGPA == NULL)
Jon Ashburn1fec4242014-11-26 11:10:26 -0700251 return NULL;
Jon Ashburn8d1b0b52015-05-18 13:20:15 -0600252 return devw->pGPA((VkObject) devw->nextObject, pName);
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600253 }
254}
255
256VK_LAYER_EXPORT void * VKAPI vkGetInstanceProcAddr(VkInstance instance, const char* pName)
257{
258 if (instance == NULL)
259 return NULL;
260
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -0600261 initLayerInstanceTable((const VkBaseLayerObject *) instance);
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600262
263 if (!strcmp("vkGetInstanceProcAddr", pName))
264 return (void *) vkGetInstanceProcAddr;
Jon Ashburn9a8a2e22015-05-19 16:34:53 -0600265 if (!strcmp("vkDestroyInstance", pName))
266 return (void *) vkDestroyInstance;
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600267 if (!strcmp("vkEnumeratePhysicalDevices", pName))
268 return (void*) vkEnumeratePhysicalDevices;
269 if (!strcmp("vkGetGlobalExtensionInfo", pName))
Jon Ashburnf6b33db2015-05-05 14:22:52 -0600270 return (void*) vkGetGlobalExtensionInfo;
271 if (!strcmp("vkCreateDevice", pName))
272 return (void *) vkCreateDevice;
273 if (!strcmp("vkEnumerateLayers", pName))
274 return (void *) vkEnumerateLayers;
275 else {
276 VkBaseLayerObject* instancew = (VkBaseLayerObject *) instance;
277 if (instancew->pGPA == NULL)
278 return NULL;
279 return instancew->pGPA((VkObject) instancew->nextObject, pName);
Jon Ashburn1fec4242014-11-26 11:10:26 -0700280 }
281}