Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/libretro/LibretroVulkanContext.cpp
5659 views
1
2
#include "Common/GPU/Vulkan/VulkanLoader.h"
3
#include "Common/GPU/Vulkan/VulkanContext.h"
4
#include "Common/GPU/Vulkan/VulkanDebug.h"
5
#include "Common/Log.h"
6
#include "Core/Config.h"
7
#include "Core/ConfigValues.h"
8
#include "Core/System.h"
9
#include "GPU/GPUCommon.h"
10
#include "Common/Data/Text/Parsers.h"
11
12
#include "libretro/LibretroVulkanContext.h"
13
#include <libretro_vulkan.h>
14
#include <GPU/Vulkan/VulkanRenderManager.h>
15
16
#undef fflush
17
18
static VulkanContext *vk;
19
20
void vk_libretro_init(VkInstance instance, VkPhysicalDevice gpu, VkSurfaceKHR surface, PFN_vkGetInstanceProcAddr get_instance_proc_addr, const char **required_device_extensions, unsigned num_required_device_extensions, const char **required_device_layers, unsigned num_required_device_layers, const VkPhysicalDeviceFeatures *required_features);
21
void vk_libretro_shutdown();
22
void vk_libretro_set_hwrender_interface(retro_hw_render_interface *hw_render_interface);
23
void vk_libretro_wait_for_presentation();
24
25
LibretroVulkanContext::LibretroVulkanContext()
26
: LibretroHWRenderContext(RETRO_HW_CONTEXT_VULKAN, VK_MAKE_VERSION(1, 0, 18)) {}
27
28
void LibretroVulkanContext::SwapBuffers() {
29
vk_libretro_wait_for_presentation();
30
LibretroHWRenderContext::SwapBuffers();
31
}
32
33
static bool create_device(retro_vulkan_context *context, VkInstance instance, VkPhysicalDevice gpu, VkSurfaceKHR surface, PFN_vkGetInstanceProcAddr get_instance_proc_addr, const char **required_device_extensions, unsigned num_required_device_extensions, const char **required_device_layers, unsigned num_required_device_layers, const VkPhysicalDeviceFeatures *required_features) {
34
init_glslang();
35
36
vk = new VulkanContext();
37
38
vk_libretro_init(instance, gpu, surface, get_instance_proc_addr, required_device_extensions, num_required_device_extensions, required_device_layers, num_required_device_layers, required_features);
39
40
// TODO: Here we'll inject the instance and all of the stuff into the VulkanContext.
41
42
vk->CreateInstance({});
43
44
int physical_device = 0;
45
while (gpu && vk->GetPhysicalDevice(physical_device) != gpu) {
46
physical_device++;
47
}
48
49
if (!gpu) {
50
physical_device = vk->GetBestPhysicalDevice();
51
}
52
53
vk->CreateDevice(physical_device);
54
#ifdef _WIN32
55
vk->InitSurface(WINDOWSYSTEM_WIN32, nullptr, nullptr);
56
#elif defined(__ANDROID__)
57
vk->InitSurface(WINDOWSYSTEM_ANDROID, nullptr, nullptr);
58
#elif defined(VK_USE_PLATFORM_METAL_EXT)
59
vk->InitSurface(WINDOWSYSTEM_METAL_EXT, nullptr, nullptr);
60
#elif defined(VK_USE_PLATFORM_XLIB_KHR)
61
vk->InitSurface(WINDOWSYSTEM_XLIB, nullptr, nullptr);
62
#elif defined(VK_USE_PLATFORM_XCB_KHR)
63
vk->InitSurface(WINDOWSYSTEM_XCB, nullptr, nullptr);
64
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
65
vk->InitSurface(WINDOWSYSTEM_WAYLAND, nullptr, nullptr);
66
#elif defined(VK_USE_PLATFORM_DISPLAY_KHR)
67
vk->InitSurface(WINDOWSYSTEM_DISPLAY, nullptr, nullptr);
68
#endif
69
70
context->gpu = vk->GetPhysicalDevice(physical_device);
71
context->device = vk->GetDevice();
72
context->queue = vk->GetGraphicsQueue();
73
context->queue_family_index = vk->GetGraphicsQueueFamilyIndex();
74
context->presentation_queue = context->queue;
75
context->presentation_queue_family_index = context->queue_family_index;
76
#ifdef _DEBUG
77
fflush(stdout);
78
#endif
79
return true;
80
}
81
82
static const VkApplicationInfo *GetApplicationInfo(void) {
83
static VkApplicationInfo app_info{ VK_STRUCTURE_TYPE_APPLICATION_INFO };
84
app_info.pApplicationName = "PPSSPP";
85
app_info.applicationVersion = Version(PPSSPP_GIT_VERSION).ToInteger();
86
app_info.pEngineName = "PPSSPP";
87
app_info.engineVersion = 2;
88
app_info.apiVersion = VK_API_VERSION_1_0;
89
return &app_info;
90
}
91
92
bool LibretroVulkanContext::Init() {
93
if (!LibretroHWRenderContext::Init(true)) {
94
return false;
95
}
96
97
static const struct retro_hw_render_context_negotiation_interface_vulkan iface = {
98
RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN,
99
RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN_VERSION,
100
GetApplicationInfo,
101
create_device, // Callback above.
102
nullptr,
103
};
104
Libretro::environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE, (void *)&iface);
105
106
g_Config.iGPUBackend = (int)GPUBackend::VULKAN;
107
return true;
108
}
109
110
void LibretroVulkanContext::ContextReset() {
111
retro_hw_render_interface *vulkan;
112
if (!Libretro::environ_cb(RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE, (void **)&vulkan) || !vulkan) {
113
ERROR_LOG(Log::G3D, "Failed to get HW rendering interface!\n");
114
return;
115
}
116
if (vulkan->interface_version != RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION) {
117
ERROR_LOG(Log::G3D, "HW render interface mismatch, expected %u, got %u!\n", RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION, vulkan->interface_version);
118
return;
119
}
120
vk_libretro_set_hwrender_interface(vulkan);
121
122
LibretroHWRenderContext::ContextReset();
123
}
124
125
void LibretroVulkanContext::ContextDestroy() {
126
INFO_LOG(Log::G3D, "LibretroVulkanContext::ContextDestroy()");
127
vk->WaitUntilQueueIdle();
128
LibretroHWRenderContext::ContextDestroy();
129
}
130
131
void LibretroVulkanContext::CreateDrawContext() {
132
vk->ReinitSurface();
133
134
// TODO: Integrate properly with libretro vulkan context. We currently use a wacky wrapper (libretro_vulkan.cpp)
135
if (!vk->InitSwapchain(VK_PRESENT_MODE_FIFO_KHR)) {
136
return;
137
}
138
139
bool useMultiThreading = g_Config.bRenderMultiThreading;
140
if (g_Config.iInflightFrames == 1) {
141
useMultiThreading = false;
142
}
143
draw_ = Draw::T3DCreateVulkanContext(vk, useMultiThreading);
144
145
((VulkanRenderManager*)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER))->SetInflightFrames(g_Config.iInflightFrames);
146
SetGPUBackend(GPUBackend::VULKAN);
147
}
148
149
void LibretroVulkanContext::Shutdown() {
150
if (!vk) {
151
return;
152
}
153
154
if (draw_)
155
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vk->GetBackbufferWidth(), vk->GetBackbufferHeight());
156
157
LibretroHWRenderContext::Shutdown();
158
159
vk->WaitUntilQueueIdle();
160
161
vk->DestroySwapchain();
162
vk->DestroySurface();
163
vk->DestroyDevice();
164
vk->DestroyInstance();
165
166
delete vk;
167
vk = nullptr;
168
169
finalize_glslang();
170
vk_libretro_shutdown();
171
}
172
173
void *LibretroVulkanContext::GetAPIContext() { return vk; }
174
175