mirror of
https://github.com/AxioDL/boo.git
synced 2025-06-06 22:53:39 +00:00
Add targetFrameTime option for Vulkan backend
This commit is contained in:
parent
bd5ea36659
commit
57cb96c1a7
@ -56,20 +56,21 @@ public:
|
|||||||
int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& cb, SystemStringView uniqueName,
|
int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& cb, SystemStringView uniqueName,
|
||||||
SystemStringView friendlyName, SystemStringView pname, const std::vector<SystemString>& args,
|
SystemStringView friendlyName, SystemStringView pname, const std::vector<SystemString>& args,
|
||||||
std::string_view gfxApi = {}, uint32_t samples = 1, uint32_t anisotropy = 1, bool deepColor = false,
|
std::string_view gfxApi = {}, uint32_t samples = 1, uint32_t anisotropy = 1, bool deepColor = false,
|
||||||
bool singleInstance = true);
|
int64_t targetFrameTime = 0, bool singleInstance = true);
|
||||||
extern IApplication* APP;
|
extern IApplication* APP;
|
||||||
|
|
||||||
static inline int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& cb,
|
static inline int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& cb,
|
||||||
SystemStringView uniqueName, SystemStringView friendlyName, int argc,
|
SystemStringView uniqueName, SystemStringView friendlyName, int argc,
|
||||||
const SystemChar** argv, std::string_view gfxApi = {}, uint32_t samples = 1,
|
const SystemChar** argv, std::string_view gfxApi = {}, uint32_t samples = 1,
|
||||||
uint32_t anisotropy = 1, bool deepColor = false, bool singleInstance = true) {
|
uint32_t anisotropy = 1, bool deepColor = false, int64_t targetFrameTime = 0,
|
||||||
|
bool singleInstance = true) {
|
||||||
if (APP)
|
if (APP)
|
||||||
return 1;
|
return 1;
|
||||||
std::vector<SystemString> args;
|
std::vector<SystemString> args;
|
||||||
for (int i = 1; i < argc; ++i)
|
for (int i = 1; i < argc; ++i)
|
||||||
args.push_back(argv[i]);
|
args.push_back(argv[i]);
|
||||||
return ApplicationRun(platform, cb, uniqueName, friendlyName, argv[0], args, gfxApi, samples, anisotropy, deepColor,
|
return ApplicationRun(platform, cb, uniqueName, friendlyName, argv[0], args, gfxApi, samples, anisotropy, deepColor,
|
||||||
singleInstance);
|
targetFrameTime, singleInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace boo
|
} // namespace boo
|
||||||
|
@ -97,6 +97,7 @@ struct VulkanContext {
|
|||||||
VkSampleCountFlags m_sampleCountDepth = VK_SAMPLE_COUNT_1_BIT;
|
VkSampleCountFlags m_sampleCountDepth = VK_SAMPLE_COUNT_1_BIT;
|
||||||
float m_anisotropy = 1.f;
|
float m_anisotropy = 1.f;
|
||||||
bool m_deepColor = false;
|
bool m_deepColor = false;
|
||||||
|
int64_t m_targetFrameTime = 0;
|
||||||
|
|
||||||
std::unordered_map<uint32_t, VkSampler> m_samplers;
|
std::unordered_map<uint32_t, VkSampler> m_samplers;
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
#include "Common.hpp"
|
#include "Common.hpp"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <numeric>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
namespace boo {
|
namespace boo {
|
||||||
|
|
||||||
@ -12,4 +15,25 @@ void UpdateGammaLUT(ITextureD* tex, float gamma) {
|
|||||||
tex->unmap();
|
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
|
} // namespace boo
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
#include <chrono>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
@ -283,4 +284,22 @@ public:
|
|||||||
#define SCOPED_GRAPHICS_DEBUG_GROUP(...)
|
#define SCOPED_GRAPHICS_DEBUG_GROUP(...)
|
||||||
#endif
|
#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
|
} // namespace boo
|
||||||
|
@ -2871,6 +2871,8 @@ struct VulkanCommandQueue final : IGraphicsCommandQueue {
|
|||||||
|
|
||||||
std::vector<boo::ObjToken<boo::IObj>> m_drawResTokens[2];
|
std::vector<boo::ObjToken<boo::IObj>> m_drawResTokens[2];
|
||||||
|
|
||||||
|
Limiter m_frameLimiter;
|
||||||
|
|
||||||
void resetCommandBuffer() {
|
void resetCommandBuffer() {
|
||||||
ThrowIfFailed(vk::ResetCommandBuffer(m_cmdBufs[m_fillBuf], 0));
|
ThrowIfFailed(vk::ResetCommandBuffer(m_cmdBufs[m_fillBuf], 0));
|
||||||
VkCommandBufferBeginInfo cmdBufBeginInfo = {};
|
VkCommandBufferBeginInfo cmdBufBeginInfo = {};
|
||||||
@ -4076,6 +4078,7 @@ void VulkanCommandQueue::execute() {
|
|||||||
present.pResults = nullptr;
|
present.pResults = nullptr;
|
||||||
|
|
||||||
ThrowIfFailed(vk::QueuePresentKHR(m_ctx->m_queue, &present));
|
ThrowIfFailed(vk::QueuePresentKHR(m_ctx->m_queue, &present));
|
||||||
|
m_frameLimiter.Sleep(m_ctx->m_targetFrameTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
resetCommandBuffer();
|
resetCommandBuffer();
|
||||||
|
@ -209,6 +209,7 @@ int ApplicationRun(IApplication::EPlatformType platform,
|
|||||||
uint32_t samples,
|
uint32_t samples,
|
||||||
uint32_t anisotropy,
|
uint32_t anisotropy,
|
||||||
bool deepColor,
|
bool deepColor,
|
||||||
|
int64_t targetFrameTime,
|
||||||
bool singleInstance) {
|
bool singleInstance) {
|
||||||
std::string thrName = std::string(friendlyName) + " Main Thread";
|
std::string thrName = std::string(friendlyName) + " Main Thread";
|
||||||
logvisor::RegisterThreadName(thrName.c_str());
|
logvisor::RegisterThreadName(thrName.c_str());
|
||||||
|
@ -97,7 +97,7 @@ class ApplicationWin32 final : public IApplication {
|
|||||||
public:
|
public:
|
||||||
ApplicationWin32(IApplicationCallback& callback, SystemStringView uniqueName, SystemStringView friendlyName,
|
ApplicationWin32(IApplicationCallback& callback, SystemStringView uniqueName, SystemStringView friendlyName,
|
||||||
SystemStringView pname, const std::vector<SystemString>& args, std::string_view gfxApi,
|
SystemStringView pname, const std::vector<SystemString>& args, std::string_view gfxApi,
|
||||||
uint32_t samples, uint32_t anisotropy, bool deepColor, bool singleInstance)
|
uint32_t samples, uint32_t anisotropy, bool deepColor, int64_t targetFrameTime, bool singleInstance)
|
||||||
: m_callback(callback), m_uniqueName(uniqueName), m_friendlyName(friendlyName), m_pname(pname), m_args(args) {
|
: m_callback(callback), m_uniqueName(uniqueName), m_friendlyName(friendlyName), m_pname(pname), m_args(args) {
|
||||||
m_3dCtx.m_ctx11.m_sampleCount = samples;
|
m_3dCtx.m_ctx11.m_sampleCount = samples;
|
||||||
m_3dCtx.m_ctx11.m_anisotropy = anisotropy;
|
m_3dCtx.m_ctx11.m_anisotropy = anisotropy;
|
||||||
@ -112,6 +112,7 @@ public:
|
|||||||
g_VulkanContext.m_sampleCountDepth = samples;
|
g_VulkanContext.m_sampleCountDepth = samples;
|
||||||
g_VulkanContext.m_anisotropy = anisotropy;
|
g_VulkanContext.m_anisotropy = anisotropy;
|
||||||
g_VulkanContext.m_deepColor = deepColor;
|
g_VulkanContext.m_deepColor = deepColor;
|
||||||
|
g_VulkanContext.m_targetFrameTime = targetFrameTime;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HMODULE dxgilib = LoadLibraryW(L"dxgi.dll");
|
HMODULE dxgilib = LoadLibraryW(L"dxgi.dll");
|
||||||
@ -472,7 +473,7 @@ IApplication* APP = nullptr;
|
|||||||
int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& cb, SystemStringView uniqueName,
|
int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& cb, SystemStringView uniqueName,
|
||||||
SystemStringView friendlyName, SystemStringView pname, const std::vector<SystemString>& args,
|
SystemStringView friendlyName, SystemStringView pname, const std::vector<SystemString>& args,
|
||||||
std::string_view gfxApi, uint32_t samples, uint32_t anisotropy, bool deepColor,
|
std::string_view gfxApi, uint32_t samples, uint32_t anisotropy, bool deepColor,
|
||||||
bool singleInstance) {
|
int64_t targetFrameTime, bool singleInstance) {
|
||||||
std::string thrName = WCSTMBS(friendlyName.data()) + " Main Thread";
|
std::string thrName = WCSTMBS(friendlyName.data()) + " Main Thread";
|
||||||
logvisor::RegisterThreadName(thrName.c_str());
|
logvisor::RegisterThreadName(thrName.c_str());
|
||||||
if (APP)
|
if (APP)
|
||||||
@ -501,7 +502,7 @@ int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& c
|
|||||||
RegisterClassW(&wndClass);
|
RegisterClassW(&wndClass);
|
||||||
|
|
||||||
APP = new ApplicationWin32(cb, uniqueName, friendlyName, pname, args, gfxApi, samples, anisotropy, deepColor,
|
APP = new ApplicationWin32(cb, uniqueName, friendlyName, pname, args, gfxApi, samples, anisotropy, deepColor,
|
||||||
singleInstance);
|
targetFrameTime, singleInstance);
|
||||||
int ret = APP->run();
|
int ret = APP->run();
|
||||||
delete APP;
|
delete APP;
|
||||||
APP = nullptr;
|
APP = nullptr;
|
||||||
|
@ -125,7 +125,7 @@ namespace boo {
|
|||||||
int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& cb, std::string_view uniqueName,
|
int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& cb, std::string_view uniqueName,
|
||||||
std::string_view friendlyName, std::string_view pname, const std::vector<std::string>& args,
|
std::string_view friendlyName, std::string_view pname, const std::vector<std::string>& args,
|
||||||
std::string_view gfxApi, uint32_t samples, uint32_t anisotropy, bool deepColor,
|
std::string_view gfxApi, uint32_t samples, uint32_t anisotropy, bool deepColor,
|
||||||
bool singleInstance) {
|
int64_t targetFrameTime, bool singleInstance) {
|
||||||
std::string thrName = std::string(friendlyName) + " Main";
|
std::string thrName = std::string(friendlyName) + " Main";
|
||||||
logvisor::RegisterThreadName(thrName.c_str());
|
logvisor::RegisterThreadName(thrName.c_str());
|
||||||
if (APP)
|
if (APP)
|
||||||
@ -135,7 +135,7 @@ int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& c
|
|||||||
singleInstance);
|
singleInstance);
|
||||||
else if (platform == IApplication::EPlatformType::Xlib || platform == IApplication::EPlatformType::Auto)
|
else if (platform == IApplication::EPlatformType::Xlib || platform == IApplication::EPlatformType::Auto)
|
||||||
APP = new ApplicationXlib(cb, uniqueName, friendlyName, pname, args, gfxApi, samples, anisotropy, deepColor,
|
APP = new ApplicationXlib(cb, uniqueName, friendlyName, pname, args, gfxApi, samples, anisotropy, deepColor,
|
||||||
singleInstance);
|
targetFrameTime, singleInstance);
|
||||||
else
|
else
|
||||||
return 1;
|
return 1;
|
||||||
int ret = APP->run();
|
int ret = APP->run();
|
||||||
|
@ -202,7 +202,7 @@ class ApplicationXlib final : public IApplication {
|
|||||||
public:
|
public:
|
||||||
ApplicationXlib(IApplicationCallback& callback, std::string_view uniqueName, std::string_view friendlyName,
|
ApplicationXlib(IApplicationCallback& callback, std::string_view uniqueName, std::string_view friendlyName,
|
||||||
std::string_view pname, const std::vector<std::string>& args, std::string_view gfxApi,
|
std::string_view pname, const std::vector<std::string>& args, std::string_view gfxApi,
|
||||||
uint32_t samples, uint32_t anisotropy, bool deepColor, bool singleInstance)
|
uint32_t samples, uint32_t anisotropy, bool deepColor, int64_t targetFrameTime, bool singleInstance)
|
||||||
: m_callback(callback)
|
: m_callback(callback)
|
||||||
, m_uniqueName(uniqueName)
|
, m_uniqueName(uniqueName)
|
||||||
, m_friendlyName(friendlyName)
|
, m_friendlyName(friendlyName)
|
||||||
@ -217,6 +217,7 @@ public:
|
|||||||
g_VulkanContext.m_sampleCountDepth = samples;
|
g_VulkanContext.m_sampleCountDepth = samples;
|
||||||
g_VulkanContext.m_anisotropy = anisotropy;
|
g_VulkanContext.m_anisotropy = anisotropy;
|
||||||
g_VulkanContext.m_deepColor = deepColor;
|
g_VulkanContext.m_deepColor = deepColor;
|
||||||
|
g_VulkanContext.m_targetFrameTime = targetFrameTime;
|
||||||
|
|
||||||
/* Check for Vulkan presence and preference */
|
/* Check for Vulkan presence and preference */
|
||||||
bool tryVulkan = true;
|
bool tryVulkan = true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user