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 24#include "vk_dispatch_table_helper.h" 25#include "vk_layer_data.h" 26#include "vk_layer_extension_utils.h" 27 28namespace test 29{ 30 31struct layer_data { 32 VkInstance instance; 33 VkLayerInstanceDispatchTable *instance_dispatch_table; 34 35 layer_data() : instance(VK_NULL_HANDLE), instance_dispatch_table(nullptr) {}; 36}; 37 38static uint32_t loader_layer_if_version = CURRENT_LOADER_LAYER_INTERFACE_VERSION; 39 40static std::unordered_map<void *, layer_data *> layer_data_map; 41 42VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, 43 VkInstance* pInstance) 44{ 45 VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 46 assert(chain_info != nullptr); 47 48 assert(chain_info->u.pLayerInfo != nullptr); 49 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 50 assert(fpGetInstanceProcAddr != nullptr); 51 52 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance"); 53 if (fpCreateInstance == nullptr) 54 { 55 return VK_ERROR_INITIALIZATION_FAILED; 56 } 57 58 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 59 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); 60 if (result != VK_SUCCESS) 61 { 62 return result; 63 } 64 65 layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map); 66 instance_data->instance = *pInstance; 67 instance_data->instance_dispatch_table = new VkLayerInstanceDispatchTable; 68 layer_init_instance_dispatch_table(*pInstance, instance_data->instance_dispatch_table, fpGetInstanceProcAddr); 69 // Marker for testing. 70 std::cout << "VK_LAYER_LUNARG_test: CreateInstance" << '\n'; 71 72 return result; 73} 74 75VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) 76{ 77 dispatch_key key = get_dispatch_key(instance); 78 layer_data *instance_data = GetLayerDataPtr(key, layer_data_map); 79 instance_data->instance_dispatch_table->DestroyInstance(instance, pAllocator); 80 81 delete instance_data->instance_dispatch_table; 82 layer_data_map.erase(key); 83 84 // Marker for testing. 85 std::cout << "VK_LAYER_LUNARG_test: DestroyInstance" << '\n'; 86} 87 88VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* funcName) 89{ 90 // Return the functions that are intercepted by this layer. 91 static const struct 92 { 93 const char *name; 94 PFN_vkVoidFunction proc; 95 } core_instance_commands[] = 96 { 97 { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) }, 98 { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) }, 99 { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) } 100 }; 101 102 for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) 103 { 104 if (!strcmp(core_instance_commands[i].name, funcName)) 105 { 106 return core_instance_commands[i].proc; 107 } 108 } 109 110 // Only call down the chain for Vulkan commands that this layer does not intercept. 111 layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map); 112 VkLayerInstanceDispatchTable *pTable = instance_data->instance_dispatch_table; 113 if (pTable->GetInstanceProcAddr == nullptr) 114 { 115 return nullptr; 116 } 117 118 return pTable->GetInstanceProcAddr(instance, funcName); 119} 120 121VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) { 122 assert(instance); 123 124 layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map); 125 VkLayerInstanceDispatchTable *pTable = instance_data->instance_dispatch_table; 126 if (pTable->GetPhysicalDeviceProcAddr == nullptr) 127 { 128 return nullptr; 129 } 130 131 return pTable->GetPhysicalDeviceProcAddr(instance, funcName); 132} 133 134} 135 136VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName) 137{ 138 return test::GetInstanceProcAddr(instance, funcName); 139} 140 141VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char *funcName) 142{ 143 return nullptr; 144} 145 146VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) 147{ 148 return VK_ERROR_LAYER_NOT_PRESENT; 149} 150 151VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) 152{ 153 return VK_ERROR_LAYER_NOT_PRESENT; 154} 155 156VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) { 157 return test::GetPhysicalDeviceProcAddr(instance, funcName); 158} 159 160VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) { 161 assert(pVersionStruct != NULL); 162 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT); 163 164 // Fill in the function pointers if our version is at least capable of having the structure contain them. 165 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) { 166 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr; 167 pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr; 168 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr; 169 } 170 171 if (pVersionStruct->loaderLayerInterfaceVersion < CURRENT_LOADER_LAYER_INTERFACE_VERSION) { 172 test::loader_layer_if_version = pVersionStruct->loaderLayerInterfaceVersion; 173 } else if (pVersionStruct->loaderLayerInterfaceVersion > CURRENT_LOADER_LAYER_INTERFACE_VERSION) { 174 pVersionStruct->loaderLayerInterfaceVersion = CURRENT_LOADER_LAYER_INTERFACE_VERSION; 175 } 176 177 return VK_SUCCESS; 178} 179