• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright (c) 2014-2021 The Khronos Group Inc.
4  * Copyright (c) 2014-2021 Valve Corporation
5  * Copyright (c) 2014-2021 LunarG, Inc.
6  * Copyright (C) 2015 Google Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19 
20  *
21  * Author: Jon Ashburn <jon@lunarg.com>
22  * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
23  * Author: Mark Young <marky@lunarg.com>
24  * Author: Lenny Komow <lenny@lunarg.com>
25  * Author: Charles Giessen <charles@lunarg.com>
26  *
27  */
28 
29 // Terminators which have simple logic belong here, since they are mostly "pass through"
30 // Function declarations are in vk_loader_extensions.h, thus not needed here
31 
32 #include "allocation.h"
33 #include "loader_common.h"
34 #include "loader.h"
35 #include "log.h"
36 
37 // Terminators for 1.0 functions
38 
terminator_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,VkPhysicalDeviceProperties * pProperties)39 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
40                                                                   VkPhysicalDeviceProperties *pProperties) {
41     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
42     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
43     if (NULL != icd_term->dispatch.GetPhysicalDeviceProperties) {
44         icd_term->dispatch.GetPhysicalDeviceProperties(phys_dev_term->phys_dev, pProperties);
45     }
46 }
47 
terminator_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,uint32_t * pQueueFamilyPropertyCount,VkQueueFamilyProperties * pProperties)48 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
49                                                                              uint32_t *pQueueFamilyPropertyCount,
50                                                                              VkQueueFamilyProperties *pProperties) {
51     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
52     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
53     if (NULL != icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties) {
54         icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties(phys_dev_term->phys_dev, pQueueFamilyPropertyCount, pProperties);
55     }
56 }
57 
terminator_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,VkPhysicalDeviceMemoryProperties * pProperties)58 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
59                                                                         VkPhysicalDeviceMemoryProperties *pProperties) {
60     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
61     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
62     if (NULL != icd_term->dispatch.GetPhysicalDeviceMemoryProperties) {
63         icd_term->dispatch.GetPhysicalDeviceMemoryProperties(phys_dev_term->phys_dev, pProperties);
64     }
65 }
66 
terminator_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,VkPhysicalDeviceFeatures * pFeatures)67 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
68                                                                 VkPhysicalDeviceFeatures *pFeatures) {
69     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
70     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
71     if (NULL != icd_term->dispatch.GetPhysicalDeviceFeatures) {
72         icd_term->dispatch.GetPhysicalDeviceFeatures(phys_dev_term->phys_dev, pFeatures);
73     }
74 }
75 
terminator_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties * pFormatInfo)76 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format,
77                                                                         VkFormatProperties *pFormatInfo) {
78     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
79     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
80     if (NULL != icd_term->dispatch.GetPhysicalDeviceFormatProperties) {
81         icd_term->dispatch.GetPhysicalDeviceFormatProperties(phys_dev_term->phys_dev, format, pFormatInfo);
82     }
83 }
84 
terminator_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,VkImageTiling tiling,VkImageUsageFlags usage,VkImageCreateFlags flags,VkImageFormatProperties * pImageFormatProperties)85 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format,
86                                                                                  VkImageType type, VkImageTiling tiling,
87                                                                                  VkImageUsageFlags usage, VkImageCreateFlags flags,
88                                                                                  VkImageFormatProperties *pImageFormatProperties) {
89     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
90     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
91     if (NULL == icd_term->dispatch.GetPhysicalDeviceImageFormatProperties) {
92         loader_log(
93             icd_term->this_instance, VULKAN_LOADER_ERROR_BIT, 0,
94             "The icd's vkGetPhysicalDeviceImageFormatProperties was null, returning with VK_ERROR_INITIALIZATION_FAILED instead.");
95         return VK_ERROR_INITIALIZATION_FAILED;
96     }
97     return icd_term->dispatch.GetPhysicalDeviceImageFormatProperties(phys_dev_term->phys_dev, format, type, tiling, usage, flags,
98                                                                      pImageFormatProperties);
99 }
100 
terminator_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,VkSampleCountFlagBits samples,VkImageUsageFlags usage,VkImageTiling tiling,uint32_t * pNumProperties,VkSparseImageFormatProperties * pProperties)101 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format,
102                                                                                    VkImageType type, VkSampleCountFlagBits samples,
103                                                                                    VkImageUsageFlags usage, VkImageTiling tiling,
104                                                                                    uint32_t *pNumProperties,
105                                                                                    VkSparseImageFormatProperties *pProperties) {
106     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
107     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
108     if (NULL != icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties) {
109         icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties(phys_dev_term->phys_dev, format, type, samples, usage,
110                                                                         tiling, pNumProperties, pProperties);
111     }
112 }
113 
terminator_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkLayerProperties * pProperties)114 VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount,
115                                                                          VkLayerProperties *pProperties) {
116     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
117     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
118     loader_log(icd_term->this_instance, VULKAN_LOADER_ERROR_BIT, 0,
119                "Encountered the vkEnumerateDeviceLayerProperties terminator.  This means a layer improperly continued.");
120     // Should never get here this call isn't dispatched down the chain
121     return VK_ERROR_INITIALIZATION_FAILED;
122 }
123 
124 // Terminators for 1.1 functions
125 
terminator_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,VkPhysicalDeviceFeatures2 * pFeatures)126 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
127                                                                  VkPhysicalDeviceFeatures2 *pFeatures) {
128     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
129     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
130     const struct loader_instance *inst = icd_term->this_instance;
131 
132     assert(inst != NULL);
133 
134     // Get the function pointer to use to call into the ICD. This could be the core or KHR version
135     PFN_vkGetPhysicalDeviceFeatures2 fpGetPhysicalDeviceFeatures2 = NULL;
136     if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
137         fpGetPhysicalDeviceFeatures2 = icd_term->dispatch.GetPhysicalDeviceFeatures2;
138     }
139     if (fpGetPhysicalDeviceFeatures2 == NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
140         fpGetPhysicalDeviceFeatures2 = icd_term->dispatch.GetPhysicalDeviceFeatures2KHR;
141     }
142 
143     if (fpGetPhysicalDeviceFeatures2 != NULL) {
144         // Pass the call to the driver
145         fpGetPhysicalDeviceFeatures2(phys_dev_term->phys_dev, pFeatures);
146     } else {
147         // Emulate the call
148         loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
149                    "vkGetPhysicalDeviceFeatures2: Emulating call in ICD \"%s\" using vkGetPhysicalDeviceFeatures",
150                    icd_term->scanned_icd->lib_name);
151 
152         // Write to the VkPhysicalDeviceFeatures2 struct
153         icd_term->dispatch.GetPhysicalDeviceFeatures(phys_dev_term->phys_dev, &pFeatures->features);
154 
155         const VkBaseInStructure *pNext = pFeatures->pNext;
156         while (pNext != NULL) {
157             switch (pNext->sType) {
158                 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: {
159                     // Skip the check if VK_KHR_multiview is enabled because it's a device extension
160                     // Write to the VkPhysicalDeviceMultiviewFeaturesKHR struct
161                     VkPhysicalDeviceMultiviewFeaturesKHR *multiview_features = (VkPhysicalDeviceMultiviewFeaturesKHR *)pNext;
162                     multiview_features->multiview = VK_FALSE;
163                     multiview_features->multiviewGeometryShader = VK_FALSE;
164                     multiview_features->multiviewTessellationShader = VK_FALSE;
165 
166                     pNext = multiview_features->pNext;
167                     break;
168                 }
169                 default: {
170                     loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0,
171                                "vkGetPhysicalDeviceFeatures2: Emulation found unrecognized structure type in pFeatures->pNext - "
172                                "this struct will be ignored");
173 
174                     pNext = pNext->pNext;
175                     break;
176                 }
177             }
178         }
179     }
180 }
181 
terminator_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,VkPhysicalDeviceProperties2 * pProperties)182 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
183                                                                    VkPhysicalDeviceProperties2 *pProperties) {
184     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
185     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
186     const struct loader_instance *inst = icd_term->this_instance;
187 
188     assert(inst != NULL);
189 
190     // Get the function pointer to use to call into the ICD. This could be the core or KHR version
191     PFN_vkGetPhysicalDeviceProperties2 fpGetPhysicalDeviceProperties2 = NULL;
192     if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
193         fpGetPhysicalDeviceProperties2 = icd_term->dispatch.GetPhysicalDeviceProperties2;
194     }
195     if (fpGetPhysicalDeviceProperties2 == NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
196         fpGetPhysicalDeviceProperties2 = icd_term->dispatch.GetPhysicalDeviceProperties2KHR;
197     }
198 
199     if (fpGetPhysicalDeviceProperties2 != NULL) {
200         // Pass the call to the driver
201         fpGetPhysicalDeviceProperties2(phys_dev_term->phys_dev, pProperties);
202     } else {
203         // Emulate the call
204         loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
205                    "vkGetPhysicalDeviceProperties2: Emulating call in ICD \"%s\" using vkGetPhysicalDeviceProperties",
206                    icd_term->scanned_icd->lib_name);
207 
208         // Write to the VkPhysicalDeviceProperties2 struct
209         icd_term->dispatch.GetPhysicalDeviceProperties(phys_dev_term->phys_dev, &pProperties->properties);
210 
211         const VkBaseInStructure *pNext = pProperties->pNext;
212         while (pNext != NULL) {
213             switch (pNext->sType) {
214                 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: {
215                     VkPhysicalDeviceIDPropertiesKHR *id_properties = (VkPhysicalDeviceIDPropertiesKHR *)pNext;
216 
217                     // Verify that "VK_KHR_external_memory_capabilities" is enabled
218                     if (icd_term->this_instance->enabled_known_extensions.khr_external_memory_capabilities) {
219                         loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0,
220                                    "vkGetPhysicalDeviceProperties2: Emulation cannot generate unique IDs for struct "
221                                    "VkPhysicalDeviceIDProperties - setting IDs to zero instead");
222 
223                         // Write to the VkPhysicalDeviceIDPropertiesKHR struct
224                         memset(id_properties->deviceUUID, 0, VK_UUID_SIZE);
225                         memset(id_properties->driverUUID, 0, VK_UUID_SIZE);
226                         id_properties->deviceLUIDValid = VK_FALSE;
227                     }
228 
229                     pNext = id_properties->pNext;
230                     break;
231                 }
232                 default: {
233                     loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0,
234                                "vkGetPhysicalDeviceProperties2KHR: Emulation found unrecognized structure type in "
235                                "pProperties->pNext - this struct will be ignored");
236 
237                     pNext = pNext->pNext;
238                     break;
239                 }
240             }
241         }
242     }
243 }
244 
terminator_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties2 * pFormatProperties)245 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format,
246                                                                          VkFormatProperties2 *pFormatProperties) {
247     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
248     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
249     const struct loader_instance *inst = icd_term->this_instance;
250 
251     assert(inst != NULL);
252 
253     // Get the function pointer to use to call into the ICD. This could be the core or KHR version
254     PFN_vkGetPhysicalDeviceFormatProperties2 fpGetPhysicalDeviceFormatProperties2 = NULL;
255     if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
256         fpGetPhysicalDeviceFormatProperties2 = icd_term->dispatch.GetPhysicalDeviceFormatProperties2;
257     }
258     if (fpGetPhysicalDeviceFormatProperties2 == NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
259         fpGetPhysicalDeviceFormatProperties2 = icd_term->dispatch.GetPhysicalDeviceFormatProperties2KHR;
260     }
261 
262     if (fpGetPhysicalDeviceFormatProperties2 != NULL) {
263         // Pass the call to the driver
264         fpGetPhysicalDeviceFormatProperties2(phys_dev_term->phys_dev, format, pFormatProperties);
265     } else {
266         // Emulate the call
267         loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
268                    "vkGetPhysicalDeviceFormatProperties2: Emulating call in ICD \"%s\" using vkGetPhysicalDeviceFormatProperties",
269                    icd_term->scanned_icd->lib_name);
270 
271         // Write to the VkFormatProperties2 struct
272         icd_term->dispatch.GetPhysicalDeviceFormatProperties(phys_dev_term->phys_dev, format, &pFormatProperties->formatProperties);
273 
274         if (pFormatProperties->pNext != NULL) {
275             loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0,
276                        "vkGetPhysicalDeviceFormatProperties2: Emulation found unrecognized structure type in "
277                        "pFormatProperties->pNext - this struct will be ignored");
278         }
279     }
280 }
281 
terminator_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceImageFormatInfo2KHR * pImageFormatInfo,VkImageFormatProperties2KHR * pImageFormatProperties)282 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceImageFormatProperties2(
283     VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2KHR *pImageFormatInfo,
284     VkImageFormatProperties2KHR *pImageFormatProperties) {
285     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
286     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
287     const struct loader_instance *inst = icd_term->this_instance;
288 
289     assert(inst != NULL);
290 
291     // Get the function pointer to use to call into the ICD. This could be the core or KHR version
292     PFN_vkGetPhysicalDeviceImageFormatProperties2 fpGetPhysicalDeviceImageFormatProperties2 = NULL;
293     if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
294         fpGetPhysicalDeviceImageFormatProperties2 = icd_term->dispatch.GetPhysicalDeviceImageFormatProperties2;
295     }
296     if (fpGetPhysicalDeviceImageFormatProperties2 == NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
297         fpGetPhysicalDeviceImageFormatProperties2 = icd_term->dispatch.GetPhysicalDeviceImageFormatProperties2KHR;
298     }
299 
300     if (fpGetPhysicalDeviceImageFormatProperties2 != NULL) {
301         // Pass the call to the driver
302         return fpGetPhysicalDeviceImageFormatProperties2(phys_dev_term->phys_dev, pImageFormatInfo, pImageFormatProperties);
303     } else {
304         // Emulate the call
305         loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
306                    "vkGetPhysicalDeviceImageFormatProperties2: Emulating call in ICD \"%s\" using "
307                    "vkGetPhysicalDeviceImageFormatProperties",
308                    icd_term->scanned_icd->lib_name);
309 
310         // If there is more info in  either pNext, then this is unsupported
311         if (pImageFormatInfo->pNext != NULL || pImageFormatProperties->pNext != NULL) {
312             return VK_ERROR_FORMAT_NOT_SUPPORTED;
313         }
314 
315         // Write to the VkImageFormatProperties2KHR struct
316         return icd_term->dispatch.GetPhysicalDeviceImageFormatProperties(
317             phys_dev_term->phys_dev, pImageFormatInfo->format, pImageFormatInfo->type, pImageFormatInfo->tiling,
318             pImageFormatInfo->usage, pImageFormatInfo->flags, &pImageFormatProperties->imageFormatProperties);
319     }
320 }
321 
terminator_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,uint32_t * pQueueFamilyPropertyCount,VkQueueFamilyProperties2KHR * pQueueFamilyProperties)322 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,
323                                                                               uint32_t *pQueueFamilyPropertyCount,
324                                                                               VkQueueFamilyProperties2KHR *pQueueFamilyProperties) {
325     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
326     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
327     const struct loader_instance *inst = icd_term->this_instance;
328 
329     assert(inst != NULL);
330 
331     // Get the function pointer to use to call into the ICD. This could be the core or KHR version
332     PFN_vkGetPhysicalDeviceQueueFamilyProperties2 fpGetPhysicalDeviceQueueFamilyProperties2 = NULL;
333     if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
334         fpGetPhysicalDeviceQueueFamilyProperties2 = icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties2;
335     }
336     if (fpGetPhysicalDeviceQueueFamilyProperties2 == NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
337         fpGetPhysicalDeviceQueueFamilyProperties2 = icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties2KHR;
338     }
339 
340     if (fpGetPhysicalDeviceQueueFamilyProperties2 != NULL) {
341         // Pass the call to the driver
342         fpGetPhysicalDeviceQueueFamilyProperties2(phys_dev_term->phys_dev, pQueueFamilyPropertyCount, pQueueFamilyProperties);
343     } else {
344         // Emulate the call
345         loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
346                    "vkGetPhysicalDeviceQueueFamilyProperties2: Emulating call in ICD \"%s\" using "
347                    "vkGetPhysicalDeviceQueueFamilyProperties",
348                    icd_term->scanned_icd->lib_name);
349 
350         if (pQueueFamilyProperties == NULL || *pQueueFamilyPropertyCount == 0) {
351             // Write to pQueueFamilyPropertyCount
352             icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties(phys_dev_term->phys_dev, pQueueFamilyPropertyCount, NULL);
353         } else {
354             // Allocate a temporary array for the output of the old function
355             VkQueueFamilyProperties *properties = loader_stack_alloc(*pQueueFamilyPropertyCount * sizeof(VkQueueFamilyProperties));
356             if (properties == NULL) {
357                 *pQueueFamilyPropertyCount = 0;
358                 loader_log(icd_term->this_instance, VULKAN_LOADER_ERROR_BIT, 0,
359                            "vkGetPhysicalDeviceQueueFamilyProperties2: Out of memory - Failed to allocate array for loader "
360                            "emulation.");
361                 return;
362             }
363 
364             icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties(phys_dev_term->phys_dev, pQueueFamilyPropertyCount,
365                                                                       properties);
366             for (uint32_t i = 0; i < *pQueueFamilyPropertyCount; ++i) {
367                 // Write to the VkQueueFamilyProperties2KHR struct
368                 memcpy(&pQueueFamilyProperties[i].queueFamilyProperties, &properties[i], sizeof(VkQueueFamilyProperties));
369 
370                 if (pQueueFamilyProperties[i].pNext != NULL) {
371                     loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0,
372                                "vkGetPhysicalDeviceQueueFamilyProperties2: Emulation found unrecognized structure type in "
373                                "pQueueFamilyProperties[%d].pNext - this struct will be ignored",
374                                i);
375                 }
376             }
377         }
378     }
379 }
380 
terminator_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice,VkPhysicalDeviceMemoryProperties2 * pMemoryProperties)381 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice,
382                                                                          VkPhysicalDeviceMemoryProperties2 *pMemoryProperties) {
383     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
384     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
385     const struct loader_instance *inst = icd_term->this_instance;
386 
387     assert(inst != NULL);
388 
389     // Get the function pointer to use to call into the ICD. This could be the core or KHR version
390     PFN_vkGetPhysicalDeviceMemoryProperties2 fpGetPhysicalDeviceMemoryProperties2 = NULL;
391     if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
392         fpGetPhysicalDeviceMemoryProperties2 = icd_term->dispatch.GetPhysicalDeviceMemoryProperties2;
393     }
394     if (fpGetPhysicalDeviceMemoryProperties2 == NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
395         fpGetPhysicalDeviceMemoryProperties2 = icd_term->dispatch.GetPhysicalDeviceMemoryProperties2KHR;
396     }
397 
398     if (fpGetPhysicalDeviceMemoryProperties2 != NULL) {
399         // Pass the call to the driver
400         fpGetPhysicalDeviceMemoryProperties2(phys_dev_term->phys_dev, pMemoryProperties);
401     } else {
402         // Emulate the call
403         loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
404                    "vkGetPhysicalDeviceMemoryProperties2: Emulating call in ICD \"%s\" using vkGetPhysicalDeviceMemoryProperties",
405                    icd_term->scanned_icd->lib_name);
406 
407         // Write to the VkPhysicalDeviceMemoryProperties2 struct
408         icd_term->dispatch.GetPhysicalDeviceMemoryProperties(phys_dev_term->phys_dev, &pMemoryProperties->memoryProperties);
409 
410         if (pMemoryProperties->pNext != NULL) {
411             loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0,
412                        "vkGetPhysicalDeviceMemoryProperties2: Emulation found unrecognized structure type in "
413                        "pMemoryProperties->pNext - this struct will be ignored");
414         }
415     }
416 }
417 
terminator_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSparseImageFormatInfo2KHR * pFormatInfo,uint32_t * pPropertyCount,VkSparseImageFormatProperties2KHR * pProperties)418 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceSparseImageFormatProperties2(
419     VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2KHR *pFormatInfo, uint32_t *pPropertyCount,
420     VkSparseImageFormatProperties2KHR *pProperties) {
421     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
422     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
423     const struct loader_instance *inst = icd_term->this_instance;
424 
425     assert(inst != NULL);
426 
427     // Get the function pointer to use to call into the ICD. This could be the core or KHR version
428     PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 fpGetPhysicalDeviceSparseImageFormatProperties2 = NULL;
429     if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
430         fpGetPhysicalDeviceSparseImageFormatProperties2 = icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties2;
431     }
432     if (fpGetPhysicalDeviceSparseImageFormatProperties2 == NULL &&
433         inst->enabled_known_extensions.khr_get_physical_device_properties2) {
434         fpGetPhysicalDeviceSparseImageFormatProperties2 = icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties2KHR;
435     }
436 
437     if (fpGetPhysicalDeviceSparseImageFormatProperties2 != NULL) {
438         // Pass the call to the driver
439         fpGetPhysicalDeviceSparseImageFormatProperties2(phys_dev_term->phys_dev, pFormatInfo, pPropertyCount, pProperties);
440     } else {
441         // Emulate the call
442         loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
443                    "vkGetPhysicalDeviceSparseImageFormatProperties2: Emulating call in ICD \"%s\" using "
444                    "vkGetPhysicalDeviceSparseImageFormatProperties",
445                    icd_term->scanned_icd->lib_name);
446 
447         if (pFormatInfo->pNext != NULL) {
448             loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0,
449                        "vkGetPhysicalDeviceSparseImageFormatProperties2: Emulation found unrecognized structure type in "
450                        "pFormatInfo->pNext - this struct will be ignored");
451         }
452 
453         if (pProperties == NULL || *pPropertyCount == 0) {
454             // Write to pPropertyCount
455             icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties(
456                 phys_dev_term->phys_dev, pFormatInfo->format, pFormatInfo->type, pFormatInfo->samples, pFormatInfo->usage,
457                 pFormatInfo->tiling, pPropertyCount, NULL);
458         } else {
459             // Allocate a temporary array for the output of the old function
460             VkSparseImageFormatProperties *properties =
461                 loader_stack_alloc(*pPropertyCount * sizeof(VkSparseImageMemoryRequirements));
462             if (properties == NULL) {
463                 *pPropertyCount = 0;
464                 loader_log(icd_term->this_instance, VULKAN_LOADER_ERROR_BIT, 0,
465                            "vkGetPhysicalDeviceSparseImageFormatProperties2: Out of memory - Failed to allocate array for "
466                            "loader emulation.");
467                 return;
468             }
469 
470             icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties(
471                 phys_dev_term->phys_dev, pFormatInfo->format, pFormatInfo->type, pFormatInfo->samples, pFormatInfo->usage,
472                 pFormatInfo->tiling, pPropertyCount, properties);
473             for (uint32_t i = 0; i < *pPropertyCount; ++i) {
474                 // Write to the VkSparseImageFormatProperties2KHR struct
475                 memcpy(&pProperties[i].properties, &properties[i], sizeof(VkSparseImageFormatProperties));
476 
477                 if (pProperties[i].pNext != NULL) {
478                     loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0,
479                                "vkGetPhysicalDeviceSparseImageFormatProperties2: Emulation found unrecognized structure type in "
480                                "pProperties[%d].pNext - this struct will be ignored",
481                                i);
482                 }
483             }
484         }
485     }
486 }
487 
terminator_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalBufferInfo * pExternalBufferInfo,VkExternalBufferProperties * pExternalBufferProperties)488 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceExternalBufferProperties(
489     VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
490     VkExternalBufferProperties *pExternalBufferProperties) {
491     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
492     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
493     const struct loader_instance *inst = icd_term->this_instance;
494 
495     assert(inst != NULL);
496 
497     // Get the function pointer to use to call into the ICD. This could be the core or KHR version
498     PFN_vkGetPhysicalDeviceExternalBufferProperties fpGetPhysicalDeviceExternalBufferProperties = NULL;
499     if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
500         fpGetPhysicalDeviceExternalBufferProperties = icd_term->dispatch.GetPhysicalDeviceExternalBufferProperties;
501     }
502     if (fpGetPhysicalDeviceExternalBufferProperties == NULL && inst->enabled_known_extensions.khr_external_memory_capabilities) {
503         fpGetPhysicalDeviceExternalBufferProperties = icd_term->dispatch.GetPhysicalDeviceExternalBufferPropertiesKHR;
504     }
505 
506     if (fpGetPhysicalDeviceExternalBufferProperties != NULL) {
507         // Pass the call to the driver
508         fpGetPhysicalDeviceExternalBufferProperties(phys_dev_term->phys_dev, pExternalBufferInfo, pExternalBufferProperties);
509     } else {
510         // Emulate the call
511         loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
512                    "vkGetPhysicalDeviceExternalBufferProperties: Emulating call in ICD \"%s\"", icd_term->scanned_icd->lib_name);
513 
514         if (pExternalBufferInfo->pNext != NULL) {
515             loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0,
516                        "vkGetPhysicalDeviceExternalBufferProperties: Emulation found unrecognized structure type in "
517                        "pExternalBufferInfo->pNext - this struct will be ignored");
518         }
519 
520         // Fill in everything being unsupported
521         memset(&pExternalBufferProperties->externalMemoryProperties, 0, sizeof(VkExternalMemoryPropertiesKHR));
522 
523         if (pExternalBufferProperties->pNext != NULL) {
524             loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0,
525                        "vkGetPhysicalDeviceExternalBufferProperties: Emulation found unrecognized structure type in "
526                        "pExternalBufferProperties->pNext - this struct will be ignored");
527         }
528     }
529 }
530 
terminator_GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalSemaphoreInfo * pExternalSemaphoreInfo,VkExternalSemaphoreProperties * pExternalSemaphoreProperties)531 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceExternalSemaphoreProperties(
532     VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo,
533     VkExternalSemaphoreProperties *pExternalSemaphoreProperties) {
534     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
535     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
536     const struct loader_instance *inst = icd_term->this_instance;
537 
538     assert(inst != NULL);
539 
540     // Get the function pointer to use to call into the ICD. This could be the core or KHR version
541     PFN_vkGetPhysicalDeviceExternalSemaphoreProperties fpGetPhysicalDeviceExternalSemaphoreProperties = NULL;
542     if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
543         fpGetPhysicalDeviceExternalSemaphoreProperties = icd_term->dispatch.GetPhysicalDeviceExternalSemaphoreProperties;
544     }
545     if (fpGetPhysicalDeviceExternalSemaphoreProperties == NULL &&
546         inst->enabled_known_extensions.khr_external_semaphore_capabilities) {
547         fpGetPhysicalDeviceExternalSemaphoreProperties = icd_term->dispatch.GetPhysicalDeviceExternalSemaphorePropertiesKHR;
548     }
549 
550     if (fpGetPhysicalDeviceExternalSemaphoreProperties != NULL) {
551         // Pass the call to the driver
552         fpGetPhysicalDeviceExternalSemaphoreProperties(phys_dev_term->phys_dev, pExternalSemaphoreInfo,
553                                                        pExternalSemaphoreProperties);
554     } else {
555         // Emulate the call
556         loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
557                    "vkGetPhysicalDeviceExternalSemaphoreProperties: Emulating call in ICD \"%s\"", icd_term->scanned_icd->lib_name);
558 
559         if (pExternalSemaphoreInfo->pNext != NULL) {
560             loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0,
561                        "vkGetPhysicalDeviceExternalSemaphoreProperties: Emulation found unrecognized structure type in "
562                        "pExternalSemaphoreInfo->pNext - this struct will be ignored");
563         }
564 
565         // Fill in everything being unsupported
566         pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
567         pExternalSemaphoreProperties->compatibleHandleTypes = 0;
568         pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
569 
570         if (pExternalSemaphoreProperties->pNext != NULL) {
571             loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0,
572                        "vkGetPhysicalDeviceExternalSemaphoreProperties: Emulation found unrecognized structure type in "
573                        "pExternalSemaphoreProperties->pNext - this struct will be ignored");
574         }
575     }
576 }
577 
terminator_GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalFenceInfo * pExternalFenceInfo,VkExternalFenceProperties * pExternalFenceProperties)578 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceExternalFenceProperties(
579     VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo,
580     VkExternalFenceProperties *pExternalFenceProperties) {
581     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
582     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
583     const struct loader_instance *inst = icd_term->this_instance;
584 
585     assert(inst != NULL);
586 
587     // Get the function pointer to use to call into the ICD. This could be the core or KHR version
588     PFN_vkGetPhysicalDeviceExternalFenceProperties fpGetPhysicalDeviceExternalFenceProperties = NULL;
589     if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
590         fpGetPhysicalDeviceExternalFenceProperties = icd_term->dispatch.GetPhysicalDeviceExternalFenceProperties;
591     }
592     if (fpGetPhysicalDeviceExternalFenceProperties == NULL && inst->enabled_known_extensions.khr_external_fence_capabilities) {
593         fpGetPhysicalDeviceExternalFenceProperties = icd_term->dispatch.GetPhysicalDeviceExternalFencePropertiesKHR;
594     }
595 
596     if (fpGetPhysicalDeviceExternalFenceProperties != NULL) {
597         // Pass the call to the driver
598         fpGetPhysicalDeviceExternalFenceProperties(phys_dev_term->phys_dev, pExternalFenceInfo, pExternalFenceProperties);
599     } else {
600         // Emulate the call
601         loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
602                    "vkGetPhysicalDeviceExternalFenceProperties: Emulating call in ICD \"%s\"", icd_term->scanned_icd->lib_name);
603 
604         if (pExternalFenceInfo->pNext != NULL) {
605             loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0,
606                        "vkGetPhysicalDeviceExternalFenceProperties: Emulation found unrecognized structure type in "
607                        "pExternalFenceInfo->pNext - this struct will be ignored");
608         }
609 
610         // Fill in everything being unsupported
611         pExternalFenceProperties->exportFromImportedHandleTypes = 0;
612         pExternalFenceProperties->compatibleHandleTypes = 0;
613         pExternalFenceProperties->externalFenceFeatures = 0;
614 
615         if (pExternalFenceProperties->pNext != NULL) {
616             loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0,
617                        "vkGetPhysicalDeviceExternalFenceProperties: Emulation found unrecognized structure type in "
618                        "pExternalFenceProperties->pNext - this struct will be ignored");
619         }
620     }
621 }
622 
623 // 1.3 Core terminators
624 
terminator_GetPhysicalDeviceToolProperties(VkPhysicalDevice physicalDevice,uint32_t * pToolCount,VkPhysicalDeviceToolProperties * pToolProperties)625 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceToolProperties(VkPhysicalDevice physicalDevice, uint32_t *pToolCount,
626                                                                           VkPhysicalDeviceToolProperties *pToolProperties) {
627     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
628     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
629 
630     if (NULL == icd_term->dispatch.GetPhysicalDeviceToolProperties) {
631         loader_log(icd_term->this_instance, VULKAN_LOADER_ERROR_BIT, 0,
632                    "terminator_GetPhysicalDeviceToolProperties: The ICD's vkGetPhysicalDeviceToolProperties was NULL yet "
633                    "the physical device supports Vulkan API Version 1.3.");
634     } else {
635         VkPhysicalDeviceProperties properties;
636         if (icd_term->dispatch.GetPhysicalDeviceProperties) {
637             icd_term->dispatch.GetPhysicalDeviceProperties(phys_dev_term->phys_dev, &properties);
638 
639             if (VK_API_VERSION_MINOR(properties.apiVersion) >= 3) {
640                 return icd_term->dispatch.GetPhysicalDeviceToolProperties(phys_dev_term->phys_dev, pToolCount, pToolProperties);
641             }
642         }
643     }
644 
645     // In the case the driver didn't support 1.3, make sure that the first layer doesn't find the count uninitialized
646     *pToolCount = 0;
647     return VK_SUCCESS;
648 }
649