Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/android/jni/AndroidVulkanContext.cpp
5698 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
#include "GPU/Vulkan/VulkanUtil.h"
16
17
AndroidVulkanContext::AndroidVulkanContext() {}
18
19
AndroidVulkanContext::~AndroidVulkanContext() {
20
delete g_Vulkan;
21
g_Vulkan = nullptr;
22
}
23
24
bool AndroidVulkanContext::InitAPI() {
25
INFO_LOG(Log::G3D, "AndroidVulkanContext::Init");
26
init_glslang();
27
28
g_LogOptions.breakOnError = true;
29
g_LogOptions.breakOnWarning = true;
30
g_LogOptions.msgBoxOnError = false;
31
32
std::string errorStr;
33
if (!VulkanLoad(&errorStr)) {
34
ERROR_LOG(Log::G3D, "Failed to load Vulkan driver library: %s", errorStr.c_str());
35
state_ = GraphicsContextState::FAILED_INIT;
36
return false;
37
}
38
39
if (!g_Vulkan) {
40
// TODO: Assert if g_Vulkan already exists here ?
41
INFO_LOG(Log::G3D, "Creating Vulkan context.");
42
g_Vulkan = new VulkanContext();
43
} else {
44
INFO_LOG(Log::G3D, "Reusing existing Vulkan context.");
45
}
46
47
VulkanContext::CreateInfo info{};
48
InitVulkanCreateInfoFromConfig(&info);
49
if (!g_Vulkan->CreateInstanceAndDevice(info)) {
50
delete g_Vulkan;
51
g_Vulkan = nullptr;
52
state_ = GraphicsContextState::FAILED_INIT;
53
return false;
54
}
55
56
INFO_LOG(Log::G3D, "Vulkan device created!");
57
state_ = GraphicsContextState::INITIALIZED;
58
return true;
59
}
60
61
bool AndroidVulkanContext::InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) {
62
INFO_LOG(Log::G3D, "AndroidVulkanContext::InitFromRenderThread: desiredwidth=%d desiredheight=%d", desiredBackbufferSizeX, desiredBackbufferSizeY);
63
if (!g_Vulkan) {
64
ERROR_LOG(Log::G3D, "AndroidVulkanContext::InitFromRenderThread: No Vulkan context");
65
return false;
66
}
67
68
VkResult res = g_Vulkan->InitSurface(WINDOWSYSTEM_ANDROID, (void *)wnd, nullptr);
69
if (res != VK_SUCCESS) {
70
ERROR_LOG(Log::G3D, "g_Vulkan->InitSurface failed: '%s'", VulkanResultToString(res));
71
return false;
72
}
73
74
bool useMultiThreading = g_Config.bRenderMultiThreading;
75
if (g_Config.iInflightFrames == 1) {
76
useMultiThreading = false;
77
}
78
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan, useMultiThreading);
79
80
VkPresentModeKHR presentMode = ConfigPresentModeToVulkan(draw_);
81
if (!g_Vulkan->InitSwapchain(presentMode)) {
82
g_Vulkan->DestroySurface();
83
return false;
84
}
85
86
SetGPUBackend(GPUBackend::VULKAN);
87
bool success = draw_->CreatePresets(); // Doesn't fail, we ship the compiler.
88
_assert_msg_(success, "Failed to compile preset shaders");
89
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
90
91
VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
92
renderManager->SetInflightFrames(g_Config.iInflightFrames);
93
if (!renderManager->HasBackbuffers()) {
94
ERROR_LOG(Log::G3D, "VulkanRenderManager has no backbuffers after InitFromRenderThread");
95
g_Vulkan->DestroySwapchain();
96
g_Vulkan->DestroySurface();
97
delete draw_;
98
draw_ = nullptr;
99
return false;
100
}
101
102
INFO_LOG(Log::G3D, "AndroidVulkanContext::Init completed successfully");
103
return true;
104
}
105
106
void AndroidVulkanContext::ShutdownFromRenderThread() {
107
INFO_LOG(Log::G3D, "AndroidVulkanContext::Shutdown");
108
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
109
delete draw_;
110
draw_ = nullptr;
111
g_Vulkan->WaitUntilQueueIdle();
112
g_Vulkan->PerformPendingDeletes();
113
g_Vulkan->DestroySwapchain();
114
g_Vulkan->DestroySurface();
115
INFO_LOG(Log::G3D, "Done with ShutdownFromRenderThread");
116
}
117
118
void AndroidVulkanContext::Shutdown() {
119
INFO_LOG(Log::G3D, "Calling NativeShutdownGraphics");
120
g_Vulkan->DestroyDevice();
121
g_Vulkan->DestroyInstance();
122
// We keep the g_Vulkan context around to avoid invalidating a ton of pointers around the app.
123
finalize_glslang();
124
INFO_LOG(Log::G3D, "AndroidVulkanContext::Shutdown completed");
125
}
126
127
void AndroidVulkanContext::Resize() {
128
INFO_LOG(Log::G3D, "AndroidVulkanContext::Resize begin (oldsize: %dx%d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
129
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
130
g_Vulkan->DestroySwapchain();
131
132
// TODO: We should only destroy the surface here if the window changed. We can track this inside g_Vulkan.
133
g_Vulkan->DestroySurface();
134
g_Vulkan->ReinitSurface();
135
136
VkPresentModeKHR presentMode = ConfigPresentModeToVulkan(draw_);
137
g_Vulkan->InitSwapchain(presentMode);
138
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
139
INFO_LOG(Log::G3D, "AndroidVulkanContext::Resize end (final size: %dx%d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
140
}
141
142