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