Add targetFrameTime option for Vulkan backend

This commit is contained in:
2020-09-15 17:08:04 -04:00
parent bd5ea36659
commit 57cb96c1a7
9 changed files with 60 additions and 9 deletions

View File

@@ -1,5 +1,8 @@
#include "Common.hpp"
#include <cmath>
#include <numeric>
#include <thread>
namespace boo {
@@ -12,4 +15,25 @@ void UpdateGammaLUT(ITextureD* tex, float gamma) {
tex->unmap();
}
void Limiter::Sleep(nanotime_t targetFrameTime) {
if (targetFrameTime == 0) {
return;
}
auto start = delta_clock::now();
nanotime_t sleepTime = targetFrameTime - TimeSince(m_oldTime);
m_overhead = std::accumulate(m_overheadTimes.begin(), m_overheadTimes.end(), nanotime_t{}) /
static_cast<nanotime_t>(m_overheadTimes.size());
if (sleepTime > m_overhead) {
nanotime_t adjustedSleepTime = sleepTime - m_overhead;
std::this_thread::sleep_for(std::chrono::nanoseconds(adjustedSleepTime));
nanotime_t overslept = TimeSince(start) - adjustedSleepTime;
if (overslept < targetFrameTime) {
m_overheadTimes[m_overheadTimeIdx] = overslept;
m_overheadTimeIdx = (m_overheadTimeIdx + 1) % m_overheadTimes.size();
}
}
m_oldTime = delta_clock::now();
}
} // namespace boo

View File

@@ -7,6 +7,7 @@
#include <atomic>
#include <cassert>
#include <condition_variable>
#include <chrono>
#include <mutex>
#include <queue>
#include <thread>
@@ -283,4 +284,22 @@ public:
#define SCOPED_GRAPHICS_DEBUG_GROUP(...)
#endif
class Limiter {
using delta_clock = std::chrono::steady_clock;
using nanotime_t = std::chrono::nanoseconds::rep;
public:
void Sleep(nanotime_t targetFrameTimeNs);
private:
delta_clock::time_point m_oldTime;
std::array<nanotime_t, 4> m_overheadTimes{};
size_t m_overheadTimeIdx = 0;
nanotime_t m_overhead = 0;
nanotime_t TimeSince(delta_clock::time_point start) {
return std::chrono::duration_cast<std::chrono::nanoseconds>(delta_clock::now() - start).count();
}
};
} // namespace boo

View File

@@ -2871,6 +2871,8 @@ struct VulkanCommandQueue final : IGraphicsCommandQueue {
std::vector<boo::ObjToken<boo::IObj>> m_drawResTokens[2];
Limiter m_frameLimiter;
void resetCommandBuffer() {
ThrowIfFailed(vk::ResetCommandBuffer(m_cmdBufs[m_fillBuf], 0));
VkCommandBufferBeginInfo cmdBufBeginInfo = {};
@@ -4076,6 +4078,7 @@ void VulkanCommandQueue::execute() {
present.pResults = nullptr;
ThrowIfFailed(vk::QueuePresentKHR(m_ctx->m_queue, &present));
m_frameLimiter.Sleep(m_ctx->m_targetFrameTime);
}
resetCommandBuffer();