• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2015-2022 The Khronos Group Inc.
3  * Copyright (c) 2015-2022 Valve Corporation
4  * Copyright (c) 2015-2022 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: Mark Young <marky@lunarg.com>
19  * Author: Lenny Komow <lenny@lunarg.com>
20  * Author: Charles Giessen <charles@lunarg.com>
21  */
22 
23 #include "extension_manual.h"
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include "allocation.h"
30 #include "loader.h"
31 #include "log.h"
32 #include "wsi.h"
33 
34 // ---- Manually added trampoline/terminator functions
35 
36 // These functions, for whatever reason, require more complex changes than
37 // can easily be automatically generated.
38 
39 // ---- VK_NV_external_memory_capabilities extension trampoline/terminators
40 
GetPhysicalDeviceExternalImageFormatPropertiesNV(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,VkImageTiling tiling,VkImageUsageFlags usage,VkImageCreateFlags flags,VkExternalMemoryHandleTypeFlagsNV externalHandleType,VkExternalImageFormatPropertiesNV * pExternalImageFormatProperties)41 VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceExternalImageFormatPropertiesNV(
42     VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage,
43     VkImageCreateFlags flags, VkExternalMemoryHandleTypeFlagsNV externalHandleType,
44     VkExternalImageFormatPropertiesNV *pExternalImageFormatProperties) {
45     const VkLayerInstanceDispatchTable *disp;
46     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
47     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
48         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
49                    "vkGetPhysicalDeviceExternalImageFormatPropertiesNV: Invalid physicalDevice "
50                    "[VUID-vkGetPhysicalDeviceExternalImageFormatPropertiesNV-physicalDevice-parameter]");
51         abort(); /* Intentionally fail so user can correct issue. */
52     }
53     disp = loader_get_instance_layer_dispatch(physicalDevice);
54 
55     return disp->GetPhysicalDeviceExternalImageFormatPropertiesNV(unwrapped_phys_dev, format, type, tiling, usage, flags,
56                                                                   externalHandleType, pExternalImageFormatProperties);
57 }
58 
terminator_GetPhysicalDeviceExternalImageFormatPropertiesNV(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,VkImageTiling tiling,VkImageUsageFlags usage,VkImageCreateFlags flags,VkExternalMemoryHandleTypeFlagsNV externalHandleType,VkExternalImageFormatPropertiesNV * pExternalImageFormatProperties)59 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceExternalImageFormatPropertiesNV(
60     VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage,
61     VkImageCreateFlags flags, VkExternalMemoryHandleTypeFlagsNV externalHandleType,
62     VkExternalImageFormatPropertiesNV *pExternalImageFormatProperties) {
63     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
64     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
65 
66     if (!icd_term->dispatch.GetPhysicalDeviceExternalImageFormatPropertiesNV) {
67         if (externalHandleType) {
68             return VK_ERROR_FORMAT_NOT_SUPPORTED;
69         }
70 
71         if (!icd_term->dispatch.GetPhysicalDeviceImageFormatProperties) {
72             return VK_ERROR_INITIALIZATION_FAILED;
73         }
74 
75         pExternalImageFormatProperties->externalMemoryFeatures = 0;
76         pExternalImageFormatProperties->exportFromImportedHandleTypes = 0;
77         pExternalImageFormatProperties->compatibleHandleTypes = 0;
78 
79         return icd_term->dispatch.GetPhysicalDeviceImageFormatProperties(
80             phys_dev_term->phys_dev, format, type, tiling, usage, flags, &pExternalImageFormatProperties->imageFormatProperties);
81     }
82 
83     return icd_term->dispatch.GetPhysicalDeviceExternalImageFormatPropertiesNV(
84         phys_dev_term->phys_dev, format, type, tiling, usage, flags, externalHandleType, pExternalImageFormatProperties);
85 }
86 
87 // ---- VK_EXT_display_surface_counter extension trampoline/terminators
88 
GetPhysicalDeviceSurfaceCapabilities2EXT(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,VkSurfaceCapabilities2EXT * pSurfaceCapabilities)89 VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilities2EXT(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
90                                                                         VkSurfaceCapabilities2EXT *pSurfaceCapabilities) {
91     const VkLayerInstanceDispatchTable *disp;
92     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
93     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
94         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
95                    "vkGetPhysicalDeviceExternalImageFormatPropertiesNV: Invalid physicalDevice "
96                    "[VUID-vkGetPhysicalDeviceSurfaceCapabilities2EXT-physicalDevice-parameter]");
97         abort(); /* Intentionally fail so user can correct issue. */
98     }
99     disp = loader_get_instance_layer_dispatch(physicalDevice);
100     return disp->GetPhysicalDeviceSurfaceCapabilities2EXT(unwrapped_phys_dev, surface, pSurfaceCapabilities);
101 }
102 
terminator_GetPhysicalDeviceSurfaceCapabilities2EXT(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,VkSurfaceCapabilities2EXT * pSurfaceCapabilities)103 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2EXT(
104     VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT *pSurfaceCapabilities) {
105     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
106     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
107 
108     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(surface);
109 
110     // Unwrap the surface if needed
111     VkSurfaceKHR unwrapped_surface = surface;
112     if (NULL != phys_dev_term->this_icd_term->surface_list.list &&
113         phys_dev_term->this_icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
114         phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index]) {
115         unwrapped_surface = phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index];
116     }
117 
118     if (NULL != icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2EXT) {
119         // Pass the call to the driver
120         return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2EXT(phys_dev_term->phys_dev, unwrapped_surface,
121                                                                            pSurfaceCapabilities);
122     } else {
123         // Emulate the call
124         loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
125                    "vkGetPhysicalDeviceSurfaceCapabilities2EXT: Emulating call in ICD \"%s\" using "
126                    "vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
127                    icd_term->scanned_icd->lib_name);
128 
129         VkSurfaceCapabilitiesKHR surface_caps;
130         VkResult res =
131             icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev_term->phys_dev, unwrapped_surface, &surface_caps);
132         pSurfaceCapabilities->minImageCount = surface_caps.minImageCount;
133         pSurfaceCapabilities->maxImageCount = surface_caps.maxImageCount;
134         pSurfaceCapabilities->currentExtent = surface_caps.currentExtent;
135         pSurfaceCapabilities->minImageExtent = surface_caps.minImageExtent;
136         pSurfaceCapabilities->maxImageExtent = surface_caps.maxImageExtent;
137         pSurfaceCapabilities->maxImageArrayLayers = surface_caps.maxImageArrayLayers;
138         pSurfaceCapabilities->supportedTransforms = surface_caps.supportedTransforms;
139         pSurfaceCapabilities->currentTransform = surface_caps.currentTransform;
140         pSurfaceCapabilities->supportedCompositeAlpha = surface_caps.supportedCompositeAlpha;
141         pSurfaceCapabilities->supportedUsageFlags = surface_caps.supportedUsageFlags;
142         pSurfaceCapabilities->supportedSurfaceCounters = 0;
143 
144         if (pSurfaceCapabilities->pNext != NULL) {
145             loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0,
146                        "vkGetPhysicalDeviceSurfaceCapabilities2EXT: Emulation found unrecognized structure type in "
147                        "pSurfaceCapabilities->pNext - this struct will be ignored");
148         }
149 
150         return res;
151     }
152 }
153 
154 // ---- VK_EXT_direct_mode_display extension trampoline/terminators
155 
ReleaseDisplayEXT(VkPhysicalDevice physicalDevice,VkDisplayKHR display)156 VKAPI_ATTR VkResult VKAPI_CALL ReleaseDisplayEXT(VkPhysicalDevice physicalDevice, VkDisplayKHR display) {
157     const VkLayerInstanceDispatchTable *disp;
158     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
159     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
160         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
161                    "vkReleaseDisplayEXT: Invalid physicalDevice [VUID-vkReleaseDisplayEXT-physicalDevice-parameter]");
162         abort(); /* Intentionally fail so user can correct issue. */
163     }
164     disp = loader_get_instance_layer_dispatch(physicalDevice);
165     return disp->ReleaseDisplayEXT(unwrapped_phys_dev, display);
166 }
167 
terminator_ReleaseDisplayEXT(VkPhysicalDevice physicalDevice,VkDisplayKHR display)168 VKAPI_ATTR VkResult VKAPI_CALL terminator_ReleaseDisplayEXT(VkPhysicalDevice physicalDevice, VkDisplayKHR display) {
169     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
170     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
171 
172     if (icd_term->dispatch.ReleaseDisplayEXT == NULL) {
173         loader_log(icd_term->this_instance, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT, 0,
174                    "ICD \"%s\" associated with VkPhysicalDevice does not support vkReleaseDisplayEXT - Consequently, the call is "
175                    "invalid because it should not be possible to acquire a display on this device",
176                    icd_term->scanned_icd->lib_name);
177         abort();
178     }
179     return icd_term->dispatch.ReleaseDisplayEXT(phys_dev_term->phys_dev, display);
180 }
181 
182 // ---- VK_EXT_acquire_xlib_display extension trampoline/terminators
183 
184 #if defined(VK_USE_PLATFORM_XLIB_XRANDR_EXT)
AcquireXlibDisplayEXT(VkPhysicalDevice physicalDevice,Display * dpy,VkDisplayKHR display)185 VKAPI_ATTR VkResult VKAPI_CALL AcquireXlibDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy, VkDisplayKHR display) {
186     const VkLayerInstanceDispatchTable *disp;
187     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
188     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
189         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
190                    "vkAcquireXlibDisplayEXT: Invalid physicalDevice [VUID-vkAcquireXlibDisplayEXT-physicalDevice-parameter]");
191         abort(); /* Intentionally fail so user can correct issue. */
192     }
193     disp = loader_get_instance_layer_dispatch(physicalDevice);
194     return disp->AcquireXlibDisplayEXT(unwrapped_phys_dev, dpy, display);
195 }
196 
terminator_AcquireXlibDisplayEXT(VkPhysicalDevice physicalDevice,Display * dpy,VkDisplayKHR display)197 VKAPI_ATTR VkResult VKAPI_CALL terminator_AcquireXlibDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy,
198                                                                 VkDisplayKHR display) {
199     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
200     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
201 
202     if (icd_term->dispatch.AcquireXlibDisplayEXT != NULL) {
203         // Pass the call to the driver
204         return icd_term->dispatch.AcquireXlibDisplayEXT(phys_dev_term->phys_dev, dpy, display);
205     } else {
206         // Emulate the call
207         loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
208                    "vkAcquireXLibDisplayEXT: Emulating call in ICD \"%s\" by returning error", icd_term->scanned_icd->lib_name);
209 
210         // Fail for the unsupported command
211         return VK_ERROR_INITIALIZATION_FAILED;
212     }
213 }
214 
GetRandROutputDisplayEXT(VkPhysicalDevice physicalDevice,Display * dpy,RROutput rrOutput,VkDisplayKHR * pDisplay)215 VKAPI_ATTR VkResult VKAPI_CALL GetRandROutputDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy, RROutput rrOutput,
216                                                         VkDisplayKHR *pDisplay) {
217     const VkLayerInstanceDispatchTable *disp;
218     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
219     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
220         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
221                    "vkGetRandROutputDisplayEXT: Invalid physicalDevice [VUID-vkGetRandROutputDisplayEXT-physicalDevice-parameter]");
222         abort(); /* Intentionally fail so user can correct issue. */
223     }
224     disp = loader_get_instance_layer_dispatch(physicalDevice);
225     return disp->GetRandROutputDisplayEXT(unwrapped_phys_dev, dpy, rrOutput, pDisplay);
226 }
227 
terminator_GetRandROutputDisplayEXT(VkPhysicalDevice physicalDevice,Display * dpy,RROutput rrOutput,VkDisplayKHR * pDisplay)228 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetRandROutputDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy, RROutput rrOutput,
229                                                                    VkDisplayKHR *pDisplay) {
230     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
231     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
232 
233     if (icd_term->dispatch.GetRandROutputDisplayEXT != NULL) {
234         // Pass the call to the driver
235         return icd_term->dispatch.GetRandROutputDisplayEXT(phys_dev_term->phys_dev, dpy, rrOutput, pDisplay);
236     } else {
237         // Emulate the call
238         loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
239                    "vkGetRandROutputDisplayEXT: Emulating call in ICD \"%s\" by returning null display",
240                    icd_term->scanned_icd->lib_name);
241 
242         // Return a null handle to indicate this can't be done
243         *pDisplay = VK_NULL_HANDLE;
244         return VK_SUCCESS;
245     }
246 }
247 
248 #endif  // VK_USE_PLATFORM_XLIB_XRANDR_EXT
249 
250 #if defined(VK_USE_PLATFORM_WIN32_KHR)
GetPhysicalDeviceSurfacePresentModes2EXT(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,uint32_t * pPresentModeCount,VkPresentModeKHR * pPresentModes)251 VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfacePresentModes2EXT(VkPhysicalDevice physicalDevice,
252                                                                         const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
253                                                                         uint32_t *pPresentModeCount,
254                                                                         VkPresentModeKHR *pPresentModes) {
255     const VkLayerInstanceDispatchTable *disp;
256     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
257     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
258         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
259                    "vkGetPhysicalDeviceSurfacePresentModes2EXT: Invalid physicalDevice "
260                    "[VUID-vkGetPhysicalDeviceSurfacePresentModes2EXT-physicalDevice-parameter]");
261         abort(); /* Intentionally fail so user can correct issue. */
262     }
263     disp = loader_get_instance_layer_dispatch(physicalDevice);
264     return disp->GetPhysicalDeviceSurfacePresentModes2EXT(unwrapped_phys_dev, pSurfaceInfo, pPresentModeCount, pPresentModes);
265 }
266 
terminator_GetPhysicalDeviceSurfacePresentModes2EXT(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,uint32_t * pPresentModeCount,VkPresentModeKHR * pPresentModes)267 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfacePresentModes2EXT(
268     VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, uint32_t *pPresentModeCount,
269     VkPresentModeKHR *pPresentModes) {
270     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
271     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
272     if (NULL == icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT) {
273         loader_log(icd_term->this_instance, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT, 0,
274                    "ICD associated with VkPhysicalDevice does not support GetPhysicalDeviceSurfacePresentModes2EXT");
275         abort();
276     }
277     if (VK_NULL_HANDLE != pSurfaceInfo->surface) {
278         VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface);
279         if (NULL != icd_surface && NULL != icd_term->surface_list.list &&
280             icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
281             icd_term->surface_list.list[icd_surface->surface_index]) {
282             VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy;
283             surface_info_copy.sType = pSurfaceInfo->sType;
284             surface_info_copy.pNext = pSurfaceInfo->pNext;
285             surface_info_copy.surface = icd_term->surface_list.list[icd_surface->surface_index];
286             return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT(phys_dev_term->phys_dev, &surface_info_copy,
287                                                                                pPresentModeCount, pPresentModes);
288         }
289     }
290     return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT(phys_dev_term->phys_dev, pSurfaceInfo, pPresentModeCount,
291                                                                        pPresentModes);
292 }
293 
GetDeviceGroupSurfacePresentModes2EXT(VkDevice device,const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,VkDeviceGroupPresentModeFlagsKHR * pModes)294 VKAPI_ATTR VkResult VKAPI_CALL GetDeviceGroupSurfacePresentModes2EXT(VkDevice device,
295                                                                      const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
296                                                                      VkDeviceGroupPresentModeFlagsKHR *pModes) {
297     const VkLayerDispatchTable *disp = loader_get_dispatch(device);
298     if (NULL == disp) {
299         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
300                    "vkGetDeviceGroupSurfacePresentModes2EXT: Invalid device "
301                    "[VUID-vkGetDeviceGroupSurfacePresentModes2EXT-device-parameter]");
302         abort(); /* Intentionally fail so user can correct issue. */
303     }
304     return disp->GetDeviceGroupSurfacePresentModes2EXT(device, pSurfaceInfo, pModes);
305 }
306 
terminator_GetDeviceGroupSurfacePresentModes2EXT(VkDevice device,const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,VkDeviceGroupPresentModeFlagsKHR * pModes)307 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModes2EXT(VkDevice device,
308                                                                                 const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
309                                                                                 VkDeviceGroupPresentModeFlagsKHR *pModes) {
310     struct loader_device *dev;
311     struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev);
312     if (NULL == icd_term || NULL == dev ||
313         NULL == dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT) {
314         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
315                    "vkGetDeviceGroupSurfacePresentModes2EXT Terminator: Invalid device handle. This is likely the result of a "
316                    "layer wrapping device handles and failing to unwrap them in all functions. "
317                    "[VUID-vkGetDeviceGroupSurfacePresentModes2EXT-device-parameter]");
318         abort(); /* Intentionally fail so user can correct issue. */
319     }
320     if (NULL == pSurfaceInfo) {
321         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
322                    "vkGetDeviceGroupSurfacePresentModes2EXT: Invalid pSurfaceInfo pointer "
323                    "[VUID-vkGetDeviceGroupSurfacePresentModes2EXT-pSurfaceInfo-parameter]");
324         abort(); /* Intentionally fail so user can correct issue. */
325     }
326     if (VK_NULL_HANDLE != pSurfaceInfo->surface) {
327         VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface);
328         if (NULL != icd_surface && NULL != icd_term->surface_list.list &&
329             icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
330             icd_term->surface_list.list[icd_surface->surface_index]) {
331             VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy;
332             surface_info_copy.sType = pSurfaceInfo->sType;
333             surface_info_copy.pNext = pSurfaceInfo->pNext;
334             surface_info_copy.surface = icd_term->surface_list.list[icd_surface->surface_index];
335             return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT(
336                 device, &surface_info_copy, pModes);
337         }
338     }
339     return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT(device, pSurfaceInfo, pModes);
340 }
341 
342 #endif  // VK_USE_PLATFORM_WIN32_KHR
343 
344 // ---- VK_EXT_tooling_info extension trampoline/terminators
345 
GetPhysicalDeviceToolPropertiesEXT(VkPhysicalDevice physicalDevice,uint32_t * pToolCount,VkPhysicalDeviceToolPropertiesEXT * pToolProperties)346 VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceToolPropertiesEXT(VkPhysicalDevice physicalDevice, uint32_t *pToolCount,
347                                                                   VkPhysicalDeviceToolPropertiesEXT *pToolProperties) {
348     const VkLayerInstanceDispatchTable *disp;
349     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
350     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
351         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
352                    "vkGetPhysicalDeviceToolPropertiesEXT: Invalid physicalDevice "
353                    "[VUID-vkGetPhysicalDeviceToolPropertiesEXT-physicalDevice-parameter]");
354         abort(); /* Intentionally fail so user can correct issue. */
355     }
356     disp = loader_get_instance_layer_dispatch(physicalDevice);
357     return disp->GetPhysicalDeviceToolPropertiesEXT(unwrapped_phys_dev, pToolCount, pToolProperties);
358 }
359 
terminator_GetPhysicalDeviceToolPropertiesEXT(VkPhysicalDevice physicalDevice,uint32_t * pToolCount,VkPhysicalDeviceToolPropertiesEXT * pToolProperties)360 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceToolPropertiesEXT(VkPhysicalDevice physicalDevice, uint32_t *pToolCount,
361                                                                              VkPhysicalDeviceToolPropertiesEXT *pToolProperties) {
362     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
363     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
364 
365     bool tooling_info_supported = false;
366     uint32_t ext_count = 0;
367     VkExtensionProperties *ext_props = NULL;
368     VkResult res = VK_SUCCESS;
369     VkResult enumerate_res = VK_SUCCESS;
370 
371     enumerate_res = icd_term->dispatch.EnumerateDeviceExtensionProperties(phys_dev_term->phys_dev, NULL, &ext_count, NULL);
372     if (enumerate_res != VK_SUCCESS) {
373         goto out;
374     }
375 
376     ext_props = loader_instance_heap_alloc(icd_term->this_instance, sizeof(VkExtensionProperties) * ext_count,
377                                            VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
378     if (!ext_props) {
379         res = VK_ERROR_OUT_OF_HOST_MEMORY;
380         goto out;
381     }
382 
383     enumerate_res = icd_term->dispatch.EnumerateDeviceExtensionProperties(phys_dev_term->phys_dev, NULL, &ext_count, ext_props);
384     if (enumerate_res != VK_SUCCESS) {
385         goto out;
386     }
387 
388     for (uint32_t i = 0; i < ext_count; i++) {
389         if (strncmp(ext_props[i].extensionName, VK_EXT_TOOLING_INFO_EXTENSION_NAME, VK_MAX_EXTENSION_NAME_SIZE) == 0) {
390             tooling_info_supported = true;
391             break;
392         }
393     }
394 
395     if (tooling_info_supported && icd_term->dispatch.GetPhysicalDeviceToolPropertiesEXT) {
396         res = icd_term->dispatch.GetPhysicalDeviceToolPropertiesEXT(phys_dev_term->phys_dev, pToolCount, pToolProperties);
397     }
398 
399 out:
400     // In the case the driver didn't support the extension, make sure that the first layer doesn't find the count uninitialized
401     if (!tooling_info_supported || !icd_term->dispatch.GetPhysicalDeviceToolPropertiesEXT) {
402         *pToolCount = 0;
403     }
404 
405     loader_instance_heap_free(icd_term->this_instance, ext_props);
406 
407     return res;
408 }
409