From ec215f7de6cfcc8d4adaeeb856c56d71e3809119 Mon Sep 17 00:00:00 2001 From: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Fri, 24 Jun 2022 09:59:28 -0700 Subject: [PATCH] renderer: attach renderer to single thread --- app/render/rendermanager.cpp | 129 ++++++++++++++++++++++++++++------- app/render/rendermanager.h | 39 ++++++++++- 2 files changed, 143 insertions(+), 25 deletions(-) diff --git a/app/render/rendermanager.cpp b/app/render/rendermanager.cpp index 6281a380b..2c4be2b1b 100644 --- a/app/render/rendermanager.cpp +++ b/app/render/rendermanager.cpp @@ -38,21 +38,11 @@ namespace olive { RenderManager* RenderManager::instance_ = nullptr; RenderManager::RenderManager(QObject *parent) : - ThreadPool(1, parent), backend_(kOpenGL), aggressive_gc_(0) { - Renderer* graphics_renderer = nullptr; - if (backend_ == kOpenGL) { - graphics_renderer = new OpenGLRenderer(); - } - - if (graphics_renderer) { - context_ = new RendererThreadWrapper(graphics_renderer, this); - context_->Init(); - context_->PostInit(); - + context_ = new OpenGLRenderer(); decoder_cache_ = new DecoderCache(); shader_cache_ = new ShaderCache(); } else { @@ -61,6 +51,14 @@ RenderManager::RenderManager(QObject *parent) : decoder_cache_ = nullptr; } + if (context_) { + video_thread_ = new RenderThread(context_, decoder_cache_, shader_cache_, this); + audio_thread_ = new RenderThread(nullptr, decoder_cache_, shader_cache_, this); + + video_thread_->start(QThread::IdlePriority); + audio_thread_->start(QThread::IdlePriority); + } + decoder_clear_timer_ = new QTimer(this); decoder_clear_timer_->setInterval(kDecoderMaximumInactivity); connect(decoder_clear_timer_, &QTimer::timeout, this, &RenderManager::ClearOldDecoders); @@ -73,9 +71,14 @@ RenderManager::~RenderManager() delete shader_cache_; delete decoder_cache_; - context_->Destroy(); + video_thread_->quit(); + video_thread_->wait(); + context_->PostDestroy(); delete context_; + + audio_thread_->quit(); + audio_thread_->wait(); } } @@ -128,7 +131,7 @@ RenderTicketPtr RenderManager::RenderFrame(Node *node, ColorManager* color_manag ticket->setProperty("cacheuuid", QVariant::fromValue(cache->GetUuid())); } - AddTicket(ticket, priority); + video_thread_->AddTicket(ticket); return ticket; } @@ -145,22 +148,20 @@ RenderTicketPtr RenderManager::RenderAudio(Node *node, const TimeRange &r, const ticket->setProperty("enablewaveforms", generate_waveforms); ticket->setProperty("aparam", QVariant::fromValue(params)); - AddTicket(ticket, priority); + audio_thread_->AddTicket(ticket); return ticket; } -void RenderManager::RunTicket(RenderTicketPtr ticket) const +bool RenderManager::RemoveTicket(RenderTicketPtr ticket) { - // Setup the ticket for ::Process - ticket->Start(); - - if (ticket->IsCancelled()) { - ticket->Finish(); - return; + if (video_thread_->RemoveTicket(ticket)) { + return true; + } else if (audio_thread_->RemoveTicket(ticket)) { + return true; + } else { + return false; } - - RenderProcessor::Process(ticket, context_, decoder_cache_, shader_cache_); } void RenderManager::SetAggressiveGarbageCollection(bool enabled) @@ -192,4 +193,86 @@ void RenderManager::ClearOldDecoders() } } +RenderThread::RenderThread(Renderer *renderer, DecoderCache *decoder_cache, ShaderCache *shader_cache, QObject *parent) : + QThread(parent), + cancelled_(false), + context_(renderer), + decoder_cache_(decoder_cache), + shader_cache_(shader_cache) +{ + if (context_) { + context_->Init(); + context_->moveToThread(this); + } +} + +void RenderThread::AddTicket(RenderTicketPtr ticket) +{ + QMutexLocker locker(&mutex_); + queue_.push_back(ticket); + wait_.wakeOne(); +} + +bool RenderThread::RemoveTicket(RenderTicketPtr ticket) +{ + QMutexLocker locker(&mutex_); + + auto it = std::find(queue_.begin(), queue_.end(), ticket); + if (it == queue_.end()) { + return false; + } + + queue_.erase(it); + return true; +} + +void RenderThread::quit() +{ + QMutexLocker locker(&mutex_); + cancelled_ = true; + wait_.wakeOne(); +} + +void RenderThread::run() +{ + if (context_) { + context_->PostInit(); + } + + QMutexLocker locker(&mutex_); + + while (!cancelled_) { + if (queue_.empty()) { + wait_.wait(&mutex_); + } + + if (cancelled_) { + break; + } + + if (!queue_.empty()) { + RenderTicketPtr ticket = queue_.front(); + queue_.pop_front(); + + locker.unlock(); + + // Setup the ticket for ::Process + ticket->Start(); + + if (ticket->IsCancelled()) { + ticket->Finish(); + } else { + RenderProcessor::Process(ticket, context_, decoder_cache_, shader_cache_); + } + + locker.relock(); + } + } + + if (context_) { + context_->Destroy(); + context_->moveToThread(this->thread()); + } +} + } diff --git a/app/render/rendermanager.h b/app/render/rendermanager.h index c79c031fc..3100915df 100644 --- a/app/render/rendermanager.h +++ b/app/render/rendermanager.h @@ -35,7 +35,39 @@ namespace olive { -class RenderManager : public ThreadPool +class RenderThread : public QThread +{ + Q_OBJECT +public: + RenderThread(Renderer *renderer, DecoderCache *decoder_cache, ShaderCache *shader_cache, QObject *parent = nullptr); + + void AddTicket(RenderTicketPtr ticket); + + bool RemoveTicket(RenderTicketPtr ticket); + + void quit(); + +protected: + virtual void run() override; + +private: + QMutex mutex_; + + QWaitCondition wait_; + + std::list queue_; + + bool cancelled_; + + Renderer *context_; + + DecoderCache *decoder_cache_; + + ShaderCache *shader_cache_; + +}; + +class RenderManager : public QObject { Q_OBJECT public: @@ -96,7 +128,7 @@ public: */ RenderTicketPtr RenderAudio(Node *viewer, const TimeRange& r, const AudioParams& params, RenderMode::Mode mode, bool generate_waveforms, RenderTicketPriority priority = RenderTicketPriority::kNormal); - virtual void RunTicket(RenderTicketPtr ticket) const override; + bool RemoveTicket(RenderTicketPtr ticket); enum TicketType { kTypeVideo, @@ -135,6 +167,9 @@ private: QTimer *decoder_clear_timer_; + RenderThread *video_thread_; + RenderThread *audio_thread_; + private slots: void ClearOldDecoders();