【发布时间】:2021-11-24 08:01:14
【问题描述】:
我读过引擎会跳过 1 或 2 帧并保持这个距离,以确保渲染线程和主线程不会前进太多。
我有一个非常简单的命令队列,它允许主线程排队命令并让渲染线程调度它们,但我不知道如何在这些线程之间保持 1/2 帧距离。
基本实现:
#include <iostream>
#include <queue>
#include <mutex>
#include <functional>
#include <thread>
#include <condition_variable>
struct CommandQueue
{
//not thread-safe
//called only by the main thread
//collects all gl calls from the main thread
void Submit(std::function<void()> command)
{
commands.push(std::move(command));
}
//called only by the main thread
//when the current frame has finished pushing gl commands
//we're ready to push them into the render thread
void Flush()
{
{
std::unique_lock<std::mutex> lock(mutex);
commandsToExecute = std::move(commands);
}
cv.notify_one();
}
//called only by the render thread
//submit gl calls from our queue into the graphics queue
bool Execute()
{
auto renderCommands = WaitForCommands();
if(renderCommands.empty()) {
return false;
}
while(!renderCommands.empty()) {
auto cmd = std::move(renderCommands.front());
renderCommands.pop();
cmd();
}
return true;
}
void Quit()
{
quit.store(true, std::memory_order_relaxed);
cv.notify_one();
}
private:
std::queue<std::function<void()>> WaitForCommands()
{
std::unique_lock<std::mutex> lock(mutex);
cv.wait(lock, [this]() { return !commandsToExecute.empty() || quit.load(std::memory_order_relaxed); });
auto result = std::move(commandsToExecute);
return result;
}
std::mutex mutex;
std::condition_variable cv;
std::queue<std::function<void()>> commands;
std::queue<std::function<void()>> commandsToExecute;
std::atomic_bool quit{false};
};
int main()
{
CommandQueue commandQueue;
std::thread renderThread([&](){
while(true) {
if(!commandQueue.Execute()) {
break;
}
}
});
bool quit = false;
while(!quit) {
//example commands...
commandQueue.Submit([](){
glClear(GL_COLOR_BUFFER_BIT);
});
commandQueue.Submit([](){
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
});
commandQueue.Submit([](){
glViewport(0, 0, 1600, 900);
});
commandQueue.Submit([](){
SDL_GL_SwapWindow(window);
});
//notify the render thread that there is work to be done
commandQueue.Flush();
}
commandQueue.Flush();
commandQueue.Quit();
renderThread.join();
return 0;
}
如何实现这个 1/2 帧延迟?
【问题讨论】:
-
如果不让渲染线程滞后会出现问题吗?
-
@Jaan 是的。它会减慢应用程序的速度,因为主线程将太多命令推送到渲染线程中。结果,例如,当我想退出应用程序时,它需要大约 5 秒才能完成所有工作。而且我认为只有 2 帧同时运行就足够了。
-
@RichardCritten 这与图形和渲染线程有什么关系?
-
我很困惑,你的应用程序是如何因为渲染线程的负载而变慢的?您的应用程序的核心不是在主线程上运行,任何渲染都被卸载到渲染线程吗?我看到的唯一线程连接是在主循环之外的应用程序末尾,因此不会减慢任何速度。
标签: c++ multithreading opengl