| /* |
| * Copyright (c) 2015-2016 Valve Corporation |
| * Copyright (c) 2015-2016 LunarG, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| * Author: Jeremy Hayes <jeremy@lunarg.com> |
| */ |
| |
| #include <cassert> |
| #include <iostream> |
| #include <unordered_map> |
| |
| #include "vk_dispatch_table_helper.h" |
| #include "vk_layer_data.h" |
| #include "vk_layer_extension_utils.h" |
| |
| namespace test |
| { |
| |
| struct layer_data { |
| VkInstance instance; |
| VkLayerInstanceDispatchTable *instance_dispatch_table; |
| |
| layer_data() : instance(VK_NULL_HANDLE), instance_dispatch_table(nullptr) {}; |
| }; |
| |
| static std::unordered_map<void *, layer_data *> layer_data_map; |
| |
| VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, |
| VkInstance* pInstance) |
| { |
| VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); |
| assert(chain_info != nullptr); |
| |
| assert(chain_info->u.pLayerInfo != nullptr); |
| PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; |
| assert(fpGetInstanceProcAddr != nullptr); |
| |
| PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance"); |
| if (fpCreateInstance == nullptr) |
| { |
| return VK_ERROR_INITIALIZATION_FAILED; |
| } |
| |
| chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; |
| VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); |
| if (result != VK_SUCCESS) |
| { |
| return result; |
| } |
| |
| layer_data *instance_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map); |
| instance_data->instance = *pInstance; |
| instance_data->instance_dispatch_table = new VkLayerInstanceDispatchTable; |
| layer_init_instance_dispatch_table(*pInstance, instance_data->instance_dispatch_table, fpGetInstanceProcAddr); |
| |
| // Marker for testing. |
| std::cout << "VK_LAYER_LUNARG_test: CreateInstance" << '\n'; |
| |
| return result; |
| } |
| |
| VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) |
| { |
| dispatch_key key = get_dispatch_key(instance); |
| layer_data *instance_data = get_my_data_ptr(key, layer_data_map); |
| instance_data->instance_dispatch_table->DestroyInstance(instance, pAllocator); |
| |
| delete instance_data->instance_dispatch_table; |
| layer_data_map.erase(key); |
| |
| // Marker for testing. |
| std::cout << "VK_LAYER_LUNARG_test: DestroyInstance" << '\n'; |
| } |
| |
| VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* funcName) |
| { |
| // Return the functions that are intercepted by this layer. |
| static const struct |
| { |
| const char *name; |
| PFN_vkVoidFunction proc; |
| } core_instance_commands[] = |
| { |
| { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) }, |
| { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) }, |
| { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) } |
| }; |
| |
| for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) |
| { |
| if (!strcmp(core_instance_commands[i].name, funcName)) |
| { |
| return core_instance_commands[i].proc; |
| } |
| } |
| |
| // Only call down the chain for Vulkan commands that this layer does not intercept. |
| layer_data *instance_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); |
| VkLayerInstanceDispatchTable *pTable = instance_data->instance_dispatch_table; |
| if (pTable->GetInstanceProcAddr == nullptr) |
| { |
| return nullptr; |
| } |
| |
| return pTable->GetInstanceProcAddr(instance, funcName); |
| } |
| |
| } |
| |
| VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName) |
| { |
| return test::GetInstanceProcAddr(instance, funcName); |
| } |
| |
| VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char *funcName) |
| { |
| return nullptr; |
| } |
| |
| VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) |
| { |
| return VK_ERROR_LAYER_NOT_PRESENT; |
| } |
| |
| VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) |
| { |
| return VK_ERROR_LAYER_NOT_PRESENT; |
| } |