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