使用PBO的非阻塞式glReadPixels深度值 [英] Non blocking glReadPixels of depth values with PBO

查看:482
本文介绍了使用PBO的非阻塞式glReadPixels深度值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从帧缓冲区读取单个像素的深度以实现拾取.最初,我的glReadPixels()花费了很长时间(大约5毫秒),在nVidia上甚至会

I am reading a single pixel's depth from the framebuffer to implement picking. Originally my glReadPixels() was taking a very long time (5ms or so) and on nVidia it would even burn 100% CPU during that time. On Intel it was slow as well, but with idle CPU.

从那时起,我使用PixelBufferObject功能 PBO 来使glReadPixels异步进行,并且还使用

Since then, I used the PixelBufferObject functionality, PBO, to make the glReadPixels asynchronous and also double buffered using this well known example.

这种方法效果很好,让我让glReadPixels()调用异步,但前提是我读取RGBA 值.如果我使用相同的PBO方法读取深度值,则glReadPixels()会再次阻塞.

This approach works well, and let's me make a glReadPixels() call asynchronous but only if I read RGBA values. If I use the same PBO approach to read depth values, the glReadPixels() blocks again.

读取RGBA:glReadPixels()需要12µs.

Reading RGBA: glReadPixels() takes 12µs.

读取深度:glReadPixels()需要5毫秒.

Reading DEPTH: glReadPixels() takes 5ms.

我在nVidia和Intel驱动程序上尝试了此操作.具有不同的格式/类型组合.我试过了:

I tried this on nVidia and Intel drivers. With different format/type combinations. I tried:

glReadPixels( srcx, srcy, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, 0 );

和:

glReadPixels( srcx, srcy, 1, 1, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0 );

和:

glReadPixels( srcx, srcy, 1, 1, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 0 );

所有这些都不会导致异步glReadPixels()调用.但是,如果我通过以下调用读取RGBA值:

None of these would result in an asynchronous glReadPixels() call. But if I read RGBA values with the following call:

glReadPixels( srcx, srcy, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 0 );

然后glReadPixels()立即返回,因此不再阻塞.

then the glReadPixels() returns immediately, thus no longer blocks.

在读取单个像素之前,我要做:

Before reading the single pixel, I do:

glReadBuffer( GL_FRONT );
glBindBuffer( GL_PIXEL_PACK_BUFFER, pboid );

然后用以下命令创建双缓冲PBO:

And I create the double buffered PBO with:

glGenBuffers( NUMPBO, pboids );
for ( int i=0; i<NUMPBO; ++i )
{
    const int pboid = pboids[i];
    glBindBuffer( GL_PIXEL_PACK_BUFFER, pboid );
    glBufferData( GL_PIXEL_PACK_BUFFER, DATA_SIZE, 0, GL_STREAM_READ );
    ...

我使用深度为24,模板大小为8,默认为双缓冲区的SDL2创建帧缓冲区.

I create my framebuffer using SDL2 with depth size 24, stencil size 8, and the default double buffer.

我正在Ubuntu LTS上使用OpenGL Core Profile 3.3.

I am using OpenGL Core Profile 3.3 on Ubuntu LTS.

推荐答案

直到下一个帧,我才真正读取像素深度(通过glMapBuffer),因此没有进行同步. glReadPixel应该已经触发了异步操作并立即返回(与RGBA一样).但这不是为了阅读深度.

I don't actually read the pixel depth (via glMapBuffer) until the next frame so there is no synchronization going on. The glReadPixel should have triggered an async operation and return immediately (as it does for RGBA). But it does not, for reading depth.

那将需要两个深度缓冲区.但是没有.多缓冲是指颜色缓冲区的数量,因为它们实际上是显示的.实现几乎永远不会给您多个深度缓冲区.

That would require there to be two depth buffers. But there aren't. Multi-buffering refers to the number of color buffers, since those are what actually get displayed. Implementations pretty much never give you multiple depth buffers.

为了服务于深度缓冲区的读取,该读取必须在下一帧"发生之前进行.因此,需要进行同步.

In order to service a read from the depth buffer, that read has to happen before "the next frame" takes place. So there would need to be synchronization.

通常来说,最好阅读自己的图像.这样,您就可以完全控制格式等内容,何时重新使用它们等,从而可以控制同步问题.如果需要两个深度缓冲区,以便可以在使用另一个深度缓冲区时读取其中的一个,则需要创建该深度缓冲区.

Generally speaking, it's best to read from your own images. That way, you have complete control over things like format, when they get reused, and the like, so that you can control issues of synchronization. If you need two depth buffers so that you can read from one while using the other, then you need to create that.

而且仅供参考:由于像素所有权问题,根本无法从默认帧缓冲区中读取内容等等.但是从 front 缓冲区读取几乎总是错误的事情.

And FYI: reading from the default framebuffer at all is dubious due to pixel ownership issues and such. But reading from the front buffer is pretty much always the wrong thing.

这篇关于使用PBO的非阻塞式glReadPixels深度值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆