• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
28 namespace test
29 {
30 
31 struct layer_data {
32     VkInstance instance;
33     VkLayerInstanceDispatchTable *instance_dispatch_table;
34 
layer_datatest::layer_data35     layer_data() : instance(VK_NULL_HANDLE), instance_dispatch_table(nullptr) {};
36 };
37 
38 static std::unordered_map<void *, layer_data *> layer_data_map;
39 
CreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)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 
DestroyInstance(VkInstance instance,const VkAllocationCallbacks * pAllocator)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 
GetInstanceProcAddr(VkInstance instance,const char * funcName)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 
vkGetInstanceProcAddr(VkInstance instance,const char * funcName)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 
vkGetDeviceProcAddr(VkDevice device,const char * funcName)127 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char *funcName)
128 {
129     return nullptr;
130 }
131 
vkEnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pCount,VkExtensionProperties * pProperties)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 
vkEnumerateInstanceLayerProperties(uint32_t * pCount,VkLayerProperties * pProperties)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