mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-29 07:22:05 +00:00
Execute scene slices on worker threads
This commit is contained in:
parent
d9e545a519
commit
8ad132b64f
3 changed files with 93 additions and 10 deletions
|
@ -23,6 +23,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
class DrawerCommandQueue;
|
||||
typedef std::shared_ptr<DrawerCommandQueue> DrawerCommandQueuePtr;
|
||||
|
@ -67,6 +68,8 @@ namespace swrenderer
|
|||
std::unique_ptr<RenderClipSegment> ClipSegments;
|
||||
DrawerCommandQueuePtr DrawQueue;
|
||||
|
||||
std::thread thread;
|
||||
|
||||
// VisibleSprite working buffers
|
||||
short clipbot[MAXWIDTH];
|
||||
short cliptop[MAXWIDTH];
|
||||
|
|
|
@ -63,6 +63,11 @@ namespace swrenderer
|
|||
Threads.push_back(std::make_unique<RenderThread>(this));
|
||||
}
|
||||
|
||||
RenderScene::~RenderScene()
|
||||
{
|
||||
StopThreads();
|
||||
}
|
||||
|
||||
void RenderScene::SetClearColor(int color)
|
||||
{
|
||||
clearcolor = color;
|
||||
|
@ -161,26 +166,38 @@ namespace swrenderer
|
|||
void RenderScene::RenderThreadSlices()
|
||||
{
|
||||
int numThreads = r_scene_multithreaded ? 8 : 1;
|
||||
|
||||
while (Threads.size() > (size_t)numThreads)
|
||||
if (numThreads != Threads.size())
|
||||
{
|
||||
Threads.pop_back();
|
||||
}
|
||||
|
||||
while (Threads.size() < (size_t)numThreads)
|
||||
{
|
||||
Threads.push_back(std::make_unique<RenderThread>(this));
|
||||
StopThreads();
|
||||
StartThreads(numThreads);
|
||||
}
|
||||
|
||||
// Setup threads:
|
||||
std::unique_lock<std::mutex> start_lock(start_mutex);
|
||||
for (int i = 0; i < numThreads; i++)
|
||||
{
|
||||
Threads[i]->X1 = viewwidth * i / numThreads;
|
||||
Threads[i]->X2 = viewwidth * (i + 1) / numThreads;
|
||||
}
|
||||
run_id++;
|
||||
start_lock.unlock();
|
||||
|
||||
for (int i = 0; i < numThreads; i++)
|
||||
// Notify threads to run
|
||||
if (Threads.size() > 1)
|
||||
{
|
||||
RenderThreadSlice(Threads[i].get());
|
||||
start_condition.notify_all();
|
||||
}
|
||||
|
||||
// Do the main thread ourselves:
|
||||
RenderThreadSlice(MainThread());
|
||||
|
||||
// Wait for everyone to finish:
|
||||
if (Threads.size() > 1)
|
||||
{
|
||||
std::unique_lock<std::mutex> end_lock(end_mutex);
|
||||
finished_threads++;
|
||||
end_condition.wait(end_lock, [&]() { return finished_threads == Threads.size(); });
|
||||
finished_threads = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,6 +263,54 @@ namespace swrenderer
|
|||
}
|
||||
}
|
||||
|
||||
void RenderScene::StartThreads(size_t numThreads)
|
||||
{
|
||||
while (Threads.size() < (size_t)numThreads)
|
||||
{
|
||||
auto thread = std::make_unique<RenderThread>(this);
|
||||
auto renderthread = thread.get();
|
||||
int start_run_id = run_id;
|
||||
thread->thread = std::thread([=]()
|
||||
{
|
||||
int last_run_id = start_run_id;
|
||||
while (true)
|
||||
{
|
||||
// Wait until we are signalled to run:
|
||||
std::unique_lock<std::mutex> start_lock(start_mutex);
|
||||
start_condition.wait(start_lock, [&]() { return run_id != last_run_id || shutdown_flag; });
|
||||
if (shutdown_flag)
|
||||
break;
|
||||
last_run_id = run_id;
|
||||
start_lock.unlock();
|
||||
|
||||
RenderThreadSlice(renderthread);
|
||||
|
||||
// Notify main thread that we finished:
|
||||
std::unique_lock<std::mutex> end_lock(end_mutex);
|
||||
finished_threads++;
|
||||
end_lock.unlock();
|
||||
end_condition.notify_all();
|
||||
}
|
||||
});
|
||||
Threads.push_back(std::move(thread));
|
||||
}
|
||||
}
|
||||
|
||||
void RenderScene::StopThreads()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(start_mutex);
|
||||
shutdown_flag = true;
|
||||
lock.unlock();
|
||||
start_condition.notify_all();
|
||||
while (Threads.size() > 1)
|
||||
{
|
||||
Threads.back()->thread.join();
|
||||
Threads.pop_back();
|
||||
}
|
||||
lock.lock();
|
||||
shutdown_flag = false;
|
||||
}
|
||||
|
||||
void RenderScene::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines)
|
||||
{
|
||||
auto viewport = RenderViewport::Instance();
|
||||
|
|
|
@ -14,7 +14,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include "r_defs.h"
|
||||
#include "d_player.h"
|
||||
|
||||
|
@ -30,6 +34,7 @@ namespace swrenderer
|
|||
{
|
||||
public:
|
||||
RenderScene();
|
||||
~RenderScene();
|
||||
|
||||
void Init();
|
||||
void ScreenResized();
|
||||
|
@ -49,10 +54,20 @@ namespace swrenderer
|
|||
void RenderDrawQueues();
|
||||
void RenderThreadSlices();
|
||||
void RenderThreadSlice(RenderThread *thread);
|
||||
|
||||
void StartThreads(size_t numThreads);
|
||||
void StopThreads();
|
||||
|
||||
bool dontmaplines = false;
|
||||
int clearcolor = 0;
|
||||
|
||||
std::vector<std::unique_ptr<RenderThread>> Threads;
|
||||
std::mutex start_mutex;
|
||||
std::condition_variable start_condition;
|
||||
bool shutdown_flag = false;
|
||||
int run_id = 0;
|
||||
std::mutex end_mutex;
|
||||
std::condition_variable end_condition;
|
||||
size_t finished_threads = 0;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue