1 /*
2 * Copyright (c) 2021-2022 The Khronos Group Inc.
3 * Copyright (c) 2021-2022 Valve Corporation
4 * Copyright (c) 2021-2022 LunarG, 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 are
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice(s) and this permission notice shall be included in
14 * 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: Charles Giessen <charles@lunarg.com>
26 */
27
28 #include "test_layer.h"
29
30 #include "loader/generated/vk_dispatch_table_helper.h"
31
32 // export the enumeration functions instance|device+layer|extension
33 #ifndef TEST_LAYER_EXPORT_ENUMERATE_FUNCTIONS
34 #define TEST_LAYER_EXPORT_ENUMERATE_FUNCTIONS 0
35 #endif
36
37 // export test_layer_GetInstanceProcAddr
38 #ifndef TEST_LAYER_EXPORT_LAYER_NAMED_GIPA
39 #define TEST_LAYER_EXPORT_LAYER_NAMED_GIPA 0
40 #endif
41
42 // export vkGetInstanceProcAddr
43 #ifndef TEST_LAYER_EXPORT_LAYER_VK_GIPA
44 #define TEST_LAYER_EXPORT_LAYER_VK_GIPA 0
45 #endif
46
47 // export test_layer_GetDeviceProcAddr
48 #ifndef TEST_LAYER_EXPORT_LAYER_NAMED_GDPA
49 #define TEST_LAYER_EXPORT_LAYER_NAMED_GDPA 0
50 #endif
51
52 // export vkGetDeviceProcAddr
53 #ifndef TEST_LAYER_EXPORT_LAYER_VK_GDPA
54 #define TEST_LAYER_EXPORT_LAYER_VK_GDPA 0
55 #endif
56
57 // export GetInstanceProcAddr
58 #ifndef TEST_LAYER_EXPORT_NO_PREFIX_GIPA
59 #define TEST_LAYER_EXPORT_NO_PREFIX_GIPA 0
60 #endif
61
62 // export GetDeviceProcAddr
63 #ifndef TEST_LAYER_EXPORT_NO_PREFIX_GDPA
64 #define TEST_LAYER_EXPORT_NO_PREFIX_GDPA 0
65 #endif
66
67 // export vk_layerGetPhysicalDeviceProcAddr
68 #ifndef TEST_LAYER_EXPORT_GET_PHYSICAL_DEVICE_PROC_ADDR
69 #define TEST_LAYER_EXPORT_GET_PHYSICAL_DEVICE_PROC_ADDR 0
70 #endif
71
72 // export vkNegotiateLoaderLayerInterfaceVersion
73 #ifndef LAYER_EXPORT_NEGOTIATE_LOADER_LAYER_INTERFACE_VERSION
74 #define LAYER_EXPORT_NEGOTIATE_LOADER_LAYER_INTERFACE_VERSION 0
75 #endif
76
77 #ifndef TEST_LAYER_NAME
78 #define TEST_LAYER_NAME "VkLayer_LunarG_test_layer"
79 #endif
80
81 TestLayer layer;
82 extern "C" {
get_test_layer_func()83 FRAMEWORK_EXPORT TestLayer* get_test_layer_func() { return &layer; }
reset_layer_func()84 FRAMEWORK_EXPORT TestLayer* reset_layer_func() {
85 layer.~TestLayer();
86 return new (&layer) TestLayer();
87 }
88 }
89
get_chain_info(const VkInstanceCreateInfo * pCreateInfo,VkLayerFunction func)90 VkLayerInstanceCreateInfo* get_chain_info(const VkInstanceCreateInfo* pCreateInfo, VkLayerFunction func) {
91 VkLayerInstanceCreateInfo* chain_info = (VkLayerInstanceCreateInfo*)pCreateInfo->pNext;
92 while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && chain_info->function == func)) {
93 chain_info = (VkLayerInstanceCreateInfo*)chain_info->pNext;
94 }
95 assert(chain_info != NULL);
96 return chain_info;
97 }
98
get_chain_info(const VkDeviceCreateInfo * pCreateInfo,VkLayerFunction func)99 VkLayerDeviceCreateInfo* get_chain_info(const VkDeviceCreateInfo* pCreateInfo, VkLayerFunction func) {
100 VkLayerDeviceCreateInfo* chain_info = (VkLayerDeviceCreateInfo*)pCreateInfo->pNext;
101 while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && chain_info->function == func)) {
102 chain_info = (VkLayerDeviceCreateInfo*)chain_info->pNext;
103 }
104 assert(chain_info != NULL);
105 return chain_info;
106 }
107
test_vkEnumerateInstanceLayerProperties(uint32_t * pPropertyCount,VkLayerProperties * pProperties)108 VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateInstanceLayerProperties(uint32_t* pPropertyCount, VkLayerProperties* pProperties) {
109 return VK_SUCCESS;
110 }
111
test_vkEnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)112 VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount,
113 VkExtensionProperties* pProperties) {
114 if (pLayerName && string_eq(pLayerName, TEST_LAYER_NAME)) {
115 *pPropertyCount = 0;
116 return VK_SUCCESS;
117 }
118 return layer.instance_dispatch_table.EnumerateInstanceExtensionProperties(pLayerName, pPropertyCount, pProperties);
119 }
120
test_vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkLayerProperties * pProperties)121 VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount,
122 VkLayerProperties* pProperties) {
123 return VK_SUCCESS;
124 }
125
test_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)126 VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName,
127 uint32_t* pPropertyCount,
128 VkExtensionProperties* pProperties) {
129 if (pLayerName && string_eq(pLayerName, TEST_LAYER_NAME)) {
130 *pPropertyCount = 0;
131 return VK_SUCCESS;
132 }
133 return layer.instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pPropertyCount,
134 pProperties);
135 }
136
test_vkEnumerateInstanceVersion(uint32_t * pApiVersion)137 VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateInstanceVersion(uint32_t* pApiVersion) {
138 if (pApiVersion != nullptr) {
139 *pApiVersion = VK_API_VERSION_1_0;
140 }
141 return VK_SUCCESS;
142 }
143
test_vkCreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)144 VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo,
145 const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) {
146 VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
147
148 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
149 PFN_vk_icdGetPhysicalDeviceProcAddr fpGetPhysicalDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetPhysicalDeviceProcAddr;
150 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
151 if (fpCreateInstance == NULL) {
152 return VK_ERROR_INITIALIZATION_FAILED;
153 }
154
155 // Advance the link info for the next element of the chain
156 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
157 layer.next_vkGetInstanceProcAddr = fpGetInstanceProcAddr;
158
159 // Continue call down the chain
160 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
161 if (result != VK_SUCCESS) {
162 return result;
163 }
164 layer.instance_handle = *pInstance;
165 if (layer.use_gipa_GetPhysicalDeviceProcAddr) {
166 layer.next_GetPhysicalDeviceProcAddr =
167 reinterpret_cast<PFN_GetPhysicalDeviceProcAddr>(fpGetInstanceProcAddr(*pInstance, "vk_layerGetPhysicalDeviceProcAddr"));
168 } else {
169 layer.next_GetPhysicalDeviceProcAddr = fpGetPhysicalDeviceProcAddr;
170 }
171 // Init layer's dispatch table using GetInstanceProcAddr of
172 // next layer in the chain.
173 layer_init_instance_dispatch_table(layer.instance_handle, &layer.instance_dispatch_table, fpGetInstanceProcAddr);
174
175 if (layer.create_instance_callback) result = layer.create_instance_callback(layer);
176
177 for (auto& func : layer.custom_physical_device_interception_functions) {
178 auto next_func = layer.next_GetPhysicalDeviceProcAddr(*pInstance, func.name.c_str());
179 layer.custom_dispatch_functions.at(func.name.c_str()) = next_func;
180 }
181
182 for (auto& func : layer.custom_device_interception_functions) {
183 auto next_func = layer.next_vkGetInstanceProcAddr(*pInstance, func.name.c_str());
184 layer.custom_dispatch_functions.at(func.name.c_str()) = next_func;
185 }
186
187 if (layer.do_spurious_allocations_in_create_instance && pAllocator && pAllocator->pfnAllocation) {
188 layer.spurious_instance_memory_allocation =
189 pAllocator->pfnAllocation(pAllocator->pUserData, 100, 8, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
190 if (layer.spurious_instance_memory_allocation == nullptr) {
191 return VK_ERROR_OUT_OF_HOST_MEMORY;
192 }
193 }
194
195 return result;
196 }
197
test_override_vkCreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)198 VKAPI_ATTR VkResult VKAPI_CALL test_override_vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo,
199 const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) {
200 return VK_ERROR_INVALID_SHADER_NV;
201 }
202
test_vkDestroyInstance(VkInstance instance,const VkAllocationCallbacks * pAllocator)203 VKAPI_ATTR void VKAPI_CALL test_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator) {
204 if (layer.spurious_instance_memory_allocation && pAllocator && pAllocator->pfnFree) {
205 pAllocator->pfnFree(pAllocator->pUserData, layer.spurious_instance_memory_allocation);
206 layer.spurious_instance_memory_allocation = nullptr;
207 }
208
209 layer.instance_dispatch_table.DestroyInstance(instance, pAllocator);
210 }
211
test_vkCreateDevice(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * pDevice)212 VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo,
213 const VkAllocationCallbacks* pAllocator, VkDevice* pDevice) {
214 VkLayerDeviceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
215
216 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
217 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
218 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(layer.instance_handle, "vkCreateDevice");
219 if (fpCreateDevice == NULL) {
220 return VK_ERROR_INITIALIZATION_FAILED;
221 }
222
223 layer.next_vkGetDeviceProcAddr = fpGetDeviceProcAddr;
224
225 // Advance the link info for the next element on the chain
226 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
227
228 VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
229 if (result != VK_SUCCESS) {
230 return result;
231 }
232 TestLayer::Device device{};
233 device.device_handle = *pDevice;
234
235 // initialize layer's dispatch table
236 layer_init_device_dispatch_table(device.device_handle, &device.dispatch_table, fpGetDeviceProcAddr);
237
238 for (auto& func : layer.custom_device_interception_functions) {
239 auto next_func = layer.next_vkGetDeviceProcAddr(*pDevice, func.name.c_str());
240 layer.custom_dispatch_functions.at(func.name.c_str()) = next_func;
241 }
242
243 if (layer.create_device_callback) {
244 result = layer.create_device_callback(layer);
245 }
246
247 // Need to add the created devices to the list so it can be freed
248 layer.created_devices.push_back(device);
249
250 if (layer.do_spurious_allocations_in_create_device && pAllocator && pAllocator->pfnAllocation) {
251 void* allocation = pAllocator->pfnAllocation(pAllocator->pUserData, 110, 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
252 if (allocation == nullptr) {
253 return VK_ERROR_OUT_OF_HOST_MEMORY;
254 } else {
255 layer.spurious_device_memory_allocations.push_back({allocation, device.device_handle});
256 }
257 }
258
259 return result;
260 }
261
test_vkEnumeratePhysicalDevices(VkInstance instance,uint32_t * pPhysicalDeviceCount,VkPhysicalDevice * pPhysicalDevices)262 VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount,
263 VkPhysicalDevice* pPhysicalDevices) {
264 if (layer.add_phys_devs || layer.remove_phys_devs || layer.reorder_phys_devs) {
265 VkResult res = VK_SUCCESS;
266
267 if (layer.complete_physical_devices.size() == 0) {
268 // Get list of all physical devices from lower down
269 // NOTE: This only works if we don't test changing the number of devices
270 // underneath us when using this test.
271 uint32_t icd_count = 0;
272 layer.instance_dispatch_table.EnumeratePhysicalDevices(instance, &icd_count, nullptr);
273 std::vector<VkPhysicalDevice> tmp_vector;
274 tmp_vector.resize(icd_count);
275 layer.instance_dispatch_table.EnumeratePhysicalDevices(instance, &icd_count, tmp_vector.data());
276 layer.complete_physical_devices.clear();
277
278 if (layer.remove_phys_devs) {
279 // Erase the 3rd and 4th items
280 layer.removed_physical_devices.push_back(tmp_vector[3]);
281 layer.removed_physical_devices.push_back(tmp_vector[4]);
282 tmp_vector.erase(tmp_vector.begin() + 3);
283 tmp_vector.erase(tmp_vector.begin() + 3);
284 }
285
286 if (layer.add_phys_devs) {
287 // Insert a new device in the beginning, middle, and end
288 uint32_t middle = static_cast<uint32_t>(tmp_vector.size() / 2);
289 VkPhysicalDevice new_phys_dev = reinterpret_cast<VkPhysicalDevice>((size_t)(0xABCD0000));
290 layer.added_physical_devices.push_back(new_phys_dev);
291 tmp_vector.insert(tmp_vector.begin(), new_phys_dev);
292 new_phys_dev = reinterpret_cast<VkPhysicalDevice>((size_t)(0xBADC0000));
293 layer.added_physical_devices.push_back(new_phys_dev);
294 tmp_vector.insert(tmp_vector.begin() + middle, new_phys_dev);
295 new_phys_dev = reinterpret_cast<VkPhysicalDevice>((size_t)(0xDCBA0000));
296 layer.added_physical_devices.push_back(new_phys_dev);
297 tmp_vector.push_back(new_phys_dev);
298 }
299
300 if (layer.reorder_phys_devs) {
301 // Flip the order of items
302 for (int32_t dev = static_cast<int32_t>(tmp_vector.size() - 1); dev >= 0; --dev) {
303 layer.complete_physical_devices.push_back(tmp_vector[dev]);
304 }
305 } else {
306 // Otherwise, keep the order the same
307 for (uint32_t dev = 0; dev < tmp_vector.size(); ++dev) {
308 layer.complete_physical_devices.push_back(tmp_vector[dev]);
309 }
310 }
311 }
312
313 if (nullptr == pPhysicalDevices) {
314 *pPhysicalDeviceCount = static_cast<uint32_t>(layer.complete_physical_devices.size());
315 } else {
316 uint32_t adj_count = static_cast<uint32_t>(layer.complete_physical_devices.size());
317 if (*pPhysicalDeviceCount < adj_count) {
318 adj_count = *pPhysicalDeviceCount;
319 res = VK_INCOMPLETE;
320 }
321 for (uint32_t dev = 0; dev < adj_count; ++dev) {
322 pPhysicalDevices[dev] = layer.complete_physical_devices[dev];
323 }
324 *pPhysicalDeviceCount = adj_count;
325 }
326
327 return res;
328 } else {
329 return layer.instance_dispatch_table.EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
330 }
331 }
332
test_vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,VkPhysicalDeviceProperties * pProperties)333 VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
334 VkPhysicalDeviceProperties* pProperties) {
335 if (std::find(layer.removed_physical_devices.begin(), layer.removed_physical_devices.end(), physicalDevice) !=
336 layer.removed_physical_devices.end()) {
337 // Should not get here since the application should not know about those devices
338 assert(false);
339 } else if (std::find(layer.added_physical_devices.begin(), layer.added_physical_devices.end(), physicalDevice) !=
340 layer.added_physical_devices.end()) {
341 // Added device so put in some placeholder info we can test against
342 pProperties->apiVersion = VK_API_VERSION_1_2;
343 pProperties->driverVersion = VK_MAKE_API_VERSION(0, 12, 14, 196);
344 pProperties->vendorID = 0xDECAFBAD;
345 pProperties->deviceID = 0xDEADBADD;
346 #if defined(_WIN32)
347 strncpy_s(pProperties->deviceName, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE, "physdev_added_xx", 17);
348 #else
349 strncpy(pProperties->deviceName, "physdev_added_xx", VK_MAX_PHYSICAL_DEVICE_NAME_SIZE);
350 #endif
351 } else {
352 // Not an affected device so just return
353 layer.instance_dispatch_table.GetPhysicalDeviceProperties(physicalDevice, pProperties);
354 }
355 }
356
test_vkEnumeratePhysicalDeviceGroups(VkInstance instance,uint32_t * pPhysicalDeviceGroupCount,VkPhysicalDeviceGroupProperties * pPhysicalDeviceGroupProperties)357 VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumeratePhysicalDeviceGroups(
358 VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
359 if (layer.add_phys_devs || layer.remove_phys_devs || layer.reorder_phys_devs) {
360 VkResult res = VK_SUCCESS;
361
362 if (layer.complete_physical_device_groups.size() == 0) {
363 uint32_t fake_count = 1000;
364 // Call EnumerateDevices to add remove devices as needed
365 test_vkEnumeratePhysicalDevices(instance, &fake_count, nullptr);
366
367 // Get list of all physical devices from lower down
368 // NOTE: This only works if we don't test changing the number of devices
369 // underneath us when using this test.
370 uint32_t icd_group_count = 0;
371 layer.instance_dispatch_table.EnumeratePhysicalDeviceGroups(instance, &icd_group_count, nullptr);
372 std::vector<VkPhysicalDeviceGroupProperties> tmp_vector(icd_group_count);
373 for (uint32_t group = 0; group < icd_group_count; ++group) {
374 tmp_vector[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
375 }
376 layer.instance_dispatch_table.EnumeratePhysicalDeviceGroups(instance, &icd_group_count, tmp_vector.data());
377 layer.complete_physical_device_groups.clear();
378
379 if (layer.remove_phys_devs) {
380 // Now, if a device has been removed, and it was the only group, we need to remove the group as well.
381 for (uint32_t rem_dev = 0; rem_dev < layer.removed_physical_devices.size(); ++rem_dev) {
382 for (uint32_t group = 0; group < icd_group_count; ++group) {
383 for (uint32_t grp_dev = 0; grp_dev < tmp_vector[group].physicalDeviceCount; ++grp_dev) {
384 if (tmp_vector[group].physicalDevices[grp_dev] == layer.removed_physical_devices[rem_dev]) {
385 for (uint32_t cp_item = grp_dev + 1; cp_item < tmp_vector[group].physicalDeviceCount; ++cp_item) {
386 tmp_vector[group].physicalDevices[grp_dev] = tmp_vector[group].physicalDevices[cp_item];
387 }
388 tmp_vector[group].physicalDeviceCount--;
389 }
390 }
391 }
392 }
393 for (uint32_t group = 0; group < tmp_vector.size(); ++group) {
394 if (tmp_vector[group].physicalDeviceCount == 0) {
395 layer.removed_physical_device_groups.push_back(tmp_vector[group]);
396 tmp_vector.erase(tmp_vector.begin() + group);
397 --group;
398 }
399 }
400 }
401
402 if (layer.add_phys_devs) {
403 // Add a new group for each physical device not associated with a current group
404 for (uint32_t dev = 0; dev < layer.added_physical_devices.size(); ++dev) {
405 VkPhysicalDeviceGroupProperties props{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES};
406 props.physicalDeviceCount = 1;
407 props.physicalDevices[0] = layer.added_physical_devices[dev];
408 tmp_vector.push_back(props);
409 layer.added_physical_device_groups.push_back(props);
410 }
411 }
412
413 if (layer.reorder_phys_devs) {
414 // Flip the order of items
415 for (int32_t dev = static_cast<int32_t>(tmp_vector.size() - 1); dev >= 0; --dev) {
416 layer.complete_physical_device_groups.push_back(tmp_vector[dev]);
417 }
418 } else {
419 // Otherwise, keep the order the same
420 for (uint32_t dev = 0; dev < tmp_vector.size(); ++dev) {
421 layer.complete_physical_device_groups.push_back(tmp_vector[dev]);
422 }
423 }
424 }
425
426 if (nullptr == pPhysicalDeviceGroupProperties) {
427 *pPhysicalDeviceGroupCount = static_cast<uint32_t>(layer.complete_physical_device_groups.size());
428 } else {
429 uint32_t adj_count = static_cast<uint32_t>(layer.complete_physical_device_groups.size());
430 if (*pPhysicalDeviceGroupCount < adj_count) {
431 adj_count = *pPhysicalDeviceGroupCount;
432 res = VK_INCOMPLETE;
433 }
434 for (uint32_t dev = 0; dev < adj_count; ++dev) {
435 pPhysicalDeviceGroupProperties[dev] = layer.complete_physical_device_groups[dev];
436 }
437 *pPhysicalDeviceGroupCount = adj_count;
438 }
439
440 return res;
441 } else {
442 return layer.instance_dispatch_table.EnumeratePhysicalDeviceGroups(instance, pPhysicalDeviceGroupCount,
443 pPhysicalDeviceGroupProperties);
444 }
445 }
446
447 // device functions
448
test_vkDestroyDevice(VkDevice device,const VkAllocationCallbacks * pAllocator)449 VKAPI_ATTR void VKAPI_CALL test_vkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
450 for (uint32_t i = 0; i < layer.spurious_device_memory_allocations.size();) {
451 auto& allocation = layer.spurious_device_memory_allocations[i];
452 if (allocation.device == device && pAllocator && pAllocator->pfnFree) {
453 pAllocator->pfnFree(pAllocator->pUserData, allocation.allocation);
454 layer.spurious_device_memory_allocations.erase(layer.spurious_device_memory_allocations.begin() + i);
455 } else {
456 i++;
457 }
458 }
459
460 for (auto& created_device : layer.created_devices) {
461 if (created_device.device_handle == device) {
462 created_device.dispatch_table.DestroyDevice(device, pAllocator);
463 break;
464 }
465 }
466 }
467 // forward declarations needed for trampolines
468 #if TEST_LAYER_EXPORT_GET_PHYSICAL_DEVICE_PROC_ADDR
469 extern "C" {
470 FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance, const char* pName);
471 }
472 #endif
473
474 // trampolines
475 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_device_func(VkDevice device, const char* pName);
get_device_func_impl(VkDevice device,const char * pName)476 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_device_func_impl(VkDevice device, const char* pName) {
477 if (string_eq(pName, "vkGetDeviceProcAddr")) return to_vkVoidFunction(get_device_func);
478 if (string_eq(pName, "vkDestroyDevice")) return to_vkVoidFunction(test_vkDestroyDevice);
479
480 for (auto& func : layer.custom_device_interception_functions) {
481 if (func.name == pName) {
482 return to_vkVoidFunction(func.function);
483 }
484 }
485
486 for (auto& func : layer.custom_device_implementation_functions) {
487 if (func.name == pName) {
488 return to_vkVoidFunction(func.function);
489 }
490 }
491
492 return nullptr;
493 }
494
get_device_func(VkDevice device,const char * pName)495 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_device_func(VkDevice device, const char* pName) {
496 PFN_vkVoidFunction ret_dev = get_device_func_impl(device, pName);
497 if (ret_dev != nullptr) return ret_dev;
498
499 return layer.next_vkGetDeviceProcAddr(device, pName);
500 }
501
get_physical_device_func(VkInstance instance,const char * pName)502 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_physical_device_func(VkInstance instance, const char* pName) {
503 if (string_eq(pName, "vkEnumerateDeviceLayerProperties")) return to_vkVoidFunction(test_vkEnumerateDeviceLayerProperties);
504 if (string_eq(pName, "vkEnumerateDeviceExtensionProperties"))
505 return to_vkVoidFunction(test_vkEnumerateDeviceExtensionProperties);
506 if (string_eq(pName, "vkEnumeratePhysicalDevices")) return (PFN_vkVoidFunction)test_vkEnumeratePhysicalDevices;
507 if (string_eq(pName, "vkEnumeratePhysicalDeviceGroups")) return (PFN_vkVoidFunction)test_vkEnumeratePhysicalDeviceGroups;
508 if (string_eq(pName, "vkGetPhysicalDeviceProperties")) return (PFN_vkVoidFunction)test_vkGetPhysicalDeviceProperties;
509
510 for (auto& func : layer.custom_physical_device_interception_functions) {
511 if (func.name == pName) {
512 return to_vkVoidFunction(func.function);
513 }
514 }
515
516 for (auto& func : layer.custom_physical_device_implementation_functions) {
517 if (func.name == pName) {
518 return to_vkVoidFunction(func.function);
519 }
520 }
521
522 #if TEST_LAYER_EXPORT_GET_PHYSICAL_DEVICE_PROC_ADDR
523 if (string_eq(pName, "vk_layerGetPhysicalDeviceProcAddr")) return to_vkVoidFunction(vk_layerGetPhysicalDeviceProcAddr);
524 #endif
525 return nullptr;
526 }
527 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_instance_func(VkInstance instance, const char* pName);
get_instance_func_impl(VkInstance instance,const char * pName)528 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_instance_func_impl(VkInstance instance, const char* pName) {
529 if (pName == nullptr) return nullptr;
530 if (string_eq(pName, "vkGetInstanceProcAddr")) return to_vkVoidFunction(get_instance_func);
531 if (string_eq(pName, "vkEnumerateInstanceLayerProperties")) return to_vkVoidFunction(test_vkEnumerateInstanceLayerProperties);
532 if (string_eq(pName, "vkEnumerateInstanceExtensionProperties"))
533 return to_vkVoidFunction(test_vkEnumerateInstanceExtensionProperties);
534 if (string_eq(pName, "vkEnumerateInstanceVersion")) return to_vkVoidFunction(test_vkEnumerateInstanceVersion);
535 if (string_eq(pName, "vkCreateInstance")) return to_vkVoidFunction(test_vkCreateInstance);
536 if (string_eq(pName, "vkDestroyInstance")) return to_vkVoidFunction(test_vkDestroyInstance);
537 if (string_eq(pName, "vkCreateDevice")) return to_vkVoidFunction(test_vkCreateDevice);
538 if (string_eq(pName, "vkGetDeviceProcAddr")) return to_vkVoidFunction(get_device_func);
539
540 PFN_vkVoidFunction ret_phys_dev = get_physical_device_func(instance, pName);
541 if (ret_phys_dev != nullptr) return ret_phys_dev;
542
543 PFN_vkVoidFunction ret_dev = get_device_func_impl(nullptr, pName);
544 if (ret_dev != nullptr) return ret_dev;
545
546 return nullptr;
547 }
548
get_instance_func(VkInstance instance,const char * pName)549 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_instance_func(VkInstance instance, const char* pName) {
550 PFN_vkVoidFunction ret_dev = get_instance_func_impl(instance, pName);
551 if (ret_dev != nullptr) return ret_dev;
552
553 return layer.next_vkGetInstanceProcAddr(instance, pName);
554 }
555
556 // Exported functions
557 extern "C" {
558 #if TEST_LAYER_EXPORT_ENUMERATE_FUNCTIONS
559
560 // Pre-instance handling functions
561
test_preinst_vkEnumerateInstanceLayerProperties(const VkEnumerateInstanceLayerPropertiesChain * pChain,uint32_t * pPropertyCount,VkLayerProperties * pProperties)562 FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL test_preinst_vkEnumerateInstanceLayerProperties(
563 const VkEnumerateInstanceLayerPropertiesChain* pChain, uint32_t* pPropertyCount, VkLayerProperties* pProperties) {
564 VkResult res = pChain->pfnNextLayer(pChain->pNextLink, pPropertyCount, pProperties);
565 if (nullptr == pProperties) {
566 *pPropertyCount = layer.reported_layer_props;
567 } else {
568 uint32_t count = layer.reported_layer_props;
569 if (*pPropertyCount < layer.reported_layer_props) {
570 count = *pPropertyCount;
571 res = VK_INCOMPLETE;
572 }
573 for (uint32_t i = 0; i < count; ++i) {
574 snprintf(pProperties[i].layerName, VK_MAX_EXTENSION_NAME_SIZE, "%02d_layer", count);
575 pProperties[i].specVersion = count;
576 pProperties[i].implementationVersion = 0xABCD0000 + count;
577 }
578 }
579 return res;
580 }
581
test_preinst_vkEnumerateInstanceExtensionProperties(const VkEnumerateInstanceExtensionPropertiesChain * pChain,const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)582 FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL test_preinst_vkEnumerateInstanceExtensionProperties(
583 const VkEnumerateInstanceExtensionPropertiesChain* pChain, const char* pLayerName, uint32_t* pPropertyCount,
584 VkExtensionProperties* pProperties) {
585 VkResult res = pChain->pfnNextLayer(pChain->pNextLink, pLayerName, pPropertyCount, pProperties);
586 if (nullptr == pProperties) {
587 *pPropertyCount = layer.reported_extension_props;
588 } else {
589 uint32_t count = layer.reported_extension_props;
590 if (*pPropertyCount < layer.reported_extension_props) {
591 count = *pPropertyCount;
592 res = VK_INCOMPLETE;
593 }
594 for (uint32_t i = 0; i < count; ++i) {
595 snprintf(pProperties[i].extensionName, VK_MAX_EXTENSION_NAME_SIZE, "%02d_ext", count);
596 pProperties[i].specVersion = count;
597 }
598 }
599 return res;
600 }
601
602 FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
test_preinst_vkEnumerateInstanceVersion(const VkEnumerateInstanceVersionChain * pChain,uint32_t * pApiVersion)603 test_preinst_vkEnumerateInstanceVersion(const VkEnumerateInstanceVersionChain* pChain, uint32_t* pApiVersion) {
604 VkResult res = pChain->pfnNextLayer(pChain->pNextLink, pApiVersion);
605 *pApiVersion = layer.reported_instance_version;
606 return res;
607 }
608
vkEnumerateInstanceLayerProperties(uint32_t * pPropertyCount,VkLayerProperties * pProperties)609 FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t* pPropertyCount,
610 VkLayerProperties* pProperties) {
611 return test_vkEnumerateInstanceLayerProperties(pPropertyCount, pProperties);
612 }
vkEnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)613 FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char* pLayerName,
614 uint32_t* pPropertyCount,
615 VkExtensionProperties* pProperties) {
616 return test_vkEnumerateInstanceExtensionProperties(pLayerName, pPropertyCount, pProperties);
617 }
618
vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkLayerProperties * pProperties)619 FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
620 uint32_t* pPropertyCount,
621 VkLayerProperties* pProperties) {
622 return test_vkEnumerateDeviceLayerProperties(physicalDevice, pPropertyCount, pProperties);
623 }
vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)624 FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
625 const char* pLayerName,
626 uint32_t* pPropertyCount,
627 VkExtensionProperties* pProperties) {
628 return test_vkEnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pPropertyCount, pProperties);
629 }
630 #endif
631
632 #if TEST_LAYER_EXPORT_LAYER_NAMED_GIPA
test_layer_GetInstanceProcAddr(VkInstance instance,const char * pName)633 FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL test_layer_GetInstanceProcAddr(VkInstance instance, const char* pName) {
634 return get_instance_func(instance, pName);
635 }
test_override_vkGetInstanceProcAddr(VkInstance instance,const char * pName)636 FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL test_override_vkGetInstanceProcAddr(VkInstance instance,
637 const char* pName) {
638 if (string_eq(pName, "vkCreateInstance")) return to_vkVoidFunction(test_override_vkCreateInstance);
639 return get_instance_func(instance, pName);
640 }
641 #endif
642
643 #if TEST_LAYER_EXPORT_LAYER_VK_GIPA
vkGetInstanceProcAddr(VkInstance instance,const char * pName)644 FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* pName) {
645 return get_instance_func(instance, pName);
646 }
647 #endif
648
649 #if TEST_LAYER_EXPORT_LAYER_NAMED_GDPA
test_layer_GetDeviceProcAddr(VkDevice device,const char * pName)650 FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL test_layer_GetDeviceProcAddr(VkDevice device, const char* pName) {
651 return get_device_func(device, pName);
652 }
653 #endif
654
655 #if TEST_LAYER_EXPORT_LAYER_VK_GDPA
vkGetDeviceProcAddr(VkDevice device,const char * pName)656 FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* pName) {
657 return get_device_func(device, pName);
658 }
659 #endif
660
661 #if TEST_LAYER_EXPORT_NO_PREFIX_GIPA
GetInstanceProcAddr(VkInstance instance,const char * pName)662 FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* pName) {
663 return get_instance_func(instance, pName);
664 }
665 #endif
666
667 #if TEST_LAYER_EXPORT_NO_PREFIX_GDPA
GetDeviceProcAddr(VkDevice device,const char * pName)668 FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char* pName) {
669 return get_device_func(device, pName);
670 }
671 #endif
672
673 #if TEST_LAYER_EXPORT_GET_PHYSICAL_DEVICE_PROC_ADDR
vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,const char * pName)674 FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
675 const char* pName) {
676 auto func = get_physical_device_func(instance, pName);
677 if (func != nullptr) return func;
678 return layer.next_GetPhysicalDeviceProcAddr(instance, pName);
679 }
680 #endif
681
682 #if LAYER_EXPORT_NEGOTIATE_LOADER_LAYER_INTERFACE_VERSION
683 // vk_layer.h has a forward declaration of vkNegotiateLoaderLayerInterfaceVersion, which doesn't have any attributes
684 // Since FRAMEWORK_EXPORT adds __declspec(dllexport), we can't do that here, thus we need our own macro
685 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
686 #define EXPORT_NEGOTIATE_FUNCTION __attribute__((visibility("default")))
687 #else
688 #define EXPORT_NEGOTIATE_FUNCTION
689 #endif
690
691 EXPORT_NEGOTIATE_FUNCTION VKAPI_ATTR VkResult VKAPI_CALL
vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface * pVersionStruct)692 vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface* pVersionStruct) {
693 if (pVersionStruct) {
694 if (pVersionStruct->loaderLayerInterfaceVersion < layer.min_implementation_version) {
695 return VK_ERROR_INITIALIZATION_FAILED;
696 }
697
698 pVersionStruct->loaderLayerInterfaceVersion = layer.implementation_version;
699 pVersionStruct->pfnGetInstanceProcAddr = get_instance_func;
700 pVersionStruct->pfnGetDeviceProcAddr = get_device_func;
701 #if TEST_LAYER_EXPORT_GET_PHYSICAL_DEVICE_PROC_ADDR
702 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
703 #else
704 pVersionStruct->pfnGetPhysicalDeviceProcAddr = nullptr;
705 #endif
706
707 return VK_SUCCESS;
708 }
709 return VK_ERROR_INITIALIZATION_FAILED;
710 }
711 #endif
712 } // extern "C"
713