CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

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