Coverage Report

Created: 2026-09-05 06:23

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