2018-01-20 21:47:16 +01:00
|
|
|
#include "AndroidVulkanContext.h"
|
2020-10-04 10:10:55 +02:00
|
|
|
#include "Common/System/Display.h"
|
2020-10-04 10:30:18 +02:00
|
|
|
#include "Common/System/NativeApp.h"
|
|
|
|
#include "Common/System/System.h"
|
2020-08-15 12:03:39 +02:00
|
|
|
#include "Common/Log.h"
|
2020-10-04 23:24:14 +02:00
|
|
|
#include "Common/GPU/Vulkan/VulkanContext.h"
|
|
|
|
#include "Common/GPU/Vulkan/VulkanDebug.h"
|
|
|
|
#include "Common/GPU/Vulkan/VulkanLoader.h"
|
|
|
|
#include "Common/GPU/Vulkan/VulkanRenderManager.h"
|
|
|
|
#include "Common/GPU/thin3d_create.h"
|
2020-10-01 13:05:04 +02:00
|
|
|
#include "Common/Data/Text/Parsers.h"
|
2018-01-20 21:47:16 +01:00
|
|
|
#include "Core/Config.h"
|
2018-06-16 18:42:31 -07:00
|
|
|
#include "Core/ConfigValues.h"
|
2018-01-20 21:47:16 +01:00
|
|
|
#include "Core/System.h"
|
|
|
|
|
2020-06-21 22:49:44 +02:00
|
|
|
AndroidVulkanContext::AndroidVulkanContext() {}
|
2018-03-03 00:00:18 +01:00
|
|
|
|
2018-01-20 21:47:16 +01:00
|
|
|
AndroidVulkanContext::~AndroidVulkanContext() {
|
|
|
|
delete g_Vulkan;
|
|
|
|
g_Vulkan = nullptr;
|
|
|
|
}
|
|
|
|
|
2020-02-29 22:45:18 -08:00
|
|
|
static uint32_t FlagsFromConfig() {
|
2022-12-15 10:45:45 +01:00
|
|
|
uint32_t flags;
|
|
|
|
|
2020-02-29 22:45:18 -08:00
|
|
|
if (g_Config.bVSync) {
|
2022-12-15 10:45:45 +01:00
|
|
|
flags = VULKAN_FLAG_PRESENT_FIFO;
|
|
|
|
} else {
|
|
|
|
flags = VULKAN_FLAG_PRESENT_MAILBOX | VULKAN_FLAG_PRESENT_FIFO_RELAXED;
|
2020-02-29 22:45:18 -08:00
|
|
|
}
|
2022-12-15 10:45:45 +01:00
|
|
|
#ifdef _DEBUG
|
|
|
|
flags |= VULKAN_FLAG_VALIDATE;
|
|
|
|
#endif
|
|
|
|
return flags;
|
2020-02-29 22:45:18 -08:00
|
|
|
}
|
|
|
|
|
2018-03-03 00:00:18 +01:00
|
|
|
bool AndroidVulkanContext::InitAPI() {
|
2020-08-15 12:03:39 +02:00
|
|
|
INFO_LOG(G3D, "AndroidVulkanContext::Init");
|
2018-01-20 21:47:16 +01:00
|
|
|
init_glslang();
|
|
|
|
|
|
|
|
g_LogOptions.breakOnError = true;
|
|
|
|
g_LogOptions.breakOnWarning = true;
|
|
|
|
g_LogOptions.msgBoxOnError = false;
|
|
|
|
|
2020-08-15 12:03:39 +02:00
|
|
|
INFO_LOG(G3D, "Creating Vulkan context");
|
2018-01-20 21:47:16 +01:00
|
|
|
Version gitVer(PPSSPP_GIT_VERSION);
|
|
|
|
|
2019-09-01 22:20:44 +02:00
|
|
|
if (!VulkanLoad()) {
|
2020-08-15 12:03:39 +02:00
|
|
|
ERROR_LOG(G3D, "Failed to load Vulkan driver library");
|
2022-12-22 23:07:30 +01:00
|
|
|
state_ = GraphicsContextState::FAILED_INIT;
|
2019-09-01 22:20:44 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-01-20 21:47:16 +01:00
|
|
|
if (!g_Vulkan) {
|
2019-09-01 22:20:44 +02:00
|
|
|
// TODO: Assert if g_Vulkan already exists here?
|
2018-01-20 21:47:16 +01:00
|
|
|
g_Vulkan = new VulkanContext();
|
|
|
|
}
|
2019-09-01 22:20:44 +02:00
|
|
|
|
2018-01-20 21:47:16 +01:00
|
|
|
VulkanContext::CreateInfo info{};
|
|
|
|
info.app_name = "PPSSPP";
|
|
|
|
info.app_ver = gitVer.ToInteger();
|
2020-02-29 22:45:18 -08:00
|
|
|
info.flags = FlagsFromConfig();
|
2018-03-17 11:03:24 +01:00
|
|
|
VkResult res = g_Vulkan->CreateInstance(info);
|
|
|
|
if (res != VK_SUCCESS) {
|
2020-08-15 12:03:39 +02:00
|
|
|
ERROR_LOG(G3D, "Failed to create vulkan context: %s", g_Vulkan->InitError().c_str());
|
2018-03-17 11:03:24 +01:00
|
|
|
VulkanSetAvailable(false);
|
2018-01-20 21:47:16 +01:00
|
|
|
delete g_Vulkan;
|
|
|
|
g_Vulkan = nullptr;
|
2022-12-22 23:07:30 +01:00
|
|
|
state_ = GraphicsContextState::FAILED_INIT;
|
2018-01-20 21:47:16 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int physicalDevice = g_Vulkan->GetBestPhysicalDevice();
|
|
|
|
if (physicalDevice < 0) {
|
2020-08-15 12:03:39 +02:00
|
|
|
ERROR_LOG(G3D, "No usable Vulkan device found.");
|
2018-01-20 21:47:16 +01:00
|
|
|
g_Vulkan->DestroyInstance();
|
|
|
|
delete g_Vulkan;
|
|
|
|
g_Vulkan = nullptr;
|
2022-12-22 23:07:30 +01:00
|
|
|
state_ = GraphicsContextState::FAILED_INIT;
|
2018-01-20 21:47:16 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_Vulkan->ChooseDevice(physicalDevice);
|
|
|
|
|
2020-08-15 12:03:39 +02:00
|
|
|
INFO_LOG(G3D, "Creating Vulkan device");
|
2018-01-20 21:47:16 +01:00
|
|
|
if (g_Vulkan->CreateDevice() != VK_SUCCESS) {
|
2020-08-15 12:03:39 +02:00
|
|
|
INFO_LOG(G3D, "Failed to create vulkan device: %s", g_Vulkan->InitError().c_str());
|
2023-03-22 23:15:08 +01:00
|
|
|
System_Toast("No Vulkan driver found. Using OpenGL instead.");
|
2018-01-20 21:47:16 +01:00
|
|
|
g_Vulkan->DestroyInstance();
|
|
|
|
delete g_Vulkan;
|
|
|
|
g_Vulkan = nullptr;
|
2022-12-22 23:07:30 +01:00
|
|
|
state_ = GraphicsContextState::FAILED_INIT;
|
2018-01-20 21:47:16 +01:00
|
|
|
return false;
|
|
|
|
}
|
2020-07-28 19:06:29 +02:00
|
|
|
|
2020-08-15 12:03:39 +02:00
|
|
|
INFO_LOG(G3D, "Vulkan device created!");
|
2022-12-22 23:07:30 +01:00
|
|
|
state_ = GraphicsContextState::INITIALIZED;
|
2018-03-03 00:00:18 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AndroidVulkanContext::InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) {
|
2020-08-15 12:03:39 +02:00
|
|
|
INFO_LOG(G3D, "AndroidVulkanContext::InitFromRenderThread: desiredwidth=%d desiredheight=%d", desiredBackbufferSizeX, desiredBackbufferSizeY);
|
2019-09-17 10:52:02 +02:00
|
|
|
if (!g_Vulkan) {
|
2020-08-15 12:03:39 +02:00
|
|
|
ERROR_LOG(G3D, "AndroidVulkanContext::InitFromRenderThread: No Vulkan context");
|
2019-09-17 10:52:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
VkResult res = g_Vulkan->InitSurface(WINDOWSYSTEM_ANDROID, (void *)wnd, nullptr);
|
|
|
|
if (res != VK_SUCCESS) {
|
2020-08-15 12:03:39 +02:00
|
|
|
ERROR_LOG(G3D, "g_Vulkan->InitSurface failed: '%s'", VulkanResultToString(res));
|
2019-09-17 10:52:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-01-20 21:47:16 +01:00
|
|
|
bool success = true;
|
2020-07-18 21:42:13 +02:00
|
|
|
if (g_Vulkan->InitSwapchain()) {
|
2023-08-01 21:07:33 +02:00
|
|
|
bool useMultiThreading = g_Config.bRenderMultiThreading;
|
|
|
|
if (g_Config.iInflightFrames == 1) {
|
|
|
|
useMultiThreading = false;
|
|
|
|
}
|
|
|
|
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan, useMultiThreading);
|
2018-01-20 21:47:16 +01:00
|
|
|
SetGPUBackend(GPUBackend::VULKAN);
|
|
|
|
success = draw_->CreatePresets(); // Doesn't fail, we ship the compiler.
|
2020-07-19 17:47:02 +02:00
|
|
|
_assert_msg_(success, "Failed to compile preset shaders");
|
2018-01-20 21:47:16 +01:00
|
|
|
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
|
|
|
|
|
|
|
|
VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
2020-03-02 19:21:15 -08:00
|
|
|
renderManager->SetInflightFrames(g_Config.iInflightFrames);
|
2018-01-20 21:47:16 +01:00
|
|
|
success = renderManager->HasBackbuffers();
|
|
|
|
} else {
|
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
|
2020-08-15 12:03:39 +02:00
|
|
|
INFO_LOG(G3D, "AndroidVulkanContext::Init completed, %s", success ? "successfully" : "but failed");
|
2018-01-20 21:47:16 +01:00
|
|
|
if (!success) {
|
2020-07-18 20:35:39 +02:00
|
|
|
g_Vulkan->DestroySwapchain();
|
|
|
|
g_Vulkan->DestroySurface();
|
2018-01-20 21:47:16 +01:00
|
|
|
g_Vulkan->DestroyDevice();
|
|
|
|
g_Vulkan->DestroyInstance();
|
|
|
|
}
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
2018-03-11 17:14:11 +01:00
|
|
|
void AndroidVulkanContext::ShutdownFromRenderThread() {
|
2020-08-15 12:03:39 +02:00
|
|
|
INFO_LOG(G3D, "AndroidVulkanContext::Shutdown");
|
2018-01-20 21:47:16 +01:00
|
|
|
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
|
|
|
|
delete draw_;
|
|
|
|
draw_ = nullptr;
|
|
|
|
g_Vulkan->WaitUntilQueueIdle();
|
2018-03-11 17:14:11 +01:00
|
|
|
g_Vulkan->PerformPendingDeletes();
|
2020-07-18 20:35:39 +02:00
|
|
|
g_Vulkan->DestroySwapchain();
|
|
|
|
g_Vulkan->DestroySurface();
|
2020-08-15 12:03:39 +02:00
|
|
|
INFO_LOG(G3D, "Done with ShutdownFromRenderThread");
|
2018-03-11 17:14:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void AndroidVulkanContext::Shutdown() {
|
2020-08-15 12:03:39 +02:00
|
|
|
INFO_LOG(G3D, "Calling NativeShutdownGraphics");
|
2018-01-20 21:47:16 +01:00
|
|
|
g_Vulkan->DestroyDevice();
|
|
|
|
g_Vulkan->DestroyInstance();
|
|
|
|
// We keep the g_Vulkan context around to avoid invalidating a ton of pointers around the app.
|
|
|
|
finalize_glslang();
|
2020-08-15 12:03:39 +02:00
|
|
|
INFO_LOG(G3D, "AndroidVulkanContext::Shutdown completed");
|
2018-01-20 21:47:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void AndroidVulkanContext::SwapBuffers() {
|
|
|
|
}
|
|
|
|
|
|
|
|
void AndroidVulkanContext::Resize() {
|
2020-08-15 12:03:39 +02:00
|
|
|
INFO_LOG(G3D, "AndroidVulkanContext::Resize begin (oldsize: %dx%d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
|
2018-01-20 21:47:16 +01:00
|
|
|
|
|
|
|
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
|
2020-07-18 20:35:39 +02:00
|
|
|
g_Vulkan->DestroySwapchain();
|
|
|
|
g_Vulkan->DestroySurface();
|
2018-01-20 21:47:16 +01:00
|
|
|
|
2020-02-29 22:45:18 -08:00
|
|
|
g_Vulkan->UpdateFlags(FlagsFromConfig());
|
2020-07-18 20:43:47 +02:00
|
|
|
|
2019-01-25 12:49:18 +01:00
|
|
|
g_Vulkan->ReinitSurface();
|
2020-07-18 20:35:39 +02:00
|
|
|
g_Vulkan->InitSwapchain();
|
2018-01-20 21:47:16 +01:00
|
|
|
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
|
2020-08-15 12:03:39 +02:00
|
|
|
INFO_LOG(G3D, "AndroidVulkanContext::Resize end (final size: %dx%d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
|
2018-01-20 21:47:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void AndroidVulkanContext::SwapInterval(int interval) {
|
|
|
|
}
|