glReadPixels () записывает все циклы ЦП одного ядра - PullRequest
0 голосов
/ 15 ноября 2018

У меня есть приложение SDL2 с окном OpenGL, и оно хорошо себя ведет: при запуске приложение синхронизируется с моим дисплеем с частотой 60 Гц, и я вижу 12% загрузки ЦП для приложения.

Итакпока все хорошо.Но когда я добавляю 3D-сборку, считывая одно (!) Значение глубины из буфера глубины (после рисования), происходит следующее:

  • FPS по-прежнему при 60
  • загрузка ЦП дляосновной поток переходит к 100%

Если я не использую glReadPixels, загрузка ЦП снова падает до 12%.Почему чтение одного значения из буфера глубины приводит к тому, что ЦП записывает все циклы?

Мое окно создается с помощью:

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, use_aa ? 1 : 0 );
SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, use_aa ? 4 : 0 );
SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

window = SDL_CreateWindow
(
            "Fragger",
            SDL_WINDOWPOS_UNDEFINED,
            SDL_WINDOWPOS_UNDEFINED,
            fbw, fbh,
            SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI
);

Мой чертеж завершается с помощью:

SDL_GL_SwapWindow( window );

Мое считывание глубины выполняется с помощью:

float depth;
glReadPixels( scrx, scry, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth );

Синхронизация моего дисплея настраивается с помощью:

int rv = SDL_GL_SetSwapInterval( -1 );
if ( rv < 0 )
{
    LOGI( "Late swap tearing not available. Using hard v-sync with display." );
    rv = SDL_GL_SetSwapInterval( 1 );
    if ( rv < 0 ) LOGE( "SDL_GL_SetSwapInterval() failed." );
}
else
{
    LOGI( "Can use late vsync swap." );
}

Исследования с помощью «perf» показывают, что циклы сгорели от nVidiaдрайвер, выполняющий неослабевающие системные вызовы, одним из которых является sys_clock_gettime (), как показано ниже:

flame graph

Я пробовал некоторые варианты, читая GL_BACKили GL_FRONT, с тем же результатом.Я также пытался читать перед и сразу после смены окна.Но загрузка процессора всегда находится на уровне 100%.

  • Платформа: Ubuntu 18.04.1
  • SDL: версия 2.0.8
  • Процессор: Intel Haswell
  • GPU: nVidia GTX750Ti
  • GL_VERSION: 3.2.0NVIDIA 390.87

ОБНОВЛЕНИЕ

В Intel HD Graphics процессор не блокируется.GlReadPixels все еще медленный, но процессор имеет низкий коэффициент заполнения (1%) или около того, по сравнению с полностью загруженным 100% процессором в драйверах nVidia.

Я также пробовал асинхронное чтение пикселей через PBO (объекты буфера пикселей), но они работают только для значений RGBA, но не для значений DEPTH.

...