mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-14 18:19:36 +01:00
Move depth raster to a background thread
This commit is contained in:
1 parent
3c2167fa15
commit
e538b13ac6
2 files changed
+78
-20
No files matched your search
@@ -23,6 +23,7 @@
|
||||
#include "Common/LogReporting.h"
|
||||
#include "Common/Math/SIMDHeaders.h"
|
||||
#include "Common/Math/CrossSIMD.h"
|
||||
#include "Common/Thread/ThreadUtil.h"
|
||||
#include "Common/Math/lin/matrix4x4.h"
|
||||
#include "Common/TimeUtil.h"
|
||||
#include "Core/System.h"
|
||||
@@ -1044,47 +1045,101 @@ void DrawEngineCommon::ProcessDepthDraw(const DepthDraw &draw) {
|
||||
}
|
||||
|
||||
void DrawEngineCommon::EnqueueDepthDraw(const DepthDraw &draw) {
|
||||
std::lock_guard<std::mutex> lock(depthEnqueueMutex_);
|
||||
if (depthDraws_.empty()) {
|
||||
_dbg_assert_(curDraw_ == 0);
|
||||
_dbg_assert_(!inDepthDrawPass_);
|
||||
|
||||
depthDraws_.push_back(draw);
|
||||
depthRasterPassStart_ = time_now_d();
|
||||
inDepthDrawPass_ = true;
|
||||
depthEnqueueCond_.notify_one();
|
||||
} else {
|
||||
depthDraws_.push_back(draw);
|
||||
depthEnqueueCond_.notify_one(); // In case the thread caught up.
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if we actually waited.
|
||||
bool DrawEngineCommon::WaitForDepthPassFinish() {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(depthEnqueueMutex_);
|
||||
if (!inDepthDrawPass_) {
|
||||
_dbg_assert_(depthIndexCount_ == 0 && depthVertexCount_ == 0 && depthDraws_.empty());
|
||||
return false;
|
||||
}
|
||||
// In case the depth raster thread is idle, we need to nudge it.
|
||||
_dbg_assert_(!finishedSubmitting_);
|
||||
finishedSubmitting_ = true;
|
||||
depthEnqueueCond_.notify_one();
|
||||
}
|
||||
|
||||
depthDraws_.push_back(draw);
|
||||
// OK, we're in a pass. Wait for the thread to finish work.
|
||||
std::unique_lock<std::mutex> lock(depthFinishMutex_);
|
||||
while (!finishedDrawing_) {
|
||||
depthFinishCond_.wait(lock);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DrawEngineCommon::FlushQueuedDepth() {
|
||||
if (!inDepthDrawPass_) {
|
||||
_dbg_assert_(depthIndexCount_ == 0 && depthVertexCount_ == 0 && depthDraws_.empty());
|
||||
return;
|
||||
if (depthRasterPassStart_ != 0.0) {
|
||||
gpuStats.msRasterTimeAvailable += time_now_d() - depthRasterPassStart_;
|
||||
depthRasterPassStart_ = 0.0;
|
||||
}
|
||||
|
||||
_dbg_assert_(depthRasterPassStart_ != 0.0);
|
||||
gpuStats.msRasterTimeAvailable += time_now_d() - depthRasterPassStart_;
|
||||
depthRasterPassStart_ = 0.0;
|
||||
if (WaitForDepthPassFinish()) {
|
||||
// At this point, we know that the depth thread is paused.
|
||||
|
||||
// TODO: here we should wait for the thread to finish.
|
||||
|
||||
for (const auto &draw : depthDraws_) {
|
||||
ProcessDepthDraw(draw);
|
||||
// Reset queue
|
||||
depthIndexCount_ = 0;
|
||||
depthVertexCount_ = 0;
|
||||
depthDraws_.clear();
|
||||
inDepthDrawPass_ = false;
|
||||
finishedSubmitting_ = false;
|
||||
finishedDrawing_ = false; // not sure if it matters who resets this.
|
||||
curDraw_ = 0;
|
||||
} else {
|
||||
_dbg_assert_(curDraw_ == 0);
|
||||
_dbg_assert_(!inDepthDrawPass_);
|
||||
}
|
||||
|
||||
// Reset queue
|
||||
depthIndexCount_ = 0;
|
||||
depthVertexCount_ = 0;
|
||||
depthDraws_.clear();
|
||||
inDepthDrawPass_ = false;
|
||||
}
|
||||
|
||||
void DrawEngineCommon::DepthThreadFunc() {
|
||||
SetCurrentThreadName("DepthRaster");
|
||||
|
||||
while (true) {
|
||||
DepthDraw draw;
|
||||
bool hasDraw = false;
|
||||
// Wait for a draw or exit.
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(depthEnqueueMutex_);
|
||||
depthEnqueueCond_.wait(lock);
|
||||
if (depthDraws_.size() == curDraw_) {
|
||||
// We've drawn all we can. Let's check if we're finished.
|
||||
// If we reach here, we've drawn everything we can. And if that's the last
|
||||
// that will come in this batch, we notify.
|
||||
if (finishedSubmitting_) {
|
||||
// lock.unlock(); // possible optimization?
|
||||
std::lock_guard<std::mutex> flock(depthFinishMutex_);
|
||||
finishedDrawing_ = true;
|
||||
depthFinishCond_.notify_one();
|
||||
}
|
||||
|
||||
// OK, wait for something to do.
|
||||
depthEnqueueCond_.wait(lock);
|
||||
} else {
|
||||
_dbg_assert_(curDraw_ < depthDraws_.size());
|
||||
draw = depthDraws_[curDraw_++];
|
||||
hasDraw = true;
|
||||
}
|
||||
if (exitDepthThread_) {
|
||||
break;
|
||||
}
|
||||
// Then just loop around and wait for the next event.
|
||||
}
|
||||
|
||||
// OK, now we *definitely* have a draw to process, and we're outside locks. Do it!
|
||||
if (hasDraw) {
|
||||
ProcessDepthDraw(draw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,6 +368,7 @@ protected:
|
||||
private:
|
||||
// Internal implementation details.
|
||||
void DepthThreadFunc();
|
||||
bool WaitForDepthPassFinish();
|
||||
|
||||
inline void EnqueueDepthDraw(const DepthDraw &draw);
|
||||
inline void ProcessDepthDraw(const DepthDraw &draw);
|
||||
@@ -391,7 +392,9 @@ private:
|
||||
std::mutex depthEnqueueMutex_;
|
||||
std::condition_variable depthEnqueueCond_;
|
||||
|
||||
bool processingDepthDraw_ = false;
|
||||
bool finishedSubmitting_ = false;
|
||||
bool finishedDrawing_ = false;
|
||||
int curDraw_ = 0;
|
||||
std::mutex depthFinishMutex_;
|
||||
std::condition_variable depthFinishCond_;
|
||||
};
|
||||
Reference in new issue
Block a user