1af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter/* 2af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * Copyright (c) 2015-2016 Valve Corporation 3af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * Copyright (c) 2015-2016 LunarG, Inc. 4af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * 5af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * Licensed under the Apache License, Version 2.0 (the "License"); 6af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * you may not use this file except in compliance with the License. 7af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * You may obtain a copy of the License at 8af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * 9af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * http://www.apache.org/licenses/LICENSE-2.0 10af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * 11af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * Unless required by applicable law or agreed to in writing, software 12af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * distributed under the License is distributed on an "AS IS" BASIS, 13af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * See the License for the specific language governing permissions and 15af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * limitations under the License. 16af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * 17af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * Author: Jeremy Hayes <jeremy@lunarg.com> 18af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter */ 19af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 20af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter#include <cassert> 21af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter#include <iostream> 22af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter#include <unordered_map> 23af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 24af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter#include "vk_dispatch_table_helper.h" 25af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter#include "vk_layer_data.h" 26af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter#include "vk_layer_extension_utils.h" 27af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 28af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchternamespace test 29af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter{ 30af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 31af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchterstruct layer_data { 32af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter VkInstance instance; 33af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter VkLayerInstanceDispatchTable *instance_dispatch_table; 34af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 35af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter layer_data() : instance(VK_NULL_HANDLE), instance_dispatch_table(nullptr) {}; 36af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter}; 37af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 38af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchterstatic std::unordered_map<void *, layer_data *> layer_data_map; 39af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 40af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney GoeltzenleuchterVKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, 41af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter VkInstance* pInstance) 42af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter{ 43af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 44af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter assert(chain_info != nullptr); 45af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 46af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter assert(chain_info->u.pLayerInfo != nullptr); 47af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 48af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter assert(fpGetInstanceProcAddr != nullptr); 49af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 50af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance"); 51af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter if (fpCreateInstance == nullptr) 52af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter { 53af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter return VK_ERROR_INITIALIZATION_FAILED; 54af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter } 55af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 56af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 57af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); 58af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter if (result != VK_SUCCESS) 59af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter { 60af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter return result; 61af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter } 62af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 63af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter layer_data *instance_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map); 64af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter instance_data->instance = *pInstance; 65af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter instance_data->instance_dispatch_table = new VkLayerInstanceDispatchTable; 66af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter layer_init_instance_dispatch_table(*pInstance, instance_data->instance_dispatch_table, fpGetInstanceProcAddr); 67af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 68af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter // Marker for testing. 69af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter std::cout << "VK_LAYER_LUNARG_test: CreateInstance" << '\n'; 70af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 71af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter return result; 72af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter} 73af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 74af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney GoeltzenleuchterVKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) 75af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter{ 76af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter dispatch_key key = get_dispatch_key(instance); 77af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter layer_data *instance_data = get_my_data_ptr(key, layer_data_map); 78af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter instance_data->instance_dispatch_table->DestroyInstance(instance, pAllocator); 79af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 80af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter delete instance_data->instance_dispatch_table; 81af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter layer_data_map.erase(key); 82af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 83af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter // Marker for testing. 84af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter std::cout << "VK_LAYER_LUNARG_test: DestroyInstance" << '\n'; 85af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter} 86af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 87af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney GoeltzenleuchterVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* funcName) 88af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter{ 89af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter // Return the functions that are intercepted by this layer. 90af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter static const struct 91af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter { 92af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter const char *name; 93af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter PFN_vkVoidFunction proc; 94af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter } core_instance_commands[] = 95af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter { 96af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) }, 97af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) }, 98af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) } 99af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter }; 100af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 101af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) 102af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter { 103af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter if (!strcmp(core_instance_commands[i].name, funcName)) 104af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter { 105af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter return core_instance_commands[i].proc; 106af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter } 107af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter } 108af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 109af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter // Only call down the chain for Vulkan commands that this layer does not intercept. 110af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter layer_data *instance_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 111af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter VkLayerInstanceDispatchTable *pTable = instance_data->instance_dispatch_table; 112af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter if (pTable->GetInstanceProcAddr == nullptr) 113af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter { 114af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter return nullptr; 115af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter } 116af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 117af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter return pTable->GetInstanceProcAddr(instance, funcName); 118af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter} 119af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 120af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter} 121af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 122af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney GoeltzenleuchterVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName) 123af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter{ 124af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter return test::GetInstanceProcAddr(instance, funcName); 125af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter} 126af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 127af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney GoeltzenleuchterVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char *funcName) 128af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter{ 129af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter return nullptr; 130af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter} 131af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 132af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney GoeltzenleuchterVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) 133af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter{ 134af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter return VK_ERROR_LAYER_NOT_PRESENT; 135af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter} 136af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter 137af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney GoeltzenleuchterVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) 138af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter{ 139af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter return VK_ERROR_LAYER_NOT_PRESENT; 140af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter} 141