15db71995Sopenharmony_ci/*
25db71995Sopenharmony_ci * Copyright (c) 2021-2023 The Khronos Group Inc.
35db71995Sopenharmony_ci * Copyright (c) 2021-2023 Valve Corporation
45db71995Sopenharmony_ci * Copyright (c) 2021-2023 LunarG, Inc.
55db71995Sopenharmony_ci *
65db71995Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
75db71995Sopenharmony_ci * of this software and/or associated documentation files (the "Materials"), to
85db71995Sopenharmony_ci * deal in the Materials without restriction, including without limitation the
95db71995Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
105db71995Sopenharmony_ci * sell copies of the Materials, and to permit persons to whom the Materials are
115db71995Sopenharmony_ci * furnished to do so, subject to the following conditions:
125db71995Sopenharmony_ci *
135db71995Sopenharmony_ci * The above copyright notice(s) and this permission notice shall be included in
145db71995Sopenharmony_ci * all copies or substantial portions of the Materials.
155db71995Sopenharmony_ci *
165db71995Sopenharmony_ci * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
175db71995Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
185db71995Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
195db71995Sopenharmony_ci *
205db71995Sopenharmony_ci * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
215db71995Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
225db71995Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
235db71995Sopenharmony_ci * USE OR OTHER DEALINGS IN THE MATERIALS.
245db71995Sopenharmony_ci *
255db71995Sopenharmony_ci * Author: Charles Giessen <charles@lunarg.com>
265db71995Sopenharmony_ci */
275db71995Sopenharmony_ci
285db71995Sopenharmony_ci/*
295db71995Sopenharmony_ci * Contains all the utilities needed to make the framework and tests work.
305db71995Sopenharmony_ci * Contains:
315db71995Sopenharmony_ci * All the standard library includes and main platform specific includes
325db71995Sopenharmony_ci * Dll export macro
335db71995Sopenharmony_ci * Manifest ICD & Layer structs
345db71995Sopenharmony_ci * path abstraction class - modelled after C++17's filesystem::path
355db71995Sopenharmony_ci * FolderManager - manages the contents of a folder, cleaning up when needed
365db71995Sopenharmony_ci * per-platform library loading - mirrors the vk_loader_platform
375db71995Sopenharmony_ci * LibraryWrapper - RAII wrapper for a library
385db71995Sopenharmony_ci * DispatchableHandle - RAII wrapper for vulkan dispatchable handle objects
395db71995Sopenharmony_ci * ostream overload for VkResult - prettifies googletest output
405db71995Sopenharmony_ci * Instance & Device create info helpers
415db71995Sopenharmony_ci * operator == overloads for many vulkan structs - more concise tests
425db71995Sopenharmony_ci */
435db71995Sopenharmony_ci#pragma once
445db71995Sopenharmony_ci
455db71995Sopenharmony_ci#include <algorithm>
465db71995Sopenharmony_ci#include <array>
475db71995Sopenharmony_ci#include <iostream>
485db71995Sopenharmony_ci#include <fstream>
495db71995Sopenharmony_ci#include <ostream>
505db71995Sopenharmony_ci#include <string>
515db71995Sopenharmony_ci#include <vector>
525db71995Sopenharmony_ci#include <unordered_map>
535db71995Sopenharmony_ci#include <utility>
545db71995Sopenharmony_ci#include <memory>
555db71995Sopenharmony_ci#include <functional>
565db71995Sopenharmony_ci
575db71995Sopenharmony_ci#include <cassert>
585db71995Sopenharmony_ci#include <cstring>
595db71995Sopenharmony_ci#include <ctime>
605db71995Sopenharmony_ci#include <inttypes.h>
615db71995Sopenharmony_ci#include <stdio.h>
625db71995Sopenharmony_ci#include <stdint.h>
635db71995Sopenharmony_ci
645db71995Sopenharmony_ci// Set of platforms with a common set of functionality which is queried throughout the program
655db71995Sopenharmony_ci#if defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__) || defined(__QNX__) || defined(__FreeBSD__) || \
665db71995Sopenharmony_ci    defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__GNU__)
675db71995Sopenharmony_ci#define COMMON_UNIX_PLATFORMS 1
685db71995Sopenharmony_ci#else
695db71995Sopenharmony_ci#define COMMON_UNIX_PLATFORMS 0
705db71995Sopenharmony_ci#endif
715db71995Sopenharmony_ci
725db71995Sopenharmony_ci#if defined(WIN32)
735db71995Sopenharmony_ci#include <direct.h>
745db71995Sopenharmony_ci#include <windows.h>
755db71995Sopenharmony_ci#include <strsafe.h>
765db71995Sopenharmony_ci#elif COMMON_UNIX_PLATFORMS
775db71995Sopenharmony_ci#include <dirent.h>
785db71995Sopenharmony_ci#include <sys/types.h>
795db71995Sopenharmony_ci#include <sys/stat.h>
805db71995Sopenharmony_ci#include <unistd.h>
815db71995Sopenharmony_ci#include <dlfcn.h>
825db71995Sopenharmony_ci
835db71995Sopenharmony_ci// Prevent macro collisions from <sys/types.h>
845db71995Sopenharmony_ci#undef major
855db71995Sopenharmony_ci#undef minor
865db71995Sopenharmony_ci
875db71995Sopenharmony_ci#endif
885db71995Sopenharmony_ci
895db71995Sopenharmony_ci#include <vulkan/vulkan.h>
905db71995Sopenharmony_ci#include <vulkan/vk_icd.h>
915db71995Sopenharmony_ci#include <vulkan/vk_layer.h>
925db71995Sopenharmony_ci
935db71995Sopenharmony_ci#include "framework_config.h"
945db71995Sopenharmony_ci
955db71995Sopenharmony_ci#if defined(__GNUC__) && __GNUC__ >= 4
965db71995Sopenharmony_ci#define FRAMEWORK_EXPORT __attribute__((visibility("default")))
975db71995Sopenharmony_ci#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
985db71995Sopenharmony_ci#define FRAMEWORK_EXPORT __attribute__((visibility("default")))
995db71995Sopenharmony_ci#elif defined(WIN32)
1005db71995Sopenharmony_ci#define FRAMEWORK_EXPORT __declspec(dllexport)
1015db71995Sopenharmony_ci#else
1025db71995Sopenharmony_ci#define FRAMEWORK_EXPORT
1035db71995Sopenharmony_ci#endif
1045db71995Sopenharmony_ci
1055db71995Sopenharmony_ci#include "json_writer.h"
1065db71995Sopenharmony_ci
1075db71995Sopenharmony_ci// get_env_var() - returns a std::string of `name`. if report_failure is true, then it will log to stderr that it didn't find the
1085db71995Sopenharmony_ci//     env-var
1095db71995Sopenharmony_ci// NOTE: This is only intended for test framework code, all test code MUST use EnvVarWrapper
1105db71995Sopenharmony_cistd::string get_env_var(std::string const& name, bool report_failure = true);
1115db71995Sopenharmony_ci
1125db71995Sopenharmony_ci/*
1135db71995Sopenharmony_ci * Wrapper around Environment Variables with common operations
1145db71995Sopenharmony_ci * Since Environment Variables leak between tests, there needs to be RAII code to remove them during test cleanup
1155db71995Sopenharmony_ci
1165db71995Sopenharmony_ci */
1175db71995Sopenharmony_ci
1185db71995Sopenharmony_ci// Wrapper to set & remove env-vars automatically
1195db71995Sopenharmony_cistruct EnvVarWrapper {
1205db71995Sopenharmony_ci    // Constructor which unsets the env-var
1215db71995Sopenharmony_ci    EnvVarWrapper(std::string const& name) noexcept : name(name) {
1225db71995Sopenharmony_ci        initial_value = get_env_var(name, false);
1235db71995Sopenharmony_ci        remove_env_var();
1245db71995Sopenharmony_ci    }
1255db71995Sopenharmony_ci    // Constructor which set the env-var to the specified value
1265db71995Sopenharmony_ci    EnvVarWrapper(std::string const& name, std::string const& value) noexcept : name(name), cur_value(value) {
1275db71995Sopenharmony_ci        initial_value = get_env_var(name, false);
1285db71995Sopenharmony_ci        set_env_var();
1295db71995Sopenharmony_ci    }
1305db71995Sopenharmony_ci    ~EnvVarWrapper() noexcept {
1315db71995Sopenharmony_ci        remove_env_var();
1325db71995Sopenharmony_ci        if (!initial_value.empty()) {
1335db71995Sopenharmony_ci            set_new_value(initial_value);
1345db71995Sopenharmony_ci        }
1355db71995Sopenharmony_ci    }
1365db71995Sopenharmony_ci
1375db71995Sopenharmony_ci    // delete copy operators
1385db71995Sopenharmony_ci    EnvVarWrapper(const EnvVarWrapper&) = delete;
1395db71995Sopenharmony_ci    EnvVarWrapper& operator=(const EnvVarWrapper&) = delete;
1405db71995Sopenharmony_ci
1415db71995Sopenharmony_ci    void set_new_value(std::string const& value) {
1425db71995Sopenharmony_ci        cur_value = value;
1435db71995Sopenharmony_ci        set_env_var();
1445db71995Sopenharmony_ci    }
1455db71995Sopenharmony_ci    void add_to_list(std::string const& list_item) {
1465db71995Sopenharmony_ci        if (!cur_value.empty()) {
1475db71995Sopenharmony_ci            cur_value += OS_ENV_VAR_LIST_SEPARATOR;
1485db71995Sopenharmony_ci        }
1495db71995Sopenharmony_ci        cur_value += list_item;
1505db71995Sopenharmony_ci        set_env_var();
1515db71995Sopenharmony_ci    }
1525db71995Sopenharmony_ci    void remove_value() const { remove_env_var(); }
1535db71995Sopenharmony_ci    const char* get() const { return name.c_str(); }
1545db71995Sopenharmony_ci    const char* value() const { return cur_value.c_str(); }
1555db71995Sopenharmony_ci
1565db71995Sopenharmony_ci   private:
1575db71995Sopenharmony_ci    std::string name;
1585db71995Sopenharmony_ci    std::string cur_value;
1595db71995Sopenharmony_ci    std::string initial_value;
1605db71995Sopenharmony_ci
1615db71995Sopenharmony_ci    void set_env_var();
1625db71995Sopenharmony_ci    void remove_env_var() const;
1635db71995Sopenharmony_ci#if defined(WIN32)
1645db71995Sopenharmony_ci    // Environment variable list separator - not for filesystem paths
1655db71995Sopenharmony_ci    const char OS_ENV_VAR_LIST_SEPARATOR = ';';
1665db71995Sopenharmony_ci#elif COMMON_UNIX_PLATFORMS
1675db71995Sopenharmony_ci    // Environment variable list separator - not for filesystem paths
1685db71995Sopenharmony_ci    const char OS_ENV_VAR_LIST_SEPARATOR = ':';
1695db71995Sopenharmony_ci#endif
1705db71995Sopenharmony_ci};
1715db71995Sopenharmony_ci
1725db71995Sopenharmony_ci// Windows specific error handling logic
1735db71995Sopenharmony_ci#if defined(WIN32)
1745db71995Sopenharmony_ciconst long ERROR_SETENV_FAILED = 10543;           // chosen at random, attempts to not conflict
1755db71995Sopenharmony_ciconst long ERROR_REMOVEDIRECTORY_FAILED = 10544;  // chosen at random, attempts to not conflict
1765db71995Sopenharmony_ciconst char* win_api_error_str(LSTATUS status);
1775db71995Sopenharmony_civoid print_error_message(LSTATUS status, const char* function_name, std::string optional_message = "");
1785db71995Sopenharmony_ci#endif
1795db71995Sopenharmony_ci
1805db71995Sopenharmony_cistruct ManifestICD;    // forward declaration for FolderManager::write
1815db71995Sopenharmony_cistruct ManifestLayer;  // forward declaration for FolderManager::write
1825db71995Sopenharmony_ci
1835db71995Sopenharmony_cinamespace fs {
1845db71995Sopenharmony_cistd::string make_native(std::string const&);
1855db71995Sopenharmony_ci
1865db71995Sopenharmony_cistruct path {
1875db71995Sopenharmony_ci#if defined(WIN32)
1885db71995Sopenharmony_ci    static const char path_separator = '\\';
1895db71995Sopenharmony_ci#elif COMMON_UNIX_PLATFORMS
1905db71995Sopenharmony_ci    static const char path_separator = '/';
1915db71995Sopenharmony_ci#endif
1925db71995Sopenharmony_ci
1935db71995Sopenharmony_ci   public:
1945db71995Sopenharmony_ci    path() {}
1955db71995Sopenharmony_ci    path(std::string const& in) : contents(make_native(in)) {}
1965db71995Sopenharmony_ci    path(const char* in) : contents(make_native(std::string(in))) {}
1975db71995Sopenharmony_ci
1985db71995Sopenharmony_ci    // concat paths without directoryseperator
1995db71995Sopenharmony_ci    path& operator+=(path const& in);
2005db71995Sopenharmony_ci    path& operator+=(std::string const& in);
2015db71995Sopenharmony_ci    path& operator+=(const char* in);
2025db71995Sopenharmony_ci
2035db71995Sopenharmony_ci    // append paths with directoryseperator
2045db71995Sopenharmony_ci    path& operator/=(path const& in);
2055db71995Sopenharmony_ci    path& operator/=(std::string const& in);
2065db71995Sopenharmony_ci    path& operator/=(const char* in);
2075db71995Sopenharmony_ci
2085db71995Sopenharmony_ci    // concat paths without directory seperator
2095db71995Sopenharmony_ci    path operator+(path const& in) const;
2105db71995Sopenharmony_ci    path operator+(std::string const& in) const;
2115db71995Sopenharmony_ci    path operator+(const char* in) const;
2125db71995Sopenharmony_ci
2135db71995Sopenharmony_ci    // append paths with directory seperator
2145db71995Sopenharmony_ci    path operator/(path const& in) const;
2155db71995Sopenharmony_ci    path operator/(std::string const& in) const;
2165db71995Sopenharmony_ci    path operator/(const char* in) const;
2175db71995Sopenharmony_ci
2185db71995Sopenharmony_ci    // accessors
2195db71995Sopenharmony_ci    path parent_path() const;      // Everything before the last path separator, if there is one.
2205db71995Sopenharmony_ci    bool has_parent_path() const;  // True if the path contains more than just a filename.
2215db71995Sopenharmony_ci    path filename() const;         // Everything after the last path separator.
2225db71995Sopenharmony_ci    path extension() const;        // The file extension, if it has one.
2235db71995Sopenharmony_ci    path stem() const;             // The filename minus the extension.
2245db71995Sopenharmony_ci
2255db71995Sopenharmony_ci    // modifiers
2265db71995Sopenharmony_ci    path& replace_filename(path const& replacement);
2275db71995Sopenharmony_ci
2285db71995Sopenharmony_ci    // get c style string
2295db71995Sopenharmony_ci    const char* c_str() const { return contents.c_str(); }
2305db71995Sopenharmony_ci    // get C++ style string
2315db71995Sopenharmony_ci    std::string const& str() const { return contents; }
2325db71995Sopenharmony_ci    std::string& str() { return contents; }
2335db71995Sopenharmony_ci    size_t size() const { return contents.size(); }
2345db71995Sopenharmony_ci
2355db71995Sopenharmony_ci    // equality
2365db71995Sopenharmony_ci    bool operator==(path const& other) const noexcept { return contents == other.contents; }
2375db71995Sopenharmony_ci    bool operator!=(path const& other) const noexcept { return !(*this == other); }
2385db71995Sopenharmony_ci
2395db71995Sopenharmony_ci   private:
2405db71995Sopenharmony_ci    std::string contents;
2415db71995Sopenharmony_ci};
2425db71995Sopenharmony_ci
2435db71995Sopenharmony_cistd::string fixup_backslashes_in_path(std::string const& in_path);
2445db71995Sopenharmony_cifs::path fixup_backslashes_in_path(fs::path const& in_path);
2455db71995Sopenharmony_ci
2465db71995Sopenharmony_ciint create_folder(path const& path);
2475db71995Sopenharmony_ciint delete_folder(path const& folder);
2485db71995Sopenharmony_ci
2495db71995Sopenharmony_ciclass FolderManager {
2505db71995Sopenharmony_ci   public:
2515db71995Sopenharmony_ci    explicit FolderManager(path root_path, std::string name) noexcept;
2525db71995Sopenharmony_ci    ~FolderManager() noexcept;
2535db71995Sopenharmony_ci    FolderManager(FolderManager const&) = delete;
2545db71995Sopenharmony_ci    FolderManager& operator=(FolderManager const&) = delete;
2555db71995Sopenharmony_ci    FolderManager(FolderManager&& other) noexcept;
2565db71995Sopenharmony_ci    FolderManager& operator=(FolderManager&& other) noexcept;
2575db71995Sopenharmony_ci
2585db71995Sopenharmony_ci    // Add a manifest to the folder
2595db71995Sopenharmony_ci    path write_manifest(std::string const& name, std::string const& contents);
2605db71995Sopenharmony_ci
2615db71995Sopenharmony_ci    // Add an already existing file to the manager, so it will be cleaned up automatically
2625db71995Sopenharmony_ci    void add_existing_file(std::string const& file_name);
2635db71995Sopenharmony_ci
2645db71995Sopenharmony_ci    // close file handle, delete file, remove `name` from managed file list.
2655db71995Sopenharmony_ci    void remove(std::string const& name);
2665db71995Sopenharmony_ci
2675db71995Sopenharmony_ci    // copy file into this folder with name `new_name`. Returns the full path of the file that was copied
2685db71995Sopenharmony_ci    path copy_file(path const& file, std::string const& new_name);
2695db71995Sopenharmony_ci
2705db71995Sopenharmony_ci    // location of the managed folder
2715db71995Sopenharmony_ci    path location() const { return folder; }
2725db71995Sopenharmony_ci
2735db71995Sopenharmony_ci    std::vector<std::string> get_files() const { return files; }
2745db71995Sopenharmony_ci
2755db71995Sopenharmony_ci   private:
2765db71995Sopenharmony_ci    path folder;
2775db71995Sopenharmony_ci    std::vector<std::string> files;
2785db71995Sopenharmony_ci};
2795db71995Sopenharmony_ci}  // namespace fs
2805db71995Sopenharmony_ci
2815db71995Sopenharmony_ci// copy the contents of a std::string into a char array and add a null terminator at the end
2825db71995Sopenharmony_ci// src - std::string to read from
2835db71995Sopenharmony_ci// dst - char array to write to
2845db71995Sopenharmony_ci// size_dst - number of characters in the dst array
2855db71995Sopenharmony_ciinline void copy_string_to_char_array(std::string const& src, char* dst, size_t size_dst) { dst[src.copy(dst, size_dst - 1)] = 0; }
2865db71995Sopenharmony_ci
2875db71995Sopenharmony_ci#if defined(WIN32)
2885db71995Sopenharmony_ci// Convert an UTF-16 wstring to an UTF-8 string
2895db71995Sopenharmony_cistd::string narrow(const std::wstring& utf16);
2905db71995Sopenharmony_ci// Convert an UTF-8 string to an UTF-16 wstring
2915db71995Sopenharmony_cistd::wstring widen(const std::string& utf8);
2925db71995Sopenharmony_ci#endif
2935db71995Sopenharmony_ci
2945db71995Sopenharmony_ci#if defined(WIN32)
2955db71995Sopenharmony_citypedef HMODULE loader_platform_dl_handle;
2965db71995Sopenharmony_ciinline loader_platform_dl_handle loader_platform_open_library(const char* lib_path) {
2975db71995Sopenharmony_ci    std::wstring lib_path_utf16 = widen(lib_path);
2985db71995Sopenharmony_ci    // Try loading the library the original way first.
2995db71995Sopenharmony_ci    loader_platform_dl_handle lib_handle = LoadLibraryW(lib_path_utf16.c_str());
3005db71995Sopenharmony_ci    if (lib_handle == nullptr && GetLastError() == ERROR_MOD_NOT_FOUND) {
3015db71995Sopenharmony_ci        // If that failed, then try loading it with broader search folders.
3025db71995Sopenharmony_ci        lib_handle =
3035db71995Sopenharmony_ci            LoadLibraryExW(lib_path_utf16.c_str(), nullptr, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
3045db71995Sopenharmony_ci    }
3055db71995Sopenharmony_ci    return lib_handle;
3065db71995Sopenharmony_ci}
3075db71995Sopenharmony_ciinline char* loader_platform_open_library_error(const char* libPath) {
3085db71995Sopenharmony_ci    static char errorMsg[164];
3095db71995Sopenharmony_ci    snprintf(errorMsg, 163, "Failed to open dynamic library \"%s\" with error %lu", libPath, GetLastError());
3105db71995Sopenharmony_ci    return errorMsg;
3115db71995Sopenharmony_ci}
3125db71995Sopenharmony_ciinline void loader_platform_close_library(loader_platform_dl_handle library) { FreeLibrary(library); }
3135db71995Sopenharmony_ciinline void* loader_platform_get_proc_address(loader_platform_dl_handle library, const char* name) {
3145db71995Sopenharmony_ci    assert(library);
3155db71995Sopenharmony_ci    assert(name);
3165db71995Sopenharmony_ci    return reinterpret_cast<void*>(GetProcAddress(library, name));
3175db71995Sopenharmony_ci}
3185db71995Sopenharmony_ciinline char* loader_platform_get_proc_address_error(const char* name) {
3195db71995Sopenharmony_ci    static char errorMsg[120];
3205db71995Sopenharmony_ci    snprintf(errorMsg, 119, "Failed to find function \"%s\" in dynamic library", name);
3215db71995Sopenharmony_ci    return errorMsg;
3225db71995Sopenharmony_ci}
3235db71995Sopenharmony_ci
3245db71995Sopenharmony_ci#elif COMMON_UNIX_PLATFORMS
3255db71995Sopenharmony_ci
3265db71995Sopenharmony_citypedef void* loader_platform_dl_handle;
3275db71995Sopenharmony_ciinline loader_platform_dl_handle loader_platform_open_library(const char* libPath) {
3285db71995Sopenharmony_ci    return dlopen(libPath, RTLD_LAZY | RTLD_LOCAL);
3295db71995Sopenharmony_ci}
3305db71995Sopenharmony_ciinline const char* loader_platform_open_library_error([[maybe_unused]] const char* libPath) { return dlerror(); }
3315db71995Sopenharmony_ciinline void loader_platform_close_library(loader_platform_dl_handle library) { dlclose(library); }
3325db71995Sopenharmony_ciinline void* loader_platform_get_proc_address(loader_platform_dl_handle library, const char* name) {
3335db71995Sopenharmony_ci    assert(library);
3345db71995Sopenharmony_ci    assert(name);
3355db71995Sopenharmony_ci    return dlsym(library, name);
3365db71995Sopenharmony_ci}
3375db71995Sopenharmony_ciinline const char* loader_platform_get_proc_address_error([[maybe_unused]] const char* name) { return dlerror(); }
3385db71995Sopenharmony_ci#endif
3395db71995Sopenharmony_ci
3405db71995Sopenharmony_ciclass FromVoidStarFunc {
3415db71995Sopenharmony_ci   private:
3425db71995Sopenharmony_ci    void* function;
3435db71995Sopenharmony_ci
3445db71995Sopenharmony_ci   public:
3455db71995Sopenharmony_ci    FromVoidStarFunc(void* function) : function(function) {}
3465db71995Sopenharmony_ci    FromVoidStarFunc(PFN_vkVoidFunction function) : function(reinterpret_cast<void*>(function)) {}
3475db71995Sopenharmony_ci
3485db71995Sopenharmony_ci    template <typename T>
3495db71995Sopenharmony_ci    operator T() {
3505db71995Sopenharmony_ci        return reinterpret_cast<T>(function);
3515db71995Sopenharmony_ci    }
3525db71995Sopenharmony_ci};
3535db71995Sopenharmony_ci
3545db71995Sopenharmony_cistruct LibraryWrapper {
3555db71995Sopenharmony_ci    explicit LibraryWrapper() noexcept {}
3565db71995Sopenharmony_ci    explicit LibraryWrapper(fs::path const& lib_path) noexcept : lib_path(lib_path) {
3575db71995Sopenharmony_ci        lib_handle = loader_platform_open_library(lib_path.c_str());
3585db71995Sopenharmony_ci        if (lib_handle == nullptr) {
3595db71995Sopenharmony_ci            fprintf(stderr, "Unable to open library %s: %s\n", lib_path.c_str(),
3605db71995Sopenharmony_ci                    loader_platform_open_library_error(lib_path.c_str()));
3615db71995Sopenharmony_ci            assert(lib_handle != nullptr && "Must be able to open library");
3625db71995Sopenharmony_ci        }
3635db71995Sopenharmony_ci    }
3645db71995Sopenharmony_ci    ~LibraryWrapper() noexcept {
3655db71995Sopenharmony_ci        if (lib_handle != nullptr) {
3665db71995Sopenharmony_ci            loader_platform_close_library(lib_handle);
3675db71995Sopenharmony_ci            lib_handle = nullptr;
3685db71995Sopenharmony_ci        }
3695db71995Sopenharmony_ci    }
3705db71995Sopenharmony_ci    LibraryWrapper(LibraryWrapper const& wrapper) = delete;
3715db71995Sopenharmony_ci    LibraryWrapper& operator=(LibraryWrapper const& wrapper) = delete;
3725db71995Sopenharmony_ci    LibraryWrapper(LibraryWrapper&& wrapper) noexcept : lib_handle(wrapper.lib_handle), lib_path(wrapper.lib_path) {
3735db71995Sopenharmony_ci        wrapper.lib_handle = nullptr;
3745db71995Sopenharmony_ci    }
3755db71995Sopenharmony_ci    LibraryWrapper& operator=(LibraryWrapper&& wrapper) noexcept {
3765db71995Sopenharmony_ci        if (this != &wrapper) {
3775db71995Sopenharmony_ci            if (lib_handle != nullptr) {
3785db71995Sopenharmony_ci                loader_platform_close_library(lib_handle);
3795db71995Sopenharmony_ci            }
3805db71995Sopenharmony_ci            lib_handle = wrapper.lib_handle;
3815db71995Sopenharmony_ci            lib_path = wrapper.lib_path;
3825db71995Sopenharmony_ci            wrapper.lib_handle = nullptr;
3835db71995Sopenharmony_ci        }
3845db71995Sopenharmony_ci        return *this;
3855db71995Sopenharmony_ci    }
3865db71995Sopenharmony_ci    FromVoidStarFunc get_symbol(const char* symbol_name) const {
3875db71995Sopenharmony_ci        assert(lib_handle != nullptr && "Cannot get symbol with null library handle");
3885db71995Sopenharmony_ci        void* symbol = loader_platform_get_proc_address(lib_handle, symbol_name);
3895db71995Sopenharmony_ci        if (symbol == nullptr) {
3905db71995Sopenharmony_ci            fprintf(stderr, "Unable to open symbol %s: %s\n", symbol_name, loader_platform_get_proc_address_error(symbol_name));
3915db71995Sopenharmony_ci            assert(symbol != nullptr && "Must be able to get symbol");
3925db71995Sopenharmony_ci        }
3935db71995Sopenharmony_ci        return FromVoidStarFunc(symbol);
3945db71995Sopenharmony_ci    }
3955db71995Sopenharmony_ci
3965db71995Sopenharmony_ci    explicit operator bool() const noexcept { return lib_handle != nullptr; }
3975db71995Sopenharmony_ci
3985db71995Sopenharmony_ci    loader_platform_dl_handle lib_handle = nullptr;
3995db71995Sopenharmony_ci    fs::path lib_path;
4005db71995Sopenharmony_ci};
4015db71995Sopenharmony_ci
4025db71995Sopenharmony_citemplate <typename T>
4035db71995Sopenharmony_ciPFN_vkVoidFunction to_vkVoidFunction(T func) {
4045db71995Sopenharmony_ci    return reinterpret_cast<PFN_vkVoidFunction>(func);
4055db71995Sopenharmony_ci}
4065db71995Sopenharmony_citemplate <typename T>
4075db71995Sopenharmony_cistruct FRAMEWORK_EXPORT DispatchableHandle {
4085db71995Sopenharmony_ci    DispatchableHandle() {
4095db71995Sopenharmony_ci        auto ptr_handle = new VK_LOADER_DATA;
4105db71995Sopenharmony_ci        set_loader_magic_value(ptr_handle);
4115db71995Sopenharmony_ci        handle = reinterpret_cast<T>(ptr_handle);
4125db71995Sopenharmony_ci    }
4135db71995Sopenharmony_ci    ~DispatchableHandle() {
4145db71995Sopenharmony_ci        delete reinterpret_cast<VK_LOADER_DATA*>(handle);
4155db71995Sopenharmony_ci        handle = nullptr;
4165db71995Sopenharmony_ci    }
4175db71995Sopenharmony_ci    DispatchableHandle(DispatchableHandle const&) = delete;
4185db71995Sopenharmony_ci    DispatchableHandle& operator=(DispatchableHandle const&) = delete;
4195db71995Sopenharmony_ci    DispatchableHandle(DispatchableHandle&& other) noexcept : handle(other.handle) { other.handle = nullptr; }
4205db71995Sopenharmony_ci    DispatchableHandle& operator=(DispatchableHandle&& other) noexcept {
4215db71995Sopenharmony_ci        if (this != &other) {
4225db71995Sopenharmony_ci            delete reinterpret_cast<VK_LOADER_DATA*>(handle);
4235db71995Sopenharmony_ci            handle = other.handle;
4245db71995Sopenharmony_ci            other.handle = nullptr;
4255db71995Sopenharmony_ci        }
4265db71995Sopenharmony_ci        return *this;
4275db71995Sopenharmony_ci    }
4285db71995Sopenharmony_ci    bool operator==(T base_handle) { return base_handle == handle; }
4295db71995Sopenharmony_ci    bool operator!=(T base_handle) { return base_handle != handle; }
4305db71995Sopenharmony_ci
4315db71995Sopenharmony_ci    T handle = nullptr;
4325db71995Sopenharmony_ci};
4335db71995Sopenharmony_ci
4345db71995Sopenharmony_ci// Stream operator for VkResult so GTEST will print out error codes as strings (automatically)
4355db71995Sopenharmony_ciinline std::ostream& operator<<(std::ostream& os, const VkResult& result) {
4365db71995Sopenharmony_ci    switch (result) {
4375db71995Sopenharmony_ci        case (VK_SUCCESS):
4385db71995Sopenharmony_ci            return os << "VK_SUCCESS";
4395db71995Sopenharmony_ci        case (VK_NOT_READY):
4405db71995Sopenharmony_ci            return os << "VK_NOT_READY";
4415db71995Sopenharmony_ci        case (VK_TIMEOUT):
4425db71995Sopenharmony_ci            return os << "VK_TIMEOUT";
4435db71995Sopenharmony_ci        case (VK_EVENT_SET):
4445db71995Sopenharmony_ci            return os << "VK_EVENT_SET";
4455db71995Sopenharmony_ci        case (VK_EVENT_RESET):
4465db71995Sopenharmony_ci            return os << "VK_EVENT_RESET";
4475db71995Sopenharmony_ci        case (VK_INCOMPLETE):
4485db71995Sopenharmony_ci            return os << "VK_INCOMPLETE";
4495db71995Sopenharmony_ci        case (VK_ERROR_OUT_OF_HOST_MEMORY):
4505db71995Sopenharmony_ci            return os << "VK_ERROR_OUT_OF_HOST_MEMORY";
4515db71995Sopenharmony_ci        case (VK_ERROR_OUT_OF_DEVICE_MEMORY):
4525db71995Sopenharmony_ci            return os << "VK_ERROR_OUT_OF_DEVICE_MEMORY";
4535db71995Sopenharmony_ci        case (VK_ERROR_INITIALIZATION_FAILED):
4545db71995Sopenharmony_ci            return os << "VK_ERROR_INITIALIZATION_FAILED";
4555db71995Sopenharmony_ci        case (VK_ERROR_DEVICE_LOST):
4565db71995Sopenharmony_ci            return os << "VK_ERROR_DEVICE_LOST";
4575db71995Sopenharmony_ci        case (VK_ERROR_MEMORY_MAP_FAILED):
4585db71995Sopenharmony_ci            return os << "VK_ERROR_MEMORY_MAP_FAILED";
4595db71995Sopenharmony_ci        case (VK_ERROR_LAYER_NOT_PRESENT):
4605db71995Sopenharmony_ci            return os << "VK_ERROR_LAYER_NOT_PRESENT";
4615db71995Sopenharmony_ci        case (VK_ERROR_EXTENSION_NOT_PRESENT):
4625db71995Sopenharmony_ci            return os << "VK_ERROR_EXTENSION_NOT_PRESENT";
4635db71995Sopenharmony_ci        case (VK_ERROR_FEATURE_NOT_PRESENT):
4645db71995Sopenharmony_ci            return os << "VK_ERROR_FEATURE_NOT_PRESENT";
4655db71995Sopenharmony_ci        case (VK_ERROR_INCOMPATIBLE_DRIVER):
4665db71995Sopenharmony_ci            return os << "VK_ERROR_INCOMPATIBLE_DRIVER";
4675db71995Sopenharmony_ci        case (VK_ERROR_TOO_MANY_OBJECTS):
4685db71995Sopenharmony_ci            return os << "VK_ERROR_TOO_MANY_OBJECTS";
4695db71995Sopenharmony_ci        case (VK_ERROR_FORMAT_NOT_SUPPORTED):
4705db71995Sopenharmony_ci            return os << "VK_ERROR_FORMAT_NOT_SUPPORTED";
4715db71995Sopenharmony_ci        case (VK_ERROR_FRAGMENTED_POOL):
4725db71995Sopenharmony_ci            return os << "VK_ERROR_FRAGMENTED_POOL";
4735db71995Sopenharmony_ci        case (VK_ERROR_UNKNOWN):
4745db71995Sopenharmony_ci            return os << "VK_ERROR_UNKNOWN";
4755db71995Sopenharmony_ci        case (VK_ERROR_OUT_OF_POOL_MEMORY):
4765db71995Sopenharmony_ci            return os << "VK_ERROR_OUT_OF_POOL_MEMORY";
4775db71995Sopenharmony_ci        case (VK_ERROR_INVALID_EXTERNAL_HANDLE):
4785db71995Sopenharmony_ci            return os << "VK_ERROR_INVALID_EXTERNAL_HANDLE";
4795db71995Sopenharmony_ci        case (VK_ERROR_FRAGMENTATION):
4805db71995Sopenharmony_ci            return os << "VK_ERROR_FRAGMENTATION";
4815db71995Sopenharmony_ci        case (VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS):
4825db71995Sopenharmony_ci            return os << "VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS";
4835db71995Sopenharmony_ci        case (VK_ERROR_SURFACE_LOST_KHR):
4845db71995Sopenharmony_ci            return os << "VK_ERROR_SURFACE_LOST_KHR";
4855db71995Sopenharmony_ci        case (VK_ERROR_NATIVE_WINDOW_IN_USE_KHR):
4865db71995Sopenharmony_ci            return os << "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";
4875db71995Sopenharmony_ci        case (VK_SUBOPTIMAL_KHR):
4885db71995Sopenharmony_ci            return os << "VK_SUBOPTIMAL_KHR";
4895db71995Sopenharmony_ci        case (VK_ERROR_OUT_OF_DATE_KHR):
4905db71995Sopenharmony_ci            return os << "VK_ERROR_OUT_OF_DATE_KHR";
4915db71995Sopenharmony_ci        case (VK_ERROR_INCOMPATIBLE_DISPLAY_KHR):
4925db71995Sopenharmony_ci            return os << "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";
4935db71995Sopenharmony_ci        case (VK_ERROR_VALIDATION_FAILED_EXT):
4945db71995Sopenharmony_ci            return os << "VK_ERROR_VALIDATION_FAILED_EXT";
4955db71995Sopenharmony_ci        case (VK_ERROR_INVALID_SHADER_NV):
4965db71995Sopenharmony_ci            return os << "VK_ERROR_INVALID_SHADER_NV";
4975db71995Sopenharmony_ci        case (VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT):
4985db71995Sopenharmony_ci            return os << "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT";
4995db71995Sopenharmony_ci        case (VK_ERROR_NOT_PERMITTED_EXT):
5005db71995Sopenharmony_ci            return os << "VK_ERROR_NOT_PERMITTED_EXT";
5015db71995Sopenharmony_ci        case (VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT):
5025db71995Sopenharmony_ci            return os << "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT";
5035db71995Sopenharmony_ci        case (VK_THREAD_IDLE_KHR):
5045db71995Sopenharmony_ci            return os << "VK_THREAD_IDLE_KHR";
5055db71995Sopenharmony_ci        case (VK_THREAD_DONE_KHR):
5065db71995Sopenharmony_ci            return os << "VK_THREAD_DONE_KHR";
5075db71995Sopenharmony_ci        case (VK_OPERATION_DEFERRED_KHR):
5085db71995Sopenharmony_ci            return os << "VK_OPERATION_DEFERRED_KHR";
5095db71995Sopenharmony_ci        case (VK_OPERATION_NOT_DEFERRED_KHR):
5105db71995Sopenharmony_ci            return os << "VK_OPERATION_NOT_DEFERRED_KHR";
5115db71995Sopenharmony_ci        case (VK_PIPELINE_COMPILE_REQUIRED_EXT):
5125db71995Sopenharmony_ci            return os << "VK_PIPELINE_COMPILE_REQUIRED_EXT";
5135db71995Sopenharmony_ci        case (VK_RESULT_MAX_ENUM):
5145db71995Sopenharmony_ci            return os << "VK_RESULT_MAX_ENUM";
5155db71995Sopenharmony_ci        case (VK_ERROR_COMPRESSION_EXHAUSTED_EXT):
5165db71995Sopenharmony_ci            return os << "VK_ERROR_COMPRESSION_EXHAUSTED_EXT";
5175db71995Sopenharmony_ci        case (VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR):
5185db71995Sopenharmony_ci            return os << "VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR";
5195db71995Sopenharmony_ci        case (VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR):
5205db71995Sopenharmony_ci            return os << "VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR";
5215db71995Sopenharmony_ci        case (VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR):
5225db71995Sopenharmony_ci            return os << "VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR";
5235db71995Sopenharmony_ci        case (VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR):
5245db71995Sopenharmony_ci            return os << "VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR";
5255db71995Sopenharmony_ci        case (VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR):
5265db71995Sopenharmony_ci            return os << "VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR";
5275db71995Sopenharmony_ci        case (VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR):
5285db71995Sopenharmony_ci            return os << "VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR";
5295db71995Sopenharmony_ci        case (VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR):
5305db71995Sopenharmony_ci            return os << "VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR";
5315db71995Sopenharmony_ci        case (VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT):
5325db71995Sopenharmony_ci            return os << "VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT";
5335db71995Sopenharmony_ci    }
5345db71995Sopenharmony_ci    return os << static_cast<int32_t>(result);
5355db71995Sopenharmony_ci}
5365db71995Sopenharmony_ci
5375db71995Sopenharmony_ciconst char* get_platform_wsi_extension([[maybe_unused]] const char* api_selection);
5385db71995Sopenharmony_ci
5395db71995Sopenharmony_cibool string_eq(const char* a, const char* b) noexcept;
5405db71995Sopenharmony_cibool string_eq(const char* a, const char* b, size_t len) noexcept;
5415db71995Sopenharmony_ci
5425db71995Sopenharmony_ciinline std::string version_to_string(uint32_t version) {
5435db71995Sopenharmony_ci    std::string out = std::to_string(VK_API_VERSION_MAJOR(version)) + "." + std::to_string(VK_API_VERSION_MINOR(version)) + "." +
5445db71995Sopenharmony_ci                      std::to_string(VK_API_VERSION_PATCH(version));
5455db71995Sopenharmony_ci    if (VK_API_VERSION_VARIANT(version) != 0) out += std::to_string(VK_API_VERSION_VARIANT(version)) + "." + out;
5465db71995Sopenharmony_ci    return out;
5475db71995Sopenharmony_ci}
5485db71995Sopenharmony_ci
5495db71995Sopenharmony_ci// Macro to ease the definition of variables with builder member functions
5505db71995Sopenharmony_ci// class_name = class the member variable is apart of
5515db71995Sopenharmony_ci// type = type of the variable
5525db71995Sopenharmony_ci// name = name of the variable
5535db71995Sopenharmony_ci// default_value = value to default initialize, use {} if nothing else makes sense
5545db71995Sopenharmony_ci#define BUILDER_VALUE(class_name, type, name, default_value) \
5555db71995Sopenharmony_ci    type name = default_value;                               \
5565db71995Sopenharmony_ci    class_name& set_##name(type const& name) {               \
5575db71995Sopenharmony_ci        this->name = name;                                   \
5585db71995Sopenharmony_ci        return *this;                                        \
5595db71995Sopenharmony_ci    }
5605db71995Sopenharmony_ci
5615db71995Sopenharmony_ci// Macro to ease the definition of vectors with builder member functions
5625db71995Sopenharmony_ci// class_name = class the member variable is apart of
5635db71995Sopenharmony_ci// type = type of the variable
5645db71995Sopenharmony_ci// name = name of the variable
5655db71995Sopenharmony_ci// singular_name = used for the `add_singular_name` member function
5665db71995Sopenharmony_ci#define BUILDER_VECTOR(class_name, type, name, singular_name)                    \
5675db71995Sopenharmony_ci    std::vector<type> name;                                                      \
5685db71995Sopenharmony_ci    class_name& add_##singular_name(type const& singular_name) {                 \
5695db71995Sopenharmony_ci        this->name.push_back(singular_name);                                     \
5705db71995Sopenharmony_ci        return *this;                                                            \
5715db71995Sopenharmony_ci    }                                                                            \
5725db71995Sopenharmony_ci    class_name& add_##singular_name##s(std::vector<type> const& singular_name) { \
5735db71995Sopenharmony_ci        for (auto& elem : singular_name) this->name.push_back(elem);             \
5745db71995Sopenharmony_ci        return *this;                                                            \
5755db71995Sopenharmony_ci    }
5765db71995Sopenharmony_ci// Like BUILDER_VECTOR but for move only types - where passing in means giving up ownership
5775db71995Sopenharmony_ci#define BUILDER_VECTOR_MOVE_ONLY(class_name, type, name, singular_name) \
5785db71995Sopenharmony_ci    std::vector<type> name;                                             \
5795db71995Sopenharmony_ci    class_name& add_##singular_name(type&& singular_name) {             \
5805db71995Sopenharmony_ci        this->name.push_back(std::move(singular_name));                 \
5815db71995Sopenharmony_ci        return *this;                                                   \
5825db71995Sopenharmony_ci    }
5835db71995Sopenharmony_ci
5845db71995Sopenharmony_cistruct ManifestVersion {
5855db71995Sopenharmony_ci    BUILDER_VALUE(ManifestVersion, uint32_t, major, 1)
5865db71995Sopenharmony_ci    BUILDER_VALUE(ManifestVersion, uint32_t, minor, 0)
5875db71995Sopenharmony_ci    BUILDER_VALUE(ManifestVersion, uint32_t, patch, 0)
5885db71995Sopenharmony_ci
5895db71995Sopenharmony_ci    std::string get_version_str() const noexcept {
5905db71995Sopenharmony_ci        return std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(patch);
5915db71995Sopenharmony_ci    }
5925db71995Sopenharmony_ci};
5935db71995Sopenharmony_ci
5945db71995Sopenharmony_ci// ManifestICD builder
5955db71995Sopenharmony_cistruct ManifestICD {
5965db71995Sopenharmony_ci    BUILDER_VALUE(ManifestICD, ManifestVersion, file_format_version, {})
5975db71995Sopenharmony_ci    BUILDER_VALUE(ManifestICD, uint32_t, api_version, 0)
5985db71995Sopenharmony_ci    BUILDER_VALUE(ManifestICD, fs::path, lib_path, {})
5995db71995Sopenharmony_ci    BUILDER_VALUE(ManifestICD, bool, is_portability_driver, false)
6005db71995Sopenharmony_ci    BUILDER_VALUE(ManifestICD, std::string, library_arch, "")
6015db71995Sopenharmony_ci    std::string get_manifest_str() const;
6025db71995Sopenharmony_ci};
6035db71995Sopenharmony_ci
6045db71995Sopenharmony_ci// ManifestLayer builder
6055db71995Sopenharmony_cistruct ManifestLayer {
6065db71995Sopenharmony_ci    struct LayerDescription {
6075db71995Sopenharmony_ci        enum class Type { INSTANCE, GLOBAL, DEVICE };
6085db71995Sopenharmony_ci        std::string get_type_str(Type layer_type) const {
6095db71995Sopenharmony_ci            if (layer_type == Type::GLOBAL)
6105db71995Sopenharmony_ci                return "GLOBAL";
6115db71995Sopenharmony_ci            else if (layer_type == Type::DEVICE)
6125db71995Sopenharmony_ci                return "DEVICE";
6135db71995Sopenharmony_ci            else  // default
6145db71995Sopenharmony_ci                return "INSTANCE";
6155db71995Sopenharmony_ci        }
6165db71995Sopenharmony_ci        struct FunctionOverride {
6175db71995Sopenharmony_ci            BUILDER_VALUE(FunctionOverride, std::string, vk_func, {})
6185db71995Sopenharmony_ci            BUILDER_VALUE(FunctionOverride, std::string, override_name, {})
6195db71995Sopenharmony_ci
6205db71995Sopenharmony_ci            void get_manifest_str(JsonWriter& writer) const { writer.AddKeyedString(vk_func, override_name); }
6215db71995Sopenharmony_ci        };
6225db71995Sopenharmony_ci        struct Extension {
6235db71995Sopenharmony_ci            Extension() noexcept {}
6245db71995Sopenharmony_ci            Extension(std::string name, uint32_t spec_version = 0, std::vector<std::string> entrypoints = {}) noexcept
6255db71995Sopenharmony_ci                : name(name), spec_version(spec_version), entrypoints(entrypoints) {}
6265db71995Sopenharmony_ci            std::string name;
6275db71995Sopenharmony_ci            uint32_t spec_version = 0;
6285db71995Sopenharmony_ci            std::vector<std::string> entrypoints;
6295db71995Sopenharmony_ci            void get_manifest_str(JsonWriter& writer) const;
6305db71995Sopenharmony_ci        };
6315db71995Sopenharmony_ci        BUILDER_VALUE(LayerDescription, std::string, name, {})
6325db71995Sopenharmony_ci        BUILDER_VALUE(LayerDescription, Type, type, Type::INSTANCE)
6335db71995Sopenharmony_ci        BUILDER_VALUE(LayerDescription, fs::path, lib_path, {})
6345db71995Sopenharmony_ci        BUILDER_VALUE(LayerDescription, uint32_t, api_version, VK_API_VERSION_1_0)
6355db71995Sopenharmony_ci        BUILDER_VALUE(LayerDescription, uint32_t, implementation_version, 0)
6365db71995Sopenharmony_ci        BUILDER_VALUE(LayerDescription, std::string, description, {})
6375db71995Sopenharmony_ci        BUILDER_VECTOR(LayerDescription, FunctionOverride, functions, function)
6385db71995Sopenharmony_ci        BUILDER_VECTOR(LayerDescription, Extension, instance_extensions, instance_extension)
6395db71995Sopenharmony_ci        BUILDER_VECTOR(LayerDescription, Extension, device_extensions, device_extension)
6405db71995Sopenharmony_ci        BUILDER_VALUE(LayerDescription, std::string, enable_environment, {})
6415db71995Sopenharmony_ci        BUILDER_VALUE(LayerDescription, std::string, disable_environment, {})
6425db71995Sopenharmony_ci        BUILDER_VECTOR(LayerDescription, std::string, component_layers, component_layer)
6435db71995Sopenharmony_ci        BUILDER_VECTOR(LayerDescription, std::string, blacklisted_layers, blacklisted_layer)
6445db71995Sopenharmony_ci        BUILDER_VECTOR(LayerDescription, std::string, override_paths, override_path)
6455db71995Sopenharmony_ci        BUILDER_VECTOR(LayerDescription, FunctionOverride, pre_instance_functions, pre_instance_function)
6465db71995Sopenharmony_ci        BUILDER_VECTOR(LayerDescription, std::string, app_keys, app_key)
6475db71995Sopenharmony_ci        BUILDER_VALUE(LayerDescription, std::string, library_arch, "")
6485db71995Sopenharmony_ci
6495db71995Sopenharmony_ci        void get_manifest_str(JsonWriter& writer) const;
6505db71995Sopenharmony_ci        VkLayerProperties get_layer_properties() const;
6515db71995Sopenharmony_ci    };
6525db71995Sopenharmony_ci    BUILDER_VALUE(ManifestLayer, ManifestVersion, file_format_version, {})
6535db71995Sopenharmony_ci    BUILDER_VECTOR(ManifestLayer, LayerDescription, layers, layer)
6545db71995Sopenharmony_ci
6555db71995Sopenharmony_ci    std::string get_manifest_str() const;
6565db71995Sopenharmony_ci};
6575db71995Sopenharmony_ci
6585db71995Sopenharmony_cistruct Extension {
6595db71995Sopenharmony_ci    BUILDER_VALUE(Extension, std::string, extensionName, {})
6605db71995Sopenharmony_ci    BUILDER_VALUE(Extension, uint32_t, specVersion, VK_API_VERSION_1_0)
6615db71995Sopenharmony_ci
6625db71995Sopenharmony_ci    Extension(const char* name, uint32_t specVersion = VK_API_VERSION_1_0) noexcept
6635db71995Sopenharmony_ci        : extensionName(name), specVersion(specVersion) {}
6645db71995Sopenharmony_ci    Extension(std::string extensionName, uint32_t specVersion = VK_API_VERSION_1_0) noexcept
6655db71995Sopenharmony_ci        : extensionName(extensionName), specVersion(specVersion) {}
6665db71995Sopenharmony_ci
6675db71995Sopenharmony_ci    VkExtensionProperties get() const noexcept {
6685db71995Sopenharmony_ci        VkExtensionProperties props{};
6695db71995Sopenharmony_ci        copy_string_to_char_array(extensionName, &props.extensionName[0], VK_MAX_EXTENSION_NAME_SIZE);
6705db71995Sopenharmony_ci        props.specVersion = specVersion;
6715db71995Sopenharmony_ci        return props;
6725db71995Sopenharmony_ci    }
6735db71995Sopenharmony_ci};
6745db71995Sopenharmony_ci
6755db71995Sopenharmony_cistruct MockQueueFamilyProperties {
6765db71995Sopenharmony_ci    BUILDER_VALUE(MockQueueFamilyProperties, VkQueueFamilyProperties, properties, {})
6775db71995Sopenharmony_ci    BUILDER_VALUE(MockQueueFamilyProperties, bool, support_present, false)
6785db71995Sopenharmony_ci
6795db71995Sopenharmony_ci    VkQueueFamilyProperties get() const noexcept { return properties; }
6805db71995Sopenharmony_ci};
6815db71995Sopenharmony_ci
6825db71995Sopenharmony_cistruct InstanceCreateInfo {
6835db71995Sopenharmony_ci    BUILDER_VALUE(InstanceCreateInfo, VkInstanceCreateInfo, instance_info, {})
6845db71995Sopenharmony_ci    BUILDER_VALUE(InstanceCreateInfo, VkApplicationInfo, application_info, {})
6855db71995Sopenharmony_ci    BUILDER_VALUE(InstanceCreateInfo, std::string, app_name, {})
6865db71995Sopenharmony_ci    BUILDER_VALUE(InstanceCreateInfo, std::string, engine_name, {})
6875db71995Sopenharmony_ci    BUILDER_VALUE(InstanceCreateInfo, uint32_t, flags, 0)
6885db71995Sopenharmony_ci    BUILDER_VALUE(InstanceCreateInfo, uint32_t, app_version, 0)
6895db71995Sopenharmony_ci    BUILDER_VALUE(InstanceCreateInfo, uint32_t, engine_version, 0)
6905db71995Sopenharmony_ci    BUILDER_VALUE(InstanceCreateInfo, uint32_t, api_version, VK_API_VERSION_1_0)
6915db71995Sopenharmony_ci    BUILDER_VECTOR(InstanceCreateInfo, const char*, enabled_layers, layer)
6925db71995Sopenharmony_ci    BUILDER_VECTOR(InstanceCreateInfo, const char*, enabled_extensions, extension)
6935db71995Sopenharmony_ci    // tell the get() function to not provide `application_info`
6945db71995Sopenharmony_ci    BUILDER_VALUE(InstanceCreateInfo, bool, fill_in_application_info, true)
6955db71995Sopenharmony_ci
6965db71995Sopenharmony_ci    InstanceCreateInfo();
6975db71995Sopenharmony_ci
6985db71995Sopenharmony_ci    VkInstanceCreateInfo* get() noexcept;
6995db71995Sopenharmony_ci
7005db71995Sopenharmony_ci    InstanceCreateInfo& set_api_version(uint32_t major, uint32_t minor, uint32_t patch);
7015db71995Sopenharmony_ci
7025db71995Sopenharmony_ci    InstanceCreateInfo& setup_WSI(const char* api_selection = nullptr);
7035db71995Sopenharmony_ci};
7045db71995Sopenharmony_ci
7055db71995Sopenharmony_cistruct DeviceQueueCreateInfo {
7065db71995Sopenharmony_ci    DeviceQueueCreateInfo();
7075db71995Sopenharmony_ci    DeviceQueueCreateInfo(const VkDeviceQueueCreateInfo* create_info);
7085db71995Sopenharmony_ci
7095db71995Sopenharmony_ci    BUILDER_VALUE(DeviceQueueCreateInfo, VkDeviceQueueCreateInfo, queue_create_info, {})
7105db71995Sopenharmony_ci    BUILDER_VECTOR(DeviceQueueCreateInfo, float, priorities, priority)
7115db71995Sopenharmony_ci
7125db71995Sopenharmony_ci    VkDeviceQueueCreateInfo get() noexcept;
7135db71995Sopenharmony_ci};
7145db71995Sopenharmony_ci
7155db71995Sopenharmony_cistruct DeviceCreateInfo {
7165db71995Sopenharmony_ci    DeviceCreateInfo() = default;
7175db71995Sopenharmony_ci    DeviceCreateInfo(const VkDeviceCreateInfo* create_info);
7185db71995Sopenharmony_ci
7195db71995Sopenharmony_ci    BUILDER_VALUE(DeviceCreateInfo, VkDeviceCreateInfo, dev, {})
7205db71995Sopenharmony_ci    BUILDER_VECTOR(DeviceCreateInfo, const char*, enabled_extensions, extension)
7215db71995Sopenharmony_ci    BUILDER_VECTOR(DeviceCreateInfo, const char*, enabled_layers, layer)
7225db71995Sopenharmony_ci    BUILDER_VECTOR(DeviceCreateInfo, DeviceQueueCreateInfo, queue_info_details, device_queue)
7235db71995Sopenharmony_ci
7245db71995Sopenharmony_ci    VkDeviceCreateInfo* get() noexcept;
7255db71995Sopenharmony_ci
7265db71995Sopenharmony_ci   private:
7275db71995Sopenharmony_ci    std::vector<VkDeviceQueueCreateInfo> device_queue_infos;
7285db71995Sopenharmony_ci};
7295db71995Sopenharmony_ci
7305db71995Sopenharmony_ciinline bool operator==(const VkExtent3D& a, const VkExtent3D& b) {
7315db71995Sopenharmony_ci    return a.width == b.width && a.height == b.height && a.depth == b.depth;
7325db71995Sopenharmony_ci}
7335db71995Sopenharmony_ciinline bool operator!=(const VkExtent3D& a, const VkExtent3D& b) { return !(a == b); }
7345db71995Sopenharmony_ci
7355db71995Sopenharmony_ciinline bool operator==(const VkQueueFamilyProperties& a, const VkQueueFamilyProperties& b) {
7365db71995Sopenharmony_ci    return a.minImageTransferGranularity == b.minImageTransferGranularity && a.queueCount == b.queueCount &&
7375db71995Sopenharmony_ci           a.queueFlags == b.queueFlags && a.timestampValidBits == b.timestampValidBits;
7385db71995Sopenharmony_ci}
7395db71995Sopenharmony_ciinline bool operator!=(const VkQueueFamilyProperties& a, const VkQueueFamilyProperties& b) { return !(a == b); }
7405db71995Sopenharmony_ci
7415db71995Sopenharmony_ciinline bool operator==(const VkLayerProperties& a, const VkLayerProperties& b) {
7425db71995Sopenharmony_ci    return string_eq(a.layerName, b.layerName, 256) && string_eq(a.description, b.description, 256) &&
7435db71995Sopenharmony_ci           a.implementationVersion == b.implementationVersion && a.specVersion == b.specVersion;
7445db71995Sopenharmony_ci}
7455db71995Sopenharmony_ciinline bool operator!=(const VkLayerProperties& a, const VkLayerProperties& b) { return !(a == b); }
7465db71995Sopenharmony_ci
7475db71995Sopenharmony_ciinline bool operator==(const VkExtensionProperties& a, const VkExtensionProperties& b) {
7485db71995Sopenharmony_ci    return string_eq(a.extensionName, b.extensionName, 256) && a.specVersion == b.specVersion;
7495db71995Sopenharmony_ci}
7505db71995Sopenharmony_ciinline bool operator!=(const VkExtensionProperties& a, const VkExtensionProperties& b) { return !(a == b); }
7515db71995Sopenharmony_ci
7525db71995Sopenharmony_cistruct VulkanFunction {
7535db71995Sopenharmony_ci    std::string name;
7545db71995Sopenharmony_ci    PFN_vkVoidFunction function = nullptr;
7555db71995Sopenharmony_ci};
7565db71995Sopenharmony_ci
7575db71995Sopenharmony_citemplate <typename T, size_t U>
7585db71995Sopenharmony_cibool check_permutation(std::initializer_list<const char*> expected, std::array<T, U> const& returned) {
7595db71995Sopenharmony_ci    if (expected.size() != returned.size()) return false;
7605db71995Sopenharmony_ci    for (uint32_t i = 0; i < expected.size(); i++) {
7615db71995Sopenharmony_ci        auto found = std::find_if(std::begin(returned), std::end(returned),
7625db71995Sopenharmony_ci                                  [&](T elem) { return string_eq(*(expected.begin() + i), elem.layerName); });
7635db71995Sopenharmony_ci        if (found == std::end(returned)) return false;
7645db71995Sopenharmony_ci    }
7655db71995Sopenharmony_ci    return true;
7665db71995Sopenharmony_ci}
7675db71995Sopenharmony_citemplate <typename T>
7685db71995Sopenharmony_cibool check_permutation(std::initializer_list<const char*> expected, std::vector<T> const& returned) {
7695db71995Sopenharmony_ci    if (expected.size() != returned.size()) return false;
7705db71995Sopenharmony_ci    for (uint32_t i = 0; i < expected.size(); i++) {
7715db71995Sopenharmony_ci        auto found = std::find_if(std::begin(returned), std::end(returned),
7725db71995Sopenharmony_ci                                  [&](T elem) { return string_eq(*(expected.begin() + i), elem.layerName); });
7735db71995Sopenharmony_ci        if (found == std::end(returned)) return false;
7745db71995Sopenharmony_ci    }
7755db71995Sopenharmony_ci    return true;
7765db71995Sopenharmony_ci}
7775db71995Sopenharmony_ci
7785db71995Sopenharmony_ciinline bool contains(std::vector<VkExtensionProperties> const& vec, const char* name) {
7795db71995Sopenharmony_ci    return std::any_of(std::begin(vec), std::end(vec),
7805db71995Sopenharmony_ci                       [name](VkExtensionProperties const& elem) { return string_eq(name, elem.extensionName); });
7815db71995Sopenharmony_ci}
7825db71995Sopenharmony_ciinline bool contains(std::vector<VkLayerProperties> const& vec, const char* name) {
7835db71995Sopenharmony_ci    return std::any_of(std::begin(vec), std::end(vec),
7845db71995Sopenharmony_ci                       [name](VkLayerProperties const& elem) { return string_eq(name, elem.layerName); });
7855db71995Sopenharmony_ci}
7865db71995Sopenharmony_ci
7875db71995Sopenharmony_ci#if defined(__linux__) || defined(__GNU__)
7885db71995Sopenharmony_ci
7895db71995Sopenharmony_ci// find application path + name. Path cannot be longer than 1024, returns NULL if it is greater than that.
7905db71995Sopenharmony_ciinline std::string test_platform_executable_path() {
7915db71995Sopenharmony_ci    std::string buffer;
7925db71995Sopenharmony_ci    buffer.resize(1024);
7935db71995Sopenharmony_ci    ssize_t count = readlink("/proc/self/exe", &buffer[0], buffer.size());
7945db71995Sopenharmony_ci    if (count == -1) return NULL;
7955db71995Sopenharmony_ci    if (count == 0) return NULL;
7965db71995Sopenharmony_ci    buffer[count] = '\0';
7975db71995Sopenharmony_ci    buffer.resize(count);
7985db71995Sopenharmony_ci    return buffer;
7995db71995Sopenharmony_ci}
8005db71995Sopenharmony_ci#elif defined(__APPLE__)
8015db71995Sopenharmony_ci#include <libproc.h>
8025db71995Sopenharmony_ciinline std::string test_platform_executable_path() {
8035db71995Sopenharmony_ci    std::string buffer;
8045db71995Sopenharmony_ci    buffer.resize(1024);
8055db71995Sopenharmony_ci    pid_t pid = getpid();
8065db71995Sopenharmony_ci    int ret = proc_pidpath(pid, &buffer[0], static_cast<uint32_t>(buffer.size()));
8075db71995Sopenharmony_ci    if (ret <= 0) return NULL;
8085db71995Sopenharmony_ci    buffer[ret] = '\0';
8095db71995Sopenharmony_ci    buffer.resize(ret);
8105db71995Sopenharmony_ci    return buffer;
8115db71995Sopenharmony_ci}
8125db71995Sopenharmony_ci#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__)
8135db71995Sopenharmony_ci#include <sys/sysctl.h>
8145db71995Sopenharmony_ciinline std::string test_platform_executable_path() {
8155db71995Sopenharmony_ci    int mib[] = {
8165db71995Sopenharmony_ci        CTL_KERN,
8175db71995Sopenharmony_ci#if defined(__NetBSD__)
8185db71995Sopenharmony_ci        KERN_PROC_ARGS,
8195db71995Sopenharmony_ci        -1,
8205db71995Sopenharmony_ci        KERN_PROC_PATHNAME,
8215db71995Sopenharmony_ci#else
8225db71995Sopenharmony_ci        KERN_PROC,
8235db71995Sopenharmony_ci        KERN_PROC_PATHNAME,
8245db71995Sopenharmony_ci        -1,
8255db71995Sopenharmony_ci#endif
8265db71995Sopenharmony_ci    };
8275db71995Sopenharmony_ci    std::string buffer;
8285db71995Sopenharmony_ci    buffer.resize(1024);
8295db71995Sopenharmony_ci    size_t size = buffer.size();
8305db71995Sopenharmony_ci    if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &buffer[0], &size, NULL, 0) < 0) {
8315db71995Sopenharmony_ci        return NULL;
8325db71995Sopenharmony_ci    }
8335db71995Sopenharmony_ci    buffer.resize(size);
8345db71995Sopenharmony_ci
8355db71995Sopenharmony_ci    return buffer;
8365db71995Sopenharmony_ci}
8375db71995Sopenharmony_ci#elif defined(__Fuchsia__) || defined(__OpenBSD__)
8385db71995Sopenharmony_ciinline std::string test_platform_executable_path() { return {}; }
8395db71995Sopenharmony_ci#elif defined(__QNX__)
8405db71995Sopenharmony_ci
8415db71995Sopenharmony_ci#define SYSCONFDIR "/etc"
8425db71995Sopenharmony_ci
8435db71995Sopenharmony_ci#include <fcntl.h>
8445db71995Sopenharmony_ci#include <sys/stat.h>
8455db71995Sopenharmony_ci
8465db71995Sopenharmony_ciinline std::string test_platform_executable_path() {
8475db71995Sopenharmony_ci    std::string buffer;
8485db71995Sopenharmony_ci    buffer.resize(1024);
8495db71995Sopenharmony_ci    int fd = open("/proc/self/exefile", O_RDONLY);
8505db71995Sopenharmony_ci    size_t rdsize;
8515db71995Sopenharmony_ci
8525db71995Sopenharmony_ci    if (fd == -1) {
8535db71995Sopenharmony_ci        return NULL;
8545db71995Sopenharmony_ci    }
8555db71995Sopenharmony_ci
8565db71995Sopenharmony_ci    rdsize = read(fd, &buffer[0], buffer.size());
8575db71995Sopenharmony_ci    if (rdsize == size) {
8585db71995Sopenharmony_ci        return NULL;
8595db71995Sopenharmony_ci    }
8605db71995Sopenharmony_ci    buffer[rdsize] = 0x00;
8615db71995Sopenharmony_ci    close(fd);
8625db71995Sopenharmony_ci    buffer.resize(rdsize);
8635db71995Sopenharmony_ci
8645db71995Sopenharmony_ci    return buffer;
8655db71995Sopenharmony_ci}
8665db71995Sopenharmony_ci#endif  // defined (__QNX__)
8675db71995Sopenharmony_ci#if defined(WIN32)
8685db71995Sopenharmony_ciinline std::string test_platform_executable_path() {
8695db71995Sopenharmony_ci    std::string buffer;
8705db71995Sopenharmony_ci    buffer.resize(1024);
8715db71995Sopenharmony_ci    DWORD ret = GetModuleFileName(NULL, static_cast<LPSTR>(&buffer[0]), (DWORD)buffer.size());
8725db71995Sopenharmony_ci    if (ret == 0) return NULL;
8735db71995Sopenharmony_ci    if (ret > buffer.size()) return NULL;
8745db71995Sopenharmony_ci    buffer.resize(ret);
8755db71995Sopenharmony_ci    buffer[ret] = '\0';
8765db71995Sopenharmony_ci    return buffer;
8775db71995Sopenharmony_ci}
8785db71995Sopenharmony_ci
8795db71995Sopenharmony_ciinline std::wstring conver_str_to_wstr(std::string const& input) {
8805db71995Sopenharmony_ci    std::wstring output{};
8815db71995Sopenharmony_ci    output.resize(input.size());
8825db71995Sopenharmony_ci    size_t characters_converted = 0;
8835db71995Sopenharmony_ci    mbstowcs_s(&characters_converted, &output[0], output.size() + 1, input.c_str(), input.size());
8845db71995Sopenharmony_ci    return output;
8855db71995Sopenharmony_ci}
8865db71995Sopenharmony_ci
8875db71995Sopenharmony_ci#endif
888