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/android/jni/AndroidVulkanContext.cpp
Views: 1401
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 uint32_t FlagsFromConfig() {
25
uint32_t flags;
26
if (g_Config.bVSync) {
27
flags = VULKAN_FLAG_PRESENT_FIFO;
28
} else {
29
flags = VULKAN_FLAG_PRESENT_MAILBOX | VULKAN_FLAG_PRESENT_IMMEDIATE;
30
}
31
if (g_Validate) {
32
flags |= VULKAN_FLAG_VALIDATE;
33
}
34
return flags;
35
}
36
37
AndroidVulkanContext::AndroidVulkanContext() {}
38
39
AndroidVulkanContext::~AndroidVulkanContext() {
40
delete g_Vulkan;
41
g_Vulkan = nullptr;
42
}
43
44
bool AndroidVulkanContext::InitAPI() {
45
INFO_LOG(Log::G3D, "AndroidVulkanContext::Init");
46
init_glslang();
47
48
g_LogOptions.breakOnError = true;
49
g_LogOptions.breakOnWarning = true;
50
g_LogOptions.msgBoxOnError = false;
51
52
INFO_LOG(Log::G3D, "Creating Vulkan context");
53
Version gitVer(PPSSPP_GIT_VERSION);
54
55
std::string errorStr;
56
if (!VulkanLoad(&errorStr)) {
57
ERROR_LOG(Log::G3D, "Failed to load Vulkan driver library: %s", errorStr.c_str());
58
state_ = GraphicsContextState::FAILED_INIT;
59
return false;
60
}
61
62
if (!g_Vulkan) {
63
// TODO: Assert if g_Vulkan already exists here?
64
g_Vulkan = new VulkanContext();
65
}
66
67
VulkanContext::CreateInfo info{};
68
info.app_name = "PPSSPP";
69
info.app_ver = gitVer.ToInteger();
70
info.flags = FlagsFromConfig();
71
if (!g_Vulkan->CreateInstanceAndDevice(info)) {
72
delete g_Vulkan;
73
g_Vulkan = nullptr;
74
state_ = GraphicsContextState::FAILED_INIT;
75
return false;
76
}
77
78
INFO_LOG(Log::G3D, "Vulkan device created!");
79
state_ = GraphicsContextState::INITIALIZED;
80
return true;
81
}
82
83
bool AndroidVulkanContext::InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) {
84
INFO_LOG(Log::G3D, "AndroidVulkanContext::InitFromRenderThread: desiredwidth=%d desiredheight=%d", desiredBackbufferSizeX, desiredBackbufferSizeY);
85
if (!g_Vulkan) {
86
ERROR_LOG(Log::G3D, "AndroidVulkanContext::InitFromRenderThread: No Vulkan context");
87
return false;
88
}
89
90
VkResult res = g_Vulkan->InitSurface(WINDOWSYSTEM_ANDROID, (void *)wnd, nullptr);
91
if (res != VK_SUCCESS) {
92
ERROR_LOG(Log::G3D, "g_Vulkan->InitSurface failed: '%s'", VulkanResultToString(res));
93
return false;
94
}
95
96
bool success = true;
97
if (g_Vulkan->InitSwapchain()) {
98
bool useMultiThreading = g_Config.bRenderMultiThreading;
99
if (g_Config.iInflightFrames == 1) {
100
useMultiThreading = false;
101
}
102
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan, useMultiThreading);
103
SetGPUBackend(GPUBackend::VULKAN);
104
success = draw_->CreatePresets(); // Doesn't fail, we ship the compiler.
105
_assert_msg_(success, "Failed to compile preset shaders");
106
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
107
108
VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
109
renderManager->SetInflightFrames(g_Config.iInflightFrames);
110
success = renderManager->HasBackbuffers();
111
} else {
112
success = false;
113
}
114
115
INFO_LOG(Log::G3D, "AndroidVulkanContext::Init completed, %s", success ? "successfully" : "but failed");
116
if (!success) {
117
g_Vulkan->DestroySwapchain();
118
g_Vulkan->DestroySurface();
119
g_Vulkan->DestroyDevice();
120
g_Vulkan->DestroyInstance();
121
}
122
return success;
123
}
124
125
void AndroidVulkanContext::ShutdownFromRenderThread() {
126
INFO_LOG(Log::G3D, "AndroidVulkanContext::Shutdown");
127
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
128
delete draw_;
129
draw_ = nullptr;
130
g_Vulkan->WaitUntilQueueIdle();
131
g_Vulkan->PerformPendingDeletes();
132
g_Vulkan->DestroySwapchain();
133
g_Vulkan->DestroySurface();
134
INFO_LOG(Log::G3D, "Done with ShutdownFromRenderThread");
135
}
136
137
void AndroidVulkanContext::Shutdown() {
138
INFO_LOG(Log::G3D, "Calling NativeShutdownGraphics");
139
g_Vulkan->DestroyDevice();
140
g_Vulkan->DestroyInstance();
141
// We keep the g_Vulkan context around to avoid invalidating a ton of pointers around the app.
142
finalize_glslang();
143
INFO_LOG(Log::G3D, "AndroidVulkanContext::Shutdown completed");
144
}
145
146
void AndroidVulkanContext::Resize() {
147
INFO_LOG(Log::G3D, "AndroidVulkanContext::Resize begin (oldsize: %dx%d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
148
149
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
150
g_Vulkan->DestroySwapchain();
151
g_Vulkan->DestroySurface();
152
153
g_Vulkan->UpdateFlags(FlagsFromConfig());
154
155
g_Vulkan->ReinitSurface();
156
g_Vulkan->InitSwapchain();
157
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
158
INFO_LOG(Log::G3D, "AndroidVulkanContext::Resize end (final size: %dx%d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
159
}
160
161