15db71995Sopenharmony_ci/*
25db71995Sopenharmony_ci *
35db71995Sopenharmony_ci * Copyright (c) 2015-2022 The Khronos Group Inc.
45db71995Sopenharmony_ci * Copyright (c) 2015-2022 Valve Corporation
55db71995Sopenharmony_ci * Copyright (c) 2015-2022 LunarG, Inc.
65db71995Sopenharmony_ci * Copyright (c) 2021-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
75db71995Sopenharmony_ci * Copyright (c) 2023-2023 RasterGrid Kft.
85db71995Sopenharmony_ci *
95db71995Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
105db71995Sopenharmony_ci * you may not use this file except in compliance with the License.
115db71995Sopenharmony_ci * You may obtain a copy of the License at
125db71995Sopenharmony_ci *
135db71995Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
145db71995Sopenharmony_ci *
155db71995Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
165db71995Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
175db71995Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
185db71995Sopenharmony_ci * See the License for the specific language governing permissions and
195db71995Sopenharmony_ci * limitations under the License.
205db71995Sopenharmony_ci *
215db71995Sopenharmony_ci * Author: Ian Elliot <ian@lunarg.com>
225db71995Sopenharmony_ci * Author: Jon Ashburn <jon@lunarg.com>
235db71995Sopenharmony_ci * Author: Lenny Komow <lenny@lunarg.com>
245db71995Sopenharmony_ci * Author: Charles Giessen <charles@lunarg.com>
255db71995Sopenharmony_ci *
265db71995Sopenharmony_ci */
275db71995Sopenharmony_ci#pragma once
285db71995Sopenharmony_ci
295db71995Sopenharmony_ci#if defined(__FreeBSD__) || defined(__OpenBSD__)
305db71995Sopenharmony_ci#include <sys/types.h>
315db71995Sopenharmony_ci#include <sys/select.h>
325db71995Sopenharmony_ci#endif
335db71995Sopenharmony_ci
345db71995Sopenharmony_ci#include <assert.h>
355db71995Sopenharmony_ci#include <float.h>
365db71995Sopenharmony_ci#include <stdbool.h>
375db71995Sopenharmony_ci#include <stdint.h>
385db71995Sopenharmony_ci#include <stdio.h>
395db71995Sopenharmony_ci#include <string.h>
405db71995Sopenharmony_ci
415db71995Sopenharmony_ci#if defined(__Fuchsia__)
425db71995Sopenharmony_ci#include "dlopen_fuchsia.h"
435db71995Sopenharmony_ci#endif  // defined(__Fuchsia__)
445db71995Sopenharmony_ci
455db71995Sopenharmony_ci// Set of platforms with a common set of functionality which is queried throughout the program
465db71995Sopenharmony_ci#if defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__) || defined(__QNX__) || defined(__FreeBSD__) || \
475db71995Sopenharmony_ci    defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__GNU__)
485db71995Sopenharmony_ci#define COMMON_UNIX_PLATFORMS 1
495db71995Sopenharmony_ci#else
505db71995Sopenharmony_ci#define COMMON_UNIX_PLATFORMS 0
515db71995Sopenharmony_ci#endif
525db71995Sopenharmony_ci
535db71995Sopenharmony_ci#if COMMON_UNIX_PLATFORMS
545db71995Sopenharmony_ci#include <unistd.h>
555db71995Sopenharmony_ci// Note: The following file is for dynamic loading:
565db71995Sopenharmony_ci#include <dlfcn.h>
575db71995Sopenharmony_ci#include <pthread.h>
585db71995Sopenharmony_ci#include <stdlib.h>
595db71995Sopenharmony_ci#include <libgen.h>
605db71995Sopenharmony_ci
615db71995Sopenharmony_ci#elif defined(_WIN32)
625db71995Sopenharmony_ci// WinBase.h defines CreateSemaphore and synchapi.h defines CreateEvent
635db71995Sopenharmony_ci//  undefine them to avoid conflicts with VkLayerDispatchTable struct members.
645db71995Sopenharmony_ci#if defined(CreateSemaphore)
655db71995Sopenharmony_ci#undef CreateSemaphore
665db71995Sopenharmony_ci#endif
675db71995Sopenharmony_ci#if defined(CreateEvent)
685db71995Sopenharmony_ci#undef CreateEvent
695db71995Sopenharmony_ci#endif
705db71995Sopenharmony_ci#include <stdio.h>
715db71995Sopenharmony_ci#include <io.h>
725db71995Sopenharmony_ci#include <shlwapi.h>
735db71995Sopenharmony_ci#include <direct.h>
745db71995Sopenharmony_ci#endif  // defined(_WIN32)
755db71995Sopenharmony_ci
765db71995Sopenharmony_ci#include "stack_allocation.h"
775db71995Sopenharmony_ci
785db71995Sopenharmony_ci#if defined(APPLE_STATIC_LOADER) && !defined(__APPLE__)
795db71995Sopenharmony_ci#error "APPLE_STATIC_LOADER can only be defined on Apple platforms!"
805db71995Sopenharmony_ci#endif
815db71995Sopenharmony_ci
825db71995Sopenharmony_ci#if defined(APPLE_STATIC_LOADER)
835db71995Sopenharmony_ci#define LOADER_EXPORT
845db71995Sopenharmony_ci#elif defined(__GNUC__) && __GNUC__ >= 4
855db71995Sopenharmony_ci#define LOADER_EXPORT __attribute__((visibility("default")))
865db71995Sopenharmony_ci#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
875db71995Sopenharmony_ci#define LOADER_EXPORT __attribute__((visibility("default")))
885db71995Sopenharmony_ci#else
895db71995Sopenharmony_ci#define LOADER_EXPORT
905db71995Sopenharmony_ci#endif
915db71995Sopenharmony_ci
925db71995Sopenharmony_ci#define MAX_STRING_SIZE 1024
935db71995Sopenharmony_ci
945db71995Sopenharmony_ci// This is defined in vk_layer.h, but if there's problems we need to create the define
955db71995Sopenharmony_ci// here.
965db71995Sopenharmony_ci#if !defined(MAX_NUM_UNKNOWN_EXTS)
975db71995Sopenharmony_ci#define MAX_NUM_UNKNOWN_EXTS 250
985db71995Sopenharmony_ci#endif
995db71995Sopenharmony_ci
1005db71995Sopenharmony_ci// Environment Variable information
1015db71995Sopenharmony_ci#define VK_ICD_FILENAMES_ENV_VAR "VK_ICD_FILENAMES"  // Deprecated in v1.3.207 loader
1025db71995Sopenharmony_ci#define VK_DRIVER_FILES_ENV_VAR "VK_DRIVER_FILES"
1035db71995Sopenharmony_ci#define VK_LAYER_PATH_ENV_VAR "VK_LAYER_PATH"
1045db71995Sopenharmony_ci// Support added in v1.3.207 loader
1055db71995Sopenharmony_ci#define VK_ADDITIONAL_DRIVER_FILES_ENV_VAR "VK_ADD_DRIVER_FILES"
1065db71995Sopenharmony_ci#define VK_ADDITIONAL_LAYER_PATH_ENV_VAR "VK_ADD_LAYER_PATH"
1075db71995Sopenharmony_ci// Support added in v1.3.234 loader
1085db71995Sopenharmony_ci#define VK_LAYERS_ENABLE_ENV_VAR "VK_LOADER_LAYERS_ENABLE"
1095db71995Sopenharmony_ci#define VK_LAYERS_DISABLE_ENV_VAR "VK_LOADER_LAYERS_DISABLE"
1105db71995Sopenharmony_ci#define VK_LAYERS_ALLOW_ENV_VAR "VK_LOADER_LAYERS_ALLOW"
1115db71995Sopenharmony_ci#define VK_DRIVERS_SELECT_ENV_VAR "VK_LOADER_DRIVERS_SELECT"
1125db71995Sopenharmony_ci#define VK_DRIVERS_DISABLE_ENV_VAR "VK_LOADER_DRIVERS_DISABLE"
1135db71995Sopenharmony_ci#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_1 "~all~"
1145db71995Sopenharmony_ci#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_2 "*"
1155db71995Sopenharmony_ci#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_3 "**"
1165db71995Sopenharmony_ci#define VK_LOADER_DISABLE_IMPLICIT_LAYERS_VAR "~implicit~"
1175db71995Sopenharmony_ci#define VK_LOADER_DISABLE_EXPLICIT_LAYERS_VAR "~explicit~"
1185db71995Sopenharmony_ci
1195db71995Sopenharmony_ci// Override layer information
1205db71995Sopenharmony_ci#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
1215db71995Sopenharmony_ci
1225db71995Sopenharmony_ci// Loader Settings filename
1235db71995Sopenharmony_ci#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
1245db71995Sopenharmony_ci
1255db71995Sopenharmony_ci#define LAYERS_PATH_ENV "VK_LAYER_PATH"
1265db71995Sopenharmony_ci#define ENABLED_LAYERS_ENV "VK_INSTANCE_LAYERS"
1275db71995Sopenharmony_ci
1285db71995Sopenharmony_ci#if COMMON_UNIX_PLATFORMS
1295db71995Sopenharmony_ci/* Linux-specific common code: */
1305db71995Sopenharmony_ci
1315db71995Sopenharmony_ci// VK Library Filenames, Paths, etc.:
1325db71995Sopenharmony_ci#define PATH_SEPARATOR ':'
1335db71995Sopenharmony_ci#define DIRECTORY_SYMBOL '/'
1345db71995Sopenharmony_ci
1355db71995Sopenharmony_ci#define VULKAN_DIR "vulkan/"
1365db71995Sopenharmony_ci#define VULKAN_ICDCONF_DIR "icd.d"
1375db71995Sopenharmony_ci#define VULKAN_ICD_DIR "icd"
1385db71995Sopenharmony_ci#define VULKAN_SETTINGSCONF_DIR "settings.d"
1395db71995Sopenharmony_ci#define VULKAN_ELAYERCONF_DIR "explicit_layer.d"
1405db71995Sopenharmony_ci#define VULKAN_ILAYERCONF_DIR "implicit_layer.d"
1415db71995Sopenharmony_ci#define VULKAN_LAYER_DIR "layer"
1425db71995Sopenharmony_ci
1435db71995Sopenharmony_ci#define VK_DRIVERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ICDCONF_DIR
1445db71995Sopenharmony_ci#define VK_SETTINGS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_SETTINGSCONF_DIR
1455db71995Sopenharmony_ci#define VK_ELAYERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ELAYERCONF_DIR
1465db71995Sopenharmony_ci#define VK_ILAYERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ILAYERCONF_DIR
1475db71995Sopenharmony_ci
1485db71995Sopenharmony_ci#define VK_DRIVERS_INFO_REGISTRY_LOC ""
1495db71995Sopenharmony_ci#define VK_ELAYERS_INFO_REGISTRY_LOC ""
1505db71995Sopenharmony_ci#define VK_ILAYERS_INFO_REGISTRY_LOC ""
1515db71995Sopenharmony_ci#define VK_SETTINGS_INFO_REGISTRY_LOC ""
1525db71995Sopenharmony_ci
1535db71995Sopenharmony_ci#if defined(__QNX__)
1545db71995Sopenharmony_ci#define SYSCONFDIR "/etc"
1555db71995Sopenharmony_ci#endif
1565db71995Sopenharmony_ci
1575db71995Sopenharmony_ci// C99:
1585db71995Sopenharmony_ci#define PRINTF_SIZE_T_SPECIFIER "%zu"
1595db71995Sopenharmony_ci
1605db71995Sopenharmony_ci// Dynamic Loading of libraries:
1615db71995Sopenharmony_citypedef void *loader_platform_dl_handle;
1625db71995Sopenharmony_ci
1635db71995Sopenharmony_ci// Threads:
1645db71995Sopenharmony_citypedef pthread_t loader_platform_thread;
1655db71995Sopenharmony_ci
1665db71995Sopenharmony_ci// Thread IDs:
1675db71995Sopenharmony_citypedef pthread_t loader_platform_thread_id;
1685db71995Sopenharmony_ci
1695db71995Sopenharmony_ci// Thread mutex:
1705db71995Sopenharmony_citypedef pthread_mutex_t loader_platform_thread_mutex;
1715db71995Sopenharmony_ci
1725db71995Sopenharmony_citypedef pthread_cond_t loader_platform_thread_cond;
1735db71995Sopenharmony_ci
1745db71995Sopenharmony_ci#elif defined(_WIN32)
1755db71995Sopenharmony_ci/* Windows-specific common code: */
1765db71995Sopenharmony_ci// VK Library Filenames, Paths, etc.:
1775db71995Sopenharmony_ci#define PATH_SEPARATOR ';'
1785db71995Sopenharmony_ci#define DIRECTORY_SYMBOL '\\'
1795db71995Sopenharmony_ci#define DEFAULT_VK_REGISTRY_HIVE HKEY_LOCAL_MACHINE
1805db71995Sopenharmony_ci#define DEFAULT_VK_REGISTRY_HIVE_STR "HKEY_LOCAL_MACHINE"
1815db71995Sopenharmony_ci#define SECONDARY_VK_REGISTRY_HIVE HKEY_CURRENT_USER
1825db71995Sopenharmony_ci#define SECONDARY_VK_REGISTRY_HIVE_STR "HKEY_CURRENT_USER"
1835db71995Sopenharmony_ci
1845db71995Sopenharmony_ci#define VK_DRIVERS_INFO_RELATIVE_DIR ""
1855db71995Sopenharmony_ci#define VK_SETTINGS_INFO_RELATIVE_DIR ""
1865db71995Sopenharmony_ci#define VK_ELAYERS_INFO_RELATIVE_DIR ""
1875db71995Sopenharmony_ci#define VK_ILAYERS_INFO_RELATIVE_DIR ""
1885db71995Sopenharmony_ci
1895db71995Sopenharmony_ci#define VK_VARIANT_REG_STR ""
1905db71995Sopenharmony_ci#define VK_VARIANT_REG_STR_W L""
1915db71995Sopenharmony_ci
1925db71995Sopenharmony_ci#define VK_DRIVERS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\Vulkan" VK_VARIANT_REG_STR "\\Drivers"
1935db71995Sopenharmony_ci#define VK_ELAYERS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\Vulkan" VK_VARIANT_REG_STR "\\ExplicitLayers"
1945db71995Sopenharmony_ci#define VK_ILAYERS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\Vulkan" VK_VARIANT_REG_STR "\\ImplicitLayers"
1955db71995Sopenharmony_ci#define VK_SETTINGS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\Vulkan" VK_VARIANT_REG_STR "\\LoaderSettings"
1965db71995Sopenharmony_ci
1975db71995Sopenharmony_ci#define PRINTF_SIZE_T_SPECIFIER "%Iu"
1985db71995Sopenharmony_ci
1995db71995Sopenharmony_ci// Dynamic Loading:
2005db71995Sopenharmony_citypedef HMODULE loader_platform_dl_handle;
2015db71995Sopenharmony_ci
2025db71995Sopenharmony_ci// Threads:
2035db71995Sopenharmony_citypedef HANDLE loader_platform_thread;
2045db71995Sopenharmony_ci
2055db71995Sopenharmony_ci// Thread IDs:
2065db71995Sopenharmony_citypedef DWORD loader_platform_thread_id;
2075db71995Sopenharmony_ci
2085db71995Sopenharmony_ci// Thread mutex:
2095db71995Sopenharmony_citypedef CRITICAL_SECTION loader_platform_thread_mutex;
2105db71995Sopenharmony_ci
2115db71995Sopenharmony_citypedef CONDITION_VARIABLE loader_platform_thread_cond;
2125db71995Sopenharmony_ci
2135db71995Sopenharmony_ci#else
2145db71995Sopenharmony_ci
2155db71995Sopenharmony_ci#warning The "vk_loader_platform.h" file must be modified for this OS.
2165db71995Sopenharmony_ci
2175db71995Sopenharmony_ci// NOTE: In order to support another OS, an #elif needs to be added (above the
2185db71995Sopenharmony_ci// "#else // defined(_WIN32)") for that OS, and OS-specific versions of the
2195db71995Sopenharmony_ci// contents of this file must be created, or extend one of the existing OS specific
2205db71995Sopenharmony_ci// sections with the necessary changes.
2215db71995Sopenharmony_ci
2225db71995Sopenharmony_ci#endif
2235db71995Sopenharmony_ci
2245db71995Sopenharmony_ci// controls whether loader_platform_close_library() closes the libraries or not - controlled by an environment variables
2255db71995Sopenharmony_ciextern bool loader_disable_dynamic_library_unloading;
2265db71995Sopenharmony_ci
2275db71995Sopenharmony_ci// Returns true if the DIRECTORY_SYMBOL is contained within path
2285db71995Sopenharmony_cistatic inline bool loader_platform_is_path(const char *path) { return strchr(path, DIRECTORY_SYMBOL) != NULL; }
2295db71995Sopenharmony_ci
2305db71995Sopenharmony_ci// The once init functionality is not used when building a DLL on Windows. This is because there is no way to clean up the
2315db71995Sopenharmony_ci// resources allocated by anything allocated by once init. This isn't a problem for static libraries, but it is for dynamic
2325db71995Sopenharmony_ci// ones. When building a DLL, we use DllMain() instead to allow properly cleaning up resources.
2335db71995Sopenharmony_ci
2345db71995Sopenharmony_ci#if defined(APPLE_STATIC_LOADER)
2355db71995Sopenharmony_cistatic inline void loader_platform_thread_once_fn(pthread_once_t *ctl, void (*func)(void)) {
2365db71995Sopenharmony_ci    assert(func != NULL);
2375db71995Sopenharmony_ci    assert(ctl != NULL);
2385db71995Sopenharmony_ci    pthread_once(ctl, func);
2395db71995Sopenharmony_ci}
2405db71995Sopenharmony_ci#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) pthread_once_t var = PTHREAD_ONCE_INIT;
2415db71995Sopenharmony_ci#define LOADER_PLATFORM_THREAD_ONCE_EXTERN_DEFINITION(var) extern pthread_once_t var;
2425db71995Sopenharmony_ci#define LOADER_PLATFORM_THREAD_ONCE(ctl, func) loader_platform_thread_once_fn(ctl, func);
2435db71995Sopenharmony_ci#else
2445db71995Sopenharmony_ci#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var)
2455db71995Sopenharmony_ci#define LOADER_PLATFORM_THREAD_ONCE_EXTERN_DEFINITION(var)
2465db71995Sopenharmony_ci#define LOADER_PLATFORM_THREAD_ONCE(ctl, func)
2475db71995Sopenharmony_ci
2485db71995Sopenharmony_ci#endif
2495db71995Sopenharmony_ci
2505db71995Sopenharmony_ci#if COMMON_UNIX_PLATFORMS
2515db71995Sopenharmony_ci
2525db71995Sopenharmony_ci// File IO
2535db71995Sopenharmony_cistatic inline bool loader_platform_file_exists(const char *path) {
2545db71995Sopenharmony_ci    if (access(path, F_OK))
2555db71995Sopenharmony_ci        return false;
2565db71995Sopenharmony_ci    else
2575db71995Sopenharmony_ci        return true;
2585db71995Sopenharmony_ci}
2595db71995Sopenharmony_ci
2605db71995Sopenharmony_ci// Returns true if the given string appears to be a relative or absolute
2615db71995Sopenharmony_ci// path, as opposed to a bare filename.
2625db71995Sopenharmony_cistatic inline bool loader_platform_is_path_absolute(const char *path) {
2635db71995Sopenharmony_ci    if (path[0] == '/')
2645db71995Sopenharmony_ci        return true;
2655db71995Sopenharmony_ci    else
2665db71995Sopenharmony_ci        return false;
2675db71995Sopenharmony_ci}
2685db71995Sopenharmony_ci
2695db71995Sopenharmony_cistatic inline char *loader_platform_dirname(char *path) { return dirname(path); }
2705db71995Sopenharmony_ci
2715db71995Sopenharmony_ci// loader_platform_executable_path finds application path + name.
2725db71995Sopenharmony_ci// Path cannot be longer than 1024, returns NULL if it is greater than that.
2735db71995Sopenharmony_ci#if defined(__linux__) || defined(__GNU__)
2745db71995Sopenharmony_cistatic inline char *loader_platform_executable_path(char *buffer, size_t size) {
2755db71995Sopenharmony_ci    ssize_t count = readlink("/proc/self/exe", buffer, size);
2765db71995Sopenharmony_ci    if (count == -1) return NULL;
2775db71995Sopenharmony_ci    if (count == 0) return NULL;
2785db71995Sopenharmony_ci    buffer[count] = '\0';
2795db71995Sopenharmony_ci    return buffer;
2805db71995Sopenharmony_ci}
2815db71995Sopenharmony_ci#elif defined(__APPLE__)
2825db71995Sopenharmony_ci#include <TargetConditionals.h>
2835db71995Sopenharmony_ci// TARGET_OS_IPHONE isn't just iOS it's also iOS/tvOS/watchOS. See TargetConditionals.h documentation.
2845db71995Sopenharmony_ci#if TARGET_OS_IPHONE
2855db71995Sopenharmony_cistatic inline char *loader_platform_executable_path(char *buffer, size_t size) {
2865db71995Sopenharmony_ci    (void)size;
2875db71995Sopenharmony_ci    buffer[0] = '\0';
2885db71995Sopenharmony_ci    return buffer;
2895db71995Sopenharmony_ci}
2905db71995Sopenharmony_ci#endif
2915db71995Sopenharmony_ci#if TARGET_OS_OSX
2925db71995Sopenharmony_ci#include <libproc.h>
2935db71995Sopenharmony_cistatic inline char *loader_platform_executable_path(char *buffer, size_t size) {
2945db71995Sopenharmony_ci    // proc_pidpath takes a uint32_t for the buffer size
2955db71995Sopenharmony_ci    if (size > UINT32_MAX) {
2965db71995Sopenharmony_ci        return NULL;
2975db71995Sopenharmony_ci    }
2985db71995Sopenharmony_ci    pid_t pid = getpid();
2995db71995Sopenharmony_ci    int ret = proc_pidpath(pid, buffer, (uint32_t)size);
3005db71995Sopenharmony_ci    if (ret <= 0) {
3015db71995Sopenharmony_ci        return NULL;
3025db71995Sopenharmony_ci    }
3035db71995Sopenharmony_ci    buffer[ret] = '\0';
3045db71995Sopenharmony_ci    return buffer;
3055db71995Sopenharmony_ci}
3065db71995Sopenharmony_ci#endif
3075db71995Sopenharmony_ci#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__)
3085db71995Sopenharmony_ci#include <sys/sysctl.h>
3095db71995Sopenharmony_cistatic inline char *loader_platform_executable_path(char *buffer, size_t size) {
3105db71995Sopenharmony_ci    int mib[] = {
3115db71995Sopenharmony_ci        CTL_KERN,
3125db71995Sopenharmony_ci#if defined(__NetBSD__)
3135db71995Sopenharmony_ci        KERN_PROC_ARGS,
3145db71995Sopenharmony_ci        -1,
3155db71995Sopenharmony_ci        KERN_PROC_PATHNAME,
3165db71995Sopenharmony_ci#else
3175db71995Sopenharmony_ci        KERN_PROC,
3185db71995Sopenharmony_ci        KERN_PROC_PATHNAME,
3195db71995Sopenharmony_ci        -1,
3205db71995Sopenharmony_ci#endif
3215db71995Sopenharmony_ci    };
3225db71995Sopenharmony_ci    if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buffer, &size, NULL, 0) < 0) {
3235db71995Sopenharmony_ci        return NULL;
3245db71995Sopenharmony_ci    }
3255db71995Sopenharmony_ci
3265db71995Sopenharmony_ci    return buffer;
3275db71995Sopenharmony_ci}
3285db71995Sopenharmony_ci#elif defined(__Fuchsia__) || defined(__OpenBSD__)
3295db71995Sopenharmony_cistatic inline char *loader_platform_executable_path(char *buffer, size_t size) { return NULL; }
3305db71995Sopenharmony_ci#elif defined(__QNX__)
3315db71995Sopenharmony_ci
3325db71995Sopenharmony_ci#define SYSCONFDIR "/etc"
3335db71995Sopenharmony_ci
3345db71995Sopenharmony_ci#include <fcntl.h>
3355db71995Sopenharmony_ci#include <sys/stat.h>
3365db71995Sopenharmony_ci
3375db71995Sopenharmony_cistatic inline char *loader_platform_executable_path(char *buffer, size_t size) {
3385db71995Sopenharmony_ci    int fd = open("/proc/self/exefile", O_RDONLY);
3395db71995Sopenharmony_ci    size_t rdsize;
3405db71995Sopenharmony_ci
3415db71995Sopenharmony_ci    if (fd == -1) {
3425db71995Sopenharmony_ci        return NULL;
3435db71995Sopenharmony_ci    }
3445db71995Sopenharmony_ci
3455db71995Sopenharmony_ci    rdsize = read(fd, buffer, size);
3465db71995Sopenharmony_ci    if (rdsize == size) {
3475db71995Sopenharmony_ci        return NULL;
3485db71995Sopenharmony_ci    }
3495db71995Sopenharmony_ci    buffer[rdsize] = 0x00;
3505db71995Sopenharmony_ci    close(fd);
3515db71995Sopenharmony_ci
3525db71995Sopenharmony_ci    return buffer;
3535db71995Sopenharmony_ci}
3545db71995Sopenharmony_ci#endif  // defined (__QNX__)
3555db71995Sopenharmony_ci
3565db71995Sopenharmony_ci// Compatibility with compilers that don't support __has_feature
3575db71995Sopenharmony_ci#if !defined(__has_feature)
3585db71995Sopenharmony_ci#define __has_feature(x) 0
3595db71995Sopenharmony_ci#endif
3605db71995Sopenharmony_ci
3615db71995Sopenharmony_ci#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
3625db71995Sopenharmony_ci#define LOADER_ADDRESS_SANITIZER_ACTIVE  // TODO: Add proper build flag for ASAN support
3635db71995Sopenharmony_ci#endif
3645db71995Sopenharmony_ci
3655db71995Sopenharmony_ci// When loading the library, we use RTLD_LAZY so that not all symbols have to be
3665db71995Sopenharmony_ci// resolved at this time (which improves performance). Note that if not all symbols
3675db71995Sopenharmony_ci// can be resolved, this could cause crashes later. Use the LD_BIND_NOW environment
3685db71995Sopenharmony_ci// variable to force all symbols to be resolved here.
3695db71995Sopenharmony_ci#define LOADER_DLOPEN_MODE (RTLD_LAZY | RTLD_LOCAL)
3705db71995Sopenharmony_ci
3715db71995Sopenharmony_ci#if defined(__Fuchsia__)
3725db71995Sopenharmony_cistatic inline loader_platform_dl_handle loader_platform_open_driver(const char *libPath) {
3735db71995Sopenharmony_ci    return dlopen_fuchsia(libPath, LOADER_DLOPEN_MODE, true);
3745db71995Sopenharmony_ci}
3755db71995Sopenharmony_cistatic inline loader_platform_dl_handle loader_platform_open_library(const char *libPath) {
3765db71995Sopenharmony_ci    return dlopen_fuchsia(libPath, LOADER_DLOPEN_MODE, false);
3775db71995Sopenharmony_ci}
3785db71995Sopenharmony_ci#else
3795db71995Sopenharmony_cistatic inline loader_platform_dl_handle loader_platform_open_library(const char *libPath) {
3805db71995Sopenharmony_ci    return dlopen(libPath, LOADER_DLOPEN_MODE);
3815db71995Sopenharmony_ci}
3825db71995Sopenharmony_ci#endif
3835db71995Sopenharmony_ci
3845db71995Sopenharmony_cistatic inline const char *loader_platform_open_library_error(const char *libPath) {
3855db71995Sopenharmony_ci    (void)libPath;
3865db71995Sopenharmony_ci#if defined(__Fuchsia__)
3875db71995Sopenharmony_ci    return dlerror_fuchsia();
3885db71995Sopenharmony_ci#else
3895db71995Sopenharmony_ci    return dlerror();
3905db71995Sopenharmony_ci#endif
3915db71995Sopenharmony_ci}
3925db71995Sopenharmony_cistatic inline void loader_platform_close_library(loader_platform_dl_handle library) {
3935db71995Sopenharmony_ci    if (!loader_disable_dynamic_library_unloading) {
3945db71995Sopenharmony_ci        dlclose(library);
3955db71995Sopenharmony_ci    } else {
3965db71995Sopenharmony_ci        (void)library;
3975db71995Sopenharmony_ci    }
3985db71995Sopenharmony_ci}
3995db71995Sopenharmony_cistatic inline void *loader_platform_get_proc_address(loader_platform_dl_handle library, const char *name) {
4005db71995Sopenharmony_ci    assert(library);
4015db71995Sopenharmony_ci    assert(name);
4025db71995Sopenharmony_ci    return dlsym(library, name);
4035db71995Sopenharmony_ci}
4045db71995Sopenharmony_cistatic inline const char *loader_platform_get_proc_address_error(const char *name) {
4055db71995Sopenharmony_ci    (void)name;
4065db71995Sopenharmony_ci    return dlerror();
4075db71995Sopenharmony_ci}
4085db71995Sopenharmony_ci
4095db71995Sopenharmony_ci// Thread mutex:
4105db71995Sopenharmony_cistatic inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_init(pMutex, NULL); }
4115db71995Sopenharmony_cistatic inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_lock(pMutex); }
4125db71995Sopenharmony_cistatic inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_unlock(pMutex); }
4135db71995Sopenharmony_cistatic inline void loader_platform_thread_delete_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_destroy(pMutex); }
4145db71995Sopenharmony_ci
4155db71995Sopenharmony_cistatic inline void *thread_safe_strtok(char *str, const char *delim, char **saveptr) { return strtok_r(str, delim, saveptr); }
4165db71995Sopenharmony_ci
4175db71995Sopenharmony_cistatic inline FILE *loader_fopen(const char *fileName, const char *mode) { return fopen(fileName, mode); }
4185db71995Sopenharmony_cistatic inline char *loader_strncat(char *dest, size_t dest_sz, const char *src, size_t count) {
4195db71995Sopenharmony_ci    (void)dest_sz;
4205db71995Sopenharmony_ci    return strncat(dest, src, count);
4215db71995Sopenharmony_ci}
4225db71995Sopenharmony_cistatic inline char *loader_strncpy(char *dest, size_t dest_sz, const char *src, size_t count) {
4235db71995Sopenharmony_ci    (void)dest_sz;
4245db71995Sopenharmony_ci    return strncpy(dest, src, count);
4255db71995Sopenharmony_ci}
4265db71995Sopenharmony_ci
4275db71995Sopenharmony_ci#elif defined(_WIN32)
4285db71995Sopenharmony_ci
4295db71995Sopenharmony_ci// Get the key for the plug n play driver registry
4305db71995Sopenharmony_ci// The string returned by this function should NOT be freed
4315db71995Sopenharmony_cistatic inline const char *LoaderPnpDriverRegistry() {
4325db71995Sopenharmony_ci    BOOL is_wow;
4335db71995Sopenharmony_ci    IsWow64Process(GetCurrentProcess(), &is_wow);
4345db71995Sopenharmony_ci    return is_wow ? "Vulkan" VK_VARIANT_REG_STR "DriverNameWow" : "Vulkan" VK_VARIANT_REG_STR "DriverName";
4355db71995Sopenharmony_ci}
4365db71995Sopenharmony_cistatic inline const wchar_t *LoaderPnpDriverRegistryWide() {
4375db71995Sopenharmony_ci    BOOL is_wow;
4385db71995Sopenharmony_ci    IsWow64Process(GetCurrentProcess(), &is_wow);
4395db71995Sopenharmony_ci    return is_wow ? L"Vulkan" VK_VARIANT_REG_STR_W L"DriverNameWow" : L"Vulkan" VK_VARIANT_REG_STR_W L"DriverName";
4405db71995Sopenharmony_ci}
4415db71995Sopenharmony_ci
4425db71995Sopenharmony_ci// Get the key for the plug 'n play explicit layer registry
4435db71995Sopenharmony_ci// The string returned by this function should NOT be freed
4445db71995Sopenharmony_cistatic inline const char *LoaderPnpELayerRegistry() {
4455db71995Sopenharmony_ci    BOOL is_wow;
4465db71995Sopenharmony_ci    IsWow64Process(GetCurrentProcess(), &is_wow);
4475db71995Sopenharmony_ci    return is_wow ? "Vulkan" VK_VARIANT_REG_STR "ExplicitLayersWow" : "Vulkan" VK_VARIANT_REG_STR "ExplicitLayers";
4485db71995Sopenharmony_ci}
4495db71995Sopenharmony_cistatic inline const wchar_t *LoaderPnpELayerRegistryWide() {
4505db71995Sopenharmony_ci    BOOL is_wow;
4515db71995Sopenharmony_ci    IsWow64Process(GetCurrentProcess(), &is_wow);
4525db71995Sopenharmony_ci    return is_wow ? L"Vulkan" VK_VARIANT_REG_STR_W L"ExplicitLayersWow" : L"Vulkan" VK_VARIANT_REG_STR_W L"ExplicitLayers";
4535db71995Sopenharmony_ci}
4545db71995Sopenharmony_ci
4555db71995Sopenharmony_ci// Get the key for the plug 'n play implicit layer registry
4565db71995Sopenharmony_ci// The string returned by this function should NOT be freed
4575db71995Sopenharmony_cistatic inline const char *LoaderPnpILayerRegistry() {
4585db71995Sopenharmony_ci    BOOL is_wow;
4595db71995Sopenharmony_ci    IsWow64Process(GetCurrentProcess(), &is_wow);
4605db71995Sopenharmony_ci    return is_wow ? "Vulkan" VK_VARIANT_REG_STR "ImplicitLayersWow" : "Vulkan" VK_VARIANT_REG_STR "ImplicitLayers";
4615db71995Sopenharmony_ci}
4625db71995Sopenharmony_cistatic inline const wchar_t *LoaderPnpILayerRegistryWide() {
4635db71995Sopenharmony_ci    BOOL is_wow;
4645db71995Sopenharmony_ci    IsWow64Process(GetCurrentProcess(), &is_wow);
4655db71995Sopenharmony_ci    return is_wow ? L"Vulkan" VK_VARIANT_REG_STR_W L"ImplicitLayersWow" : L"Vulkan" VK_VARIANT_REG_STR_W L"ImplicitLayers";
4665db71995Sopenharmony_ci}
4675db71995Sopenharmony_ci
4685db71995Sopenharmony_ci// File IO
4695db71995Sopenharmony_cistatic inline bool loader_platform_file_exists(const char *path) {
4705db71995Sopenharmony_ci    int path_utf16_size = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
4715db71995Sopenharmony_ci    if (path_utf16_size <= 0) {
4725db71995Sopenharmony_ci        return false;
4735db71995Sopenharmony_ci    }
4745db71995Sopenharmony_ci    wchar_t *path_utf16 = (wchar_t *)loader_stack_alloc(path_utf16_size * sizeof(wchar_t));
4755db71995Sopenharmony_ci    if (MultiByteToWideChar(CP_UTF8, 0, path, -1, path_utf16, path_utf16_size) != path_utf16_size) {
4765db71995Sopenharmony_ci        return false;
4775db71995Sopenharmony_ci    }
4785db71995Sopenharmony_ci    if (_waccess(path_utf16, 0) == -1)
4795db71995Sopenharmony_ci        return false;
4805db71995Sopenharmony_ci    else
4815db71995Sopenharmony_ci        return true;
4825db71995Sopenharmony_ci}
4835db71995Sopenharmony_ci
4845db71995Sopenharmony_ci// Returns true if the given string appears to be a relative or absolute
4855db71995Sopenharmony_ci// path, as opposed to a bare filename.
4865db71995Sopenharmony_cistatic inline bool loader_platform_is_path_absolute(const char *path) {
4875db71995Sopenharmony_ci    if (!path || !*path) {
4885db71995Sopenharmony_ci        return false;
4895db71995Sopenharmony_ci    }
4905db71995Sopenharmony_ci    if (*path == DIRECTORY_SYMBOL || path[1] == ':') {
4915db71995Sopenharmony_ci        return true;
4925db71995Sopenharmony_ci    }
4935db71995Sopenharmony_ci    return false;
4945db71995Sopenharmony_ci}
4955db71995Sopenharmony_ci
4965db71995Sopenharmony_ci// WIN32 runtime doesn't have dirname().
4975db71995Sopenharmony_cistatic inline char *loader_platform_dirname(char *path) {
4985db71995Sopenharmony_ci    char *current, *next;
4995db71995Sopenharmony_ci
5005db71995Sopenharmony_ci    // TODO/TBD: Do we need to deal with the Windows's ":" character?
5015db71995Sopenharmony_ci
5025db71995Sopenharmony_ci    for (current = path; *current != '\0'; current = next) {
5035db71995Sopenharmony_ci        next = strchr(current, DIRECTORY_SYMBOL);
5045db71995Sopenharmony_ci        if (next == NULL) {
5055db71995Sopenharmony_ci            if (current != path) *(current - 1) = '\0';
5065db71995Sopenharmony_ci            return path;
5075db71995Sopenharmony_ci        } else {
5085db71995Sopenharmony_ci            // Point one character past the DIRECTORY_SYMBOL:
5095db71995Sopenharmony_ci            next++;
5105db71995Sopenharmony_ci        }
5115db71995Sopenharmony_ci    }
5125db71995Sopenharmony_ci    return path;
5135db71995Sopenharmony_ci}
5145db71995Sopenharmony_ci
5155db71995Sopenharmony_cistatic inline char *loader_platform_executable_path(char *buffer, size_t size) {
5165db71995Sopenharmony_ci    wchar_t *buffer_utf16 = (wchar_t *)loader_stack_alloc(size * sizeof(wchar_t));
5175db71995Sopenharmony_ci    DWORD ret = GetModuleFileNameW(NULL, buffer_utf16, (DWORD)size);
5185db71995Sopenharmony_ci    if (ret == 0) {
5195db71995Sopenharmony_ci        return NULL;
5205db71995Sopenharmony_ci    }
5215db71995Sopenharmony_ci    if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
5225db71995Sopenharmony_ci        return NULL;
5235db71995Sopenharmony_ci    }
5245db71995Sopenharmony_ci    int buffer_utf8_size = WideCharToMultiByte(CP_UTF8, 0, buffer_utf16, -1, NULL, 0, NULL, NULL);
5255db71995Sopenharmony_ci    if (buffer_utf8_size <= 0 || (size_t)buffer_utf8_size > size) {
5265db71995Sopenharmony_ci        return NULL;
5275db71995Sopenharmony_ci    }
5285db71995Sopenharmony_ci    if (WideCharToMultiByte(CP_UTF8, 0, buffer_utf16, -1, buffer, buffer_utf8_size, NULL, NULL) != buffer_utf8_size) {
5295db71995Sopenharmony_ci        return NULL;
5305db71995Sopenharmony_ci    }
5315db71995Sopenharmony_ci    return buffer;
5325db71995Sopenharmony_ci}
5335db71995Sopenharmony_ci
5345db71995Sopenharmony_ci// Dynamic Loading:
5355db71995Sopenharmony_cistatic inline loader_platform_dl_handle loader_platform_open_library(const char *lib_path) {
5365db71995Sopenharmony_ci    int lib_path_utf16_size = MultiByteToWideChar(CP_UTF8, 0, lib_path, -1, NULL, 0);
5375db71995Sopenharmony_ci    if (lib_path_utf16_size <= 0) {
5385db71995Sopenharmony_ci        return NULL;
5395db71995Sopenharmony_ci    }
5405db71995Sopenharmony_ci    wchar_t *lib_path_utf16 = (wchar_t *)loader_stack_alloc(lib_path_utf16_size * sizeof(wchar_t));
5415db71995Sopenharmony_ci    if (MultiByteToWideChar(CP_UTF8, 0, lib_path, -1, lib_path_utf16, lib_path_utf16_size) != lib_path_utf16_size) {
5425db71995Sopenharmony_ci        return NULL;
5435db71995Sopenharmony_ci    }
5445db71995Sopenharmony_ci    // Try loading the library the original way first.
5455db71995Sopenharmony_ci    loader_platform_dl_handle lib_handle = LoadLibraryW(lib_path_utf16);
5465db71995Sopenharmony_ci    if (lib_handle == NULL && GetLastError() == ERROR_MOD_NOT_FOUND) {
5475db71995Sopenharmony_ci        // If that failed, then try loading it with broader search folders.
5485db71995Sopenharmony_ci        lib_handle = LoadLibraryExW(lib_path_utf16, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
5495db71995Sopenharmony_ci    }
5505db71995Sopenharmony_ci    return lib_handle;
5515db71995Sopenharmony_ci}
5525db71995Sopenharmony_cistatic inline const char *loader_platform_open_library_error(const char *libPath) {
5535db71995Sopenharmony_ci    static char errorMsg[512];
5545db71995Sopenharmony_ci    (void)snprintf(errorMsg, 511, "Failed to open dynamic library \"%s\" with error %lu", libPath, GetLastError());
5555db71995Sopenharmony_ci    return errorMsg;
5565db71995Sopenharmony_ci}
5575db71995Sopenharmony_cistatic inline void loader_platform_close_library(loader_platform_dl_handle library) {
5585db71995Sopenharmony_ci    if (!loader_disable_dynamic_library_unloading) {
5595db71995Sopenharmony_ci        FreeLibrary(library);
5605db71995Sopenharmony_ci    } else {
5615db71995Sopenharmony_ci        (void)library;
5625db71995Sopenharmony_ci    }
5635db71995Sopenharmony_ci}
5645db71995Sopenharmony_cistatic inline void *loader_platform_get_proc_address(loader_platform_dl_handle library, const char *name) {
5655db71995Sopenharmony_ci    assert(library);
5665db71995Sopenharmony_ci    assert(name);
5675db71995Sopenharmony_ci    return (void *)GetProcAddress(library, name);
5685db71995Sopenharmony_ci}
5695db71995Sopenharmony_cistatic inline const char *loader_platform_get_proc_address_error(const char *name) {
5705db71995Sopenharmony_ci    static char errorMsg[120];
5715db71995Sopenharmony_ci    (void)snprintf(errorMsg, 119, "Failed to find function \"%s\" in dynamic library", name);
5725db71995Sopenharmony_ci    return errorMsg;
5735db71995Sopenharmony_ci}
5745db71995Sopenharmony_ci
5755db71995Sopenharmony_ci// Thread mutex:
5765db71995Sopenharmony_cistatic inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) { InitializeCriticalSection(pMutex); }
5775db71995Sopenharmony_cistatic inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex *pMutex) { EnterCriticalSection(pMutex); }
5785db71995Sopenharmony_cistatic inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) { LeaveCriticalSection(pMutex); }
5795db71995Sopenharmony_cistatic inline void loader_platform_thread_delete_mutex(loader_platform_thread_mutex *pMutex) { DeleteCriticalSection(pMutex); }
5805db71995Sopenharmony_ci
5815db71995Sopenharmony_cistatic inline void *thread_safe_strtok(char *str, const char *delimiters, char **context) {
5825db71995Sopenharmony_ci    return strtok_s(str, delimiters, context);
5835db71995Sopenharmony_ci}
5845db71995Sopenharmony_ci
5855db71995Sopenharmony_cistatic inline FILE *loader_fopen(const char *fileName, const char *mode) {
5865db71995Sopenharmony_ci    FILE *file = NULL;
5875db71995Sopenharmony_ci    errno_t err = fopen_s(&file, fileName, mode);
5885db71995Sopenharmony_ci    if (err != 0) return NULL;
5895db71995Sopenharmony_ci    return file;
5905db71995Sopenharmony_ci}
5915db71995Sopenharmony_ci
5925db71995Sopenharmony_cistatic inline char *loader_strncat(char *dest, size_t dest_sz, const char *src, size_t count) {
5935db71995Sopenharmony_ci    errno_t err = strncat_s(dest, dest_sz, src, count);
5945db71995Sopenharmony_ci    if (err != 0) return NULL;
5955db71995Sopenharmony_ci    return dest;
5965db71995Sopenharmony_ci}
5975db71995Sopenharmony_ci
5985db71995Sopenharmony_cistatic inline char *loader_strncpy(char *dest, size_t dest_sz, const char *src, size_t count) {
5995db71995Sopenharmony_ci    errno_t err = strncpy_s(dest, dest_sz, src, count);
6005db71995Sopenharmony_ci    if (err != 0) return NULL;
6015db71995Sopenharmony_ci    return dest;
6025db71995Sopenharmony_ci}
6035db71995Sopenharmony_ci
6045db71995Sopenharmony_ci#else  // defined(_WIN32)
6055db71995Sopenharmony_ci
6065db71995Sopenharmony_ci#warning The "vk_loader_platform.h" file must be modified for this OS.
6075db71995Sopenharmony_ci
6085db71995Sopenharmony_ci// NOTE: In order to support another OS, an #elif needs to be added (above the
6095db71995Sopenharmony_ci// "#else // defined(_WIN32)") for that OS, and OS-specific versions of the
6105db71995Sopenharmony_ci// contents of this file must be created.
6115db71995Sopenharmony_ci
6125db71995Sopenharmony_ci// NOTE: Other OS-specific changes are also needed for this OS.  Search for
6135db71995Sopenharmony_ci// files with "WIN32" in it, as a quick way to find files that must be changed.
6145db71995Sopenharmony_ci
6155db71995Sopenharmony_ci#endif  // defined(_WIN32)
616