0

I implemented a glRender class which subclassed QOpenGLWidget to display YUV data from a H264 decoder (1920x1080@60fps). The problem is that the OpenGL drawing process takes about 60% of processing power of a single core (observed from output of htop), this is quite high as my program runs on an embedded platform (4 x Cortex-A53@1.35GHz, Mali-G31) and other process also requires a lot of CPU usage.

Here is my paintGL function:

void glRender::paintGL()
{
    // 1. setup a rectangle and texture coordinates
    vao.bind();
    vertexBuffer->bind();
    indexBuffer->bind();

    quintptr offset = 0;
    int vertexLocation = program->attributeLocation("a_position");
    program->enableAttributeArray(vertexLocation);
    program->setAttributeBuffer(vertexLocation, GL_FLOAT, offset, 3, sizeof(VertexData));

    offset += sizeof(QVector3D);
    int texcoordLocation = program->attributeLocation("a_texcoord");
    program->enableAttributeArray(texcoordLocation);
    program->setAttributeBuffer(texcoordLocation, GL_FLOAT, offset, 2, sizeof(VertexData));

    // 2. setup texture
    y_tex->bind(0);
    y_tex->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8, (const void *)y_data);

    u_tex->bind(1);
    u_tex->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8, (const void *)u_data);

    v_tex->bind(2);
    v_tex->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8, (const void *)v_data);

    program->setUniformValue("y_texture", 0);
    program->setUniformValue("u_texture", 1);
    program->setUniformValue("v_texture", 2);

    // 3. draw
    glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_SHORT, nullptr);

    // 4. release resources
    y_tex->release();
    u_tex->release();
    v_tex->release();

    vao.release();

    emit displayDone();
}

My questions are:

  1. Why the drawing process needs so much CPU time? I found that it's the setData call that make CPU usage high after some trial and error. If setDate is comment out, the CPU usage would drop about 60%.
  2. I printed the timestamp when entering paintGL and exiting paintGL, and the delta is always 4ms. Calculating 4ms * 60fps / 1000ms and I get 24% of CPU processing time which means 24% of CPU usage at most. But this is different from what I observe (60% of CPU usage), why?
  3. Is there any improvement I can make to make the drawing process less CPU consuming?

I have Googled around and some answer suggested that it's still software rendering. I have checked the GPU usage of my system, and it went up to around 20% when rendering.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Edmond
  • 143
  • 1
  • 10
  • Why do you bind the (same) data over and over in the paintGL function? This should not be done in paint() but when the data changes. – chehrlic May 12 '23 at 05:18
  • Thanks for your time! @chehrlic . It's not the same data. It's y_data, u_data and v_data. Those three data combined represents a picture. Just like RGB, but in a different color space. And as I am creating a video player, this paint function is called 60 times per second as the frame rate of video is 60fps. Each time a new frame is available from my H264 decoder, the update() method of QOpenGLWidget is called and a call of this paintGL() is arranged. – Edmond May 12 '23 at 06:04
  • Perhaps try using a proper profiler (instead of htop) to see where the CPU cycles are spent? Perhaps the `UInt8` type isn't directly support on the hardware, so Qt/OpenGL is converting it to something else. Another guess: could it be that the bandwidth to the GPU is actually the bottleneck? – Yun May 12 '23 at 11:50
  • If you want you could compare with this code that I wrote some time ago: https://bugfreeblog.duckdns.org/2022/01/yuv420p-opengl-shader-conversion.html. Does it behave more or less the same? – Luca Carlon May 14 '23 at 14:57

0 Answers0