render: use single base thread for rendering

This commit is contained in:
itsmattkc
2022-06-21 14:08:29 -07:00
parent de31f3351a
commit 3f8001b146
5 changed files with 44 additions and 10 deletions
+6 -2
View File
@@ -838,7 +838,7 @@ AVFramePtr FFmpegDecoder::RetrieveFrame(const rational& time, const QAtomicInt *
} else {
// Cut down to thread count - 1 before we acquire a new frame
if (cached_frames_.size() == size_t(MaximumQueueSize())) {
if (cached_frames_.size() > size_t(MaximumQueueSize())) {
RemoveFirstFrame();
}
@@ -1041,7 +1041,11 @@ void FFmpegDecoder::RemoveFirstFrame()
int FFmpegDecoder::MaximumQueueSize()
{
return QThread::idealThreadCount();
// Fairly arbitrary size. This used to need to be the number of current threads to ensure any
// thread that arrived would have its frame available, but if we only have one render thread,
// that's no longer a concern. Now, this value could technically be 1, but some memory cache
// may be useful for reversing. This value may be tweaked over time.
return 2;
}
FFmpegDecoder::Instance::Instance() :
+18 -6
View File
@@ -38,8 +38,9 @@ namespace olive {
RenderManager* RenderManager::instance_ = nullptr;
RenderManager::RenderManager(QObject *parent) :
ThreadPool(0, parent),
backend_(kOpenGL)
ThreadPool(1, parent),
backend_(kOpenGL),
aggressive_gc_(0)
{
Renderer* graphics_renderer = nullptr;
@@ -60,10 +61,10 @@ RenderManager::RenderManager(QObject *parent) :
decoder_cache_ = nullptr;
}
QTimer *decoder_clear_timer = new QTimer(this);
decoder_clear_timer->setInterval(kDecoderMaximumInactivity);
connect(decoder_clear_timer, &QTimer::timeout, this, &RenderManager::ClearOldDecoders);
decoder_clear_timer->start();
decoder_clear_timer_ = new QTimer(this);
decoder_clear_timer_->setInterval(kDecoderMaximumInactivity);
connect(decoder_clear_timer_, &QTimer::timeout, this, &RenderManager::ClearOldDecoders);
decoder_clear_timer_->start();
}
RenderManager::~RenderManager()
@@ -162,6 +163,17 @@ void RenderManager::RunTicket(RenderTicketPtr ticket) const
RenderProcessor::Process(ticket, context_, decoder_cache_, shader_cache_);
}
void RenderManager::SetAggressiveGarbageCollection(bool enabled)
{
aggressive_gc_ += enabled ? 1 : -1;
if (aggressive_gc_ > 0) {
decoder_clear_timer_->setInterval(kDecoderMaximumInactivityAggressive);
} else {
decoder_clear_timer_->setInterval(kDecoderMaximumInactivity);
}
}
void RenderManager::ClearOldDecoders()
{
QMutexLocker locker(decoder_cache_->mutex());
+9 -1
View File
@@ -113,6 +113,9 @@ public:
return QThread::idealThreadCount();
}
public slots:
void SetAggressiveGarbageCollection(bool enabled);
signals:
private:
@@ -130,7 +133,12 @@ private:
ShaderCache* shader_cache_;
static constexpr auto kDecoderMaximumInactivity = 10000;
static constexpr auto kDecoderMaximumInactivityAggressive = 1000;
static constexpr auto kDecoderMaximumInactivity = 5000;
int aggressive_gc_;
QTimer *decoder_clear_timer_;
private slots:
void ClearOldDecoders();
+4
View File
@@ -44,6 +44,8 @@ bool RenderTask::Render(ColorManager* manager,
const QMatrix4x4 &force_matrix, VideoParams::Format force_format,
ColorProcessorPtr force_color_output)
{
QMetaObject::invokeMethod(RenderManager::instance(), "SetAggressiveGarbageCollection", Q_ARG(bool, true));
// Run watchers in another thread so they can accept signals even while this thread is blocked
QThread watcher_thread;
watcher_thread.start();
@@ -236,6 +238,8 @@ bool RenderTask::Render(ColorManager* manager,
watcher_thread.quit();
watcher_thread.wait();
QMetaObject::invokeMethod(RenderManager::instance(), "SetAggressiveGarbageCollection", Q_ARG(bool, false));
return result;
}
+7 -1
View File
@@ -765,6 +765,8 @@ void ViewerWidget::PlayInternal(int speed, bool in_to_out_only)
viewer->auto_cacher_.SetAudioPaused(true);
}
RenderManager::instance()->SetAggressiveGarbageCollection(true);
// Disarm recording if armed
if (record_armed_) {
DisarmRecording();
@@ -861,6 +863,8 @@ void ViewerWidget::PauseInternal()
}
UpdateTextureFromNode();
RenderManager::instance()->SetAggressiveGarbageCollection(false);
}
prequeuing_video_ = false;
@@ -1108,7 +1112,9 @@ void ViewerWidget::RendererGeneratedFrameForQueue()
prequeuing_video_ = false;
FinishPlayPreprocess();
} else {
RequestNextFrameForQueue();
// This call was mostly necessary to keep the threads busy between prequeue and playback.
// If we only have a single render thread, it's no longer necessary.
//RequestNextFrameForQueue();
}
}
}