在为多个QSGNode调用update时增加cpu和ram的使用

时间:2016-07-02 15:45:01

标签: c++ qt ubuntu opengl

我使用Qt Scene Graph(Ubuntu 16.04上的Qt 5.6)创建了一个应用程序。它有大约12个QSGNode实例,并且每30ms调用一次更新。

我没有更新其中一个的任何问题,但是当我为所有人调用更新时,cpu和ram的使用率开始增加。几个小时后,CPU使用率将接近100%。 (在正常情况下,cpu的使用量应该在3-4左右)。

这是最小版本(对于长代码很抱歉,这是产生此错误的最简单版本):

main.cpp

#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
   MainWindow w;
   w.show();
   return a.exec();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "gui/diagramgraph.h"
namespace Ui {
   class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
private:
     Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include <QQuickView>
#include <QTimer>
#include "gui/diagramgraph.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
     QMainWindow(parent),
     ui(new Ui::MainWindow)
{
     ui->setupUi(this);
     qmlRegisterType<DiagramGraph>("DiagramGraph", 1, 0, "DiagramGraph");
     QTimer *updateTimer = new QTimer(this);
     for(int i = 1; i <= 12; i++){
         QQuickView *view = new QQuickView();
         view->setSource(QUrl("qrc:/ui/diagram.qml"));
         view->setClearBeforeRendering(true);
         QObject *object = view->rootObject();
         DiagramGraph* graph = object->findChild<DiagramGraph *>("diagram");
         QObject::connect(updateTimer, SIGNAL(timeout()), graph, SLOT(update()));
         QWidget *container = QWidget::createWindowContainer(view, this);
         ui->vetical->addWidget(container);
    }
updateTimer->setTimerType(Qt::PreciseTimer);
updateTimer->start(30);
}
MainWindow::~MainWindow()
{
     delete ui;
}

GUI / diagramgraph.h

#ifndef DIAGRAMGRAPH_H
#define DIAGRAMGRAPH_H
#include <QQuickItem>
class DiagramGraph : public QQuickItem
{
    Q_OBJECT
    public:
       DiagramGraph();
       void init();
    protected:
       QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
       void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
 };
 #endif // DIAGRAMGRAPH_H

GUI / diagramgraph.cpp

#include "samples.h"
#include "diagramgraph.h"
class DiagramGraphNode : public QSGNode
{
public:
    Samples * samples;
};
DiagramGraph::DiagramGraph()
{
     setFlag(ItemHasContents, true);
}
QSGNode * DiagramGraph::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *){
    DiagramGraphNode *n= static_cast<DiagramGraphNode *>(oldNode);
    QRectF rect = boundingRect();
    if (rect.isEmpty()) {
        delete n;
        return 0;
    }
    if (!n) {
        n = new DiagramGraphNode();
        n->samples = new Samples();
        n->appendChildNode(n->samples);
    }
    n->samples->updateGeometry();
    return n;
}
void DiagramGraph::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry){
    update();
    QQuickItem::geometryChanged(newGeometry, oldGeometry);
 }

GUI / samples.h

#ifndef SAMPLES_H
#define SAMPLES_H
#include <QSGGeometryNode>
class Samples : public QSGGeometryNode
{
public:
    Samples();
    void updateGeometry();
private:
    QSGGeometry _geometry;
};
#endif // SAMPLES_H

GUI / samples.cpp

#include "samples.h"
#include <QtGui/QColor>
#include <QtQuick/QSGSimpleMaterial>
struct LineMaterial
{
    QColor color;
};
class LineShader : public QSGSimpleMaterialShader<LineMaterial>
{
    QSG_DECLARE_SIMPLE_SHADER(LineShader, LineMaterial)

 public:
    LineShader() {
         setShaderSourceFile(QOpenGLShader::Vertex, ":/shaders/shaders/samples.vsh");
         setShaderSourceFile(QOpenGLShader::Fragment, ":/shaders/shaders/samples.fsh");
    }
    QList<QByteArray> attributes() const {  return QList<QByteArray>() << "y" << "t"; }
    void updateState(const LineMaterial *m, const LineMaterial *) {
         program()->setUniformValue(id_color, m->color);
    }
    void resolveUniforms() {
        id_color = program()->uniformLocation("color");
    }
    private:
        int id_color;
};
struct Vertex {
    float y;
    float t;
    inline void set(float yy, float tt) { y = yy; t = tt; }
};
static const QSGGeometry::AttributeSet &attributes()
{
    static QSGGeometry::Attribute attr[] = {
         QSGGeometry::Attribute::create(0, 1, GL_FLOAT, true),
         QSGGeometry::Attribute::create(1, 1, GL_FLOAT),
    };
    static QSGGeometry::AttributeSet set = { 2, 2 * sizeof(float), attr };
    return set;
 }
 Samples::Samples()
    : _geometry(attributes(), 0){
    setGeometry(&_geometry);
    _geometry.setLineWidth(3);
    _geometry.setDrawingMode(GL_LINES);
    QSGSimpleMaterial<LineMaterial> *m = LineShader::createMaterial();
    m->state()->color = QColor("red");
    m->setFlag(QSGMaterial::Blending);
    setMaterial(m);
    setFlag(OwnsMaterial);
}
void Samples::updateGeometry()
{
    _geometry.allocate(20);
    Vertex *v = (Vertex *) _geometry.vertexData();
    for (uint i=0; i < 20; i++){
        v[i].set(.5, i);
    }
 }

mainwindow.ui

 just a QVBoxLayout

diagram.qml

import QtQuick 2.0
import QtQuick.Controls 1.4
import DiagramGraph 1.0
Item{
    id: diagram_main
    DiagramGraph{
        id: diagram_graph
        objectName: "diagram"
        anchors.left: diagram_main.left
        height: 100
    }
}

着色器/ samples.fsh

uniform lowp vec4 color;
uniform lowp float qt_Opacity;
void main(void)
{
    gl_FragColor = color * qt_Opacity;
}

着色器/ samples.vsh

attribute highp float y;
attribute highp float t;
uniform highp mat4 qt_Matrix;
void main(void)
{
     gl_Position =  qt_Matrix * vec4(t, y * 100.f, 0.f, 1.f);
}

0 个答案:

没有答案