Home | History | Annotate | Download | only in layers
      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