Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 4K纹理流(多分辨率)_C++_Opengl - Fatal编程技术网

C++ 4K纹理流(多分辨率)

C++ 4K纹理流(多分辨率),c++,opengl,C++,Opengl,我的目标是使用OpenGL以尽可能高的帧速率在4K中传输单通道图像。这意味着我有一个纹理,我将经常用新内容更新它 至于现在,我正在使用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); /

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

至于现在,我正在使用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);
//每次纹理需要更新时
常量大小=4096*4096*4;
//将PBO绑定到纹理数据源
glBindBuffer(GL_像素_解包_缓冲区,pboHandle);
//丢弃PBO中的数据-已发送到GPU
glBufferData(GL_像素_解包_缓冲区,pboSize,NULL,GL_流_绘制);
//将缓冲区映射到客户端内存
浮点*数据=静态转换(glMapBuffer(GL像素解包缓冲区,仅GL写缓冲区));
如果(数据){
std::valarray&newImageContent=myImageArray[currentImage];
//这似乎太慢了
std::memcpy(数据,&newImageContent[0],newImageContent.size()*sizeof(IMG_精度));
}否则{
标准::误差尺寸();
_纹理->绑定();
//发送异步到GPU
glTexSubImage2D(
_纹理->类型(),
0,
0,
0,
GLsizei(尺寸x),
GLsizei(尺寸y),
闪烁(_纹理->格式()),
_纹理->数据类型(),
nullptr
);
//设置回法线纹理数据源
glBindBuffer(GLU像素解包缓冲区,0);
这比只使用
glTexSubImage()
而不使用PBO的速度更快,但还不够快。瓶颈似乎是
std::memcpy
,它占据了大约
0.0211
每帧。我使用
glTexImage2D()创建纹理
使用
GL\u R16F
作为内部格式,
GL\u RED
作为格式,
GL\u FLOAT
作为数据类型

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

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

编辑
目标是使用OpenGL 4.5的跨平台桌面环境。您是否尝试过使用两个或多个渲染目标?从另一个复制时渲染到一个-基本上是翻页,但反向。否则GPU将暂停。另外,您在GPUView或您最喜欢的分析工具中看到了什么?您(通常)渲染到同一缓冲区时无法复制到主机

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


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

您希望避免阻塞。一个线程上载,另一个线程绘制。您应该有多个缓冲区

在这个网站上有一个很好的例子,乒乓两个缓冲区

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

关于mipmap:如果不需要,请不要生成它们。只上载0级别

补充意见:

  • 将解码器放在另一个线程中
  • 让解码器在主内存中缓冲几个帧,这样上传就不会因为等待新帧而变得饥饿
  • 对于您的情况,如果您最终还是阻塞了,Benchmark.PBO的速度可能不会比glTexSubImage快
  • 注意内部转换。如果内部格式为GL_RGB,并且glTexSubImage显示GL_BGR(例如),则它将在cpu上进行另一次复制

感谢您的输入,使用目标平台进行编辑。不过,我并不认为使用2个渲染目标有什么意义。正如这里指出的:,这应该和使用1个PBO一样有效,因为以前的缓冲区无论如何都会被丢弃,需要新的存储。直接将帧解码到映射的缓冲区中?这是什么意思?我没有使用任何encodingcode>std::valarray中的“images”是如何填充的呢?我在一个库的帮助下从光盘上的图像文件中读取数据,并将原始图像(灰度)值作为浮动存储在valarray中。解码到映射缓冲区(几乎每一帧)有何意义?为您保存
memcpy()
调用。我听说在大多数GPU上最好将格式设置为GL_BGRA,因为这样OpenGL就不需要对其进行转换。但似乎找不到有关使用单通道纹理时使用何种格式的任何信息。GL_RED比GL_BGRA快还是应该填充输入数据(哪个会占用更多的RAM)?GL_红色是单通道(灰度)。如果要显示4K电影,我假设您需要RGB或YUV数据,每个通道可能需要8位。因此,请查找最接近该数据类型的数据。请尝试GL_BGR或GL_RGB。如果每个通道只有一个纹理,则只需要GL_RED,如果您有YUV平面4:2:0内容,这可能会很有用。