CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Common/GPU/Vulkan/VulkanLoader.cpp
Views: 1401
// Copyright (c) 2016- PPSSPP Project.12// This program is free software: you can redistribute it and/or modify3// it under the terms of the GNU General Public License as published by4// the Free Software Foundation, version 2.0 or later versions.56// This program is distributed in the hope that it will be useful,7// but WITHOUT ANY WARRANTY; without even the implied warranty of8// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9// GNU General Public License 2.0 for more details.1011// A copy of the GPL 2.0 should have been included with the program.12// If not, see http://www.gnu.org/licenses/1314// Official git repository and contact information can be found at15// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.1617#include "ppsspp_config.h"18#include <vector>19#include <string>20#include <cstring>2122#include "Core/Config.h"23#include "Common/Data/Format/JSONReader.h"24#include "Common/GPU/Vulkan/VulkanLoader.h"25#include "Common/Log.h"26#include "Common/System/System.h"27#include "Common/VR/PPSSPPVR.h"28#include "Common/File/FileUtil.h"2930#if !PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(SWITCH)31#include <dlfcn.h>32#endif3334#if PPSSPP_PLATFORM(ANDROID) && PPSSPP_ARCH(ARM64)35#include "File/AndroidStorage.h"3637#include <adrenotools/driver.h>38#endif3940namespace PPSSPP_VK {41#if !PPSSPP_PLATFORM(IOS_APP_STORE)42PFN_vkCreateInstance vkCreateInstance;43PFN_vkDestroyInstance vkDestroyInstance;44PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices;45PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion;46PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures;47PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties;48PFN_vkGetPhysicalDeviceImageFormatProperties vkGetPhysicalDeviceImageFormatProperties;49PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;50PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties;51PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties;52PFN_vkGetPhysicalDeviceMemoryProperties2 vkGetPhysicalDeviceMemoryProperties2;53PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;54PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;55PFN_vkCreateDevice vkCreateDevice;56PFN_vkDestroyDevice vkDestroyDevice;57PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties;58PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties;59PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties;60PFN_vkEnumerateDeviceLayerProperties vkEnumerateDeviceLayerProperties;61PFN_vkGetDeviceQueue vkGetDeviceQueue;62PFN_vkQueueSubmit vkQueueSubmit;63PFN_vkQueueWaitIdle vkQueueWaitIdle;64PFN_vkDeviceWaitIdle vkDeviceWaitIdle;65PFN_vkAllocateMemory vkAllocateMemory;66PFN_vkFreeMemory vkFreeMemory;67PFN_vkMapMemory vkMapMemory;68PFN_vkUnmapMemory vkUnmapMemory;69PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges;70PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges;71PFN_vkGetDeviceMemoryCommitment vkGetDeviceMemoryCommitment;72PFN_vkBindBufferMemory vkBindBufferMemory;73PFN_vkBindBufferMemory2 vkBindBufferMemory2;74PFN_vkBindImageMemory vkBindImageMemory;75PFN_vkBindImageMemory2 vkBindImageMemory2;76PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements;77PFN_vkGetDeviceBufferMemoryRequirements vkGetDeviceBufferMemoryRequirements;78PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements;79PFN_vkGetDeviceImageMemoryRequirements vkGetDeviceImageMemoryRequirements;80PFN_vkCreateFence vkCreateFence;81PFN_vkDestroyFence vkDestroyFence;82PFN_vkGetFenceStatus vkGetFenceStatus;83PFN_vkCreateSemaphore vkCreateSemaphore;84PFN_vkDestroySemaphore vkDestroySemaphore;85PFN_vkCreateEvent vkCreateEvent;86PFN_vkDestroyEvent vkDestroyEvent;87PFN_vkGetEventStatus vkGetEventStatus;88PFN_vkSetEvent vkSetEvent;89PFN_vkResetEvent vkResetEvent;90PFN_vkCreateQueryPool vkCreateQueryPool;91PFN_vkDestroyQueryPool vkDestroyQueryPool;92PFN_vkGetQueryPoolResults vkGetQueryPoolResults;93PFN_vkCreateBuffer vkCreateBuffer;94PFN_vkDestroyBuffer vkDestroyBuffer;95PFN_vkCreateBufferView vkCreateBufferView;96PFN_vkDestroyBufferView vkDestroyBufferView;97PFN_vkCreateImage vkCreateImage;98PFN_vkDestroyImage vkDestroyImage;99PFN_vkGetImageSubresourceLayout vkGetImageSubresourceLayout;100PFN_vkCreateImageView vkCreateImageView;101PFN_vkDestroyImageView vkDestroyImageView;102PFN_vkCreateShaderModule vkCreateShaderModule;103PFN_vkDestroyShaderModule vkDestroyShaderModule;104PFN_vkCreatePipelineCache vkCreatePipelineCache;105PFN_vkDestroyPipelineCache vkDestroyPipelineCache;106PFN_vkGetPipelineCacheData vkGetPipelineCacheData;107PFN_vkMergePipelineCaches vkMergePipelineCaches;108PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines;109PFN_vkCreateComputePipelines vkCreateComputePipelines;110PFN_vkDestroyPipeline vkDestroyPipeline;111PFN_vkCreatePipelineLayout vkCreatePipelineLayout;112PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout;113PFN_vkCreateSampler vkCreateSampler;114PFN_vkDestroySampler vkDestroySampler;115PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout;116PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout;117PFN_vkCreateDescriptorPool vkCreateDescriptorPool;118PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool;119PFN_vkResetDescriptorPool vkResetDescriptorPool;120PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets;121PFN_vkFreeDescriptorSets vkFreeDescriptorSets;122PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets;123PFN_vkCreateFramebuffer vkCreateFramebuffer;124PFN_vkDestroyFramebuffer vkDestroyFramebuffer;125PFN_vkCreateRenderPass vkCreateRenderPass;126PFN_vkDestroyRenderPass vkDestroyRenderPass;127PFN_vkGetRenderAreaGranularity vkGetRenderAreaGranularity;128PFN_vkCreateCommandPool vkCreateCommandPool;129PFN_vkDestroyCommandPool vkDestroyCommandPool;130PFN_vkResetCommandPool vkResetCommandPool;131PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers;132PFN_vkFreeCommandBuffers vkFreeCommandBuffers;133134// Used frequently together135PFN_vkCmdBindPipeline vkCmdBindPipeline;136PFN_vkCmdSetViewport vkCmdSetViewport;137PFN_vkCmdSetScissor vkCmdSetScissor;138PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants;139PFN_vkCmdSetStencilCompareMask vkCmdSetStencilCompareMask;140PFN_vkCmdSetStencilWriteMask vkCmdSetStencilWriteMask;141PFN_vkCmdSetStencilReference vkCmdSetStencilReference;142PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets;143PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer;144PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers;145PFN_vkCmdDraw vkCmdDraw;146PFN_vkCmdDrawIndexed vkCmdDrawIndexed;147PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier;148PFN_vkCmdPushConstants vkCmdPushConstants;149150// Every frame to a few times per frame151PFN_vkWaitForFences vkWaitForFences;152PFN_vkResetFences vkResetFences;153PFN_vkBeginCommandBuffer vkBeginCommandBuffer;154PFN_vkEndCommandBuffer vkEndCommandBuffer;155PFN_vkResetCommandBuffer vkResetCommandBuffer;156PFN_vkCmdClearAttachments vkCmdClearAttachments;157PFN_vkCmdSetEvent vkCmdSetEvent;158PFN_vkCmdResetEvent vkCmdResetEvent;159PFN_vkCmdWaitEvents vkCmdWaitEvents;160PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass;161PFN_vkCmdEndRenderPass vkCmdEndRenderPass;162PFN_vkCmdCopyBuffer vkCmdCopyBuffer;163PFN_vkCmdCopyImage vkCmdCopyImage;164PFN_vkCmdBlitImage vkCmdBlitImage;165PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage;166PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer;167168// Rare or not used169PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds;170PFN_vkCmdSetLineWidth vkCmdSetLineWidth;171PFN_vkCmdSetDepthBias vkCmdSetDepthBias;172PFN_vkCmdDrawIndirect vkCmdDrawIndirect;173PFN_vkCmdDrawIndexedIndirect vkCmdDrawIndexedIndirect;174PFN_vkCmdDispatch vkCmdDispatch;175PFN_vkCmdDispatchIndirect vkCmdDispatchIndirect;176PFN_vkCmdUpdateBuffer vkCmdUpdateBuffer;177PFN_vkCmdFillBuffer vkCmdFillBuffer;178PFN_vkCmdClearColorImage vkCmdClearColorImage;179PFN_vkCmdClearDepthStencilImage vkCmdClearDepthStencilImage;180PFN_vkCmdResolveImage vkCmdResolveImage;181PFN_vkCmdBeginQuery vkCmdBeginQuery;182PFN_vkCmdEndQuery vkCmdEndQuery;183PFN_vkCmdResetQueryPool vkCmdResetQueryPool;184PFN_vkCmdWriteTimestamp vkCmdWriteTimestamp;185PFN_vkCmdCopyQueryPoolResults vkCmdCopyQueryPoolResults;186PFN_vkCmdNextSubpass vkCmdNextSubpass;187PFN_vkCmdExecuteCommands vkCmdExecuteCommands;188189#ifdef __ANDROID__190PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR;191#elif defined(_WIN32)192PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR;193#endif194#if defined(VK_USE_PLATFORM_METAL_EXT)195PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT;196#endif197#if defined(VK_USE_PLATFORM_XLIB_KHR)198PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR;199#endif200#if defined(VK_USE_PLATFORM_WAYLAND_KHR)201PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR;202#endif203#if defined(VK_USE_PLATFORM_DISPLAY_KHR)204PFN_vkCreateDisplayPlaneSurfaceKHR vkCreateDisplayPlaneSurfaceKHR;205PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR;206PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vkGetPhysicalDeviceDisplayPlanePropertiesKHR;207PFN_vkGetDisplayModePropertiesKHR vkGetDisplayModePropertiesKHR;208PFN_vkGetDisplayPlaneSupportedDisplaysKHR vkGetDisplayPlaneSupportedDisplaysKHR;209PFN_vkGetDisplayPlaneCapabilitiesKHR vkGetDisplayPlaneCapabilitiesKHR;210#endif211212PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR;213214// WSI extension.215PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR;216PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR;217PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR;218PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR;219PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR;220PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR;221PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;222PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;223PFN_vkQueuePresentKHR vkQueuePresentKHR;224225PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT;226PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT;227PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT;228PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT;229PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT;230PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT;231PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT;232233// Assorted other extensions.234PFN_vkGetBufferMemoryRequirements2 vkGetBufferMemoryRequirements2;235PFN_vkGetImageMemoryRequirements2 vkGetImageMemoryRequirements2;236PFN_vkGetPhysicalDeviceProperties2 vkGetPhysicalDeviceProperties2;237PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2;238PFN_vkCreateRenderPass2 vkCreateRenderPass2;239240PFN_vkWaitForPresentKHR vkWaitForPresentKHR;241PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE;242PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE;243#endif244} // namespace PPSSPP_VK245246using namespace PPSSPP_VK;247248#if PPSSPP_PLATFORM(IOS_APP_STORE)249// Statically linked MoltenVK250#elif PPSSPP_PLATFORM(SWITCH)251typedef void *VulkanLibraryHandle;252static VulkanLibraryHandle vulkanLibrary;253#define dlsym(x, y) nullptr254#elif PPSSPP_PLATFORM(WINDOWS)255typedef HINSTANCE VulkanLibraryHandle;256static VulkanLibraryHandle vulkanLibrary;257#define dlsym(x, y) GetProcAddress(x, y)258#else259typedef void *VulkanLibraryHandle;260static VulkanLibraryHandle vulkanLibrary;261#endif262263bool g_vulkanAvailabilityChecked = false;264bool g_vulkanMayBeAvailable = false;265266static PFN_vkVoidFunction LoadInstanceFunc(VkInstance instance, const char *name) {267PFN_vkVoidFunction funcPtr = vkGetInstanceProcAddr(instance, name);268if (!funcPtr) {269INFO_LOG(Log::G3D, "Missing function (instance): %s", name);270}271return funcPtr;272}273#define LOAD_INSTANCE_FUNC(instance, x) x = (PFN_ ## x)LoadInstanceFunc(instance, #x);274275static PFN_vkVoidFunction LoadInstanceFuncCore(VkInstance instance, const char *name, const char *extName, u32 min_core, u32 vulkanInstanceApiVersion) {276PFN_vkVoidFunction funcPtr = vkGetInstanceProcAddr(instance, vulkanInstanceApiVersion >= min_core ? name : extName);277if (vulkanInstanceApiVersion >= min_core && !funcPtr) {278// Try the ext name.279funcPtr = vkGetInstanceProcAddr(instance, extName);280}281if (!funcPtr) {282INFO_LOG(Log::G3D, "Missing (instance): %s (%s)", name, extName);283}284return funcPtr;285}286#define LOAD_INSTANCE_FUNC_CORE(instance, x, ext_x, min_core) \287x = (PFN_ ## x)LoadInstanceFuncCore(instance, #x, #ext_x, min_core, vulkanInstanceApiVersion);288289static PFN_vkVoidFunction LoadDeviceFunc(VkDevice device, const char *name) {290PFN_vkVoidFunction funcPtr = vkGetDeviceProcAddr(device, name);291if (!funcPtr) {292INFO_LOG(Log::G3D, "Missing function (device): %s", name);293}294return funcPtr;295}296#define LOAD_DEVICE_FUNC(device, x) x = (PFN_ ## x)LoadDeviceFunc(device, #x);297298static PFN_vkVoidFunction LoadDeviceFuncCore(VkDevice device, const char *name, const char *extName, u32 min_core, u32 vulkanDeviceApiVersion) {299PFN_vkVoidFunction funcPtr = vkGetDeviceProcAddr(device, vulkanDeviceApiVersion >= min_core ? name : extName);300if (vulkanDeviceApiVersion >= min_core && !funcPtr) {301funcPtr = vkGetDeviceProcAddr(device, extName);302}303if (!funcPtr) {304INFO_LOG(Log::G3D, "Missing (device): %s (%s)", name, extName);305}306return funcPtr;307}308#define LOAD_DEVICE_FUNC_CORE(device, x, ext_x, min_core) \309x = (PFN_ ## x)LoadDeviceFuncCore(device, #x, #ext_x, min_core, vulkanDeviceApiVersion);310311#define LOAD_GLOBAL_FUNC(x) x = (PFN_ ## x)dlsym(vulkanLibrary, #x); if (!x) {INFO_LOG(Log::G3D,"Missing (global): %s", #x);}312#define LOAD_GLOBAL_FUNC_LOCAL(lib, x) (PFN_ ## x)dlsym(lib, #x);313314static const char * const device_name_blacklist[] = {315"NVIDIA:SHIELD Tablet K1",316"SDL:Horizon",317"motorola:moto g54 5G", // See issue #18681 / #17825318};319320#ifndef _WIN32321static const char * const so_names[] = {322#if PPSSPP_PLATFORM(IOS_APP_STORE)323#elif PPSSPP_PLATFORM(IOS)324"@executable_path/Frameworks/libMoltenVK.dylib",325"MoltenVK",326#elif PPSSPP_PLATFORM(MAC)327"@executable_path/../Frameworks/libMoltenVK.dylib",328"MoltenVK",329#else330"libvulkan.so",331#if !defined(__ANDROID__)332"libvulkan.so.1",333#endif334#endif335};336#endif337338#if !PPSSPP_PLATFORM(IOS_APP_STORE)339static VulkanLibraryHandle VulkanLoadLibrary(std::string *errorString) {340#if PPSSPP_PLATFORM(SWITCH)341// Always unavailable, for now.342return nullptr;343#elif PPSSPP_PLATFORM(UWP)344return nullptr;345#elif PPSSPP_PLATFORM(MACOS) && PPSSPP_ARCH(AMD64)346// Disable Vulkan on Mac/x86. Too many configurations that don't work with MoltenVK347// for whatever reason.348return nullptr;349#elif PPSSPP_PLATFORM(WINDOWS)350return LoadLibrary(L"vulkan-1.dll");351#else352void *lib = nullptr;353354#if PPSSPP_PLATFORM(ANDROID) && PPSSPP_ARCH(ARM64)355if (!g_Config.sCustomDriver.empty() && g_Config.sCustomDriver != "Default") {356const Path driverPath = g_Config.internalDataDirectory / "drivers" / g_Config.sCustomDriver;357358json::JsonReader meta = json::JsonReader((driverPath / "meta.json").c_str());359if (meta.ok()) {360std::string driverLibName = meta.root().get("libraryName")->value.toString();361362Path tempDir = g_Config.internalDataDirectory / "temp";363Path fileRedirectDir = g_Config.internalDataDirectory / "vk_file_redirect";364365File::CreateDir(tempDir);366File::CreateDir(fileRedirectDir);367368lib = adrenotools_open_libvulkan(369RTLD_NOW | RTLD_LOCAL, ADRENOTOOLS_DRIVER_FILE_REDIRECT | ADRENOTOOLS_DRIVER_CUSTOM,370(std::string(tempDir.c_str()) + "/").c_str(), g_nativeLibDir.c_str(),371(std::string(driverPath.c_str()) + "/").c_str(), driverLibName.c_str(),372(std::string(fileRedirectDir.c_str()) + "/").c_str(), nullptr);373if (!lib) {374ERROR_LOG(Log::G3D, "Failed to load custom driver with AdrenoTools ('%s')", g_Config.sCustomDriver.c_str());375} else {376INFO_LOG(Log::G3D, "Vulkan library loaded with AdrenoTools ('%s')", g_Config.sCustomDriver.c_str());377}378}379}380#endif381382if (!lib) {383for (int i = 0; i < ARRAY_SIZE(so_names); i++) {384lib = dlopen(so_names[i], RTLD_NOW | RTLD_LOCAL);385if (lib) {386INFO_LOG(Log::G3D, "Vulkan library loaded ('%s')", so_names[i]);387break;388}389}390}391return lib;392#endif393}394#endif395396#if !PPSSPP_PLATFORM(IOS_APP_STORE)397static void VulkanFreeLibrary(VulkanLibraryHandle &h) {398if (h) {399#if PPSSPP_PLATFORM(SWITCH)400// Can't load, and can't free.401#elif PPSSPP_PLATFORM(WINDOWS)402FreeLibrary(h);403#else404dlclose(h);405#endif406h = nullptr;407}408}409#endif410411void VulkanSetAvailable(bool available) {412INFO_LOG(Log::G3D, "Setting Vulkan availability to true");413g_vulkanAvailabilityChecked = true;414g_vulkanMayBeAvailable = available;415}416417bool VulkanMayBeAvailable() {418#if PPSSPP_PLATFORM(IOS)419g_vulkanAvailabilityChecked = true;420// MoltenVK does no longer seem to support iOS <= 12, despite what the docs say.421g_vulkanMayBeAvailable = System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= 13;422return g_vulkanMayBeAvailable;423#else424// Unsupported in VR at the moment425if (IsVREnabled()) {426return false;427}428429if (g_vulkanAvailabilityChecked) {430return g_vulkanMayBeAvailable;431}432433std::string name = System_GetProperty(SYSPROP_NAME);434for (const char *blacklisted_name : device_name_blacklist) {435if (!strcmp(name.c_str(), blacklisted_name)) {436INFO_LOG(Log::G3D, "VulkanMayBeAvailable: Device blacklisted ('%s')", name.c_str());437g_vulkanAvailabilityChecked = true;438g_vulkanMayBeAvailable = false;439return false;440}441}442INFO_LOG(Log::G3D, "VulkanMayBeAvailable: Device allowed ('%s')", name.c_str());443444std::string errorStr;445VulkanLibraryHandle lib = VulkanLoadLibrary(&errorStr);446if (!lib) {447INFO_LOG(Log::G3D, "Vulkan loader: Library not available: %s", errorStr.c_str());448g_vulkanAvailabilityChecked = true;449g_vulkanMayBeAvailable = false;450return false;451}452453// Do a hyper minimal initialization and teardown to figure out if there's any chance454// that any sort of Vulkan will be usable.455PFN_vkEnumerateInstanceExtensionProperties localEnumerateInstanceExtensionProperties = LOAD_GLOBAL_FUNC_LOCAL(lib, vkEnumerateInstanceExtensionProperties);456PFN_vkCreateInstance localCreateInstance = LOAD_GLOBAL_FUNC_LOCAL(lib, vkCreateInstance);457PFN_vkEnumeratePhysicalDevices localEnumerate = LOAD_GLOBAL_FUNC_LOCAL(lib, vkEnumeratePhysicalDevices);458PFN_vkDestroyInstance localDestroyInstance = LOAD_GLOBAL_FUNC_LOCAL(lib, vkDestroyInstance);459PFN_vkGetPhysicalDeviceProperties localGetPhysicalDeviceProperties = LOAD_GLOBAL_FUNC_LOCAL(lib, vkGetPhysicalDeviceProperties);460461// Need to predeclare all this because of the gotos...462VkInstanceCreateInfo ci{ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };463VkApplicationInfo info{ VK_STRUCTURE_TYPE_APPLICATION_INFO };464std::vector<VkPhysicalDevice> devices;465bool anyGood = false;466const char *instanceExtensions[10]{};467VkInstance instance = VK_NULL_HANDLE;468VkResult res = VK_SUCCESS;469uint32_t physicalDeviceCount = 0;470uint32_t instanceExtCount = 0;471bool surfaceExtensionFound = false;472bool platformSurfaceExtensionFound = false;473std::vector<VkExtensionProperties> instanceExts;474ci.enabledExtensionCount = 0; // Should have been reset by struct initialization anyway, just paranoia.475476#ifdef _WIN32477const char * const platformSurfaceExtension = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;478#elif defined(__ANDROID__)479const char *platformSurfaceExtension = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;480#elif defined(VK_USE_PLATFORM_METAL_EXT)481const char * const platformSurfaceExtension = VK_EXT_METAL_SURFACE_EXTENSION_NAME;482#else483const char *platformSurfaceExtension = 0;484#endif485486if (!localEnumerateInstanceExtensionProperties || !localCreateInstance || !localEnumerate || !localDestroyInstance || !localGetPhysicalDeviceProperties) {487WARN_LOG(Log::G3D, "VulkanMayBeAvailable: Function pointer missing, bailing");488goto bail;489}490491INFO_LOG(Log::G3D, "VulkanMayBeAvailable: Enumerating instance extensions");492res = localEnumerateInstanceExtensionProperties(nullptr, &instanceExtCount, nullptr);493// Maximum paranoia.494if (res != VK_SUCCESS) {495ERROR_LOG(Log::G3D, "Enumerating VK extensions failed (%s)", VulkanResultToString(res));496goto bail;497}498if (instanceExtCount == 0) {499ERROR_LOG(Log::G3D, "No VK instance extensions - won't be able to present.");500goto bail;501}502INFO_LOG(Log::G3D, "VulkanMayBeAvailable: Instance extension count: %d", instanceExtCount);503instanceExts.resize(instanceExtCount);504res = localEnumerateInstanceExtensionProperties(nullptr, &instanceExtCount, instanceExts.data());505if (res != VK_SUCCESS) {506ERROR_LOG(Log::G3D, "Enumerating VK extensions failed (%s)", VulkanResultToString(res));507goto bail;508}509for (const auto &iter : instanceExts) {510INFO_LOG(Log::G3D, "VulkanMaybeAvailable: Instance extension found: %s (%08x)", iter.extensionName, iter.specVersion);511if (platformSurfaceExtension && !strcmp(iter.extensionName, platformSurfaceExtension)) {512INFO_LOG(Log::G3D, "VulkanMayBeAvailable: Found platform surface extension '%s'", platformSurfaceExtension);513instanceExtensions[ci.enabledExtensionCount++] = platformSurfaceExtension;514platformSurfaceExtensionFound = true;515break;516} else if (!strcmp(iter.extensionName, VK_KHR_SURFACE_EXTENSION_NAME)) {517instanceExtensions[ci.enabledExtensionCount++] = VK_KHR_SURFACE_EXTENSION_NAME;518surfaceExtensionFound = true;519}520}521if (platformSurfaceExtension) {522if (!platformSurfaceExtensionFound || !surfaceExtensionFound) {523ERROR_LOG(Log::G3D, "Platform surface extension not found");524goto bail;525}526} else {527if (!surfaceExtensionFound) {528ERROR_LOG(Log::G3D, "Surface extension not found");529goto bail;530}531}532533// This can't happen unless the driver is double-reporting a surface extension.534if (ci.enabledExtensionCount > 2) {535ERROR_LOG(Log::G3D, "Unexpected number of enabled instance extensions");536goto bail;537}538539ci.ppEnabledExtensionNames = instanceExtensions;540ci.enabledLayerCount = 0;541info.apiVersion = VK_API_VERSION_1_0;542info.applicationVersion = 1;543info.engineVersion = 1;544info.pApplicationName = "VulkanChecker";545info.pEngineName = "VulkanCheckerEngine";546ci.pApplicationInfo = &info;547ci.flags = 0;548INFO_LOG(Log::G3D, "VulkanMayBeAvailable: Calling vkCreateInstance");549res = localCreateInstance(&ci, nullptr, &instance);550if (res != VK_SUCCESS) {551instance = nullptr;552ERROR_LOG(Log::G3D, "VulkanMayBeAvailable: Failed to create vulkan instance (%s)", VulkanResultToString(res));553goto bail;554}555INFO_LOG(Log::G3D, "VulkanMayBeAvailable: Vulkan test instance created successfully.");556res = localEnumerate(instance, &physicalDeviceCount, nullptr);557if (res != VK_SUCCESS) {558ERROR_LOG(Log::G3D, "VulkanMayBeAvailable: Failed to count physical devices (%s)", VulkanResultToString(res));559goto bail;560}561if (physicalDeviceCount == 0) {562ERROR_LOG(Log::G3D, "VulkanMayBeAvailable: No physical Vulkan devices (count = 0).");563goto bail;564}565devices.resize(physicalDeviceCount);566res = localEnumerate(instance, &physicalDeviceCount, devices.data());567if (res != VK_SUCCESS) {568ERROR_LOG(Log::G3D, "VulkanMayBeAvailable: Failed to enumerate physical devices (%s)", VulkanResultToString(res));569goto bail;570}571anyGood = false;572for (auto device : devices) {573VkPhysicalDeviceProperties props;574localGetPhysicalDeviceProperties(device, &props);575switch (props.deviceType) {576case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:577case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:578case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:579anyGood = true;580INFO_LOG(Log::G3D, "VulkanMayBeAvailable: Eligible device found: '%s'", props.deviceName);581break;582default:583INFO_LOG(Log::G3D, "VulkanMayBeAvailable: Ineligible device found and ignored: '%s'", props.deviceName);584break;585}586// TODO: Should also check queuefamilyproperties for a GRAPHICS queue family? Oh well.587}588589if (!anyGood) {590WARN_LOG(Log::G3D, "VulkanMayBeAvailable: Found Vulkan API, but no good Vulkan device!");591g_vulkanMayBeAvailable = false;592} else {593INFO_LOG(Log::G3D, "VulkanMayBeAvailable: Found working Vulkan API!");594g_vulkanMayBeAvailable = true;595}596597bail:598g_vulkanAvailabilityChecked = true;599if (instance) {600INFO_LOG(Log::G3D, "VulkanMayBeAvailable: Destroying instance");601localDestroyInstance(instance, nullptr);602}603if (lib) {604VulkanFreeLibrary(lib);605}606if (!g_vulkanMayBeAvailable) {607WARN_LOG(Log::G3D, "Vulkan with working device not detected.");608}609return g_vulkanMayBeAvailable;610#endif611}612613bool VulkanLoad(std::string *errorStr) {614#if PPSSPP_PLATFORM(IOS_APP_STORE)615INFO_LOG(Log::G3D, "iOS: Vulkan doesn't need loading");616return true;617#else618619if (!vulkanLibrary) {620vulkanLibrary = VulkanLoadLibrary(errorStr);621if (!vulkanLibrary) {622return false;623}624}625626LOAD_GLOBAL_FUNC(vkCreateInstance);627LOAD_GLOBAL_FUNC(vkGetInstanceProcAddr);628LOAD_GLOBAL_FUNC(vkGetDeviceProcAddr);629630LOAD_GLOBAL_FUNC(vkEnumerateInstanceVersion);631LOAD_GLOBAL_FUNC(vkEnumerateInstanceExtensionProperties);632LOAD_GLOBAL_FUNC(vkEnumerateInstanceLayerProperties);633634if (vkCreateInstance && vkGetInstanceProcAddr && vkGetDeviceProcAddr && vkEnumerateInstanceExtensionProperties && vkEnumerateInstanceLayerProperties) {635INFO_LOG(Log::G3D, "VulkanLoad: Base functions loaded.");636// NOTE: It's ok if vkEnumerateInstanceVersion is missing.637return true;638} else {639*errorStr = "Failed to load Vulkan base functions";640ERROR_LOG(Log::G3D, "VulkanLoad: %s", errorStr->c_str());641VulkanFreeLibrary(vulkanLibrary);642return false;643}644#endif645}646647void VulkanLoadInstanceFunctions(VkInstance instance, const VulkanExtensions &enabledExtensions, uint32_t vulkanInstanceApiVersion) {648#if !PPSSPP_PLATFORM(IOS_APP_STORE)649INFO_LOG(Log::G3D, "Loading Vulkan instance functions. Instance API version: %08x (%d.%d.%d)", vulkanInstanceApiVersion, VK_API_VERSION_MAJOR(vulkanInstanceApiVersion), VK_API_VERSION_MINOR(vulkanInstanceApiVersion), VK_API_VERSION_PATCH(vulkanInstanceApiVersion));650// OK, let's use the above functions to get the rest.651LOAD_INSTANCE_FUNC(instance, vkDestroyInstance);652LOAD_INSTANCE_FUNC(instance, vkEnumeratePhysicalDevices);653LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceFeatures);654LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceFormatProperties);655LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceImageFormatProperties);656LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceProperties);657LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceQueueFamilyProperties);658LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceMemoryProperties);659LOAD_INSTANCE_FUNC(instance, vkCreateDevice);660LOAD_INSTANCE_FUNC(instance, vkDestroyDevice);661LOAD_INSTANCE_FUNC(instance, vkEnumerateDeviceExtensionProperties);662LOAD_INSTANCE_FUNC(instance, vkEnumerateDeviceLayerProperties);663LOAD_INSTANCE_FUNC(instance, vkGetDeviceQueue);664LOAD_INSTANCE_FUNC(instance, vkDeviceWaitIdle);665666LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceSurfaceSupportKHR);667LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceSurfaceCapabilitiesKHR);668LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceSurfaceFormatsKHR);669LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceSurfacePresentModesKHR);670671LOAD_INSTANCE_FUNC(instance, vkCreateSwapchainKHR);672LOAD_INSTANCE_FUNC(instance, vkDestroySwapchainKHR);673LOAD_INSTANCE_FUNC(instance, vkGetSwapchainImagesKHR);674LOAD_INSTANCE_FUNC(instance, vkAcquireNextImageKHR);675LOAD_INSTANCE_FUNC(instance, vkQueuePresentKHR);676677#ifdef _WIN32678LOAD_INSTANCE_FUNC(instance, vkCreateWin32SurfaceKHR);679#elif defined(__ANDROID__)680LOAD_INSTANCE_FUNC(instance, vkCreateAndroidSurfaceKHR);681#elif defined(VK_USE_PLATFORM_METAL_EXT)682LOAD_INSTANCE_FUNC(instance, vkCreateMetalSurfaceEXT);683#endif684#if defined(VK_USE_PLATFORM_XLIB_KHR)685LOAD_INSTANCE_FUNC(instance, vkCreateXlibSurfaceKHR);686#endif687#if defined(VK_USE_PLATFORM_WAYLAND_KHR)688LOAD_INSTANCE_FUNC(instance, vkCreateWaylandSurfaceKHR);689#endif690#if defined(VK_USE_PLATFORM_DISPLAY_KHR)691LOAD_INSTANCE_FUNC(instance, vkCreateDisplayPlaneSurfaceKHR);692LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceDisplayPropertiesKHR);693LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceDisplayPlanePropertiesKHR);694LOAD_INSTANCE_FUNC(instance, vkGetDisplayModePropertiesKHR);695LOAD_INSTANCE_FUNC(instance, vkGetDisplayPlaneSupportedDisplaysKHR);696LOAD_INSTANCE_FUNC(instance, vkGetDisplayPlaneCapabilitiesKHR);697#endif698699LOAD_INSTANCE_FUNC(instance, vkDestroySurfaceKHR);700701if (enabledExtensions.KHR_get_physical_device_properties2) {702LOAD_INSTANCE_FUNC_CORE(instance, vkGetPhysicalDeviceProperties2, vkGetPhysicalDeviceProperties2KHR, VK_API_VERSION_1_1);703LOAD_INSTANCE_FUNC_CORE(instance, vkGetPhysicalDeviceFeatures2, vkGetPhysicalDeviceFeatures2KHR, VK_API_VERSION_1_1);704}705706if (enabledExtensions.EXT_debug_utils) {707LOAD_INSTANCE_FUNC(instance, vkCreateDebugUtilsMessengerEXT);708LOAD_INSTANCE_FUNC(instance, vkDestroyDebugUtilsMessengerEXT);709LOAD_INSTANCE_FUNC(instance, vkCmdBeginDebugUtilsLabelEXT);710LOAD_INSTANCE_FUNC(instance, vkCmdEndDebugUtilsLabelEXT);711LOAD_INSTANCE_FUNC(instance, vkCmdInsertDebugUtilsLabelEXT);712LOAD_INSTANCE_FUNC(instance, vkSetDebugUtilsObjectNameEXT);713LOAD_INSTANCE_FUNC(instance, vkSetDebugUtilsObjectTagEXT);714}715716INFO_LOG(Log::G3D, "Vulkan instance functions loaded.");717#endif718}719720// On some implementations, loading functions (that have Device as their first parameter) via vkGetDeviceProcAddr may721// increase performance - but then these function pointers will only work on that specific device. Thus, this loader is not very722// good for multi-device - not likely we'll ever try that anyway though.723void VulkanLoadDeviceFunctions(VkDevice device, const VulkanExtensions &enabledExtensions, uint32_t vulkanDeviceApiVersion) {724#if !PPSSPP_PLATFORM(IOS_APP_STORE)725INFO_LOG(Log::G3D, "Loading Vulkan device functions. Device API version: %08x (%d.%d.%d)", vulkanDeviceApiVersion, VK_API_VERSION_MAJOR(vulkanDeviceApiVersion), VK_API_VERSION_MINOR(vulkanDeviceApiVersion), VK_API_VERSION_PATCH(vulkanDeviceApiVersion));726727LOAD_DEVICE_FUNC(device, vkQueueSubmit);728LOAD_DEVICE_FUNC(device, vkQueueWaitIdle);729LOAD_DEVICE_FUNC(device, vkAllocateMemory);730LOAD_DEVICE_FUNC(device, vkFreeMemory);731LOAD_DEVICE_FUNC(device, vkMapMemory);732LOAD_DEVICE_FUNC(device, vkUnmapMemory);733LOAD_DEVICE_FUNC(device, vkFlushMappedMemoryRanges);734LOAD_DEVICE_FUNC(device, vkInvalidateMappedMemoryRanges);735LOAD_DEVICE_FUNC(device, vkGetDeviceMemoryCommitment);736LOAD_DEVICE_FUNC(device, vkBindBufferMemory);737LOAD_DEVICE_FUNC(device, vkBindBufferMemory2);738LOAD_DEVICE_FUNC(device, vkBindImageMemory);739LOAD_DEVICE_FUNC(device, vkBindImageMemory2);740LOAD_DEVICE_FUNC(device, vkGetBufferMemoryRequirements);741LOAD_DEVICE_FUNC(device, vkGetBufferMemoryRequirements2);742LOAD_DEVICE_FUNC(device, vkGetImageMemoryRequirements);743LOAD_DEVICE_FUNC(device, vkGetImageMemoryRequirements2);744LOAD_DEVICE_FUNC(device, vkCreateFence);745LOAD_DEVICE_FUNC(device, vkDestroyFence);746LOAD_DEVICE_FUNC(device, vkResetFences);747LOAD_DEVICE_FUNC(device, vkGetFenceStatus);748LOAD_DEVICE_FUNC(device, vkWaitForFences);749LOAD_DEVICE_FUNC(device, vkCreateSemaphore);750LOAD_DEVICE_FUNC(device, vkDestroySemaphore);751LOAD_DEVICE_FUNC(device, vkCreateEvent);752LOAD_DEVICE_FUNC(device, vkDestroyEvent);753LOAD_DEVICE_FUNC(device, vkGetEventStatus);754LOAD_DEVICE_FUNC(device, vkSetEvent);755LOAD_DEVICE_FUNC(device, vkResetEvent);756LOAD_DEVICE_FUNC(device, vkCreateQueryPool);757LOAD_DEVICE_FUNC(device, vkDestroyQueryPool);758LOAD_DEVICE_FUNC(device, vkGetQueryPoolResults);759LOAD_DEVICE_FUNC(device, vkCreateBuffer);760LOAD_DEVICE_FUNC(device, vkDestroyBuffer);761LOAD_DEVICE_FUNC(device, vkCreateBufferView);762LOAD_DEVICE_FUNC(device, vkDestroyBufferView);763LOAD_DEVICE_FUNC(device, vkCreateImage);764LOAD_DEVICE_FUNC(device, vkDestroyImage);765LOAD_DEVICE_FUNC(device, vkGetImageSubresourceLayout);766LOAD_DEVICE_FUNC(device, vkCreateImageView);767LOAD_DEVICE_FUNC(device, vkDestroyImageView);768LOAD_DEVICE_FUNC(device, vkCreateShaderModule);769LOAD_DEVICE_FUNC(device, vkDestroyShaderModule);770LOAD_DEVICE_FUNC(device, vkCreatePipelineCache);771LOAD_DEVICE_FUNC(device, vkDestroyPipelineCache);772LOAD_DEVICE_FUNC(device, vkGetPipelineCacheData);773LOAD_DEVICE_FUNC(device, vkMergePipelineCaches);774LOAD_DEVICE_FUNC(device, vkCreateGraphicsPipelines);775LOAD_DEVICE_FUNC(device, vkCreateComputePipelines);776LOAD_DEVICE_FUNC(device, vkDestroyPipeline);777LOAD_DEVICE_FUNC(device, vkCreatePipelineLayout);778LOAD_DEVICE_FUNC(device, vkDestroyPipelineLayout);779LOAD_DEVICE_FUNC(device, vkCreateSampler);780LOAD_DEVICE_FUNC(device, vkDestroySampler);781LOAD_DEVICE_FUNC(device, vkCreateDescriptorSetLayout);782LOAD_DEVICE_FUNC(device, vkDestroyDescriptorSetLayout);783LOAD_DEVICE_FUNC(device, vkCreateDescriptorPool);784LOAD_DEVICE_FUNC(device, vkDestroyDescriptorPool);785LOAD_DEVICE_FUNC(device, vkResetDescriptorPool);786LOAD_DEVICE_FUNC(device, vkAllocateDescriptorSets);787LOAD_DEVICE_FUNC(device, vkFreeDescriptorSets);788LOAD_DEVICE_FUNC(device, vkUpdateDescriptorSets);789LOAD_DEVICE_FUNC(device, vkCreateFramebuffer);790LOAD_DEVICE_FUNC(device, vkDestroyFramebuffer);791LOAD_DEVICE_FUNC(device, vkCreateRenderPass);792LOAD_DEVICE_FUNC(device, vkDestroyRenderPass);793LOAD_DEVICE_FUNC(device, vkGetRenderAreaGranularity);794LOAD_DEVICE_FUNC(device, vkCreateCommandPool);795LOAD_DEVICE_FUNC(device, vkDestroyCommandPool);796LOAD_DEVICE_FUNC(device, vkResetCommandPool);797LOAD_DEVICE_FUNC(device, vkAllocateCommandBuffers);798LOAD_DEVICE_FUNC(device, vkFreeCommandBuffers);799LOAD_DEVICE_FUNC(device, vkBeginCommandBuffer);800LOAD_DEVICE_FUNC(device, vkEndCommandBuffer);801LOAD_DEVICE_FUNC(device, vkResetCommandBuffer);802LOAD_DEVICE_FUNC(device, vkCmdBindPipeline);803LOAD_DEVICE_FUNC(device, vkCmdSetViewport);804LOAD_DEVICE_FUNC(device, vkCmdSetScissor);805LOAD_DEVICE_FUNC(device, vkCmdSetLineWidth);806LOAD_DEVICE_FUNC(device, vkCmdSetDepthBias);807LOAD_DEVICE_FUNC(device, vkCmdSetBlendConstants);808LOAD_DEVICE_FUNC(device, vkCmdSetDepthBounds);809LOAD_DEVICE_FUNC(device, vkCmdSetStencilCompareMask);810LOAD_DEVICE_FUNC(device, vkCmdSetStencilWriteMask);811LOAD_DEVICE_FUNC(device, vkCmdSetStencilReference);812LOAD_DEVICE_FUNC(device, vkCmdBindDescriptorSets);813LOAD_DEVICE_FUNC(device, vkCmdBindIndexBuffer);814LOAD_DEVICE_FUNC(device, vkCmdBindVertexBuffers);815LOAD_DEVICE_FUNC(device, vkCmdDraw);816LOAD_DEVICE_FUNC(device, vkCmdDrawIndexed);817LOAD_DEVICE_FUNC(device, vkCmdDrawIndirect);818LOAD_DEVICE_FUNC(device, vkCmdDrawIndexedIndirect);819LOAD_DEVICE_FUNC(device, vkCmdDispatch);820LOAD_DEVICE_FUNC(device, vkCmdDispatchIndirect);821LOAD_DEVICE_FUNC(device, vkCmdCopyBuffer);822LOAD_DEVICE_FUNC(device, vkCmdCopyImage);823LOAD_DEVICE_FUNC(device, vkCmdBlitImage);824LOAD_DEVICE_FUNC(device, vkCmdCopyBufferToImage);825LOAD_DEVICE_FUNC(device, vkCmdCopyImageToBuffer);826LOAD_DEVICE_FUNC(device, vkCmdUpdateBuffer);827LOAD_DEVICE_FUNC(device, vkCmdFillBuffer);828LOAD_DEVICE_FUNC(device, vkCmdClearColorImage);829LOAD_DEVICE_FUNC(device, vkCmdClearDepthStencilImage);830LOAD_DEVICE_FUNC(device, vkCmdClearAttachments);831LOAD_DEVICE_FUNC(device, vkCmdResolveImage);832LOAD_DEVICE_FUNC(device, vkCmdSetEvent);833LOAD_DEVICE_FUNC(device, vkCmdResetEvent);834LOAD_DEVICE_FUNC(device, vkCmdWaitEvents);835LOAD_DEVICE_FUNC(device, vkCmdPipelineBarrier);836LOAD_DEVICE_FUNC(device, vkCmdBeginQuery);837LOAD_DEVICE_FUNC(device, vkCmdEndQuery);838LOAD_DEVICE_FUNC(device, vkCmdResetQueryPool);839LOAD_DEVICE_FUNC(device, vkCmdWriteTimestamp);840LOAD_DEVICE_FUNC(device, vkCmdCopyQueryPoolResults);841LOAD_DEVICE_FUNC(device, vkCmdPushConstants);842LOAD_DEVICE_FUNC(device, vkCmdBeginRenderPass);843LOAD_DEVICE_FUNC(device, vkCmdNextSubpass);844LOAD_DEVICE_FUNC(device, vkCmdEndRenderPass);845LOAD_DEVICE_FUNC(device, vkCmdExecuteCommands);846847if (enabledExtensions.KHR_present_wait) {848LOAD_DEVICE_FUNC(device, vkWaitForPresentKHR);849}850if (enabledExtensions.GOOGLE_display_timing) {851LOAD_DEVICE_FUNC(device, vkGetPastPresentationTimingGOOGLE);852LOAD_DEVICE_FUNC(device, vkGetRefreshCycleDurationGOOGLE);853}854if (enabledExtensions.KHR_dedicated_allocation) {855LOAD_DEVICE_FUNC_CORE(device, vkGetBufferMemoryRequirements2, vkGetBufferMemoryRequirements2KHR, VK_API_VERSION_1_1);856LOAD_DEVICE_FUNC_CORE(device, vkGetImageMemoryRequirements2, vkGetImageMemoryRequirements2KHR, VK_API_VERSION_1_1);857}858if (enabledExtensions.KHR_create_renderpass2) {859LOAD_DEVICE_FUNC_CORE(device, vkCreateRenderPass2, vkCreateRenderPass2KHR, VK_API_VERSION_1_2);860}861if (enabledExtensions.KHR_maintenance4) {862LOAD_DEVICE_FUNC_CORE(device, vkGetDeviceBufferMemoryRequirements, vkGetDeviceBufferMemoryRequirementsKHR, VK_API_VERSION_1_3);863LOAD_DEVICE_FUNC_CORE(device, vkGetDeviceImageMemoryRequirements, vkGetDeviceImageMemoryRequirementsKHR, VK_API_VERSION_1_3);864}865#endif866}867868void VulkanFree() {869#if !PPSSPP_PLATFORM(IOS_APP_STORE)870VulkanFreeLibrary(vulkanLibrary);871#endif872}873874const char *VulkanResultToString(VkResult res) {875static char temp[128]{};876switch (res) {877case VK_NOT_READY: return "VK_NOT_READY";878case VK_TIMEOUT: return "VK_TIMEOUT";879case VK_EVENT_SET: return "VK_EVENT_SET";880case VK_EVENT_RESET: return "VK_EVENT_RESET";881case VK_INCOMPLETE: return "VK_INCOMPLETE";882case VK_ERROR_OUT_OF_HOST_MEMORY: return "VK_ERROR_OUT_OF_HOST_MEMORY";883case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "VK_ERROR_OUT_OF_DEVICE_MEMORY";884case VK_ERROR_INITIALIZATION_FAILED: return "VK_ERROR_INITIALIZATION_FAILED";885case VK_ERROR_DEVICE_LOST: return "VK_ERROR_DEVICE_LOST";886case VK_ERROR_MEMORY_MAP_FAILED: return "VK_ERROR_MEMORY_MAP_FAILED";887case VK_ERROR_LAYER_NOT_PRESENT: return "VK_ERROR_LAYER_NOT_PRESENT";888case VK_ERROR_EXTENSION_NOT_PRESENT: return "VK_ERROR_EXTENSION_NOT_PRESENT";889case VK_ERROR_FEATURE_NOT_PRESENT: return "VK_ERROR_FEATURE_NOT_PRESENT";890case VK_ERROR_INCOMPATIBLE_DRIVER: return "VK_ERROR_INCOMPATIBLE_DRIVER";891case VK_ERROR_TOO_MANY_OBJECTS: return "VK_ERROR_TOO_MANY_OBJECTS";892case VK_ERROR_FORMAT_NOT_SUPPORTED: return "VK_ERROR_FORMAT_NOT_SUPPORTED";893case VK_ERROR_SURFACE_LOST_KHR: return "VK_ERROR_SURFACE_LOST_KHR";894case VK_SUBOPTIMAL_KHR: return "VK_SUBOPTIMAL_KHR";895case VK_ERROR_OUT_OF_DATE_KHR: return "VK_ERROR_OUT_OF_DATE_KHR";896case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";897case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";898case VK_ERROR_OUT_OF_POOL_MEMORY: return "VK_ERROR_OUT_OF_POOL_MEMORY_KHR";899case VK_ERROR_INVALID_EXTERNAL_HANDLE: return "VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR";900case VK_ERROR_FRAGMENTED_POOL: return "VK_ERROR_FRAGMENTED_POOL";901case VK_ERROR_UNKNOWN: return "VK_ERROR_UNKNOWN (-13)";902case VK_ERROR_FRAGMENTATION: return "VK_ERROR_FRAGMENTATION";903case VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS: return "VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS";904case VK_PIPELINE_COMPILE_REQUIRED: return "VK_PIPELINE_COMPILE_REQUIRED";905case VK_ERROR_VALIDATION_FAILED_EXT: return "VK_ERROR_VALIDATION_FAILED_EXT";906case VK_ERROR_INVALID_SHADER_NV: return "VK_ERROR_INVALID_SHADER_NV";907case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT: return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT";908case VK_ERROR_NOT_PERMITTED_KHR: return "VK_ERROR_NOT_PERMITTED_KHR";909case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT";910case VK_THREAD_IDLE_KHR: return "VK_THREAD_IDLE_KHR";911case VK_THREAD_DONE_KHR: return "VK_THREAD_DONE_KHR";912case VK_OPERATION_DEFERRED_KHR: return "VK_OPERATION_DEFERRED_KHR";913case VK_OPERATION_NOT_DEFERRED_KHR: return "VK_OPERATION_NOT_DEFERRED_KHR";914default:915// This isn't thread safe, but this should be rare, and at worst, we'll get a jumble of two messages.916snprintf(temp, sizeof(temp), "VK_ERROR_???: 0x%08x", (u32)res);917return temp;918}919}920921922