【问题标题】:PBO streaming, exactly when does the sync happen?PBO 流媒体,究竟什么时候发生同步?
【发布时间】:2020-05-28 21:53:44
【问题描述】:

我试图让 ffmpeg 解码并将像素转换为 rgb8 格式并写入映射像素缓冲区并使用流式传输更新 opengl 纹理,然后将其渲染到 sdl 窗口。

解码和上传发生在一个专用线程中(使 sws_scale 写入映射的缓冲区),并且渲染在另一个上下文中的渲染线程中完成,并具有共享。 (PBO实际上有几个帧,纹理是一个二维数组纹理,用来解耦位置。)

如果我在解码线程中刷新映射范围,并在渲染线程中使用 glTextureSubImage3D 更新所需索引处的纹理,则一切正常。在这种情况下,集成的 Intel gpu 工作得非常快(应该),但 NV 驱动程序抱怨 Pixel-path performance warning: Pixel transfer is synchronized with 3D rendering.

我认为这可能是实际上只有 glTextureSubImage3D 才进行上传,所以我在刷新操作后立即移动了 glTextureSubImage3D。这次 NV gpu 工作正常,警告消失了,而 intel gpu 给出了一个黑色窗口,并且只在关闭时显示解码的内容。

代码是这样的:

//render thread
void RenderFrame(SDL_Window* window,GLobjects& glo, int index, int width, int height) {
    glUniform1f(glo.index_location,index);
    //The function in question
    glTextureSubImage3D(glo.texture, 0, 0, 0, index, width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)(index * width * height * 4));
    glClear(GL_COLOR_BUFFER_BIT);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    SDL_GL_SwapWindow(window);
}

//Decode thread
int DecodeFrameToPBO(GLobjects& glo, int index){
    //fill the mapped range needed
    glFlushMappedBufferRange(GL_PIXEL_UNPACK_BUFFER, index * width * height * 4, 4 * width * height);
    //The function in question
    //glTextureSubImage3D(glo.texture, 0, 0, 0, index, width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)(index * width * height * 4));
}

我对客户端内存的概念以及驱动程序如何异步上传纹理、上传的确切位置以及绑定 GL_PIXEL_UNPACK_BUFFER 时 glTextureSubImage3D 的实际作用感到困惑?

编辑:

在每次上传后添加glFlush()命令刷新上传上下文的命令队列后,intel版本正常工作,不黑屏。

更新:

添加 glFlush() 似乎会使 NV gpu 发出警告“像素路径性能警告:像素传输与 3D 渲染同步。”再次,同一视频样本的 GPU 利用率从 8% 增长到 10%。似乎 glFlush() 触发了一些内部同步,这可能会使事情处于忙碌等待状态?由于 Intel GPU 不能在没有 glFlush 的情况下工作,即使 clientwaitsync 版本设置了flush命令位,并且在渲染端显式调用flush也不起作用。那么应该怎么做才能让两个司机都开心(并降低利用率)?

【问题讨论】:

    标签: opengl textures buffer-objects


    【解决方案1】:

    我认为您被 nvidia 警告误导了。它确实暗示有 CPU-GPU 同步,它只告诉您纹理的渲染是同步的(必须等待)上传纹理,这很好。详情请见this answer

    所以我的答案是:没有问题,因此解决方案是不要改变任何东西。

    我认为这可能是只有glTextureSubImage3D 实际进行上传,所以我在刷新操作后立即移动了glTextureSubImage3D [进入解码线程]。

    如果你这样做了,你现在必须手动同步渲染与纹理上传,否则你有时会遇到半写帧甚至未定义的内容,并且基本上有一个竞争条件。

    您可以使用OpenGL Sync Objects 进行此类同步。但最终,您不会获得比原始变体更高的性能。

    而 intel gpu 提供一个黑色窗口,并且仅在关闭时显示解码的内容

    目前尚不清楚这是否只是缺少同步、代码中的错误甚至驱动程序错误的结果。

    【讨论】:

    • 看来这不是英特尔驱动程序的同步问题。在上传线程(围栏)中的 glTextureSubImage3D 之后和绘制数组之前(等待)添加显式围栏后,使用 intel gpu 运行仍然会出现黑屏(或者我做错了)。
    • 好吧,您的英特尔案例中发生的事情无法使用问题中提供的信息进行调试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-07
    • 2021-04-15
    • 2014-09-09
    • 2017-12-11
    • 2023-02-25
    • 2019-10-17
    • 2012-10-01
    相关资源
    最近更新 更多