From d03291eeb1efbb1005eba5a8a4b2c92ef66d2fd5 Mon Sep 17 00:00:00 2001 From: Mateusz Zalega Date: Thu, 16 Aug 2018 21:44:37 +0200 Subject: gui: improved FPGAViewWidget::paintGL() performance Profiling revealed that memcpy() in QOpenGLBuffer::allocate() had been taking the most time during paintGL() calls. I've been able to take the CPU usage down to about 1/4 of its previous values by caching elements in VBOs and updating them only after subsequent calls to renderGraphicElement(). Signed-off-by: Mateusz Zalega --- gui/lineshader.cc | 123 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 81 insertions(+), 42 deletions(-) (limited to 'gui/lineshader.cc') diff --git a/gui/lineshader.cc b/gui/lineshader.cc index eba96020..0f762b38 100644 --- a/gui/lineshader.cc +++ b/gui/lineshader.cc @@ -162,75 +162,114 @@ bool LineShader::compile(void) return false; } - if (!vao_.create()) - log_abort(); - vao_.bind(); - - if (!buffers_.position.create()) - log_abort(); - if (!buffers_.normal.create()) - log_abort(); - if (!buffers_.miter.create()) - log_abort(); - if (!buffers_.index.create()) - log_abort(); - + program_->bind(); attributes_.position = program_->attributeLocation("position"); attributes_.normal = program_->attributeLocation("normal"); attributes_.miter = program_->attributeLocation("miter"); uniforms_.thickness = program_->uniformLocation("thickness"); uniforms_.projection = program_->uniformLocation("projection"); uniforms_.color = program_->uniformLocation("color"); + program_->release(); + + for (int style = 0; style < GraphicElement::STYLE_MAX; style++) { + buffers_[style].position = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); + buffers_[style].normal = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); + buffers_[style].miter = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); + buffers_[style].index = QOpenGLBuffer(QOpenGLBuffer::IndexBuffer); + + if (!buffers_[style].vao.create()) + log_abort(); + buffers_[style].vao.bind(); + + if (!buffers_[style].position.create()) + log_abort(); + if (!buffers_[style].normal.create()) + log_abort(); + if (!buffers_[style].miter.create()) + log_abort(); + if (!buffers_[style].index.create()) + log_abort(); + + buffers_[style].position.setUsagePattern(QOpenGLBuffer::StaticDraw); + buffers_[style].normal.setUsagePattern(QOpenGLBuffer::StaticDraw); + buffers_[style].miter.setUsagePattern(QOpenGLBuffer::StaticDraw); + buffers_[style].index.setUsagePattern(QOpenGLBuffer::StaticDraw); + + buffers_[style].position.bind(); + buffers_[style].normal.bind(); + buffers_[style].miter.bind(); + buffers_[style].index.bind(); + + buffers_[style].vao.release(); + } - vao_.release(); return true; } -void LineShader::draw(const LineShaderData &line, const QColor &color, float thickness, const QMatrix4x4 &projection) +void LineShader::update_vbos(enum GraphicElement::style_t style, + const LineShaderData &line) { - auto gl = QOpenGLContext::currentContext()->functions(); - if (line.vertices.size() == 0) + if (buffers_[style].last_vbo_update == line.last_render) return; - vao_.bind(); - program_->bind(); + buffers_[style].last_vbo_update = line.last_render; + + buffers_[style].indices = line.indices.size(); + if (buffers_[style].indices == 0) { + // invalidate buffers + buffers_[style].position.allocate(nullptr, 0); + buffers_[style].normal.allocate(nullptr, 0); + buffers_[style].miter.allocate(nullptr, 0); + buffers_[style].index.allocate(nullptr, 0); + return; + } + + buffers_[style].position.bind(); + buffers_[style].position.allocate(&line.vertices[0], sizeof(Vertex2DPOD) * line.vertices.size()); - buffers_.position.bind(); - buffers_.position.allocate(&line.vertices[0], sizeof(Vertex2DPOD) * line.vertices.size()); + buffers_[style].normal.bind(); + buffers_[style].normal.allocate(&line.normals[0], sizeof(Vertex2DPOD) * line.normals.size()); - buffers_.normal.bind(); - buffers_.normal.allocate(&line.normals[0], sizeof(Vertex2DPOD) * line.normals.size()); + buffers_[style].miter.bind(); + buffers_[style].miter.allocate(&line.miters[0], sizeof(GLfloat) * line.miters.size()); - buffers_.miter.bind(); - buffers_.miter.allocate(&line.miters[0], sizeof(GLfloat) * line.miters.size()); + buffers_[style].index.bind(); + buffers_[style].index.allocate(&line.indices[0], sizeof(GLuint) * line.indices.size()); +} - buffers_.index.bind(); - buffers_.index.allocate(&line.indices[0], sizeof(GLuint) * line.indices.size()); +void LineShader::draw(enum GraphicElement::style_t style, const QColor &color, + float thickness, const QMatrix4x4 &projection) +{ + auto gl = QOpenGLContext::currentContext()->functions(); + if (buffers_[style].indices == 0) + return; + program_->bind(); + buffers_[style].vao.bind(); program_->setUniformValue(uniforms_.projection, projection); program_->setUniformValue(uniforms_.thickness, thickness); program_->setUniformValue(uniforms_.color, color.redF(), color.greenF(), color.blueF(), color.alphaF()); - buffers_.position.bind(); - program_->enableAttributeArray("position"); - gl->glVertexAttribPointer(attributes_.position, 2, GL_FLOAT, GL_FALSE, 0, (void *)0); + buffers_[style].position.bind(); + program_->enableAttributeArray(attributes_.position); + program_->setAttributeBuffer(attributes_.position, GL_FLOAT, 0, 2); - buffers_.normal.bind(); - program_->enableAttributeArray("normal"); - gl->glVertexAttribPointer(attributes_.normal, 2, GL_FLOAT, GL_FALSE, 0, (void *)0); + buffers_[style].normal.bind(); + program_->enableAttributeArray(attributes_.normal); + program_->setAttributeBuffer(attributes_.normal, GL_FLOAT, 0, 2); - buffers_.miter.bind(); - program_->enableAttributeArray("miter"); - gl->glVertexAttribPointer(attributes_.miter, 1, GL_FLOAT, GL_FALSE, 0, (void *)0); + buffers_[style].miter.bind(); + program_->enableAttributeArray(attributes_.miter); + program_->setAttributeBuffer(attributes_.miter, GL_FLOAT, 0, 1); - buffers_.index.bind(); - gl->glDrawElements(GL_TRIANGLES, line.indices.size(), GL_UNSIGNED_INT, (void *)0); + buffers_[style].index.bind(); + gl->glDrawElements(GL_TRIANGLES, buffers_[style].indices, GL_UNSIGNED_INT, (void *)0); - program_->disableAttributeArray("miter"); - program_->disableAttributeArray("normal"); - program_->disableAttributeArray("position"); + program_->disableAttributeArray(attributes_.position); + program_->disableAttributeArray(attributes_.normal); + program_->disableAttributeArray(attributes_.miter); + buffers_[style].vao.release(); program_->release(); - vao_.release(); } NEXTPNR_NAMESPACE_END -- cgit v1.2.3