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