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