【问题标题】:OpenGL PBO for texture upload, can't understand one thingOpenGL PBO 用于纹理上传,看不懂一件事
【发布时间】:2013-01-03 16:59:37
【问题描述】:

好的,我在这里阅读了有关 PBO 的所有信息:http://www.opengl.org/wiki/Pixel_Buffer_Object 还有http://www.songho.ca/opengl/gl_pbo.html,但我还有一个问题,我不知道我是否会从 PBO 中获得任何好处:

我正在做视频流,目前我有一个函数将我的数据缓冲区复制到 3 个不同的纹理,然后我在片段着色器中做一些数学运算并显示纹理。

我认为 PBO 可以增加 CPU -> GPU 的上传时间,但就是这样,假设我们这里的示例取自上面的第二个链接。

glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pboIds[nextIndex]);

        // map the buffer object into client's memory
        // Note that glMapBufferARB() causes sync issue.
        // If GPU is working with this buffer, glMapBufferARB() will wait(stall)
        // for GPU to finish its job. To avoid waiting (stall), you can call
        // first glBufferDataARB() with NULL pointer before glMapBufferARB().
        // If you do that, the previous data in PBO will be discarded and
        // glMapBufferARB() returns a new allocated pointer immediately
        // even if GPU is still working with the previous data.
        glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, DATA_SIZE, 0, GL_STREAM_DRAW_ARB);
        GLubyte* ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);
        if(ptr)
        {
            // update data directly on the mapped buffer
            updatePixels(ptr, DATA_SIZE);
            glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); // release pointer to mapping buffer
        }

        // measure the time modifying the mapped buffer
        t1.stop();
        updateTime = t1.getElapsedTimeInMilliSec();
        ///////////////////////////////////////////////////

        // it is good idea to release PBOs with ID 0 after use.
        // Once bound with 0, all pixel operations behave normal ways.
        glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);

好吧,无论updatePixels 函数的行为是什么,它仍在使用 CPU 周期将数据复制到映射缓冲区,不是吗?

假设我想以这种方式使用 PBO,即在函数中将我的帧像素更新为 PBO,然后在 display 函数中调用 glTexSubImage2D(应该立即返回).. . 我会看到性能方面的任何加速吗? 我不明白为什么它会更快......好吧,我们在 glTex* 调用期间不再等待,但我们在将帧上传到 PBO 的函数期间等待,不是吗?

有人可以帮我解决这个问题吗?

谢谢

【问题讨论】:

    标签: c++ opengl video-streaming textures pbo


    【解决方案1】:

    关于缓冲区对象的要点是,它们可以异步使用。您可以映射一个 BO,然后让程序的其他部分更新它(想想线程,想想异步 IO),同时您可以继续发出 OpenGL 命令。三重缓冲 PBO 的典型使用场景可能如下所示:

    wait_for_video_frame_load_complete(buffer[k-2])
    
    glUnmapBuffer buffer[k-2]
    
    glTexSubImage2D from buffer[k-2]
    
    buffer[k] = glMapBuffer
    
    start_load_next_video_frame(buffer[k]);
    
    draw_texture
    
    SwapBuffers
    

    这允许您的程序做有用的工作,甚至可以将数据上传到 OpenGL,同时它也用于渲染

    【讨论】:

    • 问题:为什么要在这里使用三重缓冲?让两个 load_next_video_frame 调用并行工作?
    • @axxel:允许同步延迟。典型的设置是在 SwapBuffers 之前设置 glMapBuffer,以便填充线程可以工作,而 OpenGL 线程在 V-Sync 处阻塞。然后在显示函数的开始处执行 glUnmapBuffer / glTexSubImage 。现在,如果您引用填充了该缓冲区的纹理,它将插入一个同步点并可能会增加明显的延迟。但是通过提前为帧执行此操作,这与当前渲染的帧异步发生。
    • 我明白了,所以你基本上想要一个类似于三级管道,其中每个阶段并行运行:1)缓冲区填充器(这里是 video_frame 的东西)2)缓冲区上传器(一些假定并行/DMA 驱动程序内部的魔法) 3)GPU 上使用缓冲区的实际渲染命令队列。正确的?不久前我做了一些基准测试,偶然发现了瓶颈,即至少我的特定 NVIDIA 移动芯片(不记得是哪一个)不能并行执行 DMA 与命令处理。您是否了解哪些硬件能够做到这一点?
    • @axxel:是的,正是这个想法。关于 NVidia 移动 GPU 的行为,我既不能确认也不能不同意。移动 GPU 的最大瓶颈是内存带宽,因此它适合图片,即它们在渲染几何图形时无法 DMA 到系统内存。
    猜你喜欢
    • 2014-09-29
    • 2017-08-15
    • 2013-10-25
    • 1970-01-01
    • 2019-02-07
    • 1970-01-01
    • 2011-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多