首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Qt/OpenGL :我使用PBO正确吗?

Qt/OpenGL :我使用PBO正确吗?
EN

Stack Overflow用户
提问于 2016-08-18 08:25:57
回答 1查看 647关注 0票数 1

我正在做一个用OpenGL显示视频流的项目,然后在外部屏幕上显示QOpenGLWidget上的内容。因此,我所做的是在OpenGL小部件上显示流,然后使用带有两个Pixel缓冲区对象的glReadPixels来获取缓冲区并将其发送到另一个屏幕。问题是,与不使用PBO相比,我在使用PBO时正在失去性能。

下面是代码中有趣的部分:

创建将在外部屏幕上发送的框架的代码:

screenBuffer是一个内存缓冲区,用于存储来自QOpenGLWidget的帧

在这段代码中,PBO已经填充了来自paintGL函数的数据。

代码语言:javascript
复制
void GLWidget::videodisplay(unsigned char *copy){

    update();

    unsigned char* frame = publicCreateOutputVideoFrame();

    if(pboIndex){

        pbo1->bind();
        pbo1->read(0, screenBuffer, vWidth*vHeight*3);

    }else{

        pbo2->bind();
        pbo2->read(0, screenBuffer, vWidth*vHeight*3);

    }

    pboIndex = !pboIndex;

    unsigned char* yuvFrame = convertRGBtoYUV(screenBuffer);

    memcpy(frame, yuvFrame, vWidth*vHeight*2);

    publicDisplayVideoFrameSync();

    delete yuvFrame;
    yuvFrame = NULL;

    delete copy;
    copy = NULL;

}

PBO :的初始化

代码语言:javascript
复制
void GLWidget::InitializeGL(){

    pbo1 = new QOpenGLBuffer(QOpenGLBuffer::PixelPackBuffer);
    pbo1->create();
    pbo1->bind();
    pbo1->allocate(vWidth*vHeight*3);
    pbo1->release();

    pbo2 = new QOpenGLBuffer(QOpenGLBuffer::PixelPackBuffer);
    pbo2->create();
    pbo2->bind();
    pbo2->allocate(vWidth*vHeight*3);
    pbo2->release();

}

我在这里使用PBO和glReadPixels

代码语言:javascript
复制
void GLWidget::paintGL(){


    glClear(GL_COLOR_BUFFER_BIT);

    program->bind();
    {
        vao.bind();

            glBindTexture(GL_TEXTURE_2D, tex);

                glDrawArrays(GL_QUADS, 0, 4);

            glBindTexture(GL_TEXTURE_2D, 0);

        vao.release();
    }
    program->release();

    if(!isZoomed){

        programMouse->bind();
        {
            vaoMouse.bind();

                    glLineWidth(2.0);
                    glDrawArrays(GL_LINES, 0, 8);

            vaoMouse.release();
        }
        programMouse->release();

    }

    if(pboIndex){

        pbo2->bind();

    }else{

        pbo1->bind();
    }

            glReadPixels(0, 0, vWidth, vHeight, GL_RGB, GL_UNSIGNED_BYTE, 0);

    if(pboIndex){

        pbo2->release();

    }else{

        pbo1->release();
    }



}

pboIndex只是一个布尔值,它将值切换到第一个和第二个PBO之间。

很明显,既然我失去了表演,我就做错了什么?我要么以错误的方式使用PBO,要么我没有正确地理解我应该使用它们的情况。

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-08-18 19:59:14

您对Pixel缓冲区对象的用途有一个大致的理解(我认为),通过在两个不同缓冲区之间的每一个帧进行乒乓来演示。真正的问题是,两个像素缓冲区可能不足以防止管道停滞。

许多驱动程序被配置为对三个帧排队命令,如果您试图在frame n期间读取frame n+2的结果,则有效地缩短了最大管道深度。框架n+2的命令设置将不被允许继续进行,直到n完成并读取的结果。

驱动程序的命令队列行为远远超出了OpenGL的范围,您将永远无法知道驱动程序预先设置了多少帧。将读取之间的时间增加到3会有帮助,但理想情况下,您想要使用的是一个栅栏同步

您可以将一个同步对象插入到OpenGL中的命令流中,其唯一目的是在某个点之前的所有命令完成后发出信号。检查此对象的信号状态不会以任何方式拖住管道,并允许您快速判断来自上一帧的命令何时在GPU上完成,并且像素缓冲区的读取不会带来任何CPU/GPU同步问题。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39013293

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档