mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 01:36:56 +02:00
drafting along the RenderTHread class
This commit is contained in:
parent
7def4bf29b
commit
c24083c1f0
8 changed files with 187 additions and 45 deletions
|
@ -2425,6 +2425,7 @@ void Application::cleanupBeforeQuit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
_window->saveGeometry();
|
_window->saveGeometry();
|
||||||
|
|
||||||
// _gpuContext->shutdown();
|
// _gpuContext->shutdown();
|
||||||
|
|
||||||
// Destroy third party processes after scripts have finished using them.
|
// Destroy third party processes after scripts have finished using them.
|
||||||
|
@ -4178,41 +4179,37 @@ bool Application::acceptSnapshot(const QString& urlString) {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
//
|
||||||
static uint32_t _renderedFrameIndex { INVALID_FRAME };
|
//bool Application::shouldPaint() const {
|
||||||
|
// if (_aboutToQuit || _window->isMinimized()) {
|
||||||
bool Application::shouldPaint() const {
|
// return false;
|
||||||
if (_aboutToQuit || _window->isMinimized()) {
|
// }
|
||||||
return false;
|
//
|
||||||
}
|
//
|
||||||
|
// auto displayPlugin = getActiveDisplayPlugin();
|
||||||
|
//
|
||||||
auto displayPlugin = getActiveDisplayPlugin();
|
//#ifdef DEBUG_PAINT_DELAY
|
||||||
|
// static uint64_t paintDelaySamples{ 0 };
|
||||||
#ifdef DEBUG_PAINT_DELAY
|
// static uint64_t paintDelayUsecs{ 0 };
|
||||||
static uint64_t paintDelaySamples{ 0 };
|
//
|
||||||
static uint64_t paintDelayUsecs{ 0 };
|
// paintDelayUsecs += displayPlugin->getPaintDelayUsecs();
|
||||||
|
//
|
||||||
paintDelayUsecs += displayPlugin->getPaintDelayUsecs();
|
// static const int PAINT_DELAY_THROTTLE = 1000;
|
||||||
|
// if (++paintDelaySamples % PAINT_DELAY_THROTTLE == 0) {
|
||||||
static const int PAINT_DELAY_THROTTLE = 1000;
|
// qCDebug(interfaceapp).nospace() <<
|
||||||
if (++paintDelaySamples % PAINT_DELAY_THROTTLE == 0) {
|
// "Paint delay (" << paintDelaySamples << " samples): " <<
|
||||||
qCDebug(interfaceapp).nospace() <<
|
// (float)paintDelaySamples / paintDelayUsecs << "us";
|
||||||
"Paint delay (" << paintDelaySamples << " samples): " <<
|
// }
|
||||||
(float)paintDelaySamples / paintDelayUsecs << "us";
|
//#endif
|
||||||
}
|
//
|
||||||
#endif
|
// // Throttle if requested
|
||||||
|
// //if (displayPlugin->isThrottled() && (_graphicsEngine._renderEventHandler->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) {
|
||||||
// Throttle if requested
|
// if (displayPlugin->isThrottled() && !_graphicsEngine.shouldPaint()) {
|
||||||
//if (displayPlugin->isThrottled() && (_graphicsEngine._renderEventHandler->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) {
|
// return false;
|
||||||
if (displayPlugin->isThrottled() && !_graphicsEngine.shouldPaint()) {
|
// }
|
||||||
return false;
|
//
|
||||||
}
|
// return true;
|
||||||
|
//}
|
||||||
// Sync up the _renderedFrameIndex
|
|
||||||
_renderedFrameIndex = displayPlugin->presentCount();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
|
@ -157,7 +157,7 @@ public:
|
||||||
void updateSecondaryCameraViewFrustum();
|
void updateSecondaryCameraViewFrustum();
|
||||||
|
|
||||||
void updateCamera(RenderArgs& renderArgs, float deltaTime);
|
void updateCamera(RenderArgs& renderArgs, float deltaTime);
|
||||||
bool shouldPaint() const;
|
// bool shouldPaint() const;
|
||||||
// void paintGL();
|
// void paintGL();
|
||||||
void resizeGL();
|
void resizeGL();
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ void GraphicsEngine::initializeGPU(GLWidget* glwidget) {
|
||||||
|
|
||||||
_renderEventHandler = new RenderEventHandler(
|
_renderEventHandler = new RenderEventHandler(
|
||||||
glwidget->qglContext(),
|
glwidget->qglContext(),
|
||||||
|
[this]() { return this->shouldPaint(); },
|
||||||
[this]() { this->render_performFrame(); }
|
[this]() { this->render_performFrame(); }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -147,12 +148,37 @@ static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SI
|
||||||
|
|
||||||
|
|
||||||
bool GraphicsEngine::shouldPaint() const {
|
bool GraphicsEngine::shouldPaint() const {
|
||||||
// Throttle if requested
|
|
||||||
if ((static_cast<RenderEventHandler*>(_renderEventHandler)->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) {
|
// if (_aboutToQuit || _window->isMinimized()) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return true;
|
|
||||||
|
auto displayPlugin = qApp->getActiveDisplayPlugin();
|
||||||
|
|
||||||
|
#ifdef DEBUG_PAINT_DELAY
|
||||||
|
static uint64_t paintDelaySamples{ 0 };
|
||||||
|
static uint64_t paintDelayUsecs{ 0 };
|
||||||
|
|
||||||
|
paintDelayUsecs += displayPlugin->getPaintDelayUsecs();
|
||||||
|
|
||||||
|
static const int PAINT_DELAY_THROTTLE = 1000;
|
||||||
|
if (++paintDelaySamples % PAINT_DELAY_THROTTLE == 0) {
|
||||||
|
qCDebug(interfaceapp).nospace() <<
|
||||||
|
"Paint delay (" << paintDelaySamples << " samples): " <<
|
||||||
|
(float)paintDelaySamples / paintDelayUsecs << "us";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Throttle if requested
|
||||||
|
//if (displayPlugin->isThrottled() && (_graphicsEngine._renderEventHandler->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) {
|
||||||
|
if ( displayPlugin->isThrottled() &&
|
||||||
|
(static_cast<RenderEventHandler*>(_renderEventHandler)->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GraphicsEngine::checkPendingRenderEvent() {
|
bool GraphicsEngine::checkPendingRenderEvent() {
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
#include <render/Engine.h>
|
#include <render/Engine.h>
|
||||||
|
|
||||||
|
#include "RenderThread.h"
|
||||||
|
|
||||||
#include <OctreeConstants.h>
|
#include <OctreeConstants.h>
|
||||||
#include <shared/RateCounter.h>
|
#include <shared/RateCounter.h>
|
||||||
|
|
||||||
|
@ -51,6 +53,8 @@ public:
|
||||||
render::EnginePointer getRenderEngine() const { return _renderEngine; }
|
render::EnginePointer getRenderEngine() const { return _renderEngine; }
|
||||||
gpu::ContextPointer getGPUContext() const { return _gpuContext; }
|
gpu::ContextPointer getGPUContext() const { return _gpuContext; }
|
||||||
|
|
||||||
|
FrameQueuePointer getFrameQueue() const { return _frameQueue; }
|
||||||
|
|
||||||
// Same as the one in application
|
// Same as the one in application
|
||||||
bool shouldPaint() const;
|
bool shouldPaint() const;
|
||||||
bool checkPendingRenderEvent();
|
bool checkPendingRenderEvent();
|
||||||
|
@ -79,6 +83,8 @@ protected:
|
||||||
|
|
||||||
gpu::ContextPointer _gpuContext; // initialized during window creation
|
gpu::ContextPointer _gpuContext; // initialized during window creation
|
||||||
|
|
||||||
|
FrameQueuePointer _frameQueue{ new FrameQueue() };
|
||||||
|
|
||||||
QObject* _renderEventHandler{ nullptr };
|
QObject* _renderEventHandler{ nullptr };
|
||||||
friend class RenderEventHandler;
|
friend class RenderEventHandler;
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
|
|
||||||
#include "CrashHandler.h"
|
#include "CrashHandler.h"
|
||||||
|
|
||||||
RenderEventHandler::RenderEventHandler(QOpenGLContext* context, RenderCall renderCall) :
|
RenderEventHandler::RenderEventHandler(QOpenGLContext* context, CheckCall checkCall, RenderCall renderCall) :
|
||||||
|
_checkCall(checkCall),
|
||||||
_renderCall(renderCall)
|
_renderCall(renderCall)
|
||||||
{
|
{
|
||||||
_renderContext = new OffscreenGLCanvas();
|
_renderContext = new OffscreenGLCanvas();
|
||||||
|
@ -52,7 +53,7 @@ void RenderEventHandler::resumeThread() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderEventHandler::render() {
|
void RenderEventHandler::render() {
|
||||||
if (qApp->shouldPaint()) {
|
if (_checkCall()) {
|
||||||
_lastTimeRendered.start();
|
_lastTimeRendered.start();
|
||||||
_renderCall();
|
_renderCall();
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,10 +28,13 @@ class RenderEventHandler : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
using CheckCall = std::function <bool()>;
|
||||||
using RenderCall = std::function <void()>;
|
using RenderCall = std::function <void()>;
|
||||||
|
|
||||||
|
CheckCall _checkCall;
|
||||||
RenderCall _renderCall;
|
RenderCall _renderCall;
|
||||||
|
|
||||||
RenderEventHandler(QOpenGLContext* context, RenderCall renderCall);
|
RenderEventHandler(QOpenGLContext* context, CheckCall checkCall, RenderCall renderCall);
|
||||||
|
|
||||||
QElapsedTimer _lastTimeRendered;
|
QElapsedTimer _lastTimeRendered;
|
||||||
std::atomic<bool> _pendingRenderEvent{ true };
|
std::atomic<bool> _pendingRenderEvent{ true };
|
||||||
|
|
1
interface/src/graphics/RenderThread.cpp
Normal file
1
interface/src/graphics/RenderThread.cpp
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "RenderThread.h"
|
108
interface/src/graphics/RenderThread.h
Normal file
108
interface/src/graphics/RenderThread.h
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
#ifndef PRODUCERCONSUMERPIPE_H
|
||||||
|
#define PRODUCERCONSUMERPIPE_H
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <atomic>
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
// Producer is blocked if the consumer doesn't consume enough
|
||||||
|
// Consumer reads same value if producer doesn't produce enough
|
||||||
|
template <class T>
|
||||||
|
class ProducerConsumerPipe {
|
||||||
|
public:
|
||||||
|
|
||||||
|
ProducerConsumerPipe();
|
||||||
|
ProducerConsumerPipe(const T& initValue);
|
||||||
|
|
||||||
|
const T& read();
|
||||||
|
void read(T& value, const T& resetValue);
|
||||||
|
void write(const T& value);
|
||||||
|
bool isWritePossible();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
short _readIndex;
|
||||||
|
short _writeIndex;
|
||||||
|
std::array<T, 3> _values;
|
||||||
|
std::array<std::atomic_flag, 3> _used;
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
void updateReadIndex();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
ProducerConsumerPipe<T>::ProducerConsumerPipe() {
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
ProducerConsumerPipe<T>::ProducerConsumerPipe(const T& initValue) {
|
||||||
|
_values.fill(initValue);
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void ProducerConsumerPipe<T>::initialize() {
|
||||||
|
_readIndex = 0;
|
||||||
|
_writeIndex = 2;
|
||||||
|
_used[_readIndex].test_and_set(std::memory_order_acquire);
|
||||||
|
_used[_writeIndex].test_and_set(std::memory_order_acquire);
|
||||||
|
_used[1].clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void ProducerConsumerPipe<T>::updateReadIndex() {
|
||||||
|
int nextReadIndex = (_readIndex + 1) % _values.size();
|
||||||
|
|
||||||
|
if (!_used[nextReadIndex].test_and_set(std::memory_order_acquire)) {
|
||||||
|
int readIndex = _readIndex;
|
||||||
|
_used[readIndex].clear(std::memory_order_release);
|
||||||
|
_readIndex = nextReadIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
const T& ProducerConsumerPipe<T>::read() {
|
||||||
|
updateReadIndex();
|
||||||
|
return _values[_readIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void ProducerConsumerPipe<T>::read(T& value, const T& resetValue) {
|
||||||
|
updateReadIndex();
|
||||||
|
value = _values[_readIndex];
|
||||||
|
_values[_readIndex] = resetValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
bool ProducerConsumerPipe<T>::isWritePossible() {
|
||||||
|
int nextWriteIndex = (_writeIndex + 1) % _values.size();
|
||||||
|
return (_used[nextWriteIndex].test_and_set(std::memory_order_acquire));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void ProducerConsumerPipe<T>::write(const T& value) {
|
||||||
|
int nextWriteIndex = (_writeIndex + 1) % _values.size();
|
||||||
|
int writeIndex = _writeIndex;
|
||||||
|
|
||||||
|
_values[writeIndex] = value;
|
||||||
|
|
||||||
|
while (_used[nextWriteIndex].test_and_set(std::memory_order_acquire)) {
|
||||||
|
// spin
|
||||||
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
|
_used[writeIndex].clear(std::memory_order_release);
|
||||||
|
_writeIndex = nextWriteIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include <gpu/Frame.h>
|
||||||
|
|
||||||
|
using FrameQueue = ProducerConsumerPipe<gpu::FramePointer>;
|
||||||
|
|
||||||
|
using FrameQueuePointer = std::shared_ptr<FrameQueue>;
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue