Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/android/jni/AndroidVulkanContext.cpp
3186 views
1
#include "AndroidVulkanContext.h"
2
#include "Common/System/Display.h"
3
#include "Common/System/NativeApp.h"
4
#include "Common/System/System.h"
5
#include "Common/Log.h"
6
#include "Common/GPU/Vulkan/VulkanContext.h"
7
#include "Common/GPU/Vulkan/VulkanDebug.h"
8
#include "Common/GPU/Vulkan/VulkanLoader.h"
9
#include "Common/GPU/Vulkan/VulkanRenderManager.h"
10
#include "Common/GPU/thin3d_create.h"
11
#include "Common/Data/Text/Parsers.h"
12
#include "Core/Config.h"
13
#include "Core/ConfigValues.h"
14
#include "Core/System.h"
15
16
17
#ifdef _DEBUG
18
static const bool g_Validate = true;
19
#else
20
static const bool g_Validate = false;
21
#endif
22
23
// TODO: Share this between backends.
24
static VulkanInitFlags FlagsFromConfig() {
25
VulkanInitFlags flags;
26
if (g_Config.bVSync) {
27
flags = VulkanInitFlags::PRESENT_FIFO;
28
} else {
29
flags = VulkanInitFlags::PRESENT_MAILBOX | VulkanInitFlags::PRESENT_IMMEDIATE;
30
}
31
if (g_Validate) {
32
flags |= VulkanInitFlags::VALIDATE;
33
}
34
if (g_Config.bVulkanDisableImplicitLayers) {
35
flags |= VulkanInitFlags::DISABLE_IMPLICIT_LAYERS;
36
}
37
return flags;
38
}
39
40
AndroidVulkanContext::AndroidVulkanContext() {}
41
42
AndroidVulkanContext::~AndroidVulkanContext() {
43
delete g_Vulkan;
44
g_Vulkan = nullptr;
45
}
46
47
bool AndroidVulkanContext::InitAPI() {
48
INFO_LOG(Log::G3D, "AndroidVulkanContext::Init");
49
init_glslang();
50
51
g_LogOptions.breakOnError = true;
52
g_LogOptions.breakOnWarning = true;
53
g_LogOptions.msgBoxOnError = false;
54
55
INFO_LOG(Log::G3D, "Creating Vulkan context");
56
Version gitVer(PPSSPP_GIT_VERSION);
57
58
std::string errorStr;
59
if (!VulkanLoad(&errorStr)) {
60
ERROR_LOG(Log::G3D, "Failed to load Vulkan driver library: %s", errorStr.c_str());
61
state_ = GraphicsContextState::FAILED_INIT;
62
return false;
63
}
64
65
if (!g_Vulkan) {
66
// TODO: Assert if g_Vulkan already exists here?
67
g_Vulkan = new VulkanContext();
68
}
69
70
VulkanContext::CreateInfo info{};
71
info.app_name = "PPSSPP";
72
info.app_ver = gitVer.ToInteger();
73
info.flags = FlagsFromConfig();
74
if (!g_Vulkan->CreateInstanceAndDevice(info)) {
75
delete g_Vulkan;
76
g_Vulkan = nullptr;
77
state_ = GraphicsContextState::FAILED_INIT;
78
return false;
79
}
80
81
INFO_LOG(Log::G3D, "Vulkan device created!");
82
state_ = GraphicsContextState::INITIALIZED;
83
return true;
84
}
85
86
bool AndroidVulkanContext::InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) {
87
INFO_LOG(Log::G3D, "AndroidVulkanContext::InitFromRenderThread: desiredwidth=%d desiredheight=%d", desiredBackbufferSizeX, desiredBackbufferSizeY);
88
if (!g_Vulkan) {
89
ERROR_LOG(Log::G3D, "AndroidVulkanContext::InitFromRenderThread: No Vulkan context");
90
return false;
91
}
92
93
VkResult res = g_Vulkan->InitSurface(WINDOWSYSTEM_ANDROID, (void *)wnd, nullptr);
94
if (res != VK_SUCCESS) {
95
ERROR_LOG(Log::G3D, "g_Vulkan->InitSurface failed: '%s'", VulkanResultToString(res));
96
return false;
97
}
98
99
bool success = false;
100
if (g_Vulkan->InitSwapchain()) {
101
bool useMultiThreading = g_Config.bRenderMultiThreading;
102
if (g_Config.iInflightFrames == 1) {
103
useMultiThreading = false;
104
}
105
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan, useMultiThreading);
106
SetGPUBackend(GPUBackend::VULKAN);
107
success = draw_->CreatePresets(); // Doesn't fail, we ship the compiler.
108
_assert_msg_(success, "Failed to compile preset shaders");
109
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
110
111
VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
112
renderManager->SetInflightFrames(g_Config.iInflightFrames);
113
success = renderManager->HasBackbuffers();
114
}
115
116
INFO_LOG(Log::G3D, "AndroidVulkanContext::Init completed, %s", success ? "successfully" : "but failed");
117
if (!success) {
118
g_Vulkan->DestroySwapchain();
119
g_Vulkan->DestroySurface();
120
g_Vulkan->DestroyDevice();
121
g_Vulkan->DestroyInstance();
122
}
123
return success;
124
}
125
126
void AndroidVulkanContext::ShutdownFromRenderThread() {
127
INFO_LOG(Log::G3D, "AndroidVulkanContext::Shutdown");
128
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
129
delete draw_;
130
draw_ = nullptr;
131
g_Vulkan->WaitUntilQueueIdle();
132
g_Vulkan->PerformPendingDeletes();
133
g_Vulkan->DestroySwapchain();
134
g_Vulkan->DestroySurface();
135
INFO_LOG(Log::G3D, "Done with ShutdownFromRenderThread");
136
}
137
138
void AndroidVulkanContext::Shutdown() {
139
INFO_LOG(Log::G3D, "Calling NativeShutdownGraphics");
140
g_Vulkan->DestroyDevice();
141
g_Vulkan->DestroyInstance();
142
// We keep the g_Vulkan context around to avoid invalidating a ton of pointers around the app.
143
finalize_glslang();
144
INFO_LOG(Log::G3D, "AndroidVulkanContext::Shutdown completed");
145
}
146
147
void AndroidVulkanContext::Resize() {
148
INFO_LOG(Log::G3D, "AndroidVulkanContext::Resize begin (oldsize: %dx%d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
149
150
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
151
g_Vulkan->DestroySwapchain();
152
g_Vulkan->DestroySurface();
153
154
g_Vulkan->UpdateInitFlags(FlagsFromConfig());
155
156
g_Vulkan->ReinitSurface();
157
g_Vulkan->InitSwapchain();
158
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
159
INFO_LOG(Log::G3D, "AndroidVulkanContext::Resize end (final size: %dx%d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
160
}
161
162