我试图让 ffmpeg 解码并将像素转换为 rgb8 格式并写入映射的像素缓冲区并使用流来更新 opengl 纹理,然后将其渲染到 sdl 窗口。
解码和上传发生在一个专用线程中(使 sws_scale 写入映射的缓冲区),并且渲染在另一个上下文中的渲染线程中完成,并具有共享。(PBO实际上有几个帧,纹理是一个二维数组纹理,用来解耦位置。)
如果我在解码线程中刷新映射范围,并在渲染线程中使用 glTextureSubImage3D 来更新所需索引处的纹理,则一切正常。在这种情况下,集成的英特尔 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 版本设置了刷新命令位,并且在渲染端显式调用刷新也不起作用。那么应该怎么做才能让两个司机都开心(并降低利用率)?