Есть ли эффективный способ превзойти GL_MAX_VIEWPORTS? - PullRequest
4 голосов
/ 09 апреля 2019

В настоящее время я реализую алгоритм оценки поз, предложенный в Oikonomidis et al., 2011 , который включает рендеринг сетки в N различных гипотетических позах (N, вероятно, будет около 64).В разделе 2.5 предлагается ускорить вычисления за счет использования экземпляров для одновременной генерации нескольких визуализаций (после чего они уменьшают каждый рендеринг до одного числа на графическом процессоре), и из их описания звучит так, как будто они нашли способ производить N рендеринг одновременно.

На этапе настройки моей реализации я использую массив окон просмотра OpenGL для определения GL_MAX_VIEWPORTS окон просмотра.Затем на этапе рендеринга я передаю массив GL_MAX_VIEWPORTS матриц позы модели в массив mat4 uniform в памяти графического процессора (меня интересует только оценка положения и ориентации) и использую gl_InvocationID в моей геометриишейдер, чтобы выбрать соответствующую матрицу поз и видовой экран для каждого многоугольника сетки.

GL_MAX_VIEWPORTS - это 16 на моей машине (у меня GeForce GTX Titan), поэтому этот метод позволит мне рендерить до 16гипотезы за один раз на GPU.Это может оказаться достаточно быстрым, но мне, тем не менее, любопытно узнать следующее:

Есть ли обходной путь для ограничения GL_MAX_VIEWPORTS, который может быть быстрее, чем вызов моей функции рендеринга ceil(double(N)/GL_MX_VIEWPORTS) раз?

Я только начал изучать шейдерный подход к OpenGL пару недель назад, поэтому пока не знаю всех хитростей.Сначала я подумал о том, чтобы заменить использование встроенной поддержки видового экрана комбинацией:

  1. геометрического шейдера, который добавляет h*gl_InvocationID к y координатам вершин после проекции перспективы (гдеh - желаемая высота области просмотра) и передает gl_InvocationID на фрагментный шейдер;и
  2. фрагментный шейдер, который discard фрагментов с y координатами, которые удовлетворяют y<gl_InvocationID*h || y>=(gl_InvocationID+1)*h.

Но я был отстранен от дальнейшего изучения этой идеи из-за страха, что ветвлениеи discard будет очень вредно для производительности.

Авторы вышеприведенного документа опубликовали технический отчет , описывающий некоторые из их методов ускорения на GPU, но он недостаточно подробен, чтобы ответить на мой вопрос.В разделе 3.2.3 написано «Во время создания экземпляра геометрии информация о портах прикрепляется к каждой вершине ... Пользовательский пиксельный шейдер обрезает пиксели, которые находятся за пределами их предварительно заданных окон просмотра» .Это похоже на обходной путь, который я описал выше, но они использовали Direct3D, поэтому нелегко сравнить то, чего они смогли достичь с этим в 2011 году, с тем, что я могу достичь сегодня в OpenGL.

Я понимаю, что единственным окончательным ответом на мой вопрос является внедрение обходного пути и измерение его производительности, но в настоящее время это интерес с низким приоритетом, и я не нашел ответов где-либо еще, поэтому я надеялся, что более опытный пользователь GLSL может бытьв состоянии предложить свою экономящую время мудрость.

1 Ответ

8 голосов
/ 09 апреля 2019

При беглом взгляде на бумагу мне кажется, что фактическое окно просмотра не меняется.То есть вы по-прежнему выполняете рендеринг в тех же положениях ширины / высоты и X / Y с тем же диапазоном глубины.

Вам нужно изменить, какое изображение вы визуализируетек.Для чего gl_Layer;чтобы изменить, какой слой в многослойном массиве изображений, прикрепленных к кадровому буферу, вы рендерите в.

Так что просто установите gl_ViewportIndex в 0 для всех вершин.Или, точнее, не устанавливайте его вообще.

Количество вызовов экземпляра GS не имеет ограничение;это ваш выбор.Вызовы GS могут записывать несколько примитивов, каждый на свой слой.Таким образом, каждый экземпляр может написать, например, 4 примитива, каждый на 4 отдельных слоя.

Ваши единственные ограничения должны заключаться в количестве слоев, которые вы можете использовать (определяется как GL_MAX_ARRAY_TEXTURE_LAYERS и GL_MAX_FRAMEBUFFER_LAYERS, обаиз которых должно быть не менее 2048), а также число примитивов и данных вершин, которые может выдать один вызов GS (что является сложным ).

...