gpt4 book ai didi

c++ - Qt/OpenGL : Am I using PBO correctly ?

转载 作者:行者123 更新时间:2023-11-30 03:39:09 31 4
gpt4 key购买 nike

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

这是代码中有趣的部分:

创建要在外部屏幕上发送的帧的代码:

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

的帧

此时在代码中,PBO 已经填充了来自paintGL 函数的数据

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 的初始化:

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

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 只是一个 bool 值,用于在第一个和第二个 PBO 之间切换值。

显然,由于我正在失去性能,所以我做错了什么?我要么以错误的方式使用 PBO,要么我没有正确理解我应该使用它们的情况。

谢谢

最佳答案

您对像素缓冲区对象背后的目的有一个大致的了解(我认为),通过两个不同缓冲区之间的每一帧的乒乓来证明。真正的问题是两个像素缓冲区可能不足以防止管道停顿。

如果您尝试在帧 n+2 期间回读帧 n 的结果,许多驱动程序开箱即用地配置为排队三个帧的命令您已经有效地缩短了最大管道深度。在 n 的结果完成并被回读之前,不允许继续为帧 n+2 设置命令。

驱动程序的命令排队行为远远超出了 OpenGL 的范围,您永远无法知道驱动程序设置为提前工作多少帧。将回读之间的时间长度增加到 3 会有所帮助,但理想情况下您要使用的是 fence sync。 .

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

关于c++ - Qt/OpenGL : Am I using PBO correctly ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39013293/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com