4K中的纹理流(多分辨率)

时间:2017-04-18 19:38:28

标签: c++ opengl

我的目标是使用OpenGL以最高可能的帧速率在4K中传输单通道图像。这意味着我有1个纹理,我将经常使用新内容进行更新。

至于现在,我正在使用PBO来利用GPU上的异步纹理下载。代码基本上是:

// EACH TIME TEXTURE NEEDS UPDATE
const int pboSize = 4096 * 4096 * 4;

// Bind PBO to texture data source
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboHandle);
// Discard data in PBO - already sent to GPU
glBufferData(GL_PIXEL_UNPACK_BUFFER, pboSize, NULL, GL_STREAM_DRAW);
// Map buffer to client memory
float* data = static_cast<float*>(glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
if (data) {
    std::valarray<IMG_PRECISION>& newImageContent = myImageArray[currentImage];
    // This seems too slow
    std::memcpy(data, &newImageContent[0], newImageContent.size() * sizeof(IMG_PRECISION));
} else {
    std::err << "Failed to map PBO to client memory";
}

// Release the mapped buffer
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);

const glm::uvec3& dimensions = _texture->dimensions();
_texture->bind();
// Send async to GPU
glTexSubImage2D(
    _texture->type(),
    0,
    0,
    0,
    GLsizei(dimensions.x),
    GLsizei(dimensions.y),
    GLint(_texture->format()),
    _texture->dataType(),
    nullptr
);

// Set back to normal texture data source
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

这比仅使用没有PBO的glTexSubImage()更快,但速度不够快。瓶颈似乎是std::memcpy,每帧约0.0211s。我使用glTexImage2D()作为内部格式,GL_R16F作为格式,GL_RED作为数据类型,使用GL_FLOAT创建纹理。

然而,当纹理非常接近相机时,我真的只需要4K分辨率,但是在运行时生成mipmap似乎太慢了。手动预先计算它们也会非常烦人,因为我已经在系统RAM中有很多这些图像,在CPU端加载mipmap和普通图像会太慢。

我现在还能想到任何其他多分辨率方法,或者是使用某些视频编解码器(例如ffmpeg)获得合适帧速率的唯一方法吗?当我从光盘加载它们时,我在这些图像中有很多元数据,理想情况下要避免这种情况。

修改: Target是使用OpenGL 4.5的跨平台桌面环境

2 个答案:

答案 0 :(得分:1)

你想避免阻止。有一个线程上传,而另一个线程绘制。你应该有多个缓冲区。

这个网站上有一个很好的例子可以ping两个缓冲区。 http://www.songho.ca/opengl/gl_pbo.html

这里有一种更高级的多线程方法。

http://on-demand.gputechconf.com/gtc/2012/presentations/S0356-GTC2012-Texture-Transfers.pdf

关于Mipmap:如果您不需要它们,请不要生成它们。只上传0级。

其他建议:

  • 将解码器保留在另一个线程中。
  • 让解码器在主存储器中缓冲几帧,这样上传就不会等待新帧。
  • 基准。如果最终阻止,PBO的速度可能不会比glTexSubImage快。
  • 注意内部转化。如果内部格式是GL_RGB并且glTexSubImage说GL_BGR(例如),它将在cpu上执行另一个副本。

答案 1 :(得分:0)

您是否尝试过使用2个或更多渲染目标?从另一个复制时渲染为一个 - 基本上是页面翻转,但相反。否则GPU将失速。另外,您在GPUView或您最喜欢的性能分析工具中看到了什么?您(通常)在渲染到同一缓冲区时无法复制到主机。

另外,re:mipmap。您可以根据相机距离切换目标,选择在适当的位置渲染到较低分辨率的版本。它与生成mips不同,因为你仍然只处理一个版本的纹理,而不是整个金字塔。

有关您的目标平台和用例的更多信息会很有帮助。有许多特定于供应商的库和扩展可专门为流式传输而设计。