1 /*
2 * Copyright (c) 2015-2018 The Khronos Group Inc.
3 * Copyright (c) 2015-2018 Valve Corporation
4 * Copyright (c) 2015-2018 LunarG, Inc.
5 * Copyright (C) 2015-2018 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * Author: Arda Coskunses <arda@lunarg.com>
20 * Author: Tony Barbour <tony@LunarG.com>
21 * Author: Mark Lobodzinski <mark@lunarg.com>
22 */
23 #include <string.h>
24 #include <stdlib.h>
25 #include <assert.h>
26 #include <unordered_map>
27 #include <mutex>
28
29 #include "vk_layer_data.h"
30 #include "vk_dispatch_table_helper.h"
31 #include "vk_layer_utils.h"
32 #include "vk_lunarg_device_profile_api_layer.h"
33 #include "vk_device_profile_api_layer.h"
34
35 namespace device_profile_api {
36
37 static std::mutex global_lock;
38
39 static uint32_t loader_layer_if_version = CURRENT_LOADER_LAYER_INTERFACE_VERSION;
40
41 struct layer_data {
42 VkInstance instance;
43 VkPhysicalDeviceProperties phy_device_props;
44 std::unordered_map<VkFormat, VkFormatProperties, std::hash<int> > format_properties_map;
45 VkLayerInstanceDispatchTable dispatch_table;
46 };
47
48 static std::unordered_map<void *, layer_data *> device_profile_api_dev_data_map;
49
50 // device_profile_api Layer EXT APIs
51 typedef void(VKAPI_PTR *PFN_vkGetOriginalPhysicalDeviceLimitsEXT)(VkPhysicalDevice physicalDevice,
52 const VkPhysicalDeviceLimits *limits);
53 typedef void(VKAPI_PTR *PFN_vkSetPhysicalDeviceLimitsEXT)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceLimits *newLimits);
54 typedef void(VKAPI_PTR *PFN_vkGetOriginalPhysicalDeviceFormatPropertiesEXT)(VkPhysicalDevice physicalDevice, VkFormat format,
55 const VkFormatProperties *properties);
56 typedef void(VKAPI_PTR *PFN_vkSetPhysicalDeviceFormatPropertiesEXT)(VkPhysicalDevice physicalDevice, VkFormat format,
57 const VkFormatProperties newProperties);
58
GetOriginalPhysicalDeviceLimitsEXT(VkPhysicalDevice physicalDevice,VkPhysicalDeviceLimits * orgLimits)59 VKAPI_ATTR void VKAPI_CALL GetOriginalPhysicalDeviceLimitsEXT(VkPhysicalDevice physicalDevice, VkPhysicalDeviceLimits *orgLimits) {
60 std::lock_guard<std::mutex> lock(global_lock);
61 layer_data *phy_dev_data = GetLayerDataPtr(physicalDevice, device_profile_api_dev_data_map);
62 layer_data *instance_data = GetLayerDataPtr(phy_dev_data->instance, device_profile_api_dev_data_map);
63 VkPhysicalDeviceProperties props;
64 instance_data->dispatch_table.GetPhysicalDeviceProperties(physicalDevice, &props);
65 memcpy(orgLimits, &props.limits, sizeof(VkPhysicalDeviceLimits));
66 }
67
SetPhysicalDeviceLimitsEXT(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceLimits * newLimits)68 VKAPI_ATTR void VKAPI_CALL SetPhysicalDeviceLimitsEXT(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceLimits *newLimits) {
69 std::lock_guard<std::mutex> lock(global_lock);
70 layer_data *phy_dev_data = GetLayerDataPtr(physicalDevice, device_profile_api_dev_data_map);
71 memcpy(&(phy_dev_data->phy_device_props.limits), newLimits, sizeof(VkPhysicalDeviceLimits));
72 }
73
GetOriginalPhysicalDeviceFormatPropertiesEXT(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties * properties)74 VKAPI_ATTR void VKAPI_CALL GetOriginalPhysicalDeviceFormatPropertiesEXT(VkPhysicalDevice physicalDevice, VkFormat format,
75 VkFormatProperties *properties) {
76 std::lock_guard<std::mutex> lock(global_lock);
77 layer_data *phy_dev_data = GetLayerDataPtr(physicalDevice, device_profile_api_dev_data_map);
78 layer_data *instance_data = GetLayerDataPtr(phy_dev_data->instance, device_profile_api_dev_data_map);
79 instance_data->dispatch_table.GetPhysicalDeviceFormatProperties(physicalDevice, format, properties);
80 }
81
SetPhysicalDeviceFormatPropertiesEXT(VkPhysicalDevice physicalDevice,VkFormat format,const VkFormatProperties newProperties)82 VKAPI_ATTR void VKAPI_CALL SetPhysicalDeviceFormatPropertiesEXT(VkPhysicalDevice physicalDevice, VkFormat format,
83 const VkFormatProperties newProperties) {
84 std::lock_guard<std::mutex> lock(global_lock);
85 layer_data *phy_dev_data = GetLayerDataPtr(physicalDevice, device_profile_api_dev_data_map);
86
87 memcpy(&(phy_dev_data->format_properties_map[format]), &newProperties, sizeof(VkFormatProperties));
88 }
89
CreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)90 VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
91 VkInstance *pInstance) {
92 VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
93 std::lock_guard<std::mutex> lock(global_lock);
94
95 assert(chain_info->u.pLayerInfo);
96 PFN_vkGetInstanceProcAddr fp_get_instance_proc_addr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
97 PFN_vkCreateInstance fp_create_instance = (PFN_vkCreateInstance)fp_get_instance_proc_addr(NULL, "vkCreateInstance");
98 if (fp_create_instance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
99
100 // Advance the link info for the next element on the chain
101 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
102
103 VkResult result = fp_create_instance(pCreateInfo, pAllocator, pInstance);
104 if (result != VK_SUCCESS) return result;
105
106 layer_data *instance_data = GetLayerDataPtr(*pInstance, device_profile_api_dev_data_map);
107 instance_data->instance = *pInstance;
108 layer_init_instance_dispatch_table(*pInstance, &instance_data->dispatch_table, fp_get_instance_proc_addr);
109 instance_data->dispatch_table.GetPhysicalDeviceProcAddr =
110 (PFN_GetPhysicalDeviceProcAddr)fp_get_instance_proc_addr(*pInstance, "vk_layerGetPhysicalDeviceProcAddr");
111
112 uint32_t physical_device_count = 0;
113 instance_data->dispatch_table.EnumeratePhysicalDevices(*pInstance, &physical_device_count, NULL);
114
115 VkPhysicalDevice *physical_devices = (VkPhysicalDevice *)malloc(sizeof(physical_devices[0]) * physical_device_count);
116 result = instance_data->dispatch_table.EnumeratePhysicalDevices(*pInstance, &physical_device_count, physical_devices);
117
118 for (uint8_t i = 0; i < physical_device_count; i++) {
119 layer_data *phy_dev_data = GetLayerDataPtr(physical_devices[i], device_profile_api_dev_data_map);
120 instance_data->dispatch_table.GetPhysicalDeviceProperties(physical_devices[i], &phy_dev_data->phy_device_props);
121 phy_dev_data->instance = *pInstance;
122 }
123 return result;
124 }
125
GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,VkPhysicalDeviceProperties * pProperties)126 VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) {
127 std::lock_guard<std::mutex> lock(global_lock);
128 layer_data *phy_dev_data = GetLayerDataPtr(physicalDevice, device_profile_api_dev_data_map);
129 memcpy(pProperties, &phy_dev_data->phy_device_props, sizeof(VkPhysicalDeviceProperties));
130 }
131
GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties * pProperties)132 VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format,
133 VkFormatProperties *pProperties) {
134 std::lock_guard<std::mutex> lock(global_lock);
135 layer_data *phy_dev_data = GetLayerDataPtr(physicalDevice, device_profile_api_dev_data_map);
136 layer_data *instance_data = GetLayerDataPtr(phy_dev_data->instance, device_profile_api_dev_data_map);
137 auto device_format_map_it = phy_dev_data->format_properties_map.find(format);
138 if (device_format_map_it != phy_dev_data->format_properties_map.end()) {
139 memcpy(pProperties, &phy_dev_data->format_properties_map[format], sizeof(VkFormatProperties));
140 } else {
141 instance_data->dispatch_table.GetPhysicalDeviceFormatProperties(physicalDevice, format, pProperties);
142 }
143 }
144
145 static const VkLayerProperties device_profile_api_LayerProps = {
146 "VK_LAYER_LUNARG_device_profile_api",
147 VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION), // specVersion
148 1, // implementationVersion
149 "LunarG device profile api Layer",
150 };
151
152 template <typename T>
EnumerateProperties(uint32_t src_count,const T * src_props,uint32_t * dst_count,T * dst_props)153 VkResult EnumerateProperties(uint32_t src_count, const T *src_props, uint32_t *dst_count, T *dst_props) {
154 if (!dst_props || !src_props) {
155 *dst_count = src_count;
156 return VK_SUCCESS;
157 }
158
159 uint32_t copy_count = (*dst_count < src_count) ? *dst_count : src_count;
160 memcpy(dst_props, src_props, sizeof(T) * copy_count);
161 *dst_count = copy_count;
162
163 return (copy_count == src_count) ? VK_SUCCESS : VK_INCOMPLETE;
164 }
165
EnumerateInstanceLayerProperties(uint32_t * pCount,VkLayerProperties * pProperties)166 VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
167 return EnumerateProperties(1, &device_profile_api_LayerProps, pCount, pProperties);
168 }
169
EnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pCount,VkExtensionProperties * pProperties)170 VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
171 VkExtensionProperties *pProperties) {
172 if (pLayerName && !strcmp(pLayerName, device_profile_api_LayerProps.layerName))
173 return EnumerateProperties<VkExtensionProperties>(0, NULL, pCount, pProperties);
174
175 return VK_ERROR_LAYER_NOT_PRESENT;
176 }
177
GetPhysicalDeviceProcAddr(VkInstance instance,const char * name)178 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *name) {
179 if (!strcmp(name, "vkSetPhysicalDeviceLimitsEXT")) return (PFN_vkVoidFunction)SetPhysicalDeviceLimitsEXT;
180 if (!strcmp(name, "vkGetOriginalPhysicalDeviceLimitsEXT")) return (PFN_vkVoidFunction)GetOriginalPhysicalDeviceLimitsEXT;
181 if (!strcmp(name, "vkSetPhysicalDeviceFormatPropertiesEXT")) return (PFN_vkVoidFunction)SetPhysicalDeviceFormatPropertiesEXT;
182 if (!strcmp(name, "vkGetOriginalPhysicalDeviceFormatPropertiesEXT"))
183 return (PFN_vkVoidFunction)GetOriginalPhysicalDeviceFormatPropertiesEXT;
184 layer_data *instance_data = GetLayerDataPtr(instance, device_profile_api_dev_data_map);
185 auto &table = instance_data->dispatch_table;
186 if (!table.GetPhysicalDeviceProcAddr) return nullptr;
187 return table.GetPhysicalDeviceProcAddr(instance, name);
188 }
189
GetInstanceProcAddr(VkInstance instance,const char * name)190 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *name) {
191 if (!strcmp(name, "vkCreateInstance")) return (PFN_vkVoidFunction)CreateInstance;
192 if (!strcmp(name, "vkGetPhysicalDeviceProperties")) return (PFN_vkVoidFunction)GetPhysicalDeviceProperties;
193 if (!strcmp(name, "vkGetPhysicalDeviceFormatProperties")) return (PFN_vkVoidFunction)GetPhysicalDeviceFormatProperties;
194 if (!strcmp(name, "vkGetInstanceProcAddr")) return (PFN_vkVoidFunction)GetInstanceProcAddr;
195 if (!strcmp(name, "vkEnumerateInstanceExtensionProperties")) return (PFN_vkVoidFunction)EnumerateInstanceExtensionProperties;
196 if (!strcmp(name, "vkEnumerateInstanceLayerProperties")) return (PFN_vkVoidFunction)EnumerateInstanceLayerProperties;
197 if (!strcmp(name, "vkSetPhysicalDeviceLimitsEXT")) return (PFN_vkVoidFunction)SetPhysicalDeviceLimitsEXT;
198 if (!strcmp(name, "vkGetOriginalPhysicalDeviceLimitsEXT")) return (PFN_vkVoidFunction)GetOriginalPhysicalDeviceLimitsEXT;
199 if (!strcmp(name, "vkSetPhysicalDeviceFormatPropertiesEXT")) return (PFN_vkVoidFunction)SetPhysicalDeviceFormatPropertiesEXT;
200 if (!strcmp(name, "vkGetOriginalPhysicalDeviceFormatPropertiesEXT"))
201 return (PFN_vkVoidFunction)GetOriginalPhysicalDeviceFormatPropertiesEXT;
202 assert(instance);
203 layer_data *instance_data = GetLayerDataPtr(instance, device_profile_api_dev_data_map);
204 auto &table = instance_data->dispatch_table;
205 if (!table.GetInstanceProcAddr) return nullptr;
206 return table.GetInstanceProcAddr(instance, name);
207 }
208
209 } // namespace device_profile_api
210
vkEnumerateInstanceLayerProperties(uint32_t * pCount,VkLayerProperties * pProperties)211 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
212 VkLayerProperties *pProperties) {
213 return device_profile_api::EnumerateInstanceLayerProperties(pCount, pProperties);
214 }
215
vkEnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pCount,VkExtensionProperties * pProperties)216 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
217 VkExtensionProperties *pProperties) {
218 return device_profile_api::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
219 }
220
vkGetInstanceProcAddr(VkInstance instance,const char * funcName)221 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
222 return device_profile_api::GetInstanceProcAddr(instance, funcName);
223 }
224
vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,const char * funcName)225 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
226 const char *funcName) {
227 return device_profile_api::GetPhysicalDeviceProcAddr(instance, funcName);
228 }
229
vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface * pVersionStruct)230 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
231 assert(pVersionStruct != NULL);
232 assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
233
234 // Fill in the function pointers if our version is at least capable of having the structure contain them.
235 if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
236 pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
237 pVersionStruct->pfnGetDeviceProcAddr = nullptr;
238 pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
239 }
240
241 if (pVersionStruct->loaderLayerInterfaceVersion < CURRENT_LOADER_LAYER_INTERFACE_VERSION) {
242 device_profile_api::loader_layer_if_version = pVersionStruct->loaderLayerInterfaceVersion;
243 } else if (pVersionStruct->loaderLayerInterfaceVersion > CURRENT_LOADER_LAYER_INTERFACE_VERSION) {
244 pVersionStruct->loaderLayerInterfaceVersion = CURRENT_LOADER_LAYER_INTERFACE_VERSION;
245 }
246
247 return VK_SUCCESS;
248 }
249