diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj
index 59f1e261fc..e11012bc8f 100644
--- a/Common/Common.vcxproj
+++ b/Common/Common.vcxproj
@@ -241,6 +241,7 @@
+
@@ -311,6 +312,7 @@
+
diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters
index 8f32f6e506..e5bc85c777 100644
--- a/Common/Common.vcxproj.filters
+++ b/Common/Common.vcxproj.filters
@@ -64,6 +64,9 @@
Vulkan
+
+ Vulkan
+
@@ -115,6 +118,9 @@
Vulkan
+
+ Vulkan
+
diff --git a/ext/native/thin3d/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp
similarity index 100%
rename from ext/native/thin3d/VulkanContext.cpp
rename to Common/Vulkan/VulkanContext.cpp
diff --git a/ext/native/thin3d/VulkanContext.h b/Common/Vulkan/VulkanContext.h
similarity index 100%
rename from ext/native/thin3d/VulkanContext.h
rename to Common/Vulkan/VulkanContext.h
diff --git a/GPU/Vulkan/FramebufferVulkan.cpp b/GPU/Vulkan/FramebufferVulkan.cpp
index ae5c1ca13e..14f17ba6a8 100644
--- a/GPU/Vulkan/FramebufferVulkan.cpp
+++ b/GPU/Vulkan/FramebufferVulkan.cpp
@@ -22,8 +22,8 @@
#include "base/timeutil.h"
#include "math/lin/matrix4x4.h"
-#include "thin3d/VulkanContext.h"
+#include "Common/Vulkan/VulkanContext.h"
#include "Common/ColorConv.h"
#include "Core/Host.h"
#include "Core/MemMap.h"
diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp
index a666094708..06e6733d8e 100644
--- a/GPU/Vulkan/PipelineManagerVulkan.cpp
+++ b/GPU/Vulkan/PipelineManagerVulkan.cpp
@@ -2,11 +2,10 @@
#include "Common/Log.h"
#include "Common/StringUtils.h"
+#include "Common/Vulkan/VulkanContext.h"
#include "GPU/Vulkan/VulkanUtil.h"
#include "GPU/Vulkan/PipelineManagerVulkan.h"
#include "GPU/Vulkan/ShaderManagerVulkan.h"
-// #include "GPU/Vulkan/"
-#include "thin3d/VulkanContext.h"
PipelineManagerVulkan::PipelineManagerVulkan(VulkanContext *vulkan) : vulkan_(vulkan) {
pipelineCache_ = vulkan->CreatePipelineCache();
diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp
index 691b8667ef..4f062f4e6e 100644
--- a/GPU/Vulkan/ShaderManagerVulkan.cpp
+++ b/GPU/Vulkan/ShaderManagerVulkan.cpp
@@ -26,8 +26,7 @@
#include "math/math_util.h"
#include "math/dataconv.h"
#include "util/text/utf8.h"
-#include "thin3d/VulkanContext.h"
-
+#include "Common/Vulkan/VulkanContext.h"
#include "Common/Common.h"
#include "Core/Config.h"
#include "Core/Reporting.h"
diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp
index a38835dff6..bd730d7495 100644
--- a/GPU/Vulkan/TextureCacheVulkan.cpp
+++ b/GPU/Vulkan/TextureCacheVulkan.cpp
@@ -22,7 +22,7 @@
#include "i18n/i18n.h"
#include "math/math_util.h"
#include "profiler/profiler.h"
-#include "thin3d/VulkanContext.h"
+#include "Common/Vulkan/VulkanContext.h"
#include "Common/ColorConv.h"
#include "Core/Config.h"
#include "Core/Host.h"
diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h
index 46bd17688e..17eaabf863 100644
--- a/GPU/Vulkan/TextureCacheVulkan.h
+++ b/GPU/Vulkan/TextureCacheVulkan.h
@@ -22,7 +22,7 @@
#include "Globals.h"
#include "GPU/GPUInterface.h"
#include "GPU/GPUState.h"
-#include "thin3d/VulkanContext.h"
+#include "Common/Vulkan/VulkanContext.h"
#include "GPU/Vulkan/TextureScalerVulkan.h"
#include "GPU/Common/TextureCacheCommon.h"
diff --git a/Windows/GPU/WindowsVulkanContext.cpp b/Windows/GPU/WindowsVulkanContext.cpp
index b30f7788e8..95160d7e16 100644
--- a/Windows/GPU/WindowsVulkanContext.cpp
+++ b/Windows/GPU/WindowsVulkanContext.cpp
@@ -51,7 +51,7 @@
#include
#include "Common/Vulkan/VulkanLoader.h"
-#include "ext/native/thin3d/VulkanContext.h"
+#include "Common/Vulkan/VulkanContext.h"
#include "thin3d/thin3d.h"
#include "Windows/GPU/WindowsVulkanContext.h"
diff --git a/android/jni/Android.mk b/android/jni/Android.mk
index fc6cd779ec..c752482e2d 100644
--- a/android/jni/Android.mk
+++ b/android/jni/Android.mk
@@ -126,6 +126,7 @@ EGL_FILES := \
VULKAN_FILES := \
$(SRC)/Common/Vulkan/VulkanLoader.cpp \
+ $(SRC)/Common/Vulkan/VulkanContext.cpp \
$(SRC)/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp \
$(SRC)/GPU/Vulkan/DrawEngineVulkan.cpp \
$(SRC)/GPU/Vulkan/FramebufferVulkan.cpp \
diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp
index aa66e7923b..23b84a452f 100644
--- a/android/jni/app-android.cpp
+++ b/android/jni/app-android.cpp
@@ -4,6 +4,9 @@
// It calls a set of methods defined in NativeApp.h. These should be implemented
// by your game or app.
+
+#include
+#include
#include
#include
#include
@@ -30,8 +33,12 @@
#include "gfx/gl_common.h"
#include "gfx_es2/gpu_features.h"
+#include "thin3d/thin3d.h"
+#include "Core/Config.cpp"
#include "Common/GraphicsContext.h"
#include "Common/GL/GLInterfaceBase.h"
+#include "Common/Vulkan/VulkanLoader.h"
+#include "Common/Vulkan/VulkanContext.h"
#include "UI/GameInfoCache.h"
#include "app-android.h"
@@ -56,7 +63,12 @@ struct FrameCommand {
std::string params;
};
-class AndroidEGLGraphicsContext : public GraphicsContext {
+class AndroidGraphicsContext : public GraphicsContext {
+public:
+ virtual bool Init(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) = 0;
+};
+
+class AndroidEGLGraphicsContext : public AndroidGraphicsContext {
public:
AndroidEGLGraphicsContext() : wnd_(nullptr), gl(nullptr) {}
bool Init(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion);
@@ -137,6 +149,140 @@ public:
};
+static const bool g_validate_ = true;
+static VulkanContext *g_Vulkan;
+
+class AndroidVulkanContext : public AndroidGraphicsContext {
+public:
+ AndroidVulkanContext() {}
+ bool Init(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) override;
+ void Shutdown() override;
+ void SwapInterval(int interval) override;
+ void SwapBuffers() override;
+ void Resize() override;
+
+ void *GetAPIContext() { return g_Vulkan; }
+
+ Thin3DContext *CreateThin3DContext() override {
+ return T3DCreateVulkanContext(g_Vulkan);
+ }
+};
+
+struct VulkanLogOptions {
+ bool breakOnWarning;
+ bool breakOnError;
+ bool msgBoxOnError;
+};
+static VulkanLogOptions g_LogOptions;
+
+const char *ObjTypeToString(VkDebugReportObjectTypeEXT type) {
+ switch (type) {
+ case VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT: return "Instance";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT: return "PhysicalDevice";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT: return "Device";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT: return "Queue";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT: return "CommandBuffer";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT: return "DeviceMemory";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: return "Buffer";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT: return "BufferView";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: return "Image";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT: return "ImageView";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT: return "ShaderModule";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT: return "Pipeline";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT: return "PipelineLayout";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT: return "Sampler";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT: return "DescriptorSet";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT: return "DescriptorSetLayout";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT: return "DescriptorPool";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT: return "Fence";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT: return "Semaphore";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT: return "Event";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT: return "QueryPool";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT: return "Framebuffer";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT: return "RenderPass";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT: return "PipelineCache";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT: return "SurfaceKHR";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT: return "SwapChainKHR";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT: return "CommandPool";
+ default: return "Unknown";
+ }
+}
+
+static VkBool32 VKAPI_CALL Vulkan_Dbg(VkDebugReportFlagsEXT msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void *pUserData) {
+ const VulkanLogOptions *options = (const VulkanLogOptions *)pUserData;
+ int loglevel = ANDROID_LOG_INFO;
+ if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
+ loglevel = ANDROID_LOG_ERROR;
+ } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
+ loglevel = ANDROID_LOG_WARN;
+ } else if (msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
+ loglevel = ANDROID_LOG_WARN;
+ } else if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
+ loglevel = ANDROID_LOG_WARN;
+ } else if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
+ loglevel = ANDROID_LOG_WARN;
+ }
+
+ __android_log_print(loglevel, APP_NAME, "[%s] %s Code %d : %s", pLayerPrefix, ObjTypeToString(objType), msgCode, pMsg);
+
+ // false indicates that layer should not bail-out of an
+ // API call that had validation failures. This may mean that the
+ // app dies inside the driver due to invalid parameter(s).
+ // That's what would happen without validation layers, so we'll
+ // keep that behavior here.
+ return false;
+}
+
+bool AndroidVulkanContext::Init(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) {
+ if (g_Vulkan) {
+ return false;
+ }
+
+ init_glslang();
+
+ g_LogOptions.breakOnError = true;
+ g_LogOptions.breakOnWarning = true;
+ g_LogOptions.msgBoxOnError = false;
+
+ g_Vulkan = new VulkanContext("PPSSPP", (g_validate_ ? VULKAN_FLAG_VALIDATE : 0) | VULKAN_FLAG_PRESENT_MAILBOX);
+ g_Vulkan->CreateDevice(0);
+ if (g_validate_) {
+ int bits = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
+ g_Vulkan->InitDebugMsgCallback(Vulkan_Dbg, bits, &g_LogOptions);
+ }
+ g_Vulkan->InitSurfaceAndroid(wnd, desiredBackbufferSizeX, desiredBackbufferSizeY);
+ g_Vulkan->InitObjects(true);
+
+ return true;
+}
+
+void AndroidVulkanContext::Shutdown() {
+ g_Vulkan->WaitUntilQueueIdle();
+ g_Vulkan->DestroyObjects();
+ g_Vulkan->DestroyDebugMsgCallback();
+ g_Vulkan->DestroyDevice();
+ delete g_Vulkan;
+ g_Vulkan = nullptr;
+
+ finalize_glslang();
+}
+
+void AndroidVulkanContext::SwapBuffers() {
+}
+
+void AndroidVulkanContext::Resize() {
+ /*
+ g_Vulkan->DestroyObjects();
+
+ g_Vulkan->WaitUntilQueueIdle();
+
+ g_Vulkan->InitObjects(g_Vulkan)
+ */
+}
+
+void AndroidVulkanContext::SwapInterval(int interval) {
+}
+
static recursive_mutex frameCommandLock;
static std::queue frameCommands;
@@ -827,8 +973,16 @@ extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(J
ELOG("Error: Surface is null.");
return false;
}
+
+ bool vulkan = g_Config.iGPUBackend == GPU_BACKEND_VULKAN;
+
+ AndroidGraphicsContext *graphicsContext;
+ if (vulkan) {
+ graphicsContext = new AndroidVulkanContext();
+ } else {
+ graphicsContext = new AndroidEGLGraphicsContext();
+ }
- AndroidEGLGraphicsContext *graphicsContext = new AndroidEGLGraphicsContext();
if (!graphicsContext->Init(wnd, desiredBackbufferSizeX, desiredBackbufferSizeY, backbuffer_format, androidVersion)) {
ELOG("Failed to initialize graphics context.");
delete graphicsContext;
@@ -883,7 +1037,7 @@ extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(J
renderer_inited = false;
graphicsContext->Shutdown();
-
+ delete graphicsContext;
renderLoopRunning = false;
WLOG("Render loop function exited.");
return true;
diff --git a/ext/native/Android.mk b/ext/native/Android.mk
index 9ac0f5f8db..1f3eea6530 100644
--- a/ext/native/Android.mk
+++ b/ext/native/Android.mk
@@ -82,7 +82,6 @@ LOCAL_SRC_FILES :=\
thin3d/thin3d.cpp \
thin3d/thin3d_gl.cpp \
thin3d/thin3d_vulkan.cpp \
- thin3d/VulkanContext.cpp \
ui/view.cpp \
ui/viewgroup.cpp \
ui/ui.cpp \
diff --git a/ext/native/native.vcxproj b/ext/native/native.vcxproj
index 9557ba566e..f750063f7c 100644
--- a/ext/native/native.vcxproj
+++ b/ext/native/native.vcxproj
@@ -266,7 +266,6 @@
-
@@ -729,7 +728,6 @@
-
@@ -748,4 +746,4 @@
-
+
\ No newline at end of file
diff --git a/ext/native/native.vcxproj.filters b/ext/native/native.vcxproj.filters
index a278eba455..269ac5835d 100644
--- a/ext/native/native.vcxproj.filters
+++ b/ext/native/native.vcxproj.filters
@@ -308,9 +308,6 @@
math
-
- thin3d
-
@@ -748,9 +745,6 @@
thin3d
-
- thin3d
-
diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp
index 660c12c918..bf8d412fcc 100644
--- a/ext/native/thin3d/thin3d_vulkan.cpp
+++ b/ext/native/thin3d/thin3d_vulkan.cpp
@@ -30,7 +30,7 @@
#include "math/lin/matrix4x4.h"
#include "math/dataconv.h"
#include "thin3d/thin3d.h"
-#include "thin3d/VulkanContext.h"
+#include "Common/Vulkan/VulkanContext.h"
// We use a simple descriptor set for all rendering: 1 sampler, 1 texture, 1 UBO binding point.
// binding 0 - uniform data