1 /*
2 * Copyright (c) 2015-2016 Valve Corporation
3 * Copyright (c) 2015-2016 LunarG, Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * Author: Jeremy Hayes <jeremy@lunarg.com>
18 */
19
20 #include <cassert>
21 #include <iostream>
22 #include <unordered_map>
23 #include <vector>
24
25 #include "vk_dispatch_table_helper.h"
26 #include "vk_layer_data.h"
27 #include "vk_layer_extension_utils.h"
28
29 namespace test
30 {
31
32 struct layer_data {
33 VkInstance instance;
34 VkLayerInstanceDispatchTable *instance_dispatch_table;
35
layer_datatest::layer_data36 layer_data() : instance(VK_NULL_HANDLE), instance_dispatch_table(nullptr) {};
37 };
38
39 static uint32_t loader_layer_if_version = CURRENT_LOADER_LAYER_INTERFACE_VERSION;
40
41 static std::unordered_map<void *, layer_data *> layer_data_map;
42
CreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)43 VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator,
44 VkInstance* pInstance)
45 {
46 VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
47 assert(chain_info != nullptr);
48
49 assert(chain_info->u.pLayerInfo != nullptr);
50 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
51 assert(fpGetInstanceProcAddr != nullptr);
52
53 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");
54 if (fpCreateInstance == nullptr)
55 {
56 return VK_ERROR_INITIALIZATION_FAILED;
57 }
58
59 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
60 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
61 if (result != VK_SUCCESS)
62 {
63 return result;
64 }
65
66 VkLayerInstanceCreateInfo *create_dev_info = get_chain_info(pCreateInfo, VK_LOADER_LAYER_CREATE_DEVICE_CALLBACK);
67 assert(create_dev_info != nullptr);
68 auto layer_create_device = create_dev_info->u.layerDevice.pfnLayerCreateDevice;
69 auto layer_destroy_device = create_dev_info->u.layerDevice.pfnLayerDestroyDevice;
70
71 layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
72 instance_data->instance = *pInstance;
73 instance_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
74 layer_init_instance_dispatch_table(*pInstance, instance_data->instance_dispatch_table, fpGetInstanceProcAddr);
75
76 uint32_t count = 0;
77 instance_data->instance_dispatch_table->EnumeratePhysicalDevices(*pInstance, &count, nullptr);
78 std::vector<VkPhysicalDevice> devices(count);
79 instance_data->instance_dispatch_table->EnumeratePhysicalDevices(*pInstance, &count, devices.data());
80 VkDevice device;
81 auto device_create_info = VkDeviceCreateInfo{
82 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType
83 nullptr, // pNext
84 0, // flags
85 0, // queueCreateInfoCount
86 nullptr, // pQueueCreateInfos
87 0, // enabledLayerCount
88 nullptr, // ppEnabledLayerNames
89 0, // enabledExtensionCount
90 nullptr, // ppEnabledExtensionNames
91 nullptr // pEnabledFeatures
92 };
93 auto deviceQueue = VkDeviceQueueCreateInfo{};
94 deviceQueue.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
95 float prios = 1;
96 deviceQueue.queueFamilyIndex = 0;
97 deviceQueue.queueCount = 1;
98 deviceQueue.pQueuePriorities = &prios;
99 device_create_info.pQueueCreateInfos = &deviceQueue;
100 device_create_info.queueCreateInfoCount = 1;
101
102 PFN_vkGetDeviceProcAddr newGDPA = nullptr;
103 layer_create_device(*pInstance, devices[0], &device_create_info, nullptr, &device, vkGetInstanceProcAddr, &newGDPA);
104 assert(newGDPA != nullptr);
105 PFN_vkDestroyDevice destroy = (PFN_vkDestroyDevice)newGDPA(device, "vkDestroyDevice");
106 layer_destroy_device(device, nullptr, destroy);
107
108 std::cout << "VK_LAYER_LUNARG_test: device count " << count << '\n';
109
110 // Marker for testing.
111 std::cout << "VK_LAYER_LUNARG_test: CreateInstance" << '\n';
112
113 return result;
114 }
115
DestroyInstance(VkInstance instance,const VkAllocationCallbacks * pAllocator)116 VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator)
117 {
118 dispatch_key key = get_dispatch_key(instance);
119 layer_data *instance_data = GetLayerDataPtr(key, layer_data_map);
120 instance_data->instance_dispatch_table->DestroyInstance(instance, pAllocator);
121
122 delete instance_data->instance_dispatch_table;
123 layer_data_map.erase(key);
124
125 // Marker for testing.
126 std::cout << "VK_LAYER_LUNARG_test: DestroyInstance" << '\n';
127 }
128
GetInstanceProcAddr(VkInstance instance,const char * funcName)129 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* funcName)
130 {
131 // Return the functions that are intercepted by this layer.
132 static const struct
133 {
134 const char *name;
135 PFN_vkVoidFunction proc;
136 } core_instance_commands[] =
137 {
138 { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
139 { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) },
140 { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) }
141 };
142
143 for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++)
144 {
145 if (!strcmp(core_instance_commands[i].name, funcName))
146 {
147 return core_instance_commands[i].proc;
148 }
149 }
150
151 // Only call down the chain for Vulkan commands that this layer does not intercept.
152 layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
153 VkLayerInstanceDispatchTable *pTable = instance_data->instance_dispatch_table;
154 if (pTable->GetInstanceProcAddr == nullptr)
155 {
156 return nullptr;
157 }
158
159 return pTable->GetInstanceProcAddr(instance, funcName);
160 }
161
GetPhysicalDeviceProcAddr(VkInstance instance,const char * funcName)162 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
163 assert(instance);
164
165 layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
166 VkLayerInstanceDispatchTable *pTable = instance_data->instance_dispatch_table;
167 if (pTable->GetPhysicalDeviceProcAddr == nullptr)
168 {
169 return nullptr;
170 }
171
172 return pTable->GetPhysicalDeviceProcAddr(instance, funcName);
173 }
174
175 }
176
vkGetInstanceProcAddr(VkInstance instance,const char * funcName)177 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
178 {
179 return test::GetInstanceProcAddr(instance, funcName);
180 }
181
vkEnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pCount,VkExtensionProperties * pProperties)182 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties)
183 {
184 return VK_ERROR_LAYER_NOT_PRESENT;
185 }
186
vkEnumerateInstanceLayerProperties(uint32_t * pCount,VkLayerProperties * pProperties)187 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties)
188 {
189 return VK_ERROR_LAYER_NOT_PRESENT;
190 }
191
vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,const char * funcName)192 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
193 return test::GetPhysicalDeviceProcAddr(instance, funcName);
194 }
195
vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface * pVersionStruct)196 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
197 assert(pVersionStruct != NULL);
198 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
199
200 // Fill in the function pointers if our version is at least capable of having the structure contain them.
201 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
202 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
203 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
204 }
205
206 if (pVersionStruct->loaderLayerInterfaceVersion < CURRENT_LOADER_LAYER_INTERFACE_VERSION) {
207 test::loader_layer_if_version = pVersionStruct->loaderLayerInterfaceVersion;
208 } else if (pVersionStruct->loaderLayerInterfaceVersion > CURRENT_LOADER_LAYER_INTERFACE_VERSION) {
209 pVersionStruct->loaderLayerInterfaceVersion = CURRENT_LOADER_LAYER_INTERFACE_VERSION;
210 }
211
212 return VK_SUCCESS;
213 }
214