mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-29 07:12:36 +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
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
class DrawerCommandQueue;
|
class DrawerCommandQueue;
|
||||||
typedef std::shared_ptr<DrawerCommandQueue> DrawerCommandQueuePtr;
|
typedef std::shared_ptr<DrawerCommandQueue> DrawerCommandQueuePtr;
|
||||||
|
@ -67,6 +68,8 @@ namespace swrenderer
|
||||||
std::unique_ptr<RenderClipSegment> ClipSegments;
|
std::unique_ptr<RenderClipSegment> ClipSegments;
|
||||||
DrawerCommandQueuePtr DrawQueue;
|
DrawerCommandQueuePtr DrawQueue;
|
||||||
|
|
||||||
|
std::thread thread;
|
||||||
|
|
||||||
// VisibleSprite working buffers
|
// VisibleSprite working buffers
|
||||||
short clipbot[MAXWIDTH];
|
short clipbot[MAXWIDTH];
|
||||||
short cliptop[MAXWIDTH];
|
short cliptop[MAXWIDTH];
|
||||||
|
|
|
@ -63,6 +63,11 @@ namespace swrenderer
|
||||||
Threads.push_back(std::make_unique<RenderThread>(this));
|
Threads.push_back(std::make_unique<RenderThread>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RenderScene::~RenderScene()
|
||||||
|
{
|
||||||
|
StopThreads();
|
||||||
|
}
|
||||||
|
|
||||||
void RenderScene::SetClearColor(int color)
|
void RenderScene::SetClearColor(int color)
|
||||||
{
|
{
|
||||||
clearcolor = color;
|
clearcolor = color;
|
||||||
|
@ -161,26 +166,38 @@ namespace swrenderer
|
||||||
void RenderScene::RenderThreadSlices()
|
void RenderScene::RenderThreadSlices()
|
||||||
{
|
{
|
||||||
int numThreads = r_scene_multithreaded ? 8 : 1;
|
int numThreads = r_scene_multithreaded ? 8 : 1;
|
||||||
|
if (numThreads != Threads.size())
|
||||||
while (Threads.size() > (size_t)numThreads)
|
|
||||||
{
|
{
|
||||||
Threads.pop_back();
|
StopThreads();
|
||||||
}
|
StartThreads(numThreads);
|
||||||
|
|
||||||
while (Threads.size() < (size_t)numThreads)
|
|
||||||
{
|
|
||||||
Threads.push_back(std::make_unique<RenderThread>(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup threads:
|
||||||
|
std::unique_lock<std::mutex> start_lock(start_mutex);
|
||||||
for (int i = 0; i < numThreads; i++)
|
for (int i = 0; i < numThreads; i++)
|
||||||
{
|
{
|
||||||
Threads[i]->X1 = viewwidth * i / numThreads;
|
Threads[i]->X1 = viewwidth * i / numThreads;
|
||||||
Threads[i]->X2 = viewwidth * (i + 1) / 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)
|
void RenderScene::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines)
|
||||||
{
|
{
|
||||||
auto viewport = RenderViewport::Instance();
|
auto viewport = RenderViewport::Instance();
|
||||||
|
|
|
@ -14,7 +14,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
#include "r_defs.h"
|
#include "r_defs.h"
|
||||||
#include "d_player.h"
|
#include "d_player.h"
|
||||||
|
|
||||||
|
@ -30,6 +34,7 @@ namespace swrenderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RenderScene();
|
RenderScene();
|
||||||
|
~RenderScene();
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void ScreenResized();
|
void ScreenResized();
|
||||||
|
@ -49,10 +54,20 @@ namespace swrenderer
|
||||||
void RenderDrawQueues();
|
void RenderDrawQueues();
|
||||||
void RenderThreadSlices();
|
void RenderThreadSlices();
|
||||||
void RenderThreadSlice(RenderThread *thread);
|
void RenderThreadSlice(RenderThread *thread);
|
||||||
|
|
||||||
|
void StartThreads(size_t numThreads);
|
||||||
|
void StopThreads();
|
||||||
|
|
||||||
bool dontmaplines = false;
|
bool dontmaplines = false;
|
||||||
int clearcolor = 0;
|
int clearcolor = 0;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<RenderThread>> Threads;
|
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