Skip to content

Commit

Permalink
Merge pull request hrydgard#16035 from hrydgard/vk-acquire-late
Browse files Browse the repository at this point in the history
Vulkan: "Acquire" the image from the swapchain as late as possible in the frame
  • Loading branch information
hrydgard authored Sep 17, 2022
2 parents 143be81 + 4816285 commit bf59640
Show file tree
Hide file tree
Showing 20 changed files with 393 additions and 301 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions Common/Common.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,7 @@
<ClInclude Include="GPU\Vulkan\VulkanBarrier.h" />
<ClInclude Include="GPU\Vulkan\VulkanContext.h" />
<ClInclude Include="GPU\Vulkan\VulkanDebug.h" />
<ClInclude Include="GPU\Vulkan\VulkanFrameData.h" />
<ClInclude Include="GPU\Vulkan\VulkanImage.h" />
<ClInclude Include="GPU\Vulkan\VulkanLoader.h" />
<ClInclude Include="GPU\Vulkan\VulkanMemory.h" />
Expand Down Expand Up @@ -861,6 +862,7 @@
<ClCompile Include="GPU\Vulkan\VulkanBarrier.cpp" />
<ClCompile Include="GPU\Vulkan\VulkanContext.cpp" />
<ClCompile Include="GPU\Vulkan\VulkanDebug.cpp" />
<ClCompile Include="GPU\Vulkan\VulkanFrameData.cpp" />
<ClCompile Include="GPU\Vulkan\VulkanImage.cpp" />
<ClCompile Include="GPU\Vulkan\VulkanLoader.cpp" />
<ClCompile Include="GPU\Vulkan\VulkanMemory.cpp" />
Expand Down
6 changes: 6 additions & 0 deletions Common/Common.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,9 @@
<Filter>GPU\Vulkan</Filter>
</ClInclude>
<ClInclude Include="RiscVEmitter.h" />
<ClInclude Include="GPU\Vulkan\VulkanFrameData.h">
<Filter>GPU\Vulkan</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ABI.cpp" />
Expand Down Expand Up @@ -791,6 +794,9 @@
<Filter>GPU\Vulkan</Filter>
</ClCompile>
<ClCompile Include="RiscVEmitter.cpp" />
<ClCompile Include="GPU\Vulkan\VulkanFrameData.cpp">
<Filter>GPU\Vulkan</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="Crypto">
Expand Down
1 change: 0 additions & 1 deletion Common/GPU/OpenGL/GLRenderManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,6 @@ void GLRenderManager::EndSubmitFrame(int frame) {
void GLRenderManager::Run(int frame) {
BeginSubmitFrame(frame);


FrameData &frameData = frameData_[frame];

auto &stepsOnThread = frameData_[frame].steps;
Expand Down
15 changes: 15 additions & 0 deletions Common/GPU/Vulkan/VulkanFrameData.cpp
Original file line number Diff line number Diff line change
@@ -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));
}
}
65 changes: 65 additions & 0 deletions Common/GPU/Vulkan/VulkanFrameData.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#pragma once

#include <cstdint>

#include <mutex>
#include <condition_variable>

#include "Common/GPU/Vulkan/VulkanContext.h"

struct VKRStep;

enum class VKRRunType {
END,
SYNC,
};

struct QueueProfileContext {
VkQueryPool queryPool;
std::vector<std::string> 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<VKRStep *> 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);
};
Loading

0 comments on commit bf59640

Please sign in to comment.