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 (at) lunarg.com> 18 */ 19 20 #include <cassert> 21 #include <iostream> 22 #include <unordered_map> 23 24 #include "vk_dispatch_table_helper.h" 25 #include "vk_layer_data.h" 26 #include "vk_layer_extension_utils.h" 27 28 namespace test 29 { 30 31 struct layer_data { 32 VkInstance instance; 33 VkLayerInstanceDispatchTable *instance_dispatch_table; 34 35 layer_data() : instance(VK_NULL_HANDLE), instance_dispatch_table(nullptr) {}; 36 }; 37 38 static std::unordered_map<void *, layer_data *> layer_data_map; 39 40 VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, 41 VkInstance* pInstance) 42 { 43 VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 44 assert(chain_info != nullptr); 45 46 assert(chain_info->u.pLayerInfo != nullptr); 47 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 48 assert(fpGetInstanceProcAddr != nullptr); 49 50 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance"); 51 if (fpCreateInstance == nullptr) 52 { 53 return VK_ERROR_INITIALIZATION_FAILED; 54 } 55 56 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 57 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); 58 if (result != VK_SUCCESS) 59 { 60 return result; 61 } 62 63 layer_data *instance_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map); 64 instance_data->instance = *pInstance; 65 instance_data->instance_dispatch_table = new VkLayerInstanceDispatchTable; 66 layer_init_instance_dispatch_table(*pInstance, instance_data->instance_dispatch_table, fpGetInstanceProcAddr); 67 68 // Marker for testing. 69 std::cout << "VK_LAYER_LUNARG_test: CreateInstance" << '\n'; 70 71 return result; 72 } 73 74 VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) 75 { 76 dispatch_key key = get_dispatch_key(instance); 77 layer_data *instance_data = get_my_data_ptr(key, layer_data_map); 78 instance_data->instance_dispatch_table->DestroyInstance(instance, pAllocator); 79 80 delete instance_data->instance_dispatch_table; 81 layer_data_map.erase(key); 82 83 // Marker for testing. 84 std::cout << "VK_LAYER_LUNARG_test: DestroyInstance" << '\n'; 85 } 86 87 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* funcName) 88 { 89 // Return the functions that are intercepted by this layer. 90 static const struct 91 { 92 const char *name; 93 PFN_vkVoidFunction proc; 94 } core_instance_commands[] = 95 { 96 { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) }, 97 { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) }, 98 { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) } 99 }; 100 101 for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) 102 { 103 if (!strcmp(core_instance_commands[i].name, funcName)) 104 { 105 return core_instance_commands[i].proc; 106 } 107 } 108 109 // Only call down the chain for Vulkan commands that this layer does not intercept. 110 layer_data *instance_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 111 VkLayerInstanceDispatchTable *pTable = instance_data->instance_dispatch_table; 112 if (pTable->GetInstanceProcAddr == nullptr) 113 { 114 return nullptr; 115 } 116 117 return pTable->GetInstanceProcAddr(instance, funcName); 118 } 119 120 } 121 122 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName) 123 { 124 return test::GetInstanceProcAddr(instance, funcName); 125 } 126 127 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char *funcName) 128 { 129 return nullptr; 130 } 131 132 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) 133 { 134 return VK_ERROR_LAYER_NOT_PRESENT; 135 } 136 137 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) 138 { 139 return VK_ERROR_LAYER_NOT_PRESENT; 140 } 141