Неблокирующая glReadPixels значений глубины с PBO - PullRequest
0 голосов
/ 05 мая 2019

Я читаю глубину в один пиксель из кадрового буфера для осуществления выбора. Первоначально мой glReadPixels () занимал очень много времени (5 мс или около того), и на nVidia он даже сжигал 100% CPU в течение этого времени. На Intel он тоже был медленным, но с простаивающим процессором.

С тех пор я использовал функциональность PixelBufferObject, PBO , чтобы сделать glReadPixels асинхронными, а также с двойной буферизацией с использованием этого хорошо известного примера .

Этот подход хорошо работает, и давайте я сделаю вызов glReadPixels () асинхронным , но только если я прочитал значения RGBA . Если я использую тот же подход PBO для чтения значений глубины, glReadPixels () снова блокируется.

Чтение RGBA: glReadPixels () занимает 12 мкс.

Чтение DEPTH: glReadPixels () занимает 5 мс.

Я пробовал это на драйверах nVidia и Intel. С различными комбинациями формат / тип. Я попробовал:

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 с помощью следующего вызова:

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

, затем glReadPixels () немедленно возвращается, поэтому больше не блокируется.

Перед чтением одного пикселя я делаю:

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

И я создаю PBO с двойной буферизацией с:

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 );
    ...

Я создаю свой кадровый буфер, используя SDL2 с размером глубины 24, размером трафарета 8 и двойным буфером по умолчанию.

Я использую OpenGL Core Profile 3.3 в Ubuntu LTS.

1 Ответ

1 голос
/ 05 мая 2019

На самом деле я не читаю глубину пикселя (через glMapBuffer) до следующего кадра, поэтому синхронизация не происходит.GlReadPixel должен был инициировать асинхронную операцию и немедленно вернуться (как это происходит для RGBA).Но это не так, для глубины чтения.

Это потребовало бы наличия двух буферов глубины.Но там не .Мультибуферизация относится к числу цветовых буферов , поскольку именно они и отображаются.Реализации практически никогда не дают вам несколько буферов глубины.

Чтобы обслуживать чтение из буфера глубины, это чтение должно произойти до того, как произойдет «следующий кадр».Поэтому необходима синхронизация.

Вообще говоря, лучше читать по собственным изображениям.Таким образом, вы получаете полный контроль над такими вещами, как формат, когда они используются повторно и т. Д., Так что вы можете контролировать вопросы синхронизации.Если вам нужны два буфера глубины, чтобы вы могли читать из одного при использовании другого, то вам нужно его создать.

И, к вашему сведению: чтение из кадрового буфера по умолчанию вообще сомнительно из-за владения пикселемвыдает и тому подобное.Но чтение из переднего буфера почти всегда неправильно.

...