From fabd50b1780067ff3854e0ea68af9763170ca995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 17 Sep 2022 01:34:38 +0200 Subject: [PATCH] Move FrameData out of VulkanRenderManager --- CMakeLists.txt | 2 + Common/Common.vcxproj | 2 + Common/Common.vcxproj.filters | 6 +++ Common/GPU/Vulkan/VulkanFrameData.cpp | 15 ++++++ Common/GPU/Vulkan/VulkanFrameData.h | 65 +++++++++++++++++++++++ Common/GPU/Vulkan/VulkanQueueRunner.h | 9 +--- Common/GPU/Vulkan/VulkanRenderManager.cpp | 19 +++---- Common/GPU/Vulkan/VulkanRenderManager.h | 44 --------------- android/jni/Android.mk | 1 + libretro/Makefile.common | 1 + 10 files changed, 99 insertions(+), 65 deletions(-) create mode 100644 Common/GPU/Vulkan/VulkanFrameData.cpp create mode 100644 Common/GPU/Vulkan/VulkanFrameData.h diff --git a/CMakeLists.txt b/CMakeLists.txt index bc81d9be2b..cc31004ebc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -623,6 +623,8 @@ add_library(Common STATIC Common/GPU/Vulkan/VulkanRenderManager.h Common/GPU/Vulkan/VulkanQueueRunner.cpp Common/GPU/Vulkan/VulkanQueueRunner.h + Common/GPU/Vulkan/VulkanFrameData.cpp + Common/GPU/Vulkan/VulkanFrameData.h Common/Input/GestureDetector.cpp Common/Input/GestureDetector.h Common/Input/KeyCodes.h diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index 2895cdc837..d232c01534 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -441,6 +441,7 @@ + @@ -861,6 +862,7 @@ + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index ff9fd9eaa6..991b03a71f 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -419,6 +419,9 @@ GPU\Vulkan + + GPU\Vulkan + @@ -791,6 +794,9 @@ GPU\Vulkan + + GPU\Vulkan + diff --git a/Common/GPU/Vulkan/VulkanFrameData.cpp b/Common/GPU/Vulkan/VulkanFrameData.cpp new file mode 100644 index 0000000000..58ce42deaf --- /dev/null +++ b/Common/GPU/Vulkan/VulkanFrameData.cpp @@ -0,0 +1,15 @@ +#include "VulkanFrameData.h" + +void FrameData::AcquireNextImage(VulkanContext *vulkan) { + // Get the index of the next available swapchain image, and a semaphore to block command buffer execution on. + VkResult res = vkAcquireNextImageKHR(vulkan->GetDevice(), vulkan->GetSwapchain(), UINT64_MAX, acquireSemaphore, (VkFence)VK_NULL_HANDLE, &curSwapchainImage); + if (res == VK_SUBOPTIMAL_KHR) { + // Hopefully the resize will happen shortly. Ignore - one frame might look bad or something. + WARN_LOG(G3D, "VK_SUBOPTIMAL_KHR returned - ignoring"); + } else if (res == VK_ERROR_OUT_OF_DATE_KHR) { + WARN_LOG(G3D, "VK_ERROR_OUT_OF_DATE_KHR returned - processing the frame, but not presenting"); + skipSwap = true; + } else { + _assert_msg_(res == VK_SUCCESS, "vkAcquireNextImageKHR failed! result=%s", VulkanResultToString(res)); + } +} diff --git a/Common/GPU/Vulkan/VulkanFrameData.h b/Common/GPU/Vulkan/VulkanFrameData.h new file mode 100644 index 0000000000..21c44404b9 --- /dev/null +++ b/Common/GPU/Vulkan/VulkanFrameData.h @@ -0,0 +1,65 @@ +#pragma once + +#include + +#include +#include + +#include "Common/GPU/Vulkan/VulkanContext.h" + +struct VKRStep; + +enum class VKRRunType { + END, + SYNC, +}; + +struct QueueProfileContext { + VkQueryPool queryPool; + std::vector timestampDescriptions; + std::string profileSummary; + double cpuStartTime; + double cpuEndTime; +}; + +// Per-frame data, round-robin so we can overlap submission with execution of the previous frame. +struct FrameData { + std::mutex push_mutex; + std::condition_variable push_condVar; + + std::mutex pull_mutex; + std::condition_variable pull_condVar; + + bool readyForFence = true; + bool readyForRun = false; + bool skipSwap = false; + VKRRunType type = VKRRunType::END; + + VkFence fence; + VkFence readbackFence; // Strictly speaking we might only need one of these. + bool readbackFenceUsed = false; + + // These are on different threads so need separate pools. + VkCommandPool cmdPoolInit; // Written to from main thread + VkCommandPool cmdPoolMain; // Written to from render thread, which also submits + + VkCommandBuffer initCmd; + VkCommandBuffer mainCmd; + VkCommandBuffer presentCmd; + + bool hasInitCommands = false; + bool hasPresentCommands = false; + + std::vector steps; + + // Swapchain. + bool hasBegun = false; + uint32_t curSwapchainImage = -1; + VkSemaphore acquireSemaphore; // Not owned, shared between all FrameData. + + // Profiling. + QueueProfileContext profile; + bool profilingEnabled_; + + void AcquireNextImage(VulkanContext *vulkan); +}; diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.h b/Common/GPU/Vulkan/VulkanQueueRunner.h index fc30a0554a..d7a40000d3 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.h +++ b/Common/GPU/Vulkan/VulkanQueueRunner.h @@ -8,6 +8,7 @@ #include "Common/Data/Collections/Hashmaps.h" #include "Common/GPU/Vulkan/VulkanContext.h" #include "Common/GPU/Vulkan/VulkanBarrier.h" +#include "Common/GPU/Vulkan/VulkanFrameData.h" #include "Common/Data/Convert/SmallDataConvert.h" #include "Common/Data/Collections/TinySet.h" #include "Common/GPU/DataFormat.h" @@ -149,14 +150,6 @@ struct TransitionRequest { VkImageLayout targetLayout; }; -struct QueueProfileContext { - VkQueryPool queryPool; - std::vector timestampDescriptions; - std::string profileSummary; - double cpuStartTime; - double cpuEndTime; -}; - class VKRRenderPass; struct VKRStep { diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 4ce9ca1941..01180a2a44 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -326,6 +326,8 @@ VulkanRenderManager::VulkanRenderManager(VulkanContext *vulkan) : vulkan_(vulkan query_ci.queryCount = MAX_TIMESTAMP_QUERIES; query_ci.queryType = VK_QUERY_TYPE_TIMESTAMP; res = vkCreateQueryPool(vulkan_->GetDevice(), &query_ci, nullptr, &frameData_[i].profile.queryPool); + + frameData_[i].acquireSemaphore = acquireSemaphore_; } queueRunner_.CreateDeviceObjects(); @@ -1416,23 +1418,14 @@ void VulkanRenderManager::BeginSubmitFrame(int frame) { SubmitInitCommands(frame); if (!frameData.hasBegun) { - // Get the index of the next available swapchain image, and a semaphore to block command buffer execution on. - VkResult res = vkAcquireNextImageKHR(vulkan_->GetDevice(), vulkan_->GetSwapchain(), UINT64_MAX, acquireSemaphore_, (VkFence)VK_NULL_HANDLE, &frameData.curSwapchainImage); - if (res == VK_SUBOPTIMAL_KHR) { - // Hopefully the resize will happen shortly. Ignore - one frame might look bad or something. - WARN_LOG(G3D, "VK_SUBOPTIMAL_KHR returned - ignoring"); - } else if (res == VK_ERROR_OUT_OF_DATE_KHR) { - WARN_LOG(G3D, "VK_ERROR_OUT_OF_DATE_KHR returned - processing the frame, but not presenting"); - frameData.skipSwap = true; - } else { - _assert_msg_(res == VK_SUCCESS, "vkAcquireNextImageKHR failed! result=%s", VulkanResultToString(res)); - } + frameData.AcquireNextImage(vulkan_); + // Effectively resets both main and present command buffers, since they both live in this pool. vkResetCommandPool(vulkan_->GetDevice(), frameData.cmdPoolMain, 0); + VkCommandBufferBeginInfo begin{ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; begin.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - res = vkBeginCommandBuffer(frameData.mainCmd, &begin); - + VkResult res = vkBeginCommandBuffer(frameData.mainCmd, &begin); _assert_msg_(res == VK_SUCCESS, "vkBeginCommandBuffer failed! result=%s", VulkanResultToString(res)); queueRunner_.SetBackbuffer(framebuffers_[frameData.curSwapchainImage], swapchainImages_[frameData.curSwapchainImage].image); diff --git a/Common/GPU/Vulkan/VulkanRenderManager.h b/Common/GPU/Vulkan/VulkanRenderManager.h index 362e94bcac..e34c1a6550 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.h +++ b/Common/GPU/Vulkan/VulkanRenderManager.h @@ -65,11 +65,6 @@ private: std::string tag_; }; -enum class VKRRunType { - END, - SYNC, -}; - enum { MAX_TIMESTAMP_QUERIES = 128, }; @@ -487,45 +482,6 @@ private: VkSemaphore acquireSemaphore_; VkSemaphore renderingCompleteSemaphore_; - // Per-frame data, round-robin so we can overlap submission with execution of the previous frame. - struct FrameData { - std::mutex push_mutex; - std::condition_variable push_condVar; - - std::mutex pull_mutex; - std::condition_variable pull_condVar; - - bool readyForFence = true; - bool readyForRun = false; - bool skipSwap = false; - VKRRunType type = VKRRunType::END; - - VkFence fence; - VkFence readbackFence; // Strictly speaking we might only need one of these. - bool readbackFenceUsed = false; - - // These are on different threads so need separate pools. - VkCommandPool cmdPoolInit; // Written to from main thread - VkCommandPool cmdPoolMain; // Written to from render thread, which also submits - - VkCommandBuffer initCmd; - VkCommandBuffer mainCmd; - VkCommandBuffer presentCmd; - - bool hasInitCommands = false; - bool hasPresentCommands = false; - - std::vector steps; - - // Swapchain. - bool hasBegun = false; - uint32_t curSwapchainImage = -1; - - // Profiling. - QueueProfileContext profile; - bool profilingEnabled_; - }; - FrameData frameData_[VulkanContext::MAX_INFLIGHT_FRAMES]; int newInflightFrames_ = -1; int inflightFramesAtStart_ = 0; diff --git a/android/jni/Android.mk b/android/jni/Android.mk index b47db9d5cc..f317315e0a 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -51,6 +51,7 @@ VULKAN_FILES := \ $(SRC)/Common/GPU/Vulkan/thin3d_vulkan.cpp \ $(SRC)/Common/GPU/Vulkan/VulkanQueueRunner.cpp \ $(SRC)/Common/GPU/Vulkan/VulkanRenderManager.cpp \ + $(SRC)/Common/GPU/Vulkan/VulkanFrameData.cpp \ $(SRC)/Common/GPU/Vulkan/VulkanLoader.cpp \ $(SRC)/Common/GPU/Vulkan/VulkanContext.cpp \ $(SRC)/Common/GPU/Vulkan/VulkanDebug.cpp \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index ab2c4bfe1c..f08bd45633 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -253,6 +253,7 @@ SOURCES_CXX += \ $(COMMONDIR)/GPU/Vulkan/thin3d_vulkan.cpp \ $(COMMONDIR)/GPU/Vulkan/VulkanQueueRunner.cpp \ $(COMMONDIR)/GPU/Vulkan/VulkanRenderManager.cpp \ + $(COMMONDIR)/GPU/Vulkan/VulkanFrameData.cpp \ $(COMMONDIR)/GPU/Vulkan/VulkanLoader.cpp \ $(COMMONDIR)/GPU/Vulkan/VulkanContext.cpp \ $(COMMONDIR)/GPU/Vulkan/VulkanDebug.cpp \