1 /*
2 * Copyright (c) 2021-2023 The Khronos Group Inc.
3 * Copyright (c) 2021-2023 Valve Corporation
4 * Copyright (c) 2021-2023 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and/or associated documentation files (the "Materials"), to
8 * deal in the Materials without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Materials, and to permit persons to whom the Materials are
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice(s) and this permission notice shall be included in
14 * all copies or substantial portions of the Materials.
15 *
16 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 *
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
23 * USE OR OTHER DEALINGS IN THE MATERIALS.
24 *
25 * Author: Charles Giessen <charles@lunarg.com>
26 */
27
28 #include "test_environment.h"
29
get_loader_path()30 fs::path get_loader_path() {
31 auto loader_path = fs::path(FRAMEWORK_VULKAN_LIBRARY_PATH);
32 auto env_var_res = get_env_var("VK_LOADER_TEST_LOADER_PATH", false);
33 if (!env_var_res.empty()) {
34 loader_path = fs::path(env_var_res);
35 }
36 return loader_path;
37 }
38
init_vulkan_functions(VulkanFunctions& funcs)39 void init_vulkan_functions(VulkanFunctions& funcs) {
40 #if defined(APPLE_STATIC_LOADER)
41 #define GPA(name) name
42 #else
43 #define GPA(name) funcs.loader.get_symbol(#name)
44 #endif
45
46 // clang-format off
47 funcs.vkGetInstanceProcAddr = GPA(vkGetInstanceProcAddr);
48 funcs.vkEnumerateInstanceExtensionProperties = GPA(vkEnumerateInstanceExtensionProperties);
49 funcs.vkEnumerateInstanceLayerProperties = GPA(vkEnumerateInstanceLayerProperties);
50 funcs.vkEnumerateInstanceVersion = GPA(vkEnumerateInstanceVersion);
51 funcs.vkCreateInstance = GPA(vkCreateInstance);
52 funcs.vkDestroyInstance = GPA(vkDestroyInstance);
53 funcs.vkEnumeratePhysicalDevices = GPA(vkEnumeratePhysicalDevices);
54 funcs.vkEnumeratePhysicalDeviceGroups = GPA(vkEnumeratePhysicalDeviceGroups);
55 funcs.vkGetPhysicalDeviceFeatures = GPA(vkGetPhysicalDeviceFeatures);
56 funcs.vkGetPhysicalDeviceFeatures2 = GPA(vkGetPhysicalDeviceFeatures2);
57 funcs.vkGetPhysicalDeviceFormatProperties = GPA(vkGetPhysicalDeviceFormatProperties);
58 funcs.vkGetPhysicalDeviceFormatProperties2 = GPA(vkGetPhysicalDeviceFormatProperties2);
59 funcs.vkGetPhysicalDeviceImageFormatProperties = GPA(vkGetPhysicalDeviceImageFormatProperties);
60 funcs.vkGetPhysicalDeviceImageFormatProperties2 = GPA(vkGetPhysicalDeviceImageFormatProperties2);
61 funcs.vkGetPhysicalDeviceSparseImageFormatProperties = GPA(vkGetPhysicalDeviceSparseImageFormatProperties);
62 funcs.vkGetPhysicalDeviceSparseImageFormatProperties2 = GPA(vkGetPhysicalDeviceSparseImageFormatProperties2);
63 funcs.vkGetPhysicalDeviceProperties = GPA(vkGetPhysicalDeviceProperties);
64 funcs.vkGetPhysicalDeviceProperties2 = GPA(vkGetPhysicalDeviceProperties2);
65 funcs.vkGetPhysicalDeviceQueueFamilyProperties = GPA(vkGetPhysicalDeviceQueueFamilyProperties);
66 funcs.vkGetPhysicalDeviceQueueFamilyProperties2 = GPA(vkGetPhysicalDeviceQueueFamilyProperties2);
67 funcs.vkGetPhysicalDeviceMemoryProperties = GPA(vkGetPhysicalDeviceMemoryProperties);
68 funcs.vkGetPhysicalDeviceMemoryProperties2 = GPA(vkGetPhysicalDeviceMemoryProperties2);
69 funcs.vkGetPhysicalDeviceSurfaceSupportKHR = GPA(vkGetPhysicalDeviceSurfaceSupportKHR);
70 funcs.vkGetPhysicalDeviceSurfaceFormatsKHR = GPA(vkGetPhysicalDeviceSurfaceFormatsKHR);
71 funcs.vkGetPhysicalDeviceSurfacePresentModesKHR = GPA(vkGetPhysicalDeviceSurfacePresentModesKHR);
72 funcs.vkGetPhysicalDeviceSurfaceCapabilitiesKHR = GPA(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
73 funcs.vkEnumerateDeviceExtensionProperties = GPA(vkEnumerateDeviceExtensionProperties);
74 funcs.vkEnumerateDeviceLayerProperties = GPA(vkEnumerateDeviceLayerProperties);
75 funcs.vkGetPhysicalDeviceExternalBufferProperties = GPA(vkGetPhysicalDeviceExternalBufferProperties);
76 funcs.vkGetPhysicalDeviceExternalFenceProperties = GPA(vkGetPhysicalDeviceExternalFenceProperties);
77 funcs.vkGetPhysicalDeviceExternalSemaphoreProperties = GPA(vkGetPhysicalDeviceExternalSemaphoreProperties);
78
79 funcs.vkDestroySurfaceKHR = GPA(vkDestroySurfaceKHR);
80 funcs.vkGetDeviceProcAddr = GPA(vkGetDeviceProcAddr);
81 funcs.vkCreateDevice = GPA(vkCreateDevice);
82
83 funcs.vkCreateHeadlessSurfaceEXT = GPA(vkCreateHeadlessSurfaceEXT);
84 funcs.vkCreateDisplayPlaneSurfaceKHR = GPA(vkCreateDisplayPlaneSurfaceKHR);
85 funcs.vkGetPhysicalDeviceDisplayPropertiesKHR = GPA(vkGetPhysicalDeviceDisplayPropertiesKHR);
86 funcs.vkGetPhysicalDeviceDisplayPlanePropertiesKHR = GPA(vkGetPhysicalDeviceDisplayPlanePropertiesKHR);
87 funcs.vkGetDisplayPlaneSupportedDisplaysKHR = GPA(vkGetDisplayPlaneSupportedDisplaysKHR);
88 funcs.vkGetDisplayModePropertiesKHR = GPA(vkGetDisplayModePropertiesKHR);
89 funcs.vkCreateDisplayModeKHR = GPA(vkCreateDisplayModeKHR);
90 funcs.vkGetDisplayPlaneCapabilitiesKHR = GPA(vkGetDisplayPlaneCapabilitiesKHR);
91 funcs.vkGetPhysicalDevicePresentRectanglesKHR = GPA(vkGetPhysicalDevicePresentRectanglesKHR);
92 funcs.vkGetPhysicalDeviceDisplayProperties2KHR = GPA(vkGetPhysicalDeviceDisplayProperties2KHR);
93 funcs.vkGetPhysicalDeviceDisplayPlaneProperties2KHR = GPA(vkGetPhysicalDeviceDisplayPlaneProperties2KHR);
94 funcs.vkGetDisplayModeProperties2KHR = GPA(vkGetDisplayModeProperties2KHR);
95 funcs.vkGetDisplayPlaneCapabilities2KHR = GPA(vkGetDisplayPlaneCapabilities2KHR);
96 funcs.vkGetPhysicalDeviceSurfaceCapabilities2KHR = GPA(vkGetPhysicalDeviceSurfaceCapabilities2KHR);
97 funcs.vkGetPhysicalDeviceSurfaceFormats2KHR = GPA(vkGetPhysicalDeviceSurfaceFormats2KHR);
98
99 #if defined(VK_USE_PLATFORM_ANDROID_KHR)
100 funcs.vkCreateAndroidSurfaceKHR = GPA(vkCreateAndroidSurfaceKHR);
101 #endif // VK_USE_PLATFORM_ANDROID_KHR
102 #if defined(VK_USE_PLATFORM_DIRECTFB_EXT)
103 funcs.vkCreateDirectFBSurfaceEXT = GPA(vkCreateDirectFBSurfaceEXT);
104 funcs.vkGetPhysicalDeviceDirectFBPresentationSupportEXT = GPA(vkGetPhysicalDeviceDirectFBPresentationSupportEXT);
105 #endif // VK_USE_PLATFORM_DIRECTFB_EXT
106 #if defined(VK_USE_PLATFORM_FUCHSIA)
107 funcs.vkCreateImagePipeSurfaceFUCHSIA = GPA(vkCreateImagePipeSurfaceFUCHSIA);
108 #endif // VK_USE_PLATFORM_FUCHSIA
109 #if defined(VK_USE_PLATFORM_GGP)
110 funcs.vkCreateStreamDescriptorSurfaceGGP = GPA(vkCreateStreamDescriptorSurfaceGGP);
111 #endif // VK_USE_PLATFORM_GGP
112 #if defined(VK_USE_PLATFORM_IOS_MVK)
113 funcs.vkCreateIOSSurfaceMVK = GPA(vkCreateIOSSurfaceMVK);
114 #endif // VK_USE_PLATFORM_IOS_MVK
115 #if defined(VK_USE_PLATFORM_MACOS_MVK)
116 funcs.vkCreateMacOSSurfaceMVK = GPA(vkCreateMacOSSurfaceMVK);
117 #endif // VK_USE_PLATFORM_MACOS_MVK
118 #if defined(VK_USE_PLATFORM_METAL_EXT)
119 funcs.vkCreateMetalSurfaceEXT = GPA(vkCreateMetalSurfaceEXT);
120 #endif // VK_USE_PLATFORM_METAL_EXT
121 #if defined(VK_USE_PLATFORM_SCREEN_QNX)
122 funcs.vkCreateScreenSurfaceQNX = GPA(vkCreateScreenSurfaceQNX);
123 funcs.vkGetPhysicalDeviceScreenPresentationSupportQNX = GPA(vkGetPhysicalDeviceScreenPresentationSupportQNX);
124 #endif // VK_USE_PLATFORM_SCREEN_QNX
125 #if defined(VK_USE_PLATFORM_WAYLAND_KHR)
126 funcs.vkCreateWaylandSurfaceKHR = GPA(vkCreateWaylandSurfaceKHR);
127 funcs.vkGetPhysicalDeviceWaylandPresentationSupportKHR = GPA(vkGetPhysicalDeviceWaylandPresentationSupportKHR);
128 #endif // VK_USE_PLATFORM_WAYLAND_KHR
129 #if defined(VK_USE_PLATFORM_XCB_KHR)
130 funcs.vkCreateXcbSurfaceKHR = GPA(vkCreateXcbSurfaceKHR);
131 funcs.vkGetPhysicalDeviceXcbPresentationSupportKHR = GPA(vkGetPhysicalDeviceXcbPresentationSupportKHR);
132 #endif // VK_USE_PLATFORM_XCB_KHR
133 #if defined(VK_USE_PLATFORM_XLIB_KHR)
134 funcs.vkCreateXlibSurfaceKHR = GPA(vkCreateXlibSurfaceKHR);
135 funcs.vkGetPhysicalDeviceXlibPresentationSupportKHR = GPA(vkGetPhysicalDeviceXlibPresentationSupportKHR);
136 #endif // VK_USE_PLATFORM_XLIB_KHR
137 #if defined(VK_USE_PLATFORM_WIN32_KHR)
138 funcs.vkCreateWin32SurfaceKHR = GPA(vkCreateWin32SurfaceKHR);
139 funcs.vkGetPhysicalDeviceWin32PresentationSupportKHR = GPA(vkGetPhysicalDeviceWin32PresentationSupportKHR);
140 #endif // VK_USE_PLATFORM_WIN32_KHR
141
142 funcs.vkDestroyDevice = GPA(vkDestroyDevice);
143 funcs.vkGetDeviceQueue = GPA(vkGetDeviceQueue);
144 #undef GPA
145 // clang-format on
146 }
147
148 #if defined(APPLE_STATIC_LOADER)
VulkanFunctions()149 VulkanFunctions::VulkanFunctions() {
150 #else
151 VulkanFunctions::VulkanFunctions() : loader(get_loader_path()) {
152 #endif
153 init_vulkan_functions(*this);
154 }
155
156 DeviceFunctions::DeviceFunctions(const VulkanFunctions& vulkan_functions, VkDevice device) {
157 vkGetDeviceProcAddr = vulkan_functions.vkGetDeviceProcAddr;
158 vkDestroyDevice = load(device, "vkDestroyDevice");
159 vkGetDeviceQueue = load(device, "vkGetDeviceQueue");
160 vkCreateCommandPool = load(device, "vkCreateCommandPool");
161 vkAllocateCommandBuffers = load(device, "vkAllocateCommandBuffers");
162 vkDestroyCommandPool = load(device, "vkDestroyCommandPool");
163 vkCreateSwapchainKHR = load(device, "vkCreateSwapchainKHR");
164 vkGetSwapchainImagesKHR = load(device, "vkGetSwapchainImagesKHR");
165 vkDestroySwapchainKHR = load(device, "vkDestroySwapchainKHR");
166 }
167
168 InstWrapper::InstWrapper(VulkanFunctions& functions, VkAllocationCallbacks* callbacks) noexcept
169 : functions(&functions), callbacks(callbacks) {}
170 InstWrapper::InstWrapper(VulkanFunctions& functions, VkInstance inst, VkAllocationCallbacks* callbacks) noexcept
171 : functions(&functions), inst(inst), callbacks(callbacks) {}
172 InstWrapper::~InstWrapper() noexcept {
173 if (inst != VK_NULL_HANDLE) functions->vkDestroyInstance(inst, callbacks);
174 }
175
176 InstWrapper::InstWrapper(InstWrapper&& other) noexcept {
177 functions = other.functions;
178 inst = other.inst;
179 callbacks = other.callbacks;
180 create_info = other.create_info;
181 other.inst = VK_NULL_HANDLE;
182 }
183 InstWrapper& InstWrapper::operator=(InstWrapper&& other) noexcept {
184 functions->vkDestroyInstance(inst, callbacks);
185 functions = other.functions;
186 inst = other.inst;
187 callbacks = other.callbacks;
188 create_info = other.create_info;
189 other.inst = VK_NULL_HANDLE;
190 return *this;
191 }
192
193 void InstWrapper::CheckCreate(VkResult result_to_check) {
194 ASSERT_EQ(result_to_check, functions->vkCreateInstance(create_info.get(), callbacks, &inst));
195 }
196
197 void InstWrapper::CheckCreateWithInfo(InstanceCreateInfo& create_info, VkResult result_to_check) {
198 ASSERT_EQ(result_to_check, functions->vkCreateInstance(create_info.get(), callbacks, &inst));
199 }
200
201 std::vector<VkPhysicalDevice> InstWrapper::GetPhysDevs(uint32_t phys_dev_count, VkResult result_to_check) {
202 uint32_t physical_count = phys_dev_count;
203 std::vector<VkPhysicalDevice> physical_devices;
204 physical_devices.resize(phys_dev_count);
205 VkResult res = functions->vkEnumeratePhysicalDevices(inst, &physical_count, physical_devices.data());
206 EXPECT_EQ(result_to_check, res);
207 return physical_devices;
208 }
209
210 std::vector<VkPhysicalDevice> InstWrapper::GetPhysDevs(VkResult result_to_check) {
211 uint32_t physical_count = 0;
212 VkResult res = functions->vkEnumeratePhysicalDevices(inst, &physical_count, nullptr);
213 EXPECT_EQ(result_to_check, res);
214 std::vector<VkPhysicalDevice> physical_devices;
215 physical_devices.resize(physical_count);
216 res = functions->vkEnumeratePhysicalDevices(inst, &physical_count, physical_devices.data());
217 EXPECT_EQ(result_to_check, res);
218 return physical_devices;
219 }
220
221 VkPhysicalDevice InstWrapper::GetPhysDev(VkResult result_to_check) {
222 uint32_t physical_count = 1;
223 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
224 VkResult res = this->functions->vkEnumeratePhysicalDevices(inst, &physical_count, &physical_device);
225 EXPECT_EQ(result_to_check, res);
226 return physical_device;
227 }
228
229 std::vector<VkLayerProperties> InstWrapper::GetActiveLayers(VkPhysicalDevice phys_dev, uint32_t expected_count) {
230 uint32_t count = 0;
231 VkResult res = functions->vkEnumerateDeviceLayerProperties(phys_dev, &count, nullptr);
232 EXPECT_EQ(VK_SUCCESS, res);
233 EXPECT_EQ(count, expected_count);
234 std::vector<VkLayerProperties> layer_props{count};
235 res = functions->vkEnumerateDeviceLayerProperties(phys_dev, &count, layer_props.data());
236 EXPECT_EQ(VK_SUCCESS, res);
237 EXPECT_EQ(count, expected_count);
238 return layer_props;
239 }
240
241 std::vector<VkExtensionProperties> InstWrapper::EnumerateDeviceExtensions(VkPhysicalDevice physical_device,
242 uint32_t expected_count) {
243 uint32_t count = 0;
244 VkResult res = functions->vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &count, nullptr);
245 EXPECT_EQ(VK_SUCCESS, res);
246 EXPECT_EQ(count, expected_count);
247 std::vector<VkExtensionProperties> extensions{count};
248 res = functions->vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &count, extensions.data());
249 EXPECT_EQ(VK_SUCCESS, res);
250 EXPECT_EQ(count, expected_count);
251 return extensions;
252 }
253
254 std::vector<VkExtensionProperties> InstWrapper::EnumerateLayerDeviceExtensions(VkPhysicalDevice physical_device,
255 const char* layer_name, uint32_t expected_count) {
256 uint32_t count = 0;
257 VkResult res = functions->vkEnumerateDeviceExtensionProperties(physical_device, layer_name, &count, nullptr);
258 EXPECT_EQ(VK_SUCCESS, res);
259 EXPECT_EQ(count, expected_count);
260 std::vector<VkExtensionProperties> extensions{count};
261 res = functions->vkEnumerateDeviceExtensionProperties(physical_device, layer_name, &count, extensions.data());
262 EXPECT_EQ(VK_SUCCESS, res);
263 EXPECT_EQ(count, expected_count);
264 return extensions;
265 }
266
267 DeviceWrapper::DeviceWrapper(InstWrapper& inst_wrapper, VkAllocationCallbacks* callbacks) noexcept
268 : functions(inst_wrapper.functions), callbacks(callbacks){};
269 DeviceWrapper::DeviceWrapper(VulkanFunctions& functions, VkDevice device, VkAllocationCallbacks* callbacks) noexcept
270 : functions(&functions), dev(device), callbacks(callbacks){};
271 DeviceWrapper::~DeviceWrapper() noexcept { functions->vkDestroyDevice(dev, callbacks); }
272
273 DeviceWrapper::DeviceWrapper(DeviceWrapper&& other) noexcept {
274 functions = other.functions;
275 dev = other.dev;
276 callbacks = other.callbacks;
277 create_info = other.create_info;
278 other.dev = VK_NULL_HANDLE;
279 }
280 DeviceWrapper& DeviceWrapper::operator=(DeviceWrapper&& other) noexcept {
281 functions->vkDestroyDevice(dev, callbacks);
282 functions = other.functions;
283 dev = other.dev;
284 callbacks = other.callbacks;
285 create_info = other.create_info;
286 other.dev = VK_NULL_HANDLE;
287 return *this;
288 }
289
290 void DeviceWrapper::CheckCreate(VkPhysicalDevice phys_dev, VkResult result_to_check) {
291 ASSERT_EQ(result_to_check, functions->vkCreateDevice(phys_dev, create_info.get(), callbacks, &dev));
292 }
293
294 VkResult CreateDebugUtilsMessenger(DebugUtilsWrapper& debug_utils) {
295 return debug_utils.vkCreateDebugUtilsMessengerEXT(debug_utils.inst, debug_utils.get(), debug_utils.callbacks,
296 &debug_utils.messenger);
297 }
298
299 void FillDebugUtilsCreateDetails(InstanceCreateInfo& create_info, DebugUtilsLogger& logger) {
300 create_info.add_extension("VK_EXT_debug_utils");
301 create_info.instance_info.pNext = logger.get();
302 }
303 void FillDebugUtilsCreateDetails(InstanceCreateInfo& create_info, DebugUtilsWrapper& wrapper) {
304 create_info.add_extension("VK_EXT_debug_utils");
305 create_info.instance_info.pNext = wrapper.get();
306 }
307
308 // Look through the event log. If you find a line containing the prefix we're interested in, look for the end of
309 // line character, and then see if the postfix occurs in it as well.
310 bool DebugUtilsLogger::find_prefix_then_postfix(const char* prefix, const char* postfix) const {
311 size_t new_start = 0;
312 size_t postfix_index = 0;
313 size_t next_eol = 0;
314 while ((new_start = returned_output.find(prefix, new_start)) != std::string::npos) {
315 next_eol = returned_output.find("\n", new_start);
316 if ((postfix_index = returned_output.find(postfix, new_start)) != std::string::npos) {
317 if (postfix_index < next_eol) {
318 return true;
319 }
320 }
321 new_start = next_eol + 1;
322 }
323 return false;
324 }
325
326 bool FindPrefixPostfixStringOnLine(DebugUtilsLogger const& env_log, const char* prefix, const char* postfix) {
327 return env_log.find_prefix_then_postfix(prefix, postfix);
328 }
329
330 PlatformShimWrapper::PlatformShimWrapper(std::vector<fs::FolderManager>* folders, const char* log_filter) noexcept
331 : loader_logging{"VK_LOADER_DEBUG"} {
332 #if defined(WIN32) || defined(__APPLE__)
333 shim_library = LibraryWrapper(SHIM_LIBRARY_NAME);
334 PFN_get_platform_shim get_platform_shim_func = shim_library.get_symbol(GET_PLATFORM_SHIM_STR);
335 assert(get_platform_shim_func != NULL && "Must be able to get \"platform_shim\"");
336 platform_shim = get_platform_shim_func(folders);
337 #elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__GNU__)
338 platform_shim = get_platform_shim(folders);
339 #endif
340 platform_shim->reset();
341
342 if (log_filter) {
343 loader_logging.set_new_value(log_filter);
344 }
345 }
346
347 PlatformShimWrapper::~PlatformShimWrapper() noexcept { platform_shim->reset(); }
348
349 TestICDHandle::TestICDHandle() noexcept {}
350 TestICDHandle::TestICDHandle(fs::path const& icd_path) noexcept : icd_library(icd_path) {
351 proc_addr_get_test_icd = icd_library.get_symbol(GET_TEST_ICD_FUNC_STR);
352 proc_addr_reset_icd = icd_library.get_symbol(RESET_ICD_FUNC_STR);
353 }
354 TestICD& TestICDHandle::get_test_icd() noexcept {
355 assert(proc_addr_get_test_icd != NULL && "symbol must be loaded before use");
356 return *proc_addr_get_test_icd();
357 }
358 TestICD& TestICDHandle::reset_icd() noexcept {
359 assert(proc_addr_reset_icd != NULL && "symbol must be loaded before use");
360 return *proc_addr_reset_icd();
361 }
362 fs::path TestICDHandle::get_icd_full_path() noexcept { return icd_library.lib_path; }
363 fs::path TestICDHandle::get_icd_manifest_path() noexcept { return manifest_path; }
364 fs::path TestICDHandle::get_shimmed_manifest_path() noexcept { return shimmed_manifest_path; }
365
366 TestLayerHandle::TestLayerHandle() noexcept {}
367 TestLayerHandle::TestLayerHandle(fs::path const& layer_path) noexcept : layer_library(layer_path) {
368 proc_addr_get_test_layer = layer_library.get_symbol(GET_TEST_LAYER_FUNC_STR);
369 proc_addr_reset_layer = layer_library.get_symbol(RESET_LAYER_FUNC_STR);
370 }
371 TestLayer& TestLayerHandle::get_test_layer() noexcept {
372 assert(proc_addr_get_test_layer != NULL && "symbol must be loaded before use");
373 return *proc_addr_get_test_layer();
374 }
375 TestLayer& TestLayerHandle::reset_layer() noexcept {
376 assert(proc_addr_reset_layer != NULL && "symbol must be loaded before use");
377 return *proc_addr_reset_layer();
378 }
379 fs::path TestLayerHandle::get_layer_full_path() noexcept { return layer_library.lib_path; }
380 fs::path TestLayerHandle::get_layer_manifest_path() noexcept { return manifest_path; }
381 fs::path TestLayerHandle::get_shimmed_manifest_path() noexcept { return shimmed_manifest_path; }
382
383 FrameworkEnvironment::FrameworkEnvironment() noexcept : FrameworkEnvironment(FrameworkSettings{}) {}
384 FrameworkEnvironment::FrameworkEnvironment(FrameworkSettings const& settings) noexcept
385 : settings(settings), platform_shim(&folders, settings.log_filter) {
386 // This order is important, it matches the enum ManifestLocation, used to index the folders vector
387 folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("null_dir"));
388 folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("icd_manifests"));
389 folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("icd_env_vars_manifests"));
390 folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("explicit_layer_manifests"));
391 folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("explicit_env_var_layer_folder"));
392 folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("explicit_add_env_var_layer_folder"));
393 folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("implicit_layer_manifests"));
394 folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("override_layer_manifests"));
395 folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("app_package_manifests"));
396 folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("macos_bundle"));
397 folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("unsecured_location"));
398 folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("settings_location"));
399
400 platform_shim->redirect_all_paths(get_folder(ManifestLocation::null).location());
401 if (settings.enable_default_search_paths) {
402 platform_shim->set_fake_path(ManifestCategory::icd, get_folder(ManifestLocation::driver).location());
403 platform_shim->set_fake_path(ManifestCategory::explicit_layer, get_folder(ManifestLocation::explicit_layer).location());
404 platform_shim->set_fake_path(ManifestCategory::implicit_layer, get_folder(ManifestLocation::implicit_layer).location());
405 #if COMMON_UNIX_PLATFORMS
406 auto home = get_env_var("HOME");
407 auto unsecured_location = get_folder(ManifestLocation::unsecured_location).location();
408 platform_shim->redirect_path(home + "/.local/share/vulkan/icd.d", unsecured_location);
409 platform_shim->redirect_path(home + "/.local/share/vulkan/implicit_layer.d", unsecured_location);
410 platform_shim->redirect_path(home + "/.local/share/vulkan/explicit_layer.d", unsecured_location);
411 #endif
412 }
413 #if COMMON_UNIX_PLATFORMS
414 if (settings.secure_loader_settings) {
415 platform_shim->redirect_path("/etc/vulkan/loader_settings.d", get_folder(ManifestLocation::settings_location).location());
416 } else {
417 platform_shim->redirect_path(get_env_var("HOME") + "/.local/share/vulkan/loader_settings.d",
418 get_folder(ManifestLocation::settings_location).location());
419 }
420 #endif
421
422 #if defined(__APPLE__)
423 // Necessary since bundles look in sub folders for manifests, not the test framework folder itself
424 auto bundle_location = get_folder(ManifestLocation::macos_bundle).location();
425 platform_shim->redirect_path(bundle_location / "vulkan/icd.d", bundle_location);
426 platform_shim->redirect_path(bundle_location / "vulkan/explicit_layer.d", bundle_location);
427 platform_shim->redirect_path(bundle_location / "vulkan/implicit_layer.d", bundle_location);
428 #endif
429 // only set the settings file if there are elements in the app_specific_settings vector
430 if (!settings.loader_settings.app_specific_settings.empty()) {
431 update_loader_settings(settings.loader_settings);
432 }
433 }
434
435 FrameworkEnvironment::~FrameworkEnvironment() {
436 // This is necessary to prevent the folder manager from using dead memory during destruction.
437 // What happens is that each folder manager tries to cleanup itself. Except, folders that were never called did not have their
438 // DirEntry array's filled out. So when that folder calls delete_folder, which calls readdir, the shim tries to order the files.
439 // Except, the list of files is in a object that is currently being destroyed.
440 platform_shim->is_during_destruction = true;
441 }
442
443 TestICD& FrameworkEnvironment::add_icd(TestICDDetails icd_details) noexcept {
444 size_t cur_icd_index = icds.size();
445 fs::FolderManager* folder = &get_folder(ManifestLocation::driver);
446 if (icd_details.discovery_type == ManifestDiscoveryType::env_var ||
447 icd_details.discovery_type == ManifestDiscoveryType::add_env_var) {
448 folder = &get_folder(ManifestLocation::driver_env_var);
449 }
450 if (icd_details.discovery_type == ManifestDiscoveryType::windows_app_package) {
451 folder = &get_folder(ManifestLocation::windows_app_package);
452 }
453 if (icd_details.discovery_type == ManifestDiscoveryType::macos_bundle) {
454 folder = &get_folder(ManifestLocation::macos_bundle);
455 }
456 if (icd_details.discovery_type == ManifestDiscoveryType::unsecured_generic) {
457 folder = &get_folder(ManifestLocation::unsecured_location);
458 }
459 if (icd_details.discovery_type == ManifestDiscoveryType::null_dir ||
460 icd_details.discovery_type == ManifestDiscoveryType::none) {
461 folder = &get_folder(ManifestLocation::null);
462 }
463 if (!icd_details.is_fake) {
464 fs::path new_driver_name = fs::path(icd_details.icd_manifest.lib_path).stem() + "_" + std::to_string(cur_icd_index) +
465 fs::path(icd_details.icd_manifest.lib_path).extension();
466
467 auto new_driver_location = folder->copy_file(icd_details.icd_manifest.lib_path, new_driver_name.str());
468
469 #if COMMON_UNIX_PLATFORMS
470 if (icd_details.library_path_type == LibraryPathType::default_search_paths) {
471 platform_shim->redirect_dlopen_name(new_driver_name, new_driver_location);
472 } else if (icd_details.library_path_type == LibraryPathType::relative) {
473 platform_shim->redirect_dlopen_name(fs::path(SYSCONFDIR) / "vulkan" / "icd.d" / "." / new_driver_name,
474 new_driver_location);
475 }
476 #endif
477 #if defined(WIN32)
478 if (icd_details.library_path_type == LibraryPathType::default_search_paths) {
479 SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_USER_DIRS);
480 AddDllDirectory(conver_str_to_wstr(new_driver_location.parent_path().str()).c_str());
481 }
482 #endif
483 icds.push_back(TestICDHandle(new_driver_location));
484 icds.back().reset_icd();
485 if (icd_details.library_path_type == LibraryPathType::relative) {
486 icd_details.icd_manifest.lib_path = fs::path(".") / new_driver_name;
487 } else if (icd_details.library_path_type == LibraryPathType::default_search_paths) {
488 icd_details.icd_manifest.lib_path = new_driver_name.str();
489 } else {
490 icd_details.icd_manifest.lib_path = new_driver_location.str();
491 }
492 }
493 if (icd_details.discovery_type != ManifestDiscoveryType::none) {
494 std::string full_json_name = icd_details.json_name;
495 if (!icd_details.disable_icd_inc) {
496 full_json_name += "_" + std::to_string(cur_icd_index);
497 }
498 full_json_name += ".json";
499 icds.back().manifest_path = folder->write_manifest(full_json_name, icd_details.icd_manifest.get_manifest_str());
500 icds.back().shimmed_manifest_path = icds.back().manifest_path;
501 switch (icd_details.discovery_type) {
502 default:
503 case (ManifestDiscoveryType::generic):
504 platform_shim->add_manifest(ManifestCategory::icd, icds.back().manifest_path);
505 #if COMMON_UNIX_PLATFORMS
506 icds.back().shimmed_manifest_path =
507 platform_shim->query_default_redirect_path(ManifestCategory::icd) / full_json_name;
508 #endif
509 break;
510 case (ManifestDiscoveryType::env_var):
511 if (icd_details.is_dir) {
512 env_var_vk_icd_filenames.add_to_list(folder->location().str());
513 } else {
514 env_var_vk_icd_filenames.add_to_list((folder->location() / full_json_name).str());
515 }
516 platform_shim->add_known_path(folder->location());
517 break;
518 case (ManifestDiscoveryType::add_env_var):
519 if (icd_details.is_dir) {
520 add_env_var_vk_icd_filenames.add_to_list(folder->location().str());
521 } else {
522 add_env_var_vk_icd_filenames.add_to_list((folder->location() / full_json_name).str());
523 }
524 platform_shim->add_known_path(folder->location());
525 break;
526 case (ManifestDiscoveryType::macos_bundle):
527 platform_shim->add_manifest(ManifestCategory::icd, icds.back().manifest_path);
528 break;
529 case (ManifestDiscoveryType::unsecured_generic):
530 platform_shim->add_unsecured_manifest(ManifestCategory::icd, icds.back().manifest_path);
531 break;
532 case (ManifestDiscoveryType::null_dir):
533 break;
534 #if defined(_WIN32)
535 case (ManifestDiscoveryType::windows_app_package):
536 platform_shim->set_app_package_path(folder->location());
537 break;
538 #endif
539 }
540 }
541 return icds.back().get_test_icd();
542 }
543
544 void FrameworkEnvironment::add_implicit_layer(ManifestLayer layer_manifest, const std::string& json_name) noexcept {
545 add_layer_impl(TestLayerDetails{layer_manifest, json_name}, ManifestCategory::implicit_layer);
546 }
547 void FrameworkEnvironment::add_explicit_layer(ManifestLayer layer_manifest, const std::string& json_name) noexcept {
548 add_layer_impl(TestLayerDetails{layer_manifest, json_name}, ManifestCategory::explicit_layer);
549 }
550 void FrameworkEnvironment::add_fake_implicit_layer(ManifestLayer layer_manifest, const std::string& json_name) noexcept {
551 add_layer_impl(TestLayerDetails{layer_manifest, json_name}.set_is_fake(true), ManifestCategory::implicit_layer);
552 }
553 void FrameworkEnvironment::add_fake_explicit_layer(ManifestLayer layer_manifest, const std::string& json_name) noexcept {
554 add_layer_impl(TestLayerDetails{layer_manifest, json_name}.set_is_fake(true), ManifestCategory::explicit_layer);
555 }
556 void FrameworkEnvironment::add_implicit_layer(TestLayerDetails layer_details) noexcept {
557 add_layer_impl(layer_details, ManifestCategory::implicit_layer);
558 }
559 void FrameworkEnvironment::add_explicit_layer(TestLayerDetails layer_details) noexcept {
560 add_layer_impl(layer_details, ManifestCategory::explicit_layer);
561 }
562
563 void FrameworkEnvironment::add_layer_impl(TestLayerDetails layer_details, ManifestCategory category) {
564 fs::FolderManager* fs_ptr = &get_folder(ManifestLocation::explicit_layer);
565 switch (layer_details.discovery_type) {
566 default:
567 case (ManifestDiscoveryType::generic):
568 if (category == ManifestCategory::implicit_layer) fs_ptr = &get_folder(ManifestLocation::implicit_layer);
569 break;
570 case (ManifestDiscoveryType::env_var):
571 fs_ptr = &get_folder(ManifestLocation::explicit_layer_env_var);
572 if (layer_details.is_dir) {
573 env_var_vk_layer_paths.add_to_list(fs_ptr->location().str());
574 } else {
575 env_var_vk_layer_paths.add_to_list((fs_ptr->location() / layer_details.json_name).str());
576 }
577 platform_shim->add_known_path(fs_ptr->location());
578 break;
579 case (ManifestDiscoveryType::add_env_var):
580 fs_ptr = &get_folder(ManifestLocation::explicit_layer_add_env_var);
581 if (layer_details.is_dir) {
582 add_env_var_vk_layer_paths.add_to_list(fs_ptr->location().str());
583 } else {
584 add_env_var_vk_layer_paths.add_to_list((fs_ptr->location() / layer_details.json_name).str());
585 }
586 platform_shim->add_known_path(fs_ptr->location());
587 break;
588 case (ManifestDiscoveryType::override_folder):
589 fs_ptr = &get_folder(ManifestLocation::override_layer);
590 break;
591 case (ManifestDiscoveryType::macos_bundle):
592 fs_ptr = &(get_folder(ManifestLocation::macos_bundle));
593 break;
594 case (ManifestDiscoveryType::unsecured_generic):
595 fs_ptr = &(get_folder(ManifestLocation::unsecured_location));
596 break;
597 case (ManifestDiscoveryType::none):
598 case (ManifestDiscoveryType::null_dir):
599 fs_ptr = &(get_folder(ManifestLocation::null));
600 break;
601 }
602 auto& folder = *fs_ptr;
603 size_t new_layers_start = layers.size();
604 for (auto& layer : layer_details.layer_manifest.layers) {
605 if (!layer.lib_path.str().empty()) {
606 fs::path layer_binary_name =
607 layer.lib_path.filename().stem() + "_" + std::to_string(layers.size()) + layer.lib_path.filename().extension();
608
609 auto new_layer_location = folder.copy_file(layer.lib_path, layer_binary_name.str());
610
611 #if COMMON_UNIX_PLATFORMS
612 if (layer_details.library_path_type == LibraryPathType::default_search_paths) {
613 platform_shim->redirect_dlopen_name(layer_binary_name, new_layer_location);
614 }
615 if (layer_details.library_path_type == LibraryPathType::relative) {
616 platform_shim->redirect_dlopen_name(
617 fs::path(SYSCONFDIR) / "vulkan" / category_path_name(category) / "." / layer_binary_name, new_layer_location);
618 }
619 #endif
620 #if defined(WIN32)
621 if (layer_details.library_path_type == LibraryPathType::default_search_paths) {
622 SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_USER_DIRS);
623 AddDllDirectory(conver_str_to_wstr(new_layer_location.parent_path().str()).c_str());
624 }
625 #endif
626
627 // Don't load the layer binary if using any of the wrap objects layers, since it doesn't export the same interface
628 // functions
629 if (!layer_details.is_fake &&
630 layer.lib_path.stem().str().find(fs::path(TEST_LAYER_WRAP_OBJECTS).stem().str()) == std::string::npos) {
631 layers.push_back(TestLayerHandle(new_layer_location));
632 layers.back().reset_layer();
633 }
634 if (layer_details.library_path_type == LibraryPathType::relative) {
635 layer.lib_path = fs::path(".") / layer_binary_name;
636 } else if (layer_details.library_path_type == LibraryPathType::default_search_paths) {
637 layer.lib_path = layer_binary_name;
638 } else {
639 layer.lib_path = new_layer_location;
640 }
641 }
642 }
643 if (layer_details.discovery_type != ManifestDiscoveryType::none) {
644 // Write a manifest file to a folder as long as the discovery type isn't none
645 auto layer_manifest_loc = folder.write_manifest(layer_details.json_name, layer_details.layer_manifest.get_manifest_str());
646 // only add the manifest to the registry if its a generic location (as if it was installed) - both system and user local
647 if (layer_details.discovery_type == ManifestDiscoveryType::generic) {
648 platform_shim->add_manifest(category, layer_manifest_loc);
649 }
650 if (layer_details.discovery_type == ManifestDiscoveryType::unsecured_generic) {
651 platform_shim->add_unsecured_manifest(category, layer_manifest_loc);
652 }
653 for (size_t i = new_layers_start; i < layers.size(); i++) {
654 layers.at(i).manifest_path = layer_manifest_loc;
655 layers.at(i).shimmed_manifest_path = layer_manifest_loc;
656 #if COMMON_UNIX_PLATFORMS
657 if (layer_details.discovery_type == ManifestDiscoveryType::generic) {
658 layers.at(i).shimmed_manifest_path = platform_shim->query_default_redirect_path(category) / layer_details.json_name;
659 }
660 #endif
661 }
662 }
663 }
664
665 std::string get_loader_settings_file_contents(const LoaderSettings& loader_settings) noexcept {
666 JsonWriter writer;
667 writer.StartObject();
668 writer.AddKeyedString("file_format_version", loader_settings.file_format_version.get_version_str());
669 bool one_setting_file = true;
670 if (loader_settings.app_specific_settings.size() > 1) {
671 writer.StartKeyedArray("settings_array");
672 one_setting_file = false;
673 }
674 for (const auto& setting : loader_settings.app_specific_settings) {
675 if (one_setting_file) {
676 writer.StartKeyedObject("settings");
677 } else {
678 writer.StartObject();
679 }
680 if (!setting.app_keys.empty()) {
681 writer.StartKeyedArray("app_keys");
682 for (const auto& app_key : setting.app_keys) {
683 writer.AddString(app_key);
684 }
685 writer.EndArray();
686 }
687 if (!setting.layer_configurations.empty()) {
688 writer.StartKeyedArray("layers");
689 for (const auto& config : setting.layer_configurations) {
690 writer.StartObject();
691 writer.AddKeyedString("name", config.name);
692 writer.AddKeyedString("path", fs::fixup_backslashes_in_path(config.path));
693 writer.AddKeyedString("control", config.control);
694 writer.AddKeyedBool("treat_as_implicit_manifest", config.treat_as_implicit_manifest);
695 writer.EndObject();
696 }
697 writer.EndArray();
698 }
699 if (!setting.stderr_log.empty()) {
700 writer.StartKeyedArray("stderr_log");
701 for (const auto& filter : setting.stderr_log) {
702 writer.AddString(filter);
703 }
704 writer.EndArray();
705 }
706 if (!setting.log_configurations.empty()) {
707 writer.StartKeyedArray("log_locations");
708 for (const auto& config : setting.log_configurations) {
709 writer.StartObject();
710 writer.StartKeyedArray("destinations");
711 for (const auto& dest : config.destinations) {
712 writer.AddString(dest);
713 }
714 writer.EndArray();
715 writer.StartKeyedArray("filter");
716 for (const auto& filter : config.filters) {
717 writer.AddString(filter);
718 }
719 writer.EndArray();
720 writer.EndObject();
721 }
722 writer.EndArray();
723 }
724 writer.EndObject();
725 }
726 if (!one_setting_file) {
727 writer.EndArray();
728 }
729
730 writer.EndObject();
731 return writer.output;
732 }
733 void FrameworkEnvironment::write_settings_file(std::string const& file_contents) {
734 auto out_path = get_folder(ManifestLocation::settings_location).write_manifest("vk_loader_settings.json", file_contents);
735 #if defined(WIN32)
736 platform_shim->hkey_current_user_settings.clear();
737 platform_shim->hkey_local_machine_settings.clear();
738 #endif
739 if (settings.secure_loader_settings)
740 platform_shim->add_manifest(ManifestCategory::settings, out_path);
741 else
742 platform_shim->add_unsecured_manifest(ManifestCategory::settings, out_path);
743 }
744 void FrameworkEnvironment::update_loader_settings(const LoaderSettings& settings) noexcept {
745 write_settings_file(get_loader_settings_file_contents(settings));
746 }
747 void FrameworkEnvironment::remove_loader_settings() {
748 get_folder(ManifestLocation::settings_location).remove("vk_loader_settings.json");
749 }
750
751 TestICD& FrameworkEnvironment::get_test_icd(size_t index) noexcept { return icds[index].get_test_icd(); }
752 TestICD& FrameworkEnvironment::reset_icd(size_t index) noexcept { return icds[index].reset_icd(); }
753 fs::path FrameworkEnvironment::get_test_icd_path(size_t index) noexcept { return icds[index].get_icd_full_path(); }
754 fs::path FrameworkEnvironment::get_icd_manifest_path(size_t index) noexcept { return icds[index].get_icd_manifest_path(); }
755 fs::path FrameworkEnvironment::get_shimmed_icd_manifest_path(size_t index) noexcept {
756 return icds[index].get_shimmed_manifest_path();
757 }
758
759 TestLayer& FrameworkEnvironment::get_test_layer(size_t index) noexcept { return layers[index].get_test_layer(); }
760 TestLayer& FrameworkEnvironment::reset_layer(size_t index) noexcept { return layers[index].reset_layer(); }
761 fs::path FrameworkEnvironment::get_test_layer_path(size_t index) noexcept { return layers[index].get_layer_full_path(); }
762 fs::path FrameworkEnvironment::get_layer_manifest_path(size_t index) noexcept { return layers[index].get_layer_manifest_path(); }
763 fs::path FrameworkEnvironment::get_shimmed_layer_manifest_path(size_t index) noexcept {
764 return layers[index].get_shimmed_manifest_path();
765 }
766
767 fs::FolderManager& FrameworkEnvironment::get_folder(ManifestLocation location) noexcept {
768 // index it directly using the enum location since they will always be in that order
769 return folders.at(static_cast<size_t>(location));
770 }
771 fs::FolderManager const& FrameworkEnvironment::get_folder(ManifestLocation location) const noexcept {
772 return folders.at(static_cast<size_t>(location));
773 }
774 #if defined(__APPLE__)
775 void FrameworkEnvironment::setup_macos_bundle() noexcept {
776 platform_shim->bundle_contents = get_folder(ManifestLocation::macos_bundle).location().str();
777 }
778 #endif
779
780 std::vector<VkExtensionProperties> FrameworkEnvironment::GetInstanceExtensions(uint32_t expected_count, const char* layer_name) {
781 uint32_t count = 0;
782 VkResult res = vulkan_functions.vkEnumerateInstanceExtensionProperties(layer_name, &count, nullptr);
783 EXPECT_EQ(VK_SUCCESS, res);
784 EXPECT_EQ(count, expected_count);
785 std::vector<VkExtensionProperties> extension_props{count};
786 res = vulkan_functions.vkEnumerateInstanceExtensionProperties(layer_name, &count, extension_props.data());
787 EXPECT_EQ(VK_SUCCESS, res);
788 EXPECT_EQ(count, expected_count);
789 return extension_props;
790 }
791 std::vector<VkLayerProperties> FrameworkEnvironment::GetLayerProperties(uint32_t expected_count) {
792 uint32_t count = 0;
793 VkResult res = vulkan_functions.vkEnumerateInstanceLayerProperties(&count, nullptr);
794 EXPECT_EQ(VK_SUCCESS, res);
795 EXPECT_EQ(count, expected_count);
796 std::vector<VkLayerProperties> layer_props{count};
797 res = vulkan_functions.vkEnumerateInstanceLayerProperties(&count, layer_props.data());
798 EXPECT_EQ(VK_SUCCESS, res);
799 EXPECT_EQ(count, expected_count);
800 return layer_props;
801 }
802
803 template <typename CreationFunc, typename CreateInfo>
804 VkResult create_surface_helper(VulkanFunctions* functions, VkInstance inst, VkSurfaceKHR& surface, const char* load_func_name) {
805 CreationFunc pfn_CreateSurface = functions->load(inst, load_func_name);
806 if (!pfn_CreateSurface) return VK_ERROR_EXTENSION_NOT_PRESENT;
807 CreateInfo surf_create_info{};
808 return pfn_CreateSurface(inst, &surf_create_info, nullptr, &surface);
809 }
810 VkResult create_surface(VulkanFunctions* functions, VkInstance inst, VkSurfaceKHR& surface,
811 [[maybe_unused]] const char* api_selection) {
812 #if defined(VK_USE_PLATFORM_ANDROID_KHR)
813 return create_surface_helper<PFN_vkCreateAndroidSurfaceKHR, VkAndroidSurfaceCreateInfoKHR>(functions, inst, surface,
814 "vkCreateAndroidSurfaceKHR");
815 #elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
816 return create_surface_helper<PFN_vkCreateDirectFBSurfaceEXT, VkDirectFBSurfaceCreateInfoEXT>(functions, inst, surface,
817 "vkCreateDirectFBSurfaceEXT");
818 #elif defined(VK_USE_PLATFORM_FUCHSIA)
819 return create_surface_helper<PFN_vkCreateImagePipeSurfaceFUCHSIA, VkImagePipeSurfaceCreateInfoFUCHSIA>(
820 functions, inst, surface, "vkCreateImagePipeSurfaceFUCHSIA");
821 #elif defined(VK_USE_PLATFORM_GGP)
822 return create_surface_helper<PFN__vkCreateStreamDescriptorSurfaceGGP, VkStreamDescriptorSurfaceCreateInfoGGP>(
823 functions, inst, surface, "vkCreateStreamDescriptorSurfaceGGP");
824 #elif defined(VK_USE_PLATFORM_IOS_MVK)
825 return create_surface_helper<PFN_vkCreateIOSSurfaceMVK, VkIOSSurfaceCreateInfoMVK>(functions, inst, surface,
826 "vkCreateIOSSurfaceMVK");
827 #elif defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)
828 #if defined(VK_USE_PLATFORM_MACOS_MVK)
829 if (api_selection != nullptr && string_eq(api_selection, "VK_USE_PLATFORM_MACOS_MVK"))
830 return create_surface_helper<PFN_vkCreateMacOSSurfaceMVK, VkMacOSSurfaceCreateInfoMVK>(functions, inst, surface,
831 "vkCreateMacOSSurfaceMVK");
832 #endif
833 #if defined(VK_USE_PLATFORM_METAL_EXT)
834 if (api_selection == nullptr || (api_selection != nullptr && string_eq(api_selection, "VK_USE_PLATFORM_METAL_EXT")))
835 return create_surface_helper<PFN_vkCreateMetalSurfaceEXT, VkMetalSurfaceCreateInfoEXT>(functions, inst, surface,
836 "vkCreateMetalSurfaceEXT");
837 #endif
838 return VK_ERROR_NOT_PERMITTED_KHR;
839 #elif defined(VK_USE_PLATFORM_SCREEN_QNX)
840 return create_surface_helper<PFN_vkCreateScreenSurfaceQNX, VkScreenSurfaceCreateInfoQNX>(functions, inst, surface,
841 "vkCreateScreenSurfaceQNX");
842 #elif defined(VK_USE_PLATFORM_VI_NN)
843 return create_surface_helper<PFN_vkCreateViSurfaceNN, VkViSurfaceCreateInfoNN>(functions, inst, surface, "vkCreateViSurfaceNN");
844 #elif defined(VK_USE_PLATFORM_WIN32_KHR)
845 return create_surface_helper<PFN_vkCreateWin32SurfaceKHR, VkWin32SurfaceCreateInfoKHR>(functions, inst, surface,
846 "vkCreateWin32SurfaceKHR");
847 #elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_WAYLAND_KHR)
848 #if defined(VK_USE_PLATFORM_XLIB_KHR)
849 if (string_eq(api_selection, "VK_USE_PLATFORM_XLIB_KHR"))
850 return create_surface_helper<PFN_vkCreateXlibSurfaceKHR, VkXlibSurfaceCreateInfoKHR>(functions, inst, surface,
851 "vkCreateXlibSurfaceKHR");
852 #endif
853 #if defined(VK_USE_PLATFORM_WAYLAND_KHR)
854 if (string_eq(api_selection, "VK_USE_PLATFORM_WAYLAND_KHR"))
855 return create_surface_helper<PFN_vkCreateWaylandSurfaceKHR, VkWaylandSurfaceCreateInfoKHR>(functions, inst, surface,
856 "vkCreateWaylandSurfaceKHR");
857 #endif
858 #if defined(VK_USE_PLATFORM_XCB_KHR)
859 if (api_selection == nullptr || string_eq(api_selection, "VK_USE_PLATFORM_XCB_KHR"))
860 return create_surface_helper<PFN_vkCreateXcbSurfaceKHR, VkXcbSurfaceCreateInfoKHR>(functions, inst, surface,
861 "vkCreateXcbSurfaceKHR");
862 #endif
863 return VK_ERROR_NOT_PERMITTED_KHR;
864 #else
865 return create_surface_helper<PFN_vkCreateDisplayPlaneSurfaceKHR, VkDisplaySurfaceCreateInfoKHR>(
866 functions, inst, surface, "vkCreateDisplayPlaneSurfaceKHR");
867 #endif
868 }
869 VkResult create_surface(InstWrapper& inst, VkSurfaceKHR& surface, const char* api_selection) {
870 return create_surface(inst.functions, inst.inst, surface, api_selection);
871 }
872
873 extern "C" {
874 void __ubsan_on_report() { FAIL() << "Encountered an undefined behavior sanitizer error"; }
875 void __asan_on_error() { FAIL() << "Encountered an address sanitizer error"; }
876 void __tsan_on_report() { FAIL() << "Encountered a thread sanitizer error"; }
877 } // extern "C"
878